From: Damian Hobson-Garcia Date: Tue, 5 Apr 2022 03:11:38 +0000 (+0900) Subject: Add configuration file loading and parsing X-Git-Tag: 13.0.1^2~5 X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?p=src%2Fdrm-lease-manager.git;a=commitdiff_plain;h=e9e5cf1f67a45e4d409dc9e1caa6ce8151579c88 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. Bug-AGL: SPEC-3815 Change-Id: Iec4eaf37fba5db17a22e4945de10a06ac94063e4 Signed-off-by: Damian Hobson-Garcia --- diff --git a/drm-lease-manager/lease-config.c b/drm-lease-manager/lease-config.c new file mode 100644 index 0000000..abb7fc1 --- /dev/null +++ b/drm-lease-manager/lease-config.c @@ -0,0 +1,121 @@ +/* Copyright 2022 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 +#include +#include +#include +#include + +#define CONFIG_ERROR(x, ...) ERROR_LOG("%s: " x, filename, ##__VA_ARGS__) + +static bool populate_connector_names(struct lease_config *config, + toml_array_t *conns) +{ + int cnames = toml_array_nelem(conns); + config->connector_names = calloc(cnames, sizeof(char *)); + if (!config->connector_names) { + DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno)); + return false; + } + + config->cnames = cnames; + + for (int i = 0; i < config->cnames; i++) { + toml_datum_t conn = toml_string_at(conns, i); + if (!conn.ok) { + return false; + } + config->connector_names[i] = conn.u.s; + } + return true; +} + +int parse_config(char *filename, struct lease_config **parsed_config) +{ + struct lease_config *config = NULL; + int nconfigs, i, ret = 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); + fclose(fp); + return 0; + } + + toml_array_t *leases = toml_array_in(t_config, "lease"); + if (!leases) { + CONFIG_ERROR( + "Invalid config - cannot find any 'lease' configs"); + goto err; + } + nconfigs = toml_array_nelem(leases); + config = calloc(nconfigs, sizeof *config); + + if (!config) { + DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno)); + goto err; + } + + for (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); + goto err_free_config; + } + + config[i].lease_name = name.u.s; + + toml_array_t *conns = toml_array_in(lease, "connectors"); + if (conns && !populate_connector_names(&config[i], conns)) { + CONFIG_ERROR("Non string connector name in lease: %s\n", + config[i].lease_name); + goto err_free_config; + } + } + + *parsed_config = config; + ret = nconfigs; +err: + toml_free(t_config); + fclose(fp); + return ret; +err_free_config: + release_config(i, config); + goto err; +} + +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..0760a99 --- /dev/null +++ b/drm-lease-manager/lease-config.h @@ -0,0 +1,19 @@ +/* Copyright 2022 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..ff69e75 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..4732283 100644 --- a/drm-lease-manager/meson.build +++ b/drm-lease-manager/meson.build @@ -1,9 +1,10 @@ lease_manager_files = files('lease-manager.c') lease_server_files = files('lease-server.c') +lease_config_files = files('lease-config.c') main = executable('drm-lease-manager', - [ 'main.c', lease_manager_files, lease_server_files ], - dependencies: [ drm_dep, dlmcommon_dep, thread_dep ], + [ 'main.c', lease_manager_files, lease_server_files, lease_config_files ], + dependencies: [ drm_dep, dlmcommon_dep, thread_dep, toml_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..fa5edcd --- /dev/null +++ b/drm-lease-manager/test/lease-config-test.c @@ -0,0 +1,102 @@ +/* Copyright 2022 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 +#include + +#define CONFIG_FILE_TEMPLATE "/tmp/dlmconfig_tmpXXXXXX" +int config_fd; +char config_file[] = CONFIG_FILE_TEMPLATE; + +static void test_setup(void) +{ + strcpy(config_file, CONFIG_FILE_TEMPLATE); + config_fd = mkstemp(config_file); + ck_assert_int_ge(config_fd, 0); +} + +static void test_shutdown(void) +{ + close(config_fd); + unlink(config_file); +} + +/* parse config file test */ +/* Test details: Parse a config file + * Expected results: a config with the expected results + */ + +START_TEST(parse_leases) +{ + 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"; + + write(config_fd, test_data, sizeof(test_data)); + + struct lease_config *config = NULL; + int nconfigs = parse_config(config_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 bb97274..8d5c06f 100644 --- a/drm-lease-manager/test/meson.build +++ b/drm-lease-manager/test/meson.build @@ -32,5 +32,17 @@ lm_test = executable('lease-manager-test', c_args: test_c_args, 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, toml_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) diff --git a/meson.build b/meson.build index 7f8adf5..c2c88a6 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ configuration_inc = include_directories('.') drm_dep = dependency('libdrm', version: '>= 2.4.89') thread_dep = dependency('threads') +toml_dep = dependency('libtoml') enable_tests = get_option('enable-tests')