Skip to content

Commit 78919f8

Browse files
committed
YARN-4245. Generalize config file handling in container-executor. Contributed by Sidharta Seethana.
(cherry picked from commit 8ed2e06)
1 parent e9a0ffc commit 78919f8

File tree

6 files changed

+112
-66
lines changed

6 files changed

+112
-66
lines changed

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.c

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,22 @@
3434

3535
#define MAX_SIZE 10
3636

37-
struct confentry {
38-
const char *key;
39-
const char *value;
40-
};
41-
42-
struct configuration {
43-
int size;
44-
struct confentry **confdetails;
45-
};
46-
47-
struct configuration config={.size=0, .confdetails=NULL};
48-
4937
//clean up method for freeing configuration
50-
void free_configurations() {
38+
void free_configurations(struct configuration *cfg) {
5139
int i = 0;
52-
for (i = 0; i < config.size; i++) {
53-
if (config.confdetails[i]->key != NULL) {
54-
free((void *)config.confdetails[i]->key);
40+
for (i = 0; i < cfg->size; i++) {
41+
if (cfg->confdetails[i]->key != NULL) {
42+
free((void *)cfg->confdetails[i]->key);
5543
}
56-
if (config.confdetails[i]->value != NULL) {
57-
free((void *)config.confdetails[i]->value);
44+
if (cfg->confdetails[i]->value != NULL) {
45+
free((void *)cfg->confdetails[i]->value);
5846
}
59-
free(config.confdetails[i]);
47+
free(cfg->confdetails[i]);
6048
}
61-
if (config.size > 0) {
62-
free(config.confdetails);
49+
if (cfg->size > 0) {
50+
free(cfg->confdetails);
6351
}
64-
config.size = 0;
52+
cfg->size = 0;
6553
}
6654

6755
/**
@@ -133,8 +121,8 @@ int check_configuration_permissions(const char* file_name) {
133121
return 0;
134122
}
135123

136-
//function used to load the configurations present in the secure config
137-
void read_config(const char* file_name) {
124+
125+
void read_config(const char* file_name, struct configuration *cfg) {
138126
FILE *conf_file;
139127
char *line;
140128
char *equaltok;
@@ -152,9 +140,9 @@ void read_config(const char* file_name) {
152140
#endif
153141

154142
//allocate space for ten configuration items.
155-
config.confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
143+
cfg->confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
156144
* MAX_SIZE);
157-
config.size = 0;
145+
cfg->size = 0;
158146
conf_file = fopen(file_name, "r");
159147
if (conf_file == NULL) {
160148
fprintf(ERRORFILE, "Invalid conf file provided : %s \n", file_name);
@@ -196,9 +184,9 @@ void read_config(const char* file_name) {
196184
free(line);
197185
continue;
198186
}
199-
config.confdetails[config.size] = (struct confentry *) malloc(
187+
cfg->confdetails[cfg->size] = (struct confentry *) malloc(
200188
sizeof(struct confentry));
201-
if(config.confdetails[config.size] == NULL) {
189+
if(cfg->confdetails[cfg->size] == NULL) {
202190
fprintf(LOGFILE,
203191
"Failed allocating memory for single configuration item\n");
204192
goto cleanup;
@@ -208,10 +196,10 @@ void read_config(const char* file_name) {
208196
fprintf(LOGFILE, "read_config : Adding conf key : %s \n", equaltok);
209197
#endif
210198

211-
memset(config.confdetails[config.size], 0, sizeof(struct confentry));
212-
config.confdetails[config.size]->key = (char *) malloc(
199+
memset(cfg->confdetails[cfg->size], 0, sizeof(struct confentry));
200+
cfg->confdetails[cfg->size]->key = (char *) malloc(
213201
sizeof(char) * (strlen(equaltok)+1));
214-
strcpy((char *)config.confdetails[config.size]->key, equaltok);
202+
strcpy((char *)cfg->confdetails[cfg->size]->key, equaltok);
215203
equaltok = strtok_r(NULL, "=", &temp_equaltok);
216204
if (equaltok == NULL) {
217205
fprintf(LOGFILE, "configuration tokenization failed \n");
@@ -220,36 +208,38 @@ void read_config(const char* file_name) {
220208
//means value is commented so don't store the key
221209
if(equaltok[0] == '#') {
222210
free(line);
223-
free((void *)config.confdetails[config.size]->key);
224-
free(config.confdetails[config.size]);
211+
free((void *)cfg->confdetails[cfg->size]->key);
212+
free(cfg->confdetails[cfg->size]);
225213
continue;
226214
}
227215

228216
#ifdef DEBUG
229217
fprintf(LOGFILE, "read_config : Adding conf value : %s \n", equaltok);
230218
#endif
231219

232-
config.confdetails[config.size]->value = (char *) malloc(
220+
cfg->confdetails[cfg->size]->value = (char *) malloc(
233221
sizeof(char) * (strlen(equaltok)+1));
234-
strcpy((char *)config.confdetails[config.size]->value, equaltok);
235-
if((config.size + 1) % MAX_SIZE == 0) {
236-
config.confdetails = (struct confentry **) realloc(config.confdetails,
237-
sizeof(struct confentry **) * (MAX_SIZE + config.size));
238-
if (config.confdetails == NULL) {
222+
strcpy((char *)cfg->confdetails[cfg->size]->value, equaltok);
223+
if((cfg->size + 1) % MAX_SIZE == 0) {
224+
cfg->confdetails = (struct confentry **) realloc(cfg->confdetails,
225+
sizeof(struct confentry **) * (MAX_SIZE + cfg->size));
226+
if (cfg->confdetails == NULL) {
239227
fprintf(LOGFILE,
240228
"Failed re-allocating memory for configuration items\n");
241229
goto cleanup;
242230
}
243231
}
244-
if(config.confdetails[config.size] )
245-
config.size++;
232+
if(cfg->confdetails[cfg->size]) {
233+
cfg->size++;
234+
}
235+
246236
free(line);
247237
}
248238

249239
//close the file
250240
fclose(conf_file);
251241

252-
if (config.size == 0) {
242+
if (cfg->size == 0) {
253243
fprintf(ERRORFILE, "Invalid configuration provided in %s\n", file_name);
254244
exit(INVALID_CONFIG_FILE);
255245
}
@@ -262,7 +252,7 @@ void read_config(const char* file_name) {
262252
free(line);
263253
}
264254
fclose(conf_file);
265-
free_configurations();
255+
free_configurations(cfg);
266256
return;
267257
}
268258

@@ -272,11 +262,11 @@ void read_config(const char* file_name) {
272262
* array, next time onwards used the populated array.
273263
*
274264
*/
275-
char * get_value(const char* key) {
265+
char * get_value(const char* key, struct configuration *cfg) {
276266
int count;
277-
for (count = 0; count < config.size; count++) {
278-
if (strcmp(config.confdetails[count]->key, key) == 0) {
279-
return strdup(config.confdetails[count]->value);
267+
for (count = 0; count < cfg->size; count++) {
268+
if (strcmp(cfg->confdetails[count]->key, key) == 0) {
269+
return strdup(cfg->confdetails[count]->value);
280270
}
281271
}
282272
return NULL;
@@ -286,11 +276,21 @@ char * get_value(const char* key) {
286276
* Function to return an array of values for a key.
287277
* Value delimiter is assumed to be a ','.
288278
*/
289-
char ** get_values(const char * key) {
290-
char *value = get_value(key);
279+
char ** get_values(const char * key, struct configuration *cfg) {
280+
char *value = get_value(key, cfg);
291281
return extract_values_delim(value, ",");
292282
}
293283

284+
/**
285+
* Function to return an array of values for a key, using the specified
286+
delimiter.
287+
*/
288+
char ** get_values_delim(const char * key, struct configuration *cfg,
289+
const char *delim) {
290+
char *value = get_value(key, cfg);
291+
return extract_values_delim(value, delim);
292+
}
293+
294294
char ** extract_values_delim(char *value, const char *delim) {
295295
char ** toPass = NULL;
296296
char *tempTok = NULL;

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/configuration.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,33 @@ int check_configuration_permissions(const char* file_name);
3737
*/
3838
char *resolve_config_path(const char* file_name, const char *root);
3939

40-
// read the given configuration file
41-
void read_config(const char* config_file);
40+
// Config data structures.
41+
struct confentry {
42+
const char *key;
43+
const char *value;
44+
};
45+
46+
struct configuration {
47+
int size;
48+
struct confentry **confdetails;
49+
};
50+
51+
// read the given configuration file into the specified config struct.
52+
void read_config(const char* config_file, struct configuration *cfg);
4253

4354
//method exposed to get the configurations
44-
char *get_value(const char* key);
55+
char *get_value(const char* key, struct configuration *cfg);
4556

4657
//function to return array of values pointing to the key. Values are
4758
//comma seperated strings.
48-
char ** get_values(const char* key);
59+
char ** get_values(const char* key, struct configuration *cfg);
60+
61+
/**
62+
* Function to return an array of values for a key, using the specified
63+
delimiter.
64+
*/
65+
char ** get_values_delim(const char * key, struct configuration *cfg,
66+
const char *delim);
4967

5068
// Extracts array of values from the comma separated list of values.
5169
char ** extract_values(char *value);
@@ -56,7 +74,7 @@ char ** extract_values_delim(char *value, const char *delim);
5674
void free_values(char** values);
5775

5876
//method to free allocated configuration
59-
void free_configurations();
77+
void free_configurations(struct configuration *cfg);
6078

6179
/**
6280
* If str is a string of the form key=val, find 'key'

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ FILE* ERRORFILE = NULL;
5959
static uid_t nm_uid = -1;
6060
static gid_t nm_gid = -1;
6161

62+
struct configuration executor_cfg = {.size=0, .confdetails=NULL};
63+
6264
char *concatenate(char *concat_pattern, char *return_path_name,
6365
int numArgs, ...);
6466

@@ -67,6 +69,21 @@ void set_nm_uid(uid_t user, gid_t group) {
6769
nm_gid = group;
6870
}
6971

72+
//function used to load the configurations present in the secure config
73+
void read_executor_config(const char* file_name) {
74+
read_config(file_name, &executor_cfg);
75+
}
76+
77+
//function used to free executor configuration data
78+
void free_executor_configurations() {
79+
free_configurations(&executor_cfg);
80+
}
81+
82+
//Lookup nodemanager group from container executor configuration.
83+
char *get_nodemanager_group() {
84+
return get_value(NM_GROUP_KEY, &executor_cfg);
85+
}
86+
7087
/**
7188
* get the executable filename.
7289
*/
@@ -658,7 +675,7 @@ static struct passwd* get_user_info(const char* user) {
658675
}
659676

660677
int is_whitelisted(const char *user) {
661-
char **whitelist = get_values(ALLOWED_SYSTEM_USERS_KEY);
678+
char **whitelist = get_values(ALLOWED_SYSTEM_USERS_KEY, &executor_cfg);
662679
char **users = whitelist;
663680
if (whitelist != NULL) {
664681
for(; *users; ++users) {
@@ -686,7 +703,7 @@ struct passwd* check_user(const char *user) {
686703
fflush(LOGFILE);
687704
return NULL;
688705
}
689-
char *min_uid_str = get_value(MIN_USERID_KEY);
706+
char *min_uid_str = get_value(MIN_USERID_KEY, &executor_cfg);
690707
int min_uid = DEFAULT_MIN_USERID;
691708
if (min_uid_str != NULL) {
692709
char *end_ptr = NULL;
@@ -713,7 +730,7 @@ struct passwd* check_user(const char *user) {
713730
free(user_info);
714731
return NULL;
715732
}
716-
char **banned_users = get_values(BANNED_USERS_KEY);
733+
char **banned_users = get_values(BANNED_USERS_KEY, &executor_cfg);
717734
banned_users = banned_users == NULL ?
718735
(char**) DEFAULT_BANNED_USERS : banned_users;
719736
char **banned_user = banned_users;
@@ -1062,7 +1079,7 @@ char* parse_docker_command_file(const char* command_file) {
10621079

10631080
int run_docker(const char *command_file) {
10641081
char* docker_command = parse_docker_command_file(command_file);
1065-
char* docker_binary = get_value(DOCKER_BINARY_KEY);
1082+
char* docker_binary = get_value(DOCKER_BINARY_KEY, &executor_cfg);
10661083
char* docker_command_with_binary = calloc(sizeof(char), EXECUTOR_PATH_MAX);
10671084
snprintf(docker_command_with_binary, EXECUTOR_PATH_MAX, "%s %s", docker_binary, docker_command);
10681085
char **args = extract_values_delim(docker_command_with_binary, " ");
@@ -1224,7 +1241,7 @@ int launch_docker_container_as_user(const char * user, const char *app_id,
12241241
char buffer[BUFFER_SIZE];
12251242

12261243
char *docker_command = parse_docker_command_file(command_file);
1227-
char *docker_binary = get_value(DOCKER_BINARY_KEY);
1244+
char *docker_binary = get_value(DOCKER_BINARY_KEY, &executor_cfg);
12281245
if (docker_binary == NULL) {
12291246
docker_binary = "docker";
12301247
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,15 @@ extern FILE *LOGFILE;
9595
// the log file for error messages
9696
extern FILE *ERRORFILE;
9797

98-
9998
// get the executable's filename
10099
char* get_executable();
101100

101+
//function used to load the configurations present in the secure config
102+
void read_executor_config(const char* file_name);
103+
104+
//Lookup nodemanager group from container executor configuration.
105+
char *get_nodemanager_group();
106+
102107
/**
103108
* Check the permissions on the container-executor to make sure that security is
104109
* permissible. For this, we need container-executor binary to
@@ -111,6 +116,12 @@ char* get_executable();
111116
*/
112117
int check_executor_permissions(char *executable_file);
113118

119+
//function used to load the configurations present in the secure config.
120+
void read_executor_config(const char* file_name);
121+
122+
//function used to free executor configuration data
123+
void free_executor_configurations();
124+
114125
// initialize the application directory
115126
int initialize_app(const char *user, const char *app_id,
116127
const char *credentials, char* const* local_dirs,

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ static void assert_valid_setup(char *current_executable) {
112112
flush_and_close_log_files();
113113
exit(INVALID_CONFIG_FILE);
114114
}
115-
read_config(conf_file);
115+
read_executor_config(conf_file);
116116
free(conf_file);
117117

118118
// look up the node manager group in the config file
119-
char *nm_group = get_value(NM_GROUP_KEY);
119+
char *nm_group = get_nodemanager_group();
120120
if (nm_group == NULL) {
121121
fprintf(ERRORFILE, "Can't get configured value for %s.\n", NM_GROUP_KEY);
122122
flush_and_close_log_files();

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ int main(int argc, char **argv) {
873873
if (write_config_file(TEST_ROOT "/test.cfg", 1) != 0) {
874874
exit(1);
875875
}
876-
read_config(TEST_ROOT "/test.cfg");
876+
read_executor_config(TEST_ROOT "/test.cfg");
877877

878878
local_dirs = extract_values(strdup(NM_LOCAL_DIRS));
879879
log_dirs = extract_values(strdup(NM_LOG_DIRS));
@@ -945,14 +945,14 @@ int main(int argc, char **argv) {
945945
seteuid(0);
946946
// test_delete_user must run as root since that's how we use the delete_as_user
947947
test_delete_user();
948-
free_configurations();
948+
free_executor_configurations();
949949

950950
printf("\nTrying banned default user()\n");
951951
if (write_config_file(TEST_ROOT "/test.cfg", 0) != 0) {
952952
exit(1);
953953
}
954954

955-
read_config(TEST_ROOT "/test.cfg");
955+
read_executor_config(TEST_ROOT "/test.cfg");
956956
username = "bin";
957957
test_check_user(1);
958958

@@ -963,6 +963,6 @@ int main(int argc, char **argv) {
963963
printf("\nFinished tests\n");
964964

965965
free(current_username);
966-
free_configurations();
966+
free_executor_configurations();
967967
return 0;
968968
}

0 commit comments

Comments
 (0)