From fa0315bfa87455cfd557072f496b940af6db7190 Mon Sep 17 00:00:00 2001 From: Damian Hobson-Garcia Date: Tue, 5 Apr 2022 12:11:38 +0900 Subject: Add configuration file loading and parsing Parse the lease configuration information from a configuration file. Each lease configuration takes a name and list of connectors to add to the lease. As long as one connector is found for a given configuration, the lease will be created. Change-Id: Iec4eaf37fba5db17a22e4945de10a06ac94063e4 Signed-off-by: Damian Hobson-Garcia --- drm-lease-manager/lease-config.c | 97 +++++++++++++++++++++++++++++ drm-lease-manager/lease-config.h | 19 ++++++ drm-lease-manager/main.c | 18 +++++- drm-lease-manager/meson.build | 3 +- drm-lease-manager/test/lease-config-test.c | 99 ++++++++++++++++++++++++++++++ drm-lease-manager/test/meson.build | 12 ++++ 6 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 drm-lease-manager/lease-config.c create mode 100644 drm-lease-manager/lease-config.h create mode 100644 drm-lease-manager/test/lease-config-test.c diff --git a/drm-lease-manager/lease-config.c b/drm-lease-manager/lease-config.c new file mode 100644 index 0000000..7dfb7e5 --- /dev/null +++ b/drm-lease-manager/lease-config.c @@ -0,0 +1,97 @@ +/* Copyright 2021 IGEL Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lease-config.h" +#include "log.h" +#include "toml/toml.h" +#include +#include + +#define CONFIG_ERROR(x, ...) ERROR_LOG("%s: " x, filename, ##__VA_ARGS__) + +int parse_config(char *filename, struct lease_config **parsed_config) +{ + struct lease_config *config = NULL; + int nconfigs = 0; + char parse_error[160]; + + FILE *fp = fopen(filename, "r"); + if (!fp) + return 0; + + toml_table_t *t_config = + toml_parse_file(fp, parse_error, sizeof parse_error); + if (!t_config) { + CONFIG_ERROR("configuration file parse error: %s\n", + parse_error); + return 0; + } + + toml_array_t *leases = toml_array_in(t_config, "lease"); + if (!leases) { + CONFIG_ERROR( + "Invalid config - cannot find any 'lease' configs"); + } + nconfigs = toml_array_nelem(leases); + config = calloc(nconfigs, sizeof *config); + + for (int i = 0; i < toml_array_nelem(leases); i++) { + toml_table_t *lease = toml_table_at(leases, i); + + toml_datum_t name = toml_string_in(lease, "name"); + if (!name.ok) { + CONFIG_ERROR("Invalid lease name in entry #%d\n", i); + continue; + } + + config[i].lease_name = name.u.s; + + toml_array_t *conns = toml_array_in(lease, "connectors"); + if (conns) { + config[i].cnames = toml_array_nelem(conns); + config[i].connector_names = + calloc(config[i].cnames, sizeof(char *)); + for (int j = 0; j < config[i].cnames; j++) { + toml_datum_t conn = toml_string_at(conns, j); + if (!conn.ok) { + CONFIG_ERROR("Non string connector " + "name in lease: %s\n", + config[i].lease_name); + goto out; + } + config[i].connector_names[j] = conn.u.s; + } + } + } + + toml_free(t_config); + *parsed_config = config; + return nconfigs; +out: + free(config); + return 0; +} + +void release_config(int num_leases, struct lease_config *config) +{ + for (int i = 0; i < num_leases; i++) { + struct lease_config *c = &config[i]; + free(c->lease_name); + for (int j = 0; j < c->cnames; j++) + free(c->connector_names[j]); + free(c->connector_names); + } + free(config); +} diff --git a/drm-lease-manager/lease-config.h b/drm-lease-manager/lease-config.h new file mode 100644 index 0000000..cb5e785 --- /dev/null +++ b/drm-lease-manager/lease-config.h @@ -0,0 +1,19 @@ +/* Copyright 2021 IGEL Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm-lease.h" + +int parse_config(char *filename, struct lease_config **parsed_config); +void release_config(int num_leasess, struct lease_config *config); diff --git a/drm-lease-manager/main.c b/drm-lease-manager/main.c index 2927253..7ff9048 100644 --- a/drm-lease-manager/main.c +++ b/drm-lease-manager/main.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "lease-config.h" #include "lease-manager.h" #include "lease-server.h" #include "log.h" @@ -27,24 +28,28 @@ static void usage(const char *progname) printf("Usage: %s [OPTIONS] []\n\n" "Options:\n" "-h, --help \tPrint this help\n" + "-c, --config \t path to configuration file (default " + "/etc/drm-lease-manager.toml)\n" "-v, --verbose \tEnable verbose debug messages\n" "-t, --lease-transfer \tAllow lease transfter to new clients\n" "-k, --keep-on-crash \tDon't close lease on client crash\n", progname); } -const char *opts = "vtkh"; +const char *opts = "vtkhc"; const struct option options[] = { {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"lease-transfer", no_argument, NULL, 't'}, {"keep-on-crash", no_argument, NULL, 'k'}, + {"config", required_argument, NULL, 'c'}, {NULL, 0, NULL, 0}, }; int main(int argc, char **argv) { char *device = "/dev/dri/card0"; + char *config_file = "/etc/drm-lease-manager.toml"; bool debug_log = false; bool can_transfer_leases = false; @@ -63,6 +68,9 @@ int main(int argc, char **argv) case 'k': keep_on_crash = true; break; + case 'c': + config_file = optarg; + break; case 'h': ret = EXIT_SUCCESS; /* fall through */ @@ -77,7 +85,12 @@ int main(int argc, char **argv) dlm_log_enable_debug(debug_log); - struct lm *lm = lm_create(device); + struct lease_config *lease_configs = NULL; + int num_configs = parse_config(config_file, &lease_configs); + + struct lm *lm = + lm_create_with_config(device, num_configs, lease_configs); + if (!lm) { ERROR_LOG("DRM Lease initialization failed\n"); return EXIT_FAILURE; @@ -145,5 +158,6 @@ int main(int argc, char **argv) done: ls_destroy(ls); lm_destroy(lm); + release_config(num_configs, lease_configs); return EXIT_FAILURE; } diff --git a/drm-lease-manager/meson.build b/drm-lease-manager/meson.build index 7157f01..f749f8f 100644 --- a/drm-lease-manager/meson.build +++ b/drm-lease-manager/meson.build @@ -1,8 +1,9 @@ lease_manager_files = files('lease-manager.c') lease_server_files = files('lease-server.c') +lease_config_files = files('lease-config.c', 'toml/toml.c') main = executable('drm-lease-manager', - [ 'main.c', lease_manager_files, lease_server_files ], + [ 'main.c', lease_manager_files, lease_server_files, lease_config_files ], dependencies: [ drm_dep, dlmcommon_dep, thread_dep ], install: true, ) diff --git a/drm-lease-manager/test/lease-config-test.c b/drm-lease-manager/test/lease-config-test.c new file mode 100644 index 0000000..6f69865 --- /dev/null +++ b/drm-lease-manager/test/lease-config-test.c @@ -0,0 +1,99 @@ +/* Copyright 2021 IGEL Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lease-config.h" +#include +#include +#include + +static void test_setup(void) +{ +} + +static void test_shutdown(void) +{ +} + +/* parse config file test */ +/* Test details: Parse a config file + * Expected results: a config with the expected results + */ + +START_TEST(parse_leases) +{ + char tmp_file[] = "/tmp/dlmconfig_tmpXXXXXX"; + int fd = mkstemp(tmp_file); + + ck_assert_int_ge(fd, 0); + + FILE *config_file = fdopen(fd, "w"); + ck_assert_ptr_ne(config_file, NULL); + + char test_data[] = "[[lease]]\n" + "name = \"lease 1\"\n" + "connectors = [\"1\", \"b\",\"gamma\" ]\n" + "[[lease]]\n" + "name = \"lease 2\"\n" + "connectors = [\"connector 3\"]\n"; + + fwrite(test_data, 1, sizeof(test_data), config_file); + fclose(config_file); + + struct lease_config *config = NULL; + int nconfigs = parse_config(tmp_file, &config); + + ck_assert_int_eq(nconfigs, 2); + ck_assert_ptr_ne(config, NULL); + + ck_assert_str_eq(config[0].lease_name, "lease 1"); + ck_assert_int_eq(config[0].cnames, 3); + ck_assert_str_eq(config[0].connector_names[0], "1"); + ck_assert_str_eq(config[0].connector_names[1], "b"); + ck_assert_str_eq(config[0].connector_names[2], "gamma"); + + ck_assert_str_eq(config[1].lease_name, "lease 2"); + ck_assert_int_eq(config[1].cnames, 1); + ck_assert_str_eq(config[1].connector_names[0], "connector 3"); + + release_config(nconfigs, config); +} +END_TEST + +static void add_parse_tests(Suite *s) +{ + TCase *tc = tcase_create("Config file parsing tests"); + + tcase_add_checked_fixture(tc, test_setup, test_shutdown); + + tcase_add_test(tc, parse_leases); + suite_add_tcase(s, tc); +} + +int main(void) +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = suite_create("DLM lease manager tests"); + + add_parse_tests(s); + + sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/drm-lease-manager/test/meson.build b/drm-lease-manager/test/meson.build index 7d42bec..9e52b13 100644 --- a/drm-lease-manager/test/meson.build +++ b/drm-lease-manager/test/meson.build @@ -26,5 +26,17 @@ lm_test = executable('lease-manager-test', dependencies: [check_dep, fff_dep, dlmcommon_dep, drm_dep], include_directories: ls_inc) +lc_objects = main.extract_objects(lease_config_files) +lc_test_sources = [ + 'lease-config-test.c' +] + +lc_test = executable('lease-config-test', + sources: lc_test_sources, + objects: lc_objects, + dependencies: [check_dep, dlmcommon_dep], + include_directories: ls_inc) + test('DRM Lease manager - socket server test', ls_test, is_parallel: false) test('DRM Lease manager - DRM interface test', lm_test) +test('DRM Lease manager - config parse test', lc_test) -- cgit 1.2.3-korg