示例#1
0
static void main_loop(int fd)
{
	int ret_code;
	char cmd_string[JSONRPC_MAX_STRING_LEN] = {0};
	fd_set fds;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	jrpc_req_pkg_t req;
	json_t *rsp = NULL;
	int func_id = 0;
	int reg_connection = -1;

	char *rsp_str = malloc(JSONRPC_MAX_STRING_LEN);

	if (rsp_str == NULL)
		goto err;

	for (;;) {
		FD_ZERO(&fds);
		FD_SET(fd, &fds);

		ret_code = select(fd + 1, &fds, NULL, NULL, NULL);
		if (ret_code < 0)
			continue;

		memset(cmd_string, 0, sizeof(cmd_string));
		ret_code = recvfrom(fd, cmd_string, sizeof(cmd_string), 0, (struct sockaddr *)&addr, &addrlen);
		if (ret_code < 0)
			continue;

		rsp = json_object();
		if (rsp == NULL)
			goto err;

		rmm_log(INFO, "receive: %s.\n", cmd_string);
		parse_req(cmd_string, &req, &func_id);
		ret_code = process_req(func_id, &req, rsp);
		jrpc_req_pkg_free(&req);
		if (ret_code < 0) {
			continue;
		}

		memset(rsp_str, 0, JSONRPC_MAX_STRING_LEN);
		ret_code = jrpc_create_result_rsp_string(req.id, JSONRPC_ID_TYPE_NORMAL, rsp, JSON_OBJECT, rsp_str);
		if (ret_code < 0)
			continue;

		rmm_log(INFO, "send: %s.\n", rsp_str);
		sendto(fd, rsp_str, strnlen_s(rsp_str, JSONRPC_MAX_STRING_LEN)+1, 0, (struct sockaddr *)&addr, addrlen);
	}

	free(rsp_str);

err:

	close(fd);
	return;
}
示例#2
0
int get_fans_speed_rsp(int result, unsigned char *rsp, int rsp_len,
			void *cb_data)
{
	am_node_t *fans;
	fans_data_t *fans_data;
	int i;
	unsigned int speed[MAX_PWM_NUM] = {0};
	bool is_changed = false;

	if (NULL == cb_data) {
		rmm_log(ERROR, "cb_data is NULL\n");
		exit(-1);
	}

	fans = (am_node_t *)cb_data;
	fans_data = (fans_data_t *)(fans->priv_data);
	if (IPMI_CC_OK != rsp[0])
		goto err;

	rmm_log(DBG, "TZone speed[%d][%d][%d][%d][%d][%d] uuid[%s]\n",
				(rsp[0*2+2])|(rsp[0*2+1]<<8),
				(rsp[1*2+2])|(rsp[1*2+1]<<8),
				(rsp[2*2+2])|(rsp[2*2+1]<<8),
				(rsp[3*2+2])|(rsp[3*2+1]<<8),
				(rsp[4*2+2])|(rsp[4*2+1]<<8),
				(rsp[5*2+2])|(rsp[5*2+1]<<8),
				fans_data->uuid);

	for (i = 0; i < MAX_PWM_NUM; i++) {
		speed[i]  = (rsp[i*2+2])|(rsp[i*2+1]<<8);
		if (speed[i] != fans_data->speed[i]) {
			is_changed = true;
		}
	}

	if (is_changed)
		notify_fans_speed_change(fans, speed);

	for (i = 0; i < MAX_PWM_NUM; i++) {
		fans_data->speed[i] = speed[i];
	}

	fans->node_status = ONLINE;
	process_next_func(get_cm_node(fans));

	return 0;

err:
	rmm_log(ERROR, "response error IPMI CC %d.\n", rsp[0]);
	notify_fans_speed_change(fans, speed);
	set_fn_status(fans, FUNC_FAIL);
	//set_node_status(fans, OFFLINE, true);
	process_next_func(get_cm_node(fans));

	return -1;
}
示例#3
0
static bool get_index_by_uuid(const int8 *uuid, const int32 type, int32 *index)
{
	struct node_info *subnode = NULL;
	struct node_info *sub_node = NULL;
	int32 subnode_num = 0;
	int32 i;
	int8 rs[128] = {0};
	int64 error_code = 0;
	int32 loc_id = 0;

	subnode = libdb_list_node_by_type(DB_RMM, (uint32)type, (uint32)type, &subnode_num, NULL, LOCK_ID_NULL);

	if (subnode == NULL) {
		rmm_log(ERROR, "get subnode error\n");
		return FALSE;
	}

	sub_node = (struct node_info *)malloc(sizeof(struct node_info) * subnode_num);
	if (sub_node == NULL) {
		rmm_log(ERROR, "malloc error\n");
		return FALSE;
	}

	memcpy_s(sub_node, sizeof(struct node_info) * subnode_num, subnode, sizeof(struct node_info) * subnode_num);

	for (i = 0; i < subnode_num; i++) {
		memset(rs, 0, 128);
		error_code = 0;
		error_code = libdb_attr_get_string(DB_RMM, sub_node[i].node_id, WRAP_UUID_STR, rs, 128, LOCK_ID_NULL);

		if (error_code != 0) {
			rmm_log(ERROR, "%s:%d: error code:%d\n", __func__, __LINE__, error_code);
			libdb_free_node(sub_node);
			return FALSE;
		} else {
			if (0 == strcasecmp(uuid, rs)) {
				memset(rs, 0, 128);
				error_code = 0;
				error_code = libdb_attr_get_string(DB_RMM, sub_node[i].node_id, WRAP_LOC_ID_STR, rs, 128, LOCK_ID_NULL);
				if (error_code != 0) {
					rmm_log(ERROR, "%s:%d: error code:%d\n", __func__, __LINE__, error_code);
					libdb_free_node(sub_node);
					return FALSE;
				} else if (index != NULL) {
					loc_id = str2int(rs);
					*index = gen_asset_index(type, loc_id, sub_node[i].node_id);
					libdb_free_node(sub_node);
					return TRUE;
				}
			}
		}
	}

	libdb_free_node(sub_node);
	return FALSE;
}
示例#4
0
static void *asset_module_set_gami_attr_thread()
{
	int attr_set = -1;
	long expire = 0;
	memdb_integer reg_node_id = 0;
	int self_ip = 0;
	int port = 0;
	int self_port = 0;
	int i = 0;
	char cap_name[GAMI_MAX_NAME_LEN] = {0};
	struct node_info *subnode = NULL;
	struct node_info *sub_node = NULL;
	int node_num = 0;
	prctl(PR_SET_NAME, "attr_thread");
	while(attr_set) {
		subnode = libdb_list_subnode_by_type(DB_RMM, MC_NODE_ROOT, MC_TYPE_REG, &node_num, NULL, LOCK_ID_NULL);
		if (node_num != 1) {
			rmm_log(ERROR, "invalid registry node num in memdb\n");
			continue;
		}
		sub_node = (struct node_info *)malloc(CMDBUFSIZ);
		if (sub_node == NULL) {
			return 0;
		}
		memcpy_s(sub_node, sizeof(struct node_info) * node_num, subnode, sizeof(struct node_info) * node_num);

		reg_node_id = sub_node[0].node_id;
		subnode = libdb_list_subnode_by_type(DB_RMM, reg_node_id, MC_TYPE_REG_MODULE, &node_num, NULL, LOCK_ID_NULL);
		if (node_num == 0) {
			rmm_log(ERROR, "no asset module registry info found\n");
			continue;
		}
		memset(sub_node, 0, CMDBUFSIZ);
		memcpy_s(sub_node, sizeof(struct node_info) * node_num, subnode, sizeof(struct node_info) * node_num);

		for (i = 0; i < node_num; i++) {
			libdb_attr_get_string(DB_RMM, sub_node[i].node_id, JRPC_GAMI_REG_NAME, cap_name, GAMI_MAX_NAME_LEN, LOCK_ID_NULL);
			if (strcmp(cap_name, PROC_ASSET_MODULE) == 0) {
				libdb_attr_get_int(DB_RMM, sub_node[i].node_id, JRPC_GAMI_REG_PORT, &port, LOCK_ID_NULL);
				connect_asset_module(port);
				self_port = rmm_cfg_get_port(ASSETD_PORT);
				if(asset_module_set_gami_attr(&self_ip, &self_port) != -1) {
					rmm_log(INFO, "asset module set gami attr success\n");
					attr_set = 0;
					break;
				}
			}
		}
		libdb_free_node(sub_node);
		sleep(1);
	}
	return NULL;
}
示例#5
0
static void ad_connect_am(void)
{
	int port = rmm_cfg_get_port(ASSETD_PORT);

	if (port == 0) {
		rmm_log(ERROR, "Can't get asset monitor port...\n");
		exit(-1);
	}
	cmfd = udp_connect(INADDR_LOOPBACK, port);
	if (cmfd < 0) {
		rmm_log(ERROR, "Connect memdbd failed...\n");
		exit(-1);
	}
}
static memdb_integer get_rf_node_id(void)
{
	int32 output = 0;
	struct node_info *subnode = NULL;
	int32 subnode_num = 0;
	int32 retry = 3;
	memdb_integer node_id = 0;

	while (retry--) {
		subnode = libdb_list_node_by_type(DB_RMM, MC_REDFISH, MC_REDFISH, &subnode_num, NULL, LOCK_ID_NULL);
		if (subnode)
			break;
		sleep(1);
	}

	if (subnode_num != 1  || subnode == NULL) {
		libdb_free_node(subnode);
		rmm_log(ERROR, "failed to get subnode\n");
		return 0;
	}

	node_id = subnode[0].node_id;
	libdb_free_node(subnode);

	return node_id;
}
示例#7
0
void set_tzone_pwm(am_node_t *cm)
{
	jipmi_msg_t req = { {0} };
	am_node_t *tzone = node_lookup(cm, TZONE_NODE);
	tzone_data_t *tzone_data = (tzone_data_t *)tzone->priv_data;
	cm_data_t *cm_data = (cm_data_t *)cm->priv_data;
	func_tbl_t func = fn_tbl[cm_data->func_idx];
	int32 tz_num = 1;

	if (func_not_ready(tzone, tzone_data->set_tzone_pwm, func.once))
		goto next;

	if (update_pwm_ready(tzone_data) == false)
		goto next;

	FILL_INT(req.netfn,		IPMI_CM_NETFN);
	FILL_INT(req.cmd,		SET_DEFAULT_PWM_CMD);
	FILL_STR(req.name,		am_rmcp_username);
	FILL_STR(req.password,	am_rmcp_password);
	FILL_INT(req.data_len,	2);
	req.data[0] = 0xff;
	req.data[1] = tzone_data->pwm[tz_num - 1];

	rmm_log(DBG, "set pwm is %d\n", tzone_data->pwm[0]);

	tzone_data->set_tzone_pwm.expire = get_current_tick() + func.timeout;
	libjipmi_rmcp_cmd(cm_data->ip_address, IPMI_RMCP_PORT, &req, func.callback, tzone, JIPMI_NON_SYNC);
	return;

next:
	process_next_func(cm);
	return;
}
示例#8
0
static void create_listen_socket(int *fd)
{
	int port; 
	
	port = rmm_cfg_get_port(ASSETD_PORT);
	if (port == 0) {
		rmm_log(ERROR, "Fail to call port.\n");
		exit(-1);
	}
	*fd = create_udp_listen(INADDR_LOOPBACK, port, 0, 0);
	if (*fd < 0) {
		rmm_log(ERROR, "create udp on port %d error: %s\n", port, strerror(errno));
		exit(-1);
	}

	return;
}
示例#9
0
int gami_register(void)
{
	gami_reg_t reg_info = {{0}};

	generate_gami_reg_info(&reg_info);

	while (1) {
		if (0 == gami_register_req(&reg_info)) {
			rmm_log(INFO, "Sending gami registry request\n");
			break;
		} else {
			rmm_log(ERROR, "GAMI registry error\n");
			sleep(1);
		}
	}

	rmm_log(INFO, "GAMI registry finished\n");
	return 0;
}
/**
 * @brief Create event type node for each event(such as change, alert and so on).
 *
 */
static void create_rf_event_action_node(memdb_integer parent, uint32 type, int8 *msg_id_str)
{
	memdb_integer evt_type_node = libdb_create_node(DB_RMM, parent, type, SNAPSHOT_NEED, LOCK_ID_NULL);
	int32 rc = 0;

	rc = libdb_attr_set_string(DB_RMM, evt_type_node, MSG_ID_KEY, 0, msg_id_str, SNAPSHOT_NEED, LOCK_ID_NULL);
	if (rc == -1) {
		rmm_log(ERROR, "memdb set %s fail\n", msg_id_str);
	}
}
示例#11
0
int main()
{
	int rc;
	int max_fd;
	fd_set rfds;
	struct cooling_ctrl *ctrl;
	int port;

	if (daemon(1, 1) < 0)
		exit(-1);

	if (rmm_modules_init(MODULEINIT_LOG, IPMICOOLINGCTRL_PORT, JSONRPCINIT_MEMDB | JSONRPCINIT_JIPMI) == -1)
		exit(-1);

	ctrl = cooling_allocate();

	if (ctrl == NULL)
		exit(-1);

	if (libdb_init_subscription(NOTIFY_BY_SELECT, cooling_event_ops, ctrl) < 0) {
		rmm_log(ERROR, "Failed to init select subscirbe mode!\n");
		return -1;
	}

	cooling_init(ctrl);

	rmm_log(INFO, "cooling ctrl default init success!\n");

	for (;;) {
		max_fd = -1;
		FD_ZERO(&rfds);

		libjsonrpcapi_callback_selectfds(&rfds, &max_fd);

		rc = select(max_fd + 1, &rfds, NULL, NULL, NULL);
		if (rc <= 0)
			continue;

		libjsonrpcapi_callback_processfds(&rfds);
	}

}
static bool get_index_by_uuid(const int8 *uuid, const int32 type, int32 *index)
{
	struct node_info *subnode = NULL;
	int32 subnode_num = 0;
	int32 i;
	int8 rs[128] = {0};
	int64 error_code = 0;
	int32 loc_id = 0;

	subnode = libdb_list_node_by_type(DB_RMM, (uint32)type, (uint32)type, &subnode_num, NULL, LOCK_ID_NULL);

	for (i = 0; i < subnode_num; i++) {
		memset(rs, 0, 128);
		error_code = 0;
		error_code = libdb_attr_get_string(DB_RMM, subnode[i].node_id, (int8 *)type_key[type].uuid_key, rs, 128, LOCK_ID_NULL);
		if (error_code != 0) {
			rmm_log(ERROR, "%s:%d: error code:%d\n", __func__, __LINE__, error_code);
			libdb_free_node(subnode);
			return FALSE;
		} else {
			if (0 == strcmp(uuid, rs)) {
				memset(rs, 0, 128);
				error_code = 0;
				error_code = libdb_attr_get_string(DB_RMM, subnode[i].node_id, (int8 *)type_key[type].id_key, rs, 128, LOCK_ID_NULL);
				if (error_code != 0) {
					rmm_log(ERROR, "%s:%d: error code:%d\n", __func__, __LINE__, error_code);
					libdb_free_node(subnode);
					return FALSE;
				} else if (index != NULL) {
					loc_id = str2int(rs);
					*index = gen_asset_index(type, loc_id, subnode[i].node_id);
					libdb_free_node(subnode);
					return TRUE;
				}
			}
		}
	}

	libdb_free_node(subnode);
	return FALSE;
}
示例#13
0
int set_tzone_pwm_cb(int result, unsigned char *rsp, int rsp_len,
			void *cb_data)
{
	am_node_t *tz;
	tzone_data_t *tz_data;
	int32 tz_num = 1;
	int32 rpm = 0;

	if (NULL == cb_data) {
		rmm_log(ERROR, "cb_data is NULL\n");
		exit(-1);
	}

	tz = (am_node_t *)cb_data;
	tz_data = (tzone_data_t *)tz->priv_data;

	if (IPMI_CC_OK != rsp[0])
		goto err;

	rpm = convert_pwm_to_rpm(tz_data->pwm[tz_num - 1]);

	if (rpm == -1)
		goto err;

	if (notify_tzone_rpm_change(tz_data->uuid[tz_num - 1], rpm) != 0)
		return -1;

	process_next_func(get_cm_node(tz));
	return 0;

err:
	rmm_log(ERROR, "response error IPMI CC %d.\n", rsp[0]);
	set_fn_status(tz, FUNC_FAIL);
	process_next_func(get_cm_node(tz));

	return -1;
}
示例#14
0
int process_register(jrpc_req_pkg_t *req, json_t *resp)
{
	jrpc_data_integer port = 0;

	jrpc_get_named_param_value(req->json, JRPC_GAMI_REG_PORT, JSON_INTEGER, &port);
	if (port == 0)
		return -1;
	rmm_log(DBG, "%s port: %lld\n", __func__, port);

	if (connect_assetd((int)port) == 0) {
		cm_runnable = true;
	}
	return 0;

}
示例#15
0
int get_fans_present_rsp(int result, unsigned char *rsp, int rsp_len,
			void *cb_data)
{
	am_node_t *tz;
	tzone_data_t *tz_data;
	int present = 0;

	if (NULL == cb_data) {
		rmm_log(ERROR, "cb_data is NULL\n");
		exit(-1);
	}

	tz = (am_node_t *)cb_data;
	tz_data = (tzone_data_t *)(tz->priv_data);
	if (IPMI_CC_OK != rsp[0])
		goto err;
    rmm_log(DBG, "TZone present[%d:%d] uuid[%s]\n", tz_data->present, rsp[1], tz_data->uuid);
	present = rsp[1];
	if (tz_data->present != present)
		notify_fan_present_change(tz, present);
	tz_data->present = present;
	tz->node_status = ONLINE;
	process_next_func(get_cm_node(tz));

	return 0;

err:
	rmm_log(ERROR, "response error IPMI CC %d.\n", rsp[0]);
	notify_fan_present_change(tz, 0);
	tz_data->present = 0;
	set_fn_status(tz, FUNC_FAIL);
	//set_node_status(tz, OFFLINE, true);
	process_next_func(get_cm_node(tz));

	return -1;
}
static int32 gen_asset_index(const int32 type, int32 loc_id,  memdb_integer node_id)
{
	int8 *name;
	struct node_info *pnode = NULL;
	int64 error_code = 0;
	int32 zone_num = 0;
	int32 cm_lid = 0;
	int32 index = 0;
	int8 rs[128] = {0};

	switch (type) {
	case MC_TYPE_PZONE:
		zone_num = MAX_PZONE_NUM;
		break;
	case MC_TYPE_TZONE:
		zone_num = MAX_TZONE_NUM;
		break;
	case MC_TYPE_DZONE:
		zone_num = MAX_DZONE_NUM;
		break;
	default:
		return loc_id;
	}

	pnode = libdb_get_node_by_node_id(DB_RMM, node_id, LOCK_ID_NULL);
	if (pnode == NULL) {
		 return -1;
	}

	memset(rs, 0, 128);
	error_code = 0;
	error_code = libdb_attr_get_string(DB_RMM, pnode->parent, MBP_LOC_ID_STR, rs, 128, LOCK_ID_NULL);
	if (error_code != 0) {
		rmm_log(ERROR, "%s:%d: error code:%d\n", __func__, __LINE__, error_code);
		return -1;
	}
	cm_lid = str2int(rs);

	index = (cm_lid - 1) * zone_num + loc_id;

	return index;
}
示例#17
0
static void *ipmi_cb_thread(void *unused)
{
	int		rc;
	int		max_fd;
	fd_set	rfds;

	prctl(PR_SET_NAME, "ipmi_cb_thread");
	while (1) {
		max_fd = -1;
		FD_ZERO(&rfds);
		libjipmi_callback_selectfds(&rfds, &max_fd);
		rc = select(max_fd + 1, &rfds, NULL, NULL, NULL);
		if (rc <= 0) {
			rmm_log(INFO, "select timeout\n");
			continue;
		}

		libjipmi_callback_processfds(&rfds);
	}
	printf("ipmi_cb_thread task exit, errno:%d %s\n", errno, strerror(errno));
	return NULL;
}
示例#18
0
static result_t add_listener(listener_t** header, int8 *tmp_url, listener_dest_t *listener, int type_id)
{
	int32 ret = 0;
	listener_t *plast = NULL;
	listener_t *new_node;

	if (*header == NULL) {
		/* No listener has been added before */
		*header = (struct listener *)malloc(sizeof(struct listener));
		if (*header == NULL)
			return RESULT_MALLOC_ERR;

		memset(*header, 0, sizeof(struct listener));
		strncpy_safe((*header)->url, tmp_url, sizeof((*header)->url), sizeof((*header)->url) - 1);
		strncpy_safe((*header)->context, listener->context, sizeof((*header)->context), sizeof((*header)->context) - 1);
		strncpy_safe((*header)->protocol, listener->protocol, sizeof((*header)->protocol), sizeof((*header)->protocol) - 1);
		strncpy_safe((*header)->name, listener->name, sizeof((*header)->name), sizeof((*header)->name) - 1);
		strncpy_safe((*header)->description, listener->description, sizeof((*header)->description), sizeof((*header)->description) - 1);
		(*header)->event_types[(*header)->evt_index] = type_id;
		(*header)->evt_index = (*header)->evt_index + 1;

		return RESULT_OK;
	} else {
		listener_t *orig_header = *header;

		while (*header) {
			ret = strcmp((*header)->url, tmp_url);
			if (ret == 0) {
				if ((*header)->evt_index < TYPES_NUM) {
					/* Add a new event type to exist listener. */
					(*header)->event_types[(*header)->evt_index] = type_id;
					(*header)->evt_index = (*header)->evt_index + 1;
					*header = orig_header;
					return RESULT_OK;
				} else
					rmm_log(ERROR, "Invalid event index:%d\n", (*header)->evt_index);

			} else {
				plast = *header;
				*header = plast->pnext;
			}
		}
		if (*header == NULL && plast != NULL) {
			/* Add a new listener */
			new_node = (struct listener *)malloc(sizeof(struct listener));
			if (new_node == NULL)
				return RESULT_MALLOC_ERR;
			memset(new_node, 0, sizeof(struct listener));
			strncpy_safe(new_node->url, tmp_url, sizeof(new_node->url), sizeof(new_node->url) - 1);
			strncpy_safe(new_node->context, listener->context, sizeof(new_node->context), sizeof(new_node->context) - 1);
			strncpy_safe(new_node->protocol, listener->protocol, sizeof(new_node->protocol), sizeof(new_node->protocol) - 1);
			strncpy_safe(new_node->name, listener->name, sizeof(new_node->name), sizeof(new_node->name) - 1);
			strncpy_safe(new_node->description, listener->description, sizeof(new_node->description), sizeof(new_node->description) - 1);
			new_node->event_types[new_node->evt_index] = type_id;
			new_node->evt_index = new_node->evt_index + 1;
			plast->pnext = new_node;
			*header = orig_header;
		}

		return RESULT_OK;
	}
}
示例#19
0
int main(int argc, char **argv)
{
	int fd;
	int port;
	pthread_t	tid_ipmi_cb;
	pthread_t	tid_asset_module_set_attr;
	gami_reg_t reg_info = {{0}};
	char value[WRAP_DB_MAX_VALUE_LEN] = {0};
	int64 error_code;
	memdb_integer root_service_nid = 0;
	memdb_integer rmc_nid = 0;
	struct node_info *pnode = NULL;
	int32 node_num = 0;

	reg_sigterm_handler(sigterm_handler);

	if (rmm_modules_init(MODULEINIT_LOG | MODULEINIT_COREDUMP | MODULEINIT_REDFISHD,
				ASSETMGR_JSONRPC_PORT,
				JSONRPCINIT_MEMDB | JSONRPCINIT_JIPMI) == -1) {
		exit(-1);
	}

	rmm_log(INFO, "Assetd daemon is Running ...\n");

	create_listen_socket(&fd);

	libdb_is_ready(DB_RMM, LOCK_ID_NULL, -1);
	error_code = libdb_attr_get_string(DB_RMM, MC_NODE_ROOT, RACK_FW_VER_STR, value, WRAP_DB_MAX_VALUE_LEN, LOCK_ID_NULL);
	if (error_code == 0) {
		/*TODO: compare the fw version to decide if need to do db-migration. */
	}

	init_rack_attr();

	pnode = libdb_list_node_by_type(DB_RMM, MC_TYPE_V1, MC_TYPE_V1, &node_num, NULL, LOCK_ID_NULL);
	if ((pnode == NULL) || (node_num == 0)) {
		root_service_nid = libdb_create_node(DB_RMM, MC_NODE_ROOT, MC_TYPE_V1, SNAPSHOT_NEED, LOCK_ID_NULL);
		if (root_service_nid == 0) {
			rmm_log(ERROR, "Failed to create root service node!\n");
			return -1;
		}
		init_root_service_attr(&root_service_nid, PERSISTENT_ALL);

		rmc_nid = libdb_create_node(DB_RMM, root_service_nid, MC_TYPE_RMC, SNAPSHOT_NEED, LOCK_ID_NULL);
		if (rmc_nid == 0) {
			rmm_log(ERROR, "Failed to create root service node!\n");
			return -1;
		}
		init_rmc_attr(&rmc_nid, PERSISTENT_ALL);
	} else {
		root_service_nid = pnode[0].node_id;
		init_root_service_attr(&root_service_nid, PERSISTENT_N);

		pnode = libdb_list_subnode_by_type(DB_RMM, root_service_nid, MC_TYPE_RMC, &node_num, NULL, LOCK_ID_NULL);
		if (pnode != NULL)
			rmc_nid = pnode[0].node_id;
		init_rmc_attr(&rmc_nid, PERSISTENT_N);
	}

	if (pthread_create(&tid_ipmi_cb, NULL, ipmi_cb_thread, NULL) != 0) {
		rmm_log(ERROR, "Failed to create ipmi callback thread!\n");
		return -1;
	}

	if (pthread_create(&tid_asset_module_set_attr, NULL, asset_module_set_gami_attr_thread, NULL) != 0) {
		rmm_log(ERROR, "Failed to create asset module notify thread!\n");
		return -1;
	}

	main_loop(fd);
	return 0;
}