misc: life_mngr: add config module

In the config module, the following functions are implemented:
- load_config
Provide one interface to load lifecycle manager configuration
from config file (life_mngr.conf), in the config file, user
can specify the VM type of VM which lifecycle manager will run
in, the VM name, the communication device name, and
the device name in service VM which is used to communicate with
the VM which is allowed to send system shutdown request.
- check_dir
Check folder exist or not, if not, create the folder
- get_allow_s5_config
Get the name of the device which is allowed to trigger
system shutdown.

v1-->v2:
	Add comments in head file.
v2-->v3:
	Update some log message.
v3-->v6:
	Simply configuration item parsing logic.
	Add get_allow_s5_config interface.

Tracked-On: #6652

Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Reviewed-by: fei1.li@intel.com
This commit is contained in:
Xiangyang Wu 2021-10-19 10:31:18 +08:00 committed by wenlingz
parent ed3a110f5f
commit aa31587857
3 changed files with 184 additions and 0 deletions

View File

@ -0,0 +1,96 @@
/*
* Copyright (C)2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "log.h"
#include "config.h"
struct life_mngr_config life_conf;
int check_dir(const char *path, int flags)
{
struct stat st;
if (stat(path, &st)) {
if (flags) {
if (mkdir(path, 0666)) {
LOG_PRINTF("Failed to create folder (%s)\n", path);
return -1;
}
return 0;
} else {
LOG_PRINTF("%s doesn't exist!\n", path);
return -1;
}
}
if (S_ISDIR(st.st_mode))
return 0;
fprintf(stderr, "%s exists, and is not a directory!\n", path);
return -1;
}
bool load_config(char *conf_path)
{
int pos;
char buf[MAX_FILE_LINE_LEN];
char *key_str, *value_str;
FILE *fd;
int ret;
ret = check_dir(LIFE_MNGR_CONFIG_FOLDER, CHK_CREAT);
if (ret) {
LOG_PRINTF("%s %d\r\n", __func__, __LINE__);
return false;
}
fd = fopen(conf_path, "r");
if (fd == NULL) {
LOG_PRINTF("Failed to open config file: %s", conf_path);
return false;
}
while (fgets(buf, MAX_FILE_LINE_LEN, fd) != NULL) {
pos = 0;
while (buf[pos] == ' ')
pos++;
key_str = &buf[pos];
if (key_str[0] == '#' || key_str[0] == '\n')
continue;
(void) strtok_r(key_str, "=", &value_str);
if (strlen(value_str) == 0) {
LOG_PRINTF("Config file: config item (%s) is invalid\n", buf);
continue;
}
value_str[strlen(value_str) - 1] = '\0';
LOG_PRINTF("Config file: key=%s, value=%s\n", key_str, value_str);
if (strncmp(VM_TYPE, (const char *)key_str, sizeof(VM_TYPE)) == 0)
memcpy(life_conf.vm_type, value_str, strlen(value_str));
else if (strncmp(VM_NAME, (const char *)key_str, sizeof(VM_NAME)) == 0)
memcpy(life_conf.vm_name, value_str, strlen(value_str));
else if (strncmp(DEV_NAME, (const char *)key_str, sizeof(DEV_NAME)) == 0)
memcpy(life_conf.dev_names, value_str, strlen(value_str));
else if (strncmp(ALLOW_TRIGGER_S5, (const char *)key_str,
sizeof(ALLOW_TRIGGER_S5)) == 0)
memcpy(life_conf.allow_trigger_s5, value_str, strlen(value_str));
else
LOG_PRINTF("Invalid item in the configuration file, key=%s, value=%s\n",
key_str, value_str);
}
if (strlen(life_conf.vm_name) == 0) {
LOG_WRITE("Invalid VM name in configuration file\n");
return false;
}
return true;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C)2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
/**
* @brief Number of seconds we're willing to retry to send shutdown request to a guest.
* If this is 0, then there is no retry (use with caution, as guests might miss shutdown
* command from service VM). The default value is 3.
*/
#define VM_SHUTDOWN_RETRY_TIMES 5
/**
* @brief Number of seconds we're willing to wait for all guests to shutdown. If this is 0,
* then there is no time out (use with caution, as guests might not respond to a shutdown
* request). The default value is 300 seconds (5 minutes).
*/
#define SHUTDOWN_TIMEOUT 300
#define LIFE_MNGR_CONFIG_PATH "/etc/life_mngr/life_mngr.conf"
#define LIFE_MNGR_CONFIG_FOLDER "/etc/life_mngr"
#define MAX_FILE_LINE_LEN 120
#define VM_TYPE "VM_TYPE"
#define VM_NAME "VM_NAME"
#define DEV_NAME "DEV_NAME"
#define ALLOW_TRIGGER_S5 "ALLOW_TRIGGER_S5"
#define MAX_CONFIG_VALUE_LEN 128
#define CHK_CREAT 1 /* create a directory, if it does not exist */
#define CHK_ONLY 0 /* check if the directory exist only */
struct life_mngr_config {
char vm_type[MAX_CONFIG_VALUE_LEN];
char vm_name[MAX_CONFIG_VALUE_LEN];
char dev_names[MAX_CONFIG_VALUE_LEN];
char allow_trigger_s5[MAX_CONFIG_VALUE_LEN];
};
extern struct life_mngr_config life_conf;
/**
* @brief Get the name of the device which is allowed to trigger system shutdown
*/
static inline char *get_allow_s5_config(struct life_mngr_config *conf)
{
return conf->allow_trigger_s5;
}
/**
* @brief Load configuration item from config file
*
* @param conf_path config file path
* @return true Load configuration items successfully
* @return false fail to load configuration items
*/
bool load_config(char *conf_path);
/**
* @brief Check folder exist or not, if not, create the folder
*
* @param path the folder path
* @param flags the folder attribute
*/
int check_dir(const char *path, int flags);
#endif

View File

@ -0,0 +1,26 @@
# The VM type of a VM which lifecycle manager will run on
# -service_vm the lifecycle manager will be run on the service VM
# -user_vm the lifecycle manager will be run on the user VM
VM_TYPE=service_vm
# The VM name of a VM which lifecycle manager will run on, the name should
# be unique in the whole system, this name will be embedded log message to
# help user to do system debugging.
VM_NAME=service_VM
# The device type and device names of the devices which are used to
# communicate with other VMs in lifecycle manager.
# For user VM, the default value is tty:/dev/ttyS1;
#
# For service VM, the default setting rule of this field: /dev/ttyS8 is to
# communicate with VM1 (VM ID in hypervisor = 1), /dev/ttyS9 is for VM2 (VM ID is 2),
# /dev/ttyS10 is for VM3 (VM ID is 3) ... /dev/ttyS14 is for VM7 (VM ID is 7)
# note: need to double check related communication vuarts are valid in hypervisor scenario config
# file.
DEV_NAME=tty:/dev/ttyS8,/dev/ttyS9,/dev/ttyS10,/dev/ttyS11,/dev/ttyS12,/dev/ttyS13,/dev/ttyS14
# The device name of the device which is used to communicate with the VM,
# and this VM is allowed to trigger system shutdown through executing
# s5_trigger.sh.
# For user VM, this field is useless.
ALLOW_TRIGGER_S5=/dev/ttyS10