From 3549c65fae455b44c0dd03bbb58473694753d9f5 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Mon, 13 May 2024 09:31:45 -0400 Subject: [PATCH 1/4] This is a proof of concept of running the launcher without using zwe - this calls the configmgr binary instead of zwe doing the same, by creating all environment variables that configmgr and the javascript files need to operate Signed-off-by: 1000TurquoisePogs --- src/main.c | 64 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/main.c b/src/main.c index 1e46cca..d9259f9 100644 --- a/src/main.c +++ b/src/main.c @@ -460,7 +460,7 @@ static void set_shared_uss_env(ConfigManager *configmgr) { object = jsonAsObject(env); } - int maxRecords = 2; + int maxRecords = 5; for (char **env = environ; *env != 0; env++) { maxRecords++; @@ -471,6 +471,12 @@ static void set_shared_uss_env(ConfigManager *configmgr) { // _BPX_SHAREAS is set on component level arrayListAdd(list, "_BPX_SHAREAS"); + + //These are all properties that should not be changed by zowe.environments + arrayListAdd(list, "ZWE_CLI_PARAMETER_CONFIG"); + arrayListAdd(list, "ZWE_CLI_PARAMETER_HA_INSTANCE"); + arrayListAdd(list, "ZWE_zowe_runtimeDirectory"); + if (object) { // environments block is defined in zowe.yaml for (JsonProperty *property = jsonObjectGetFirstProperty(object); property != NULL; property = jsonObjectGetNextProperty(property)) { maxRecords++; @@ -480,6 +486,16 @@ static void set_shared_uss_env(ConfigManager *configmgr) { shared_uss_env = malloc(maxRecords * sizeof(char*)); memset(shared_uss_env, 0, maxRecords * sizeof(char*)); + char *configEnv = malloc(PATH_MAX+32); + char *runtimeEnv = malloc(PATH_MAX+32); + char *haEnv = malloc(256); + snprintf(configEnv, PATH_MAX+32, "ZWE_CLI_PARAMETER_CONFIG=%s", zl_context.config_path); + shared_uss_env[idx++] = configEnv; + snprintf(runtimeEnv, PATH_MAX+32, "ZWE_zowe_runtimeDirectory=%s", zl_context.root_dir); + shared_uss_env[idx++] = runtimeEnv; + snprintf(haEnv, 256, "ZWE_CLI_PARAMETER_HA_INSTANCE=%s", zl_context.ha_instance_id); + shared_uss_env[idx++] = haEnv; + if (object) { // Get all environment variables defined in zowe.yaml and put them in the output as they are for (JsonProperty *property = jsonObjectGetFirstProperty(object); property != NULL; property = jsonObjectGetNextProperty(property)) { @@ -513,6 +529,7 @@ static void set_shared_uss_env(ConfigManager *configmgr) { } } + // Get all environment variables defined in the system and put them in output if they were not already defined in zowe.yaml for (char **env = environ; *env != 0; env++) { char *thisEnv = *env; @@ -540,6 +557,7 @@ static void set_shared_uss_env(ConfigManager *configmgr) { shared_uss_env[idx++] = new_env; } } + shared_uss_env[idx] = NULL; arrayListFree(list); } @@ -865,10 +883,15 @@ static const char **env_comp(zl_comp_t *comp) { env_records++; } - const char **env_comp = malloc((env_records + 2) * sizeof(char*)); + const char **env_comp = malloc((env_records + 3) * sizeof(char*)); + + char *componentEnv = malloc(256); + snprintf(componentEnv, 256, "ZWE_CLI_PARAMETER_COMPONENT=%s", comp->name); + int i = 0; env_comp[i++] = shareas; + env_comp[i++] = componentEnv; for (char **env = shared_uss_env; *env != 0 && i < env_records; env++) { char *thisEnv = *env; char *aux = malloc(strlen(thisEnv) + 1); @@ -912,8 +935,11 @@ static int start_component(zl_comp_t *comp) { int fd_count = 3; int fd_map[3]; char bin[PATH_MAX]; + char js_path[PATH_MAX]; + snprintf(bin, sizeof(bin), "%s/bin/utils/configmgr", zl_context.root_dir); + snprintf(js_path, sizeof(js_path), "%s/bin/commands/internal/start/component/cli.js", zl_context.root_dir); + - snprintf(bin, sizeof(bin), "%s/bin/zwe", zl_context.root_dir); script = fopen(bin, "r"); if (script == NULL) { DEBUG("script not open for %s - %s\n", comp->name, strerror(errno)); @@ -929,28 +955,24 @@ static int start_component(zl_comp_t *comp) { const char *c_args[] = { bin, - "internal", - "start", - "component", - "--config", zl_context.config_path, - "--ha-instance", zl_context.ha_instance_id, - "--component", comp->name, + "-script", + js_path, NULL }; const char **c_envp = env_comp(comp); - if (zl_context.config.debug_mode) { - DEBUG("params for %s:\n", bin); + if (false) { + INFO("params for %s:\n", bin); for (const char **parm = c_args; *parm != 0; parm++) { const char *thisParm = *parm; - DEBUG("for %s, include param: %s\n", bin, thisParm); + INFO("for %s, include param: %s\n", bin, thisParm); } - DEBUG("environment for %s: \n", bin); + INFO("environment for %s: \n", bin); for (const char **env = c_envp; *env != 0; env++) { const char *thisEnv = *env; - DEBUG("for %s, include env: %s\n", bin, thisEnv); + INFO("for %s, include env: %s\n", bin, thisEnv); } } @@ -1419,13 +1441,12 @@ static void handle_get_component_line(void *data, const char *line) { } static char* get_launch_components_cmd(char* sharedenv) { - const char basecmd[] = "%s %s/bin/zwe internal get-launch-components --config \"%s\" --ha-instance %s 2>&1"; - int size = strlen(zl_context.root_dir) + strlen(zl_context.config_path) + strlen(zl_context.ha_instance_id) + strlen(sharedenv) + sizeof(basecmd) + 1; + const char basecmd[] = "%s ZWE_CLI_PARAMETER_CONFIG=\"%s\" %s/bin/utils/configmgr -script %s/bin/commands/internal/get-launch-components/cli.js 2>&1"; + int size = (strlen(zl_context.root_dir) * 2) + strlen(zl_context.config_path) + strlen(sharedenv) + sizeof(basecmd) + 1; char *command = malloc(size); snprintf(command, size, basecmd, - sharedenv, zl_context.root_dir, zl_context.config_path, zl_context.ha_instance_id); - + sharedenv, zl_context.config_path, zl_context.root_dir, zl_context.root_dir); return command; } @@ -1581,13 +1602,12 @@ static void print_line(void *data, const char *line) { } static char* get_start_prepare_cmd(char *sharedenv) { - const char basecmd[] = "%s %s/bin/zwe internal start prepare --config \"%s\" --ha-instance %s 2>&1"; - int size = strlen(zl_context.root_dir) + strlen(zl_context.config_path) + strlen(zl_context.ha_instance_id) + strlen(sharedenv) + sizeof(basecmd) + 1; + const char basecmd[] = "%s ZWE_CLI_PARAMETER_CONFIG=\"%s\" %s/bin/utils/configmgr -script %s/bin/commands/internal/start/prepare/cli.js 2>&1"; + int size = (strlen(zl_context.root_dir) * 2) + strlen(zl_context.config_path) + strlen(sharedenv) + sizeof(basecmd) + 1; char *command = malloc(size); snprintf(command, size, basecmd, - sharedenv, zl_context.root_dir, zl_context.config_path, zl_context.ha_instance_id); - + sharedenv, zl_context.config_path, zl_context.root_dir, zl_context.root_dir); return command; } From 2e57f1ac4a6361f791c16f198aea4f54677c3e50 Mon Sep 17 00:00:00 2001 From: Gautham Kuppuswamy Date: Wed, 12 Jun 2024 02:38:03 -0400 Subject: [PATCH 2/4] Using configmgr to read config yaml for enabled components and check for start script in /instance/component-name/manifest, if both are present then add to component list, instead of zwe Signed-off-by: Gautham Kuppuswamy --- CHANGELOG.md | 3 ++ src/main.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 143 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dec888..b0b8aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to the Zowe Launcher package will be documented in this file. This repo is part of the app-server Zowe Component, and the change logs here may appear on Zowe.org in that section. +## 2.17.0 +- Using configmgr to create the component list rather than zwe. (#117) + ## 2.13.0 - Bugfix: Changed timestamp to UTC to match the server timestamps (#103) - Bugfix: Removed server timestamps from syslog to avoid duplicate logging of time (#103) diff --git a/src/main.c b/src/main.c index 1e46cca..ad1a247 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ #include "logging.h" #include "stcbase.h" #include "zos.h" +#include "yaml2json.h" extern char ** environ; /* @@ -73,6 +74,8 @@ extern char ** environ; #define PATH_MAX _POSIX_PATH_MAX #endif +#define YAML_ERROR_MAX 1024 + // Progressive restart internals in seconds static int restart_intervals_default[] = {1, 1, 1, 5, 5, 10, 20, 60, 120, 240}; @@ -1473,23 +1476,151 @@ static char* get_sharedenv(void) { return output; } -static int get_component_list(char *buf, size_t buf_size) { - char *sharedenv = get_sharedenv(); - char *command = get_launch_components_cmd(sharedenv); +static int check_if_yaml_exists(const char *yaml, const char *name) { + struct stat s; + if (stat(yaml, &s) != 0) { + DEBUG("failed to get properties for file %s='%s' - %s\n", name, yaml, strerror(errno)); + return -1; + } + return 0; +} - free(sharedenv); +static void get_yaml_pair_key(yaml_document_t *document, yaml_node_pair_t *pair, char *buf, size_t buf_size) { + yaml_node_t *node = yaml_document_get_node(document, pair->key); + if (node) { + snprintf(buf, buf_size, "%.*s", (int)node->data.scalar.length, (const char *)node->data.scalar.value); +#ifdef __MVS__ + __atoe(buf); +#endif + } else { + snprintf(buf, buf_size, ""); + DEBUG ("key node not found\n"); + } +} - DEBUG("about to get component list\n"); +static yaml_node_t *get_child_node(yaml_document_t *doc, yaml_node_t *node, const char *name) { + char key[ZL_YAML_KEY_LEN + 1]; + yaml_node_t *value_node = NULL; + for (yaml_node_pair_t *pair = node->data.mapping.pairs.start; pair != node->data.mapping.pairs.top; pair++) { + get_yaml_pair_key(doc, pair, key, sizeof(key)); + if (0 == strcmp(key, name)) { + value_node = yaml_document_get_node(doc, pair->value); + break; + } + } + return value_node; +} + +static void get_yaml_scalar(yaml_document_t *doc, yaml_node_t *node, char *buf, size_t buf_size) { + char *value = (char *)node->data.scalar.value; + snprintf(buf, buf_size, "%s", value); +#ifdef __MVS__ + __atoe(buf); +#endif +} + +static yaml_node_t *get_node_by_path(yaml_document_t *doc, yaml_node_t *node, const char **path, size_t path_len) { + for (size_t i = 0; i < path_len; i++) { + node = get_child_node(doc, node, path[i]); + if (!node) { + break; + } + } + return node; +} + +static int get_string_by_yaml_path(yaml_document_t *doc, yaml_node_t *root, const char **path, size_t path_len, char *buf, int buf_size) { + yaml_node_t *node = get_node_by_path(doc, root, path, path_len); + if (node && node->type == YAML_SCALAR_NODE) { + get_yaml_scalar(doc, node, buf, buf_size); + return 0; + } + return -1; +} + +static int get_component_list(char *buf, size_t buf_size,ConfigManager *configmgr) { char comp_list[COMP_LIST_SIZE] = {0}; - if (run_command(command, handle_get_component_line, (void*)comp_list)) { - ERROR(MSG_COMP_LIST_ERR); + Json *result = NULL; + char manifestPath[PATH_MAX]={0}; + char *runtimeDirectory=NULL; + char *extensionDirectory=NULL; + char item[128] = {0}; + const char *start_path[] = {"commands", "start"}; + int len = 0; + char errorBuffer[YAML_ERROR_MAX]; + bool yamlExists; + bool startScript; + bool enabled; + bool wasMissing = false; + + DEBUG("about to get component list\n"); + int rc = cfgGetAnyC(configmgr, ZOWE_CONFIG_NAME, &result, 1, "components"); + if (jsonIsObject(result)) { + JsonObject *resultObj = jsonAsObject(result); + JsonProperty *prop = resultObj->firstProperty; + int getStatus = cfgGetStringC(configmgr, ZOWE_CONFIG_NAME, &runtimeDirectory, 2, "zowe", "runtimeDirectory"); + if (getStatus) { + getStatus = cfgGetStringC(configmgr, ZOWE_CONFIG_NAME, &extensionDirectory, 2, "zowe", "extensionDirectory"); + if (getStatus) { + ERROR(" failed to get runtimeDirectory and extensionDirectory"); + return -1; + } + } + + while (prop!=NULL) { + enabled = false; + // check if component is enabled + getStatus = cfgGetBooleanC(configmgr, ZOWE_CONFIG_NAME, &enabled,3, "components", prop->key, "enabled"); + if (getStatus) { // failed to get enabled value of the component + DEBUG("failed to get enabled value of the component %s\n", prop->key); + prop = prop->next; + continue; + } + snprintf(manifestPath, PATH_MAX, "%s/components/%s/manifest.yaml", runtimeDirectory, prop->key); + DEBUG("manifest path for component %s is %s\n", prop->key, manifestPath); + + // check if manifest.yaml is in instance/components/component-name/manifest.yaml + yamlExists = true; + if (check_if_yaml_exists(manifestPath, "MANIFEST.YAML")) { + yamlExists = false; + // if not check instance/extensions/component/manifest.yaml + snprintf(manifestPath, PATH_MAX, "%s/components/%s/manifest.yaml", extensionDirectory, prop->key); + DEBUG("manifest path for component %s is %s\n", prop->key, manifestPath); + if(!check_if_yaml_exists(manifestPath, "MANIFEST.YAML")) + yamlExists = true; + } + + // read the yaml and check for item 'commands.start', if present then add enabled component to component list + startScript = false; + if(enabled && yamlExists) { + yaml_document_t *document = readYAML2(manifestPath, errorBuffer, YAML_ERROR_MAX, &wasMissing); + yaml_node_t *root = yaml_document_get_root_node(document); + if (root) { + getStatus = get_string_by_yaml_path(document, root, start_path, sizeof(start_path)/sizeof(start_path[0]), item, sizeof(item)); + memset(item, 0, sizeof(item)); + if(!getStatus) + startScript = true; + } + if (startScript) { + strncpy(comp_list + len, prop->key, strlen(prop->key)); + strncpy(comp_list + len + strlen(prop->key), ",", 1); + len += (strlen(prop->key)+1); + } + } + prop = prop->next; + } + if (len) + comp_list[len-1] = '\0'; } + if (strlen(comp_list) == 0) { ERROR(MSG_COMP_LIST_EMPTY); return -1; } + snprintf(buf, buf_size, "%s", comp_list); INFO(MSG_START_COMP_LIST, buf); + return 0; } @@ -1676,6 +1807,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + setenv("_BPXK_AUTOCVT", "ON", 1); INFO(MSG_LAUNCHER_START); INFO(MSG_LINE_LENGTH); printf_wto(MSG_LAUNCHER_START); // Manual sys log print (messages not set here yet) @@ -1751,7 +1883,7 @@ int main(int argc, char **argv) { if (prepare_instance()) { exit(EXIT_FAILURE); } - if (get_component_list(comp_buf, sizeof(comp_buf))) { + if (get_component_list(comp_buf, sizeof(comp_buf), configmgr)) { exit(EXIT_FAILURE); } component_list = comp_buf; From f40ce5e741300edecfeef45220f4695424d05e39 Mon Sep 17 00:00:00 2001 From: Gautham Kuppuswamy Date: Tue, 18 Jun 2024 12:19:10 -0400 Subject: [PATCH 3/4] Appending the copied env string with NULL character for correct behavior Signed-off-by: Gautham Kuppuswamy --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index d9259f9..c6a985c 100644 --- a/src/main.c +++ b/src/main.c @@ -896,6 +896,7 @@ static const char **env_comp(zl_comp_t *comp) { char *thisEnv = *env; char *aux = malloc(strlen(thisEnv) + 1); strncpy(aux, thisEnv, strlen(thisEnv)); + aux[strlen(thisEnv)] = '\0'; trimRight(aux, strlen(aux)); env_comp[i] = aux; i++; From f574e26684986e4e712d2f8f0cf130f020f0f279 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 20 Jun 2024 13:40:51 +0200 Subject: [PATCH 4/4] Restore debug lines Signed-off-by: 1000TurquoisePogs --- src/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index c6a985c..691e426 100644 --- a/src/main.c +++ b/src/main.c @@ -963,17 +963,17 @@ static int start_component(zl_comp_t *comp) { const char **c_envp = env_comp(comp); - if (false) { - INFO("params for %s:\n", bin); + if (zl_context.config.debug_mode) { + DEBUG("params for %s:\n", bin); for (const char **parm = c_args; *parm != 0; parm++) { const char *thisParm = *parm; - INFO("for %s, include param: %s\n", bin, thisParm); + DEBUG("for %s, include param: %s\n", bin, thisParm); } - INFO("environment for %s: \n", bin); + DEBUG("environment for %s: \n", bin); for (const char **env = c_envp; *env != 0; env++) { const char *thisEnv = *env; - INFO("for %s, include env: %s\n", bin, thisEnv); + DEBUG("for %s, include env: %s\n", bin, thisEnv); } }