You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
heartbeat/cim/resource_common.c

572 lines
17 KiB

/*
* resource_common.c: common functions for resource providers
*
* Author: Jia Ming Pan <jmltc@cn.ibm.com>
* Copyright (c) 2005 International Business Machines
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <lha_internal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <cmpidt.h>
#include <cmpift.h>
#include <cmpimacs.h>
#include "cluster_info.h"
#include "resource_common.h"
#include "cmpi_utils.h"
static char SystemName [] = "LinuxHACluster";
static char SystemClassName [] = "HA_Cluster";
static char PrimitiveClassName [] = "HA_PrimitiveResource";
static char GroupClassName [] = "HA_ResourceGroup";
static char CloneClassName [] = "HA_ResourceClone";
static char MasterClassName [] = "HA_MasterSlaveResource";
static void primitive_set_instance(CMPIBroker * broker,
CMPIInstance * ci, struct ha_msg *, CMPIStatus *);
static void group_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *, CMPIStatus *);
static void clone_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *, CMPIStatus *);
static void master_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *, CMPIStatus *);
static CMPIInstance * make_instance(CMPIBroker * broker, char * classname,
CMPIObjectPath * op, struct ha_msg *info,
uint32_t type, CMPIStatus * rc);
static CMPIInstance * make_instance_byid(CMPIBroker * broker,
CMPIObjectPath * ref, char * rscid,
uint32_t type, CMPIStatus * rc);
static CMPIObjectPath * make_objectpath_byid(CMPIBroker * broker,
CMPIObjectPath * ref, char * rscid,
uint32_t type, CMPIStatus * rc);
static void
primitive_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *info, CMPIStatus * rc)
{
const char *const_host= NULL, *id;
char * host = NULL;
struct ha_msg *msg = NULL;
cmpi_msg2inst(broker, ci, HA_PRIMITIVE_RESOURCE, info, rc);
id = cl_get_string(info, "id");
if ( RESOURCE_ENABLED(id) ) {
msg = cim_query_dispatch(GET_RSC_HOST, id, NULL);
}
/* get hosting node */
if ( msg && (const_host = cl_get_string(msg, "host")) != NULL ){
host = cim_strdup(const_host);
cl_log(LOG_INFO, "Hosting node is %s", host);
CMSetProperty(ci, "HostingNode", host, CMPI_chars);
} else {
/* OpenWBEM will segment fault in HostedResource provider
if "HostingNode" not set */
host = cim_strdup ("Unknown");
CMSetProperty(ci, "HostingNode", host, CMPI_chars);
}
cim_free(host);
}
static void
group_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *info, CMPIStatus * rc)
{
cmpi_msg2inst(broker, ci, HA_RESOURCE_GROUP, info, rc);
}
static void
clone_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *clone, CMPIStatus * rc)
{
cmpi_msg2inst(broker, ci, HA_RESOURCE_CLONE, clone, rc);
}
static void
master_set_instance(CMPIBroker * broker, CMPIInstance * ci,
struct ha_msg *master, CMPIStatus * rc)
{
cmpi_msg2inst(broker, ci, HA_MASTERSLAVE_RESOURCE, master, rc);
}
static CMPIInstance *
make_instance(CMPIBroker * broker, char * classname, CMPIObjectPath * op,
struct ha_msg* info, uint32_t type, CMPIStatus * rc)
{
CMPIInstance * ci = NULL;
char *id, *status;
const char *constid, *conststatus;
char caption [MAXLEN];
struct ha_msg *msg;
ci = CMNewInstance(broker, op, rc);
if ( CMIsNullObject(ci) ) {
cl_log(LOG_ERR, "%s: Can't create instance.", __FUNCTION__);
CMSetStatusWithChars(broker, rc,
CMPI_RC_ERR_FAILED, "Can't get create instance");
return NULL;
}
constid = cl_get_string(info, "id");
id = cim_strdup(constid);
snprintf(caption, MAXLEN, "Resource.%s", id);
/* set other key properties inherited from super classes */
CMSetProperty(ci, "SystemCreationClassName",
SystemClassName, CMPI_chars);
CMSetProperty(ci, "SystemName", SystemName, CMPI_chars);
CMSetProperty(ci, "CreationClassName", classname, CMPI_chars);
CMSetProperty(ci, "Id", id, CMPI_chars);
/* set Caption */
CMSetProperty(ci, "Caption", caption, CMPI_chars);
if ((msg = cim_query_dispatch(GET_RSC_STATUS, id, NULL)) ){
if (( conststatus = cl_get_string(msg, "status")) ) {
status = cim_strdup(conststatus);
CMSetProperty(ci, "ResourceStatus", status, CMPI_chars);
cim_free(status);
}
}
ha_msg_del(msg);
if (type == TID_RES_PRIMITIVE) {
/* attributes2inst(broker, ci, id, info, rc); */
primitive_set_instance(broker, ci, info, rc);
} else if ( type == TID_RES_GROUP){
group_set_instance(broker, ci, info, rc);
} else if ( type == TID_RES_CLONE){
clone_set_instance(broker, ci, info, rc);
} else if ( type == TID_RES_MASTER) {
master_set_instance(broker, ci, info, rc);
}
cim_free(id);
return ci;
}
static CMPIInstance *
make_instance_byid(CMPIBroker * broker, CMPIObjectPath * ref,
char * rscid, uint32_t type, CMPIStatus * rc)
{
CMPIInstance * ci = NULL;
char * namespace, * classname;
CMPIObjectPath * op;
struct ha_msg *info = NULL;
namespace = CMGetCharPtr(CMGetNameSpace(ref, rc));
switch(type) {
case TID_RES_PRIMITIVE:
classname = PrimitiveClassName;
break;
case TID_RES_GROUP:
classname = GroupClassName;
break;
case TID_RES_CLONE:
classname = CloneClassName;
break;
case TID_RES_MASTER:
classname = MasterClassName;
break;
default:
return NULL;
}
if ((info = cim_find_rsc(type, rscid)) == NULL ) {
cl_log(LOG_ERR, "%s: failed to get resource", __FUNCTION__);
return NULL;
}
if ( RESOURCE_ENABLED(rscid)) {
ha_msg_add(info, "enabled", "true");
} else {
ha_msg_add(info, "enabled", "false");
}
op = CMNewObjectPath(broker, namespace, classname, rc);
if ( CMIsNullObject(op) ) {
cl_log(LOG_ERR, "%s: can't create objectpath", __FUNCTION__);
return NULL;
}
ci = make_instance(broker, classname, op, info, type, rc);
ha_msg_del(info);
CMRelease(op);
return ci;
}
static CMPIObjectPath *
make_objectpath_byid(CMPIBroker * broker, CMPIObjectPath * ref,
char * rscid, uint32_t type, CMPIStatus * rc)
{
char *namespace, *classname;
CMPIObjectPath * op;
DEBUG_ENTER();
if ( rscid == NULL ) { return NULL; }
namespace = CMGetCharPtr(CMGetNameSpace(ref, rc));
switch(type) {
case TID_RES_PRIMITIVE:
classname = PrimitiveClassName;
break;
case TID_RES_GROUP:
classname = GroupClassName;
break;
case TID_RES_CLONE:
classname = CloneClassName;
break;
case TID_RES_MASTER:
classname = MasterClassName;
break;
default:
return NULL;
}
op = CMNewObjectPath(broker, namespace, classname, rc);
if ( CMIsNullObject(op) ) {
return NULL;
}
CMAddKey(op, "Id", rscid, CMPI_chars);
CMAddKey(op, "SystemName", SystemName, CMPI_chars);
CMAddKey(op, "SystemCreationClassName", SystemClassName, CMPI_chars);
CMAddKey(op, "CreationClassName", classname, CMPI_chars);
DEBUG_LEAVE();
return op;
}
int
resource_get_inst(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * ref,
char ** properties, uint32_t type, CMPIStatus * rc)
{
CMPIInstance * ci = NULL;
CMPIData data_name;
char * rscid = NULL;
uint32_t this_type;
if ( cim_get_hb_status() != HB_RUNNING ) {
rc->rc = CMPI_RC_ERR_FAILED;
cl_log(LOG_WARNING, "Heartbeat not running.");
return HA_FAIL;
}
data_name = CMGetKey(ref, "Id", rc);
if ( data_name.value.string == NULL ) {
cl_log(LOG_WARNING, "key %s is NULL", "Id");
return HA_FAIL;
}
rscid = CMGetCharPtr(data_name.value.string);
this_type = (type == 0)
? cim_get_rsctype(rscid) : type;
ci = make_instance_byid(broker, ref, rscid, this_type, rc);
if ( CMIsNullObject(ci) ) {
cl_log(LOG_WARNING, "Can not create resource instance.");
return HA_FAIL;
}
CMReturnInstance(rslt, ci);
CMReturnDone(rslt);
return HA_OK;
}
/* should return primitives in group for primitive provider? no */
int
resource_enum_insts(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * ref, int need_inst,
uint32_t type, CMPIStatus * rc)
{
struct ha_msg* names;
int i, len;
DEBUG_ENTER();
if ( cim_get_hb_status() != HB_RUNNING ) {
rc->rc = CMPI_RC_ERR_FAILED;
cl_log(LOG_WARNING, "Heartbeat not running.");
return HA_FAIL;
}
if ( ( names = cim_get_all_rsc_list()) == NULL ) {
rc->rc = CMPI_RC_ERR_FAILED;
cl_log(LOG_WARNING, "Get resource list failed.");
return HA_FAIL;
}
len = cim_list_length(names);
for ( i = 0; i < len; i++) {
char *rsc = NULL;
if ((rsc = cim_list_index(names, i)) == NULL) {
continue;
}
if ( type != cim_get_rsctype(rsc)){
continue;
}
/* should we return all sub resource of group/clone/master
for the primitive resources enumeration operation? */
if ( need_inst ) {
CMPIInstance * ci = NULL;
ci = make_instance_byid(broker, ref, rsc, type, rc);
if( ci ) {
CMReturnInstance(rslt, ci);
}
} else {
CMPIObjectPath * op;
op = make_objectpath_byid(broker, ref, rsc, type, rc);
if (op) {
/* add object to rslt */
CMReturnObjectPath(rslt, op);
}
}
}
CMReturnDone(rslt);
ha_msg_del(names);
DEBUG_LEAVE();
return HA_OK;
}
int
resource_cleanup(CMPIBroker * broker, char * classname, CMPIInstanceMI * mi,
CMPIContext * ctx, uint32_t type, CMPIStatus * rc)
{
return HA_OK;
}
int
resource_del_inst(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * ref, CMPIStatus * rc)
{
char * rscid;
CMPIString * string;
int ret = HA_FAIL;
if ((string = CMGetKey(ref, "Id", rc).value.string) == NULL ) {
cl_log(LOG_WARNING, "Resource id missing.");
return HA_FAIL;
}
rscid = CMGetCharPtr(string);
ret = cim_remove_rsc(rscid);
rc->rc = (ret==HA_OK)? CMPI_RC_OK : CMPI_RC_ERR_FAILED;
return ret;
}
#if 0
static int
resource_update_instattrs(const char *rscid, struct ha_msg * attributes)
{
int i, len;
struct ha_msg * old = cim_get_rscattrs(rscid);
/* delete nvpair */
len = (old) ? cim_msg_children_count(old): 0;
for (i = 0; i < len; i++) {
const char * id = cim_msg_child_name(old, i);
if (id && cl_get_struct(attributes, id) == NULL ) {
cim_remove_attrnvpair(rscid, id);
}
}
len = cim_msg_children_count(attributes);
for (i = 0; i < len; i++) {
struct ha_msg * nvpair = cim_msg_child_index(attributes, i);
if ( nvpair ) {
const char * id = cim_msg_child_name(attributes, i);
cim_update_attrnvpair(rscid, id, nvpair);
}
}
return HA_OK;
}
#endif
int
resource_update_inst(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * cop, CMPIInstance * ci,
char ** properties, uint32_t type, CMPIStatus * rc)
{
struct ha_msg *resource = NULL /*, *attributes = NULL*/;
char * rscid;
int ret = 0;
DEBUG_ENTER();
/* get resource id */
if ((rscid = CMGetKeyString(cop, "Id", rc)) == NULL ) {
return HA_FAIL;
}
/* get original values, and set new values */
resource = cim_find_rsc(type, rscid);
if ( type == TID_RES_PRIMITIVE ) {
cl_msg_remove(resource, CIM_MSG_ATTR);
cmpi_inst2msg(ci, HA_PRIMITIVE_RESOURCE, resource, rc);
/* attributes = inst2attributes(cop, ci, rc); */
} else if (type == TID_RES_MASTER) {
cmpi_inst2msg(ci, HA_MASTERSLAVE_RESOURCE, resource, rc);
} else if (type == TID_RES_CLONE ) {
cmpi_inst2msg(ci, HA_RESOURCE_CLONE, resource, rc);
}
/* update resource */
ret = cim_update_rsc(type, rscid, resource);
if ( type != TID_RES_PRIMITIVE) {
goto done;
}
/* update its attributes */
/*
ret = resource_update_instattrs(rscid, attributes);
ha_msg_del(attributes);
*/
done:
ha_msg_del(resource);
rc->rc = (ret==HA_OK) ? CMPI_RC_OK: CMPI_RC_ERR_FAILED;
DEBUG_LEAVE();
return ret;
}
int
resource_create_inst(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * cop, CMPIInstance * ci,
uint32_t type, CMPIStatus * rc)
{
struct ha_msg *resource /*, *attributes*/;
int ret = HA_FAIL;
char * rscid = NULL;
const char * rsctype = NULL;
DEBUG_ENTER();
if((resource = ha_msg_new(16)) == NULL ) {
return HA_FAIL;
}
/* get resource id */
if ((rscid = CMGetKeyString(cop, "Id", rc)) == NULL ) {
ha_msg_del(resource);
return HA_FAIL;
}
switch(type){
case TID_RES_PRIMITIVE:
/* get resource attributes */
/* attributes = inst2attributes(cop, ci, rc); */
ret = cmpi_inst2msg(ci, HA_PRIMITIVE_RESOURCE, resource, rc);
rsctype = "native";
break;
case TID_RES_CLONE:
ret = cmpi_inst2msg(ci, HA_RESOURCE_CLONE, resource, rc);
ha_msg_add(resource, "advance", "clone");
rsctype = "clone";
break;
case TID_RES_MASTER:
ret = cmpi_inst2msg(ci, HA_MASTERSLAVE_RESOURCE, resource, rc);
ha_msg_add(resource, "advance", "master");
rsctype = "master";
break;
case TID_RES_GROUP:
ha_msg_add(resource, "id", rscid);
rsctype = "group";
break;
}
ha_msg_add(resource, "enabled", "false");
ret = cim_rscdb_store(type, rscid, resource);
rc->rc = (ret==HA_OK) ? CMPI_RC_OK: CMPI_RC_ERR_FAILED;
ha_msg_del(resource);
DEBUG_LEAVE();
return ret;
}
#if 0
/* add a operation to resource */
int
resource_add_operation(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * ref, uint32_t type,
CMPIArgs *in, CMPIArgs *out, CMPIStatus * rc)
{
CMPIObjectPath * opop;
const char * key[] = {"Id", "SystemName", "SystemCreationClassName"};
char *id, *sysname, *syscrname, *namespace;
struct ha_msg *msg;
if((opop = CMGetArg(in, "Operation", rc).value.ref) == NULL ) {
cl_log(LOG_ERR, "%s: can't get Operation ObjectPath.",
__FUNCTION__);
return HA_FAIL;
}
id = CMGetKeyString(opop, key[0], rc);
sysname = CMGetKeyString(opop, key[1], rc);
syscrname = CMGetKeyString(opop, key[2], rc);
namespace = CMGetCharPtr(CMGetNameSpace(opop, rc));
if ((msg = cim_load_operation(sysname, id)) == NULL ) {
cl_log(LOG_ERR, "%s: can't find instance for %s:%s:%s:%s.",
__FUNCTION__, namespace, id, sysname, syscrname);
return HA_FAIL;
}
cim_add_rscop(sysname, msg);
ha_msg_del(msg);
return HA_OK;
}
#endif
/* add sub resource to group/clone/master-slave */
int
resource_add_subrsc(CMPIBroker * broker, char * classname, CMPIContext * ctx,
CMPIResult * rslt, CMPIObjectPath * ref, uint32_t type,
CMPIArgs *in, CMPIArgs *out, CMPIStatus * rc)
{
CMPIObjectPath * rscop;
char *subrscid, *rscid;
struct ha_msg *subrsc, *resource;
int ret ;
rscid = CMGetKeyString(ref, "Id", rc);
resource = cim_find_rsc(type, rscid);
if((rscop = CMGetArg(in, "Resource", rc).value.ref) == NULL ) {
cl_log(LOG_ERR, "%s: can't get Resource ObjectPath.",
__FUNCTION__);
return HA_FAIL;
}
subrscid = CMGetKeyString(rscop, "Id", rc);
subrsc = cim_find_rsc(TID_RES_PRIMITIVE, subrscid);
if (subrsc == NULL ) {
cl_log(LOG_ERR, "%s: resource %s not exist.",
__FUNCTION__, subrscid);
return HA_FAIL;
}
ret = cim_add_subrsc(resource, subrsc);
ha_msg_del(subrsc);
ha_msg_del(resource);
rc->rc = (ret == HA_OK) ? CMPI_RC_OK : CMPI_RC_ERR_FAILED;
return ret;
}