blob: 527b7a8080c680036667caea9d96747ef42f8d11 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2004-2006 Intel Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corp. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* @author Anas Nashif
* @author Liang Hou
* @author Sumeet Kukreja, Dell Inc.
*/
#ifdef HAVE_CONFIG_H
#include <wsman_config.h>
#endif
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <CimClientLib/cmci.h>
#include <CimClientLib/native.h>
#include "u/libu.h"
#include "wsman-xml.h"
#include "wsman-xml-binding.h"
#include "wsman-client-api.h"
#include "wsman-soap.h"
#include "wsman-soap-envelope.h"
#include "wsman-epr.h"
#include "sfcc-interface.h"
#include "cim-interface.h"
#include "cim_data.h"
#define SYSTEMCREATIONCLASSNAME "CIM_ComputerSystem"
#define SYSTEMNAME "localhost.localdomain"
extern char *get_server_port(void);
typedef struct _sfcc_enumcontext {
CimClientInfo *ecClient;
CMPIEnumeration *ecEnumeration;
} sfcc_enumcontext;
static int cim_getEprObjAt(CimClientInfo * client, WsEnumerateInfo * enumInfo,
WsXmlNodeH itemsNode);
static int cim_getEprAt(CimClientInfo * client, WsEnumerateInfo * enumInfo,
WsXmlNodeH itemsNode);
static int cim_getElementAt(CimClientInfo * client, WsEnumerateInfo * enumInfo,
WsXmlNodeH itemsNode);
static char *
cim_find_namespace_for_class(CimClientInfo * client,
WsEnumerateInfo * enumInfo,
char *classname)
{
char *ns = NULL;
char *sub, *target_class = NULL;
hscan_t hs;
hnode_t *hn;
if (strcmp(client->requested_class, "*") &&
enumInfo && (enumInfo->flags & WSMAN_ENUMINFO_POLY_EXCLUDE)) {
if ( (enumInfo->flags & WSMAN_ENUMINFO_EPR ) &&
!(enumInfo->flags & WSMAN_ENUMINFO_OBJEPR)) {
target_class = classname;
} else {
target_class = client->requested_class;
}
} else {
target_class = classname;
}
//debug("target class:%s", target_class);
if (strstr(client->resource_uri, XML_NS_CIM_CLASS) != NULL &&
(strcmp(client->method, TRANSFER_GET) == 0 ||
strcmp(client->method, TRANSFER_DELETE) == 0 ||
strcmp(client->method, TRANSFER_PUT) == 0)) {
ns = u_strdup(client->resource_uri);
return ns;
}
if (target_class && client->namespaces) {
hash_scan_begin(&hs, client->namespaces);
while ((hn = hash_scan_next(&hs))) {
//debug("namespace=%s", (char *) hnode_get(hn));
if ((sub = strstr(target_class, (char *) hnode_getkey(hn)))) {
ns = u_strdup_printf("%s/%s",(char *) hnode_get(hn), target_class);
//debug("vendor namespace match...");
break;
}
}
}
if (!ns)
ns = u_strdup_printf("%s/%s", XML_NS_CIM_CLASS,
target_class);
return ns;
}
static char *
cmpitype2string (CMPIType type)
{
type &= ~CMPI_ARRAY;
switch (type) {
case CMPI_instance:
return "instance";
case CMPI_ref:
return "reference";
case CMPI_args:
return "args";
case CMPI_filter:
return "filter";
case CMPI_string:
return "string";
case CMPI_numericString:
return "numericstring";
case CMPI_booleanString:
return "booleanstring";
case CMPI_dateTimeString:
return "datetimestring";
case CMPI_classNameString: /* identical with CMPI_chars */
return "classnamestring";
case CMPI_dateTime:
return "datetime";
case CMPI_boolean:
return "boolean";
case CMPI_char16:
return "char16";
case CMPI_uint8:
return "uint8";
case CMPI_sint8:
return "sint8";
case CMPI_uint16:
return "uint16";
case CMPI_sint16:
return "sint16";
case CMPI_uint32:
return "uint32";
case CMPI_sint32:
return "sint32";
case CMPI_uint64:
return "uint64";
case CMPI_sint64:
return "sint64";
case CMPI_real32:
return "real32";
case CMPI_real64:
return "real64";
}
return "***Unknown***";
}
void
path2xml(CimClientInfo * client,
WsXmlNodeH node, char *resource_uri, CMPIValue * val)
{
int i = 0, numkeys = 0;
char *_path_res_uri = NULL, *cv = NULL;
WsXmlNodeH cimns, wsman_selector_set, refparam;
CMPIObjectPath *objectpath = val->ref;
CMPIString *namespace = objectpath->ft->getNameSpace(objectpath, NULL);
#if 0
CMPIString *opstr = CMObjectPathToString(objectpath, NULL);
debug("objectpath: %s", (char *) CMGetCharPtr(opstr));
debug("namespace: %s", (char *) CMGetCharPtr(namespace));
#endif
CMPIString *classname = objectpath->ft->getClassName(objectpath, NULL);
numkeys = objectpath->ft->getKeyCount(objectpath, NULL);
ws_xml_add_child(node, XML_NS_ADDRESSING, WSA_ADDRESS,
WSA_TO_ANONYMOUS);
refparam = ws_xml_add_child(node, XML_NS_ADDRESSING,
WSA_REFERENCE_PARAMETERS,
NULL);
_path_res_uri = cim_find_namespace_for_class(client, NULL, CMGetCharPtr(classname));
ws_xml_add_child_format(refparam, XML_NS_WS_MAN, WSM_RESOURCE_URI,
"%s", _path_res_uri);
u_free(_path_res_uri);
wsman_selector_set = ws_xml_add_child(refparam,
XML_NS_WS_MAN,
WSM_SELECTOR_SET,
NULL);
for (i = 0; i < numkeys; i++) {
CMPIString *keyname;
WsXmlNodeH s = NULL;
CMPIData data = objectpath->ft->getKeyAt(objectpath, i,
&keyname, NULL);
cv = (char *) value2Chars(data. type, &data.value);
s = ws_xml_add_child(wsman_selector_set, XML_NS_WS_MAN,
WSM_SELECTOR, cv );
ws_xml_add_node_attr(s, NULL, "Name", CMGetCharPtr(keyname));
if (cv)
u_free(cv);
if (keyname)
CMRelease(keyname);
}
if (CMGetCharPtr(namespace) != NULL) {
cimns = ws_xml_add_child(wsman_selector_set,
XML_NS_WS_MAN, WSM_SELECTOR,
CMGetCharPtr(namespace));
ws_xml_add_node_attr(cimns, NULL, "Name",
CIM_NAMESPACE_SELECTOR);
}
if (classname) {
CMRelease(classname);
}
if (namespace) {
CMRelease(namespace);
}
}
/*
* convert xml (string) value to CMPIData honoring type
* I: data.type = expected type
* I: value = pointer to string representation
* O: data.value = type-correct value
*/
static void
xml2data(CMPIData *data, char *value, char *name,
WsXmlNodeH resource, const char *resource_uri)
{
CMPIType type = data->type;
if (type & CMPI_ARRAY) {
WsXmlNodeH child;
CMPIData adata;
int count, ii;
adata.type = (type ^ CMPI_ARRAY);
count = ws_xml_get_child_count_by_qname(resource, resource_uri, name);
data->value.array = newCMPIArray(count, adata.type, NULL);
for (ii = 0; ii < count; ii++) {
child = ws_xml_get_child(resource, ii, resource_uri, name);
if (child) {
if ((value = ws_xml_get_node_text(child))) {
xml2data(&adata, value, name, resource, resource_uri);
CMSetArrayElementAt(data->value.array, ii, &(adata.value), adata.type);
}
}
}
} else {
switch (type) {
case CMPI_instance:
data->value.inst = NULL;
break;
case CMPI_ref:
data->value.ref = NULL;
break;
case CMPI_args:
data->value.args = NULL;
break;
#if CMPI_VER_200
case CMPI_filter:
data->value.filter = NULL;
break;
#endif
case CMPI_string:
case CMPI_numericString:
case CMPI_booleanString:
case CMPI_dateTimeString:
case CMPI_classNameString: /* identical to CMPI_chars */
data->value.string = newCMPIString(value, NULL);
break;
case CMPI_dateTime:
data->value.dateTime = NULL;
break;
case CMPI_boolean: {
int yes = 0;
if (strcmp(value, "true") == 0)
yes = 1;
data->value.boolean = yes;
break;
}
case CMPI_uint8:
data->value.uint8 = strtoul(value, NULL, 10);
break;
case CMPI_sint8:
data->value.sint8 = atoi(value);
break;
case CMPI_uint16:
data->value.uint16 = strtoul(value, NULL, 10);
break;
case CMPI_sint16:
data->value.sint16 = atoi(value);
break;
case CMPI_uint32:
data->value.uint32 = strtoul(value, NULL, 10);
break;
case CMPI_sint32:
data->value.sint32 = atol(value);
break;
case CMPI_uint64:
data->value.uint64 = strtoull(value, NULL, 10);
break;
case CMPI_sint64:
data->value.sint64 = atoll(value);
break;
case CMPI_real32:
data->value.real32 = atof(value);
break;
case CMPI_real64:
data->value.real64 = atof(value);
break;
default:
debug("*** xml2data: type %x unsupported", type);
}
}
}
void
xml2objectpath(CMPIObjectPath * objectpath,
CMPIData *data, char *name, char *value)
{
debug("xml2objectpath([0x%04x]%s:%s)", data->type, name, value);
xml2data(data, value, NULL, NULL, NULL);
CMAddKey(objectpath, name, &(data->value), data->type);
}
void
xml2property(CMPIInstance * instance,
CMPIData *data, char *name, char *value,
WsXmlNodeH resource, const char *resource_uri)
{
debug("xml2property([0x%04x]%s:%s)", data->type, name, value);
xml2data(data, value, name, resource, resource_uri);
CMSetProperty(instance, name, &(data->value), data->type);
}
void
type2xml(CimClientInfo * client, WsXmlNodeH node, char *resource_uri, CMPIType type)
{
const char *typestr = cmpitype2string(type);
if (type & CMPI_ARRAY) {
WsXmlNodeH typenode = ws_xml_add_child(node, resource_uri, "type", NULL);
ws_xml_add_child(typenode, resource_uri, "array", typestr);
}
else {
ws_xml_add_child(node, resource_uri, "type", typestr);
}
}
void
property2xml(CimClientInfo * client, CMPIData *data,
const char *name, WsXmlNodeH node, char *resource_uri,
int frag_type, int is_key)
{
char *valuestr = NULL;
int xmlescape = strcasecmp("SfcbLocal", get_cim_client_frontend())==0 ? 1 : 0;
if (CMIsArray((*data))) {
WsXmlNodeH nilnode;
if (( client->flags & FLAG_CIM_SCHEMA_OPT ) == FLAG_CIM_SCHEMA_OPT
&& data->state == CMPI_nullValue) {
return;
} else if (data->type == CMPI_null && data->state == CMPI_nullValue) {
nilnode = ws_xml_add_child_sort(node, resource_uri, name, NULL, xmlescape);
ws_xml_add_node_attr(nilnode, XML_NS_SCHEMA_INSTANCE, "nil", "true");
return;
}
CMPIArray *arr = data->value.array;
CMPIType eletyp = data->type & ~CMPI_ARRAY;
int j, n;
if (arr != NULL) {
n = CMGetArrayCount(arr, NULL);
for (j = 0; j < n; ++j) {
CMPIData ele = CMGetArrayElementAt(arr, j, NULL);
valuestr = value2Chars(eletyp, &ele.value);
ws_xml_add_child_sort(node, resource_uri, name, valuestr, xmlescape);
free(valuestr);
}
}
} else {
if (( client->flags & FLAG_CIM_SCHEMA_OPT ) == FLAG_CIM_SCHEMA_OPT
&& data->state == CMPI_nullValue) {
return;
} else if (data->type != CMPI_null && data->state != CMPI_nullValue) {
WsXmlNodeH refpoint = NULL;
WsXmlNodeH propnode;
if (data->type == CMPI_ref) {
refpoint = ws_xml_add_child_sort(node, resource_uri, name, NULL, xmlescape);
path2xml(client, refpoint, resource_uri, &(data->value));
} else {
valuestr = value2Chars(data->type, &(data->value));
if(frag_type == 2)
ws_xml_set_node_text(node, valuestr);
else if(frag_type == 1) {
ws_xml_add_child(node, NULL, name, valuestr);
}
else {
propnode = ws_xml_add_child_sort(node, resource_uri, name, valuestr, xmlescape);
if (is_key == 0 &&
(client->flags & WSMAN_ENUMINFO_EXT )) {
ws_xml_add_node_attr(propnode, XML_NS_CIM_SCHEMA, "Key",
"true");
}
}
if (valuestr)
u_free(valuestr);
}
} else {
WsXmlNodeH nilnode = ws_xml_add_child_sort(node, resource_uri, name,
NULL, xmlescape);
ws_xml_add_node_attr(nilnode, XML_NS_SCHEMA_INSTANCE, "nil", "true");
}
}
}
WsXmlNodeH
datatype2xml(CimClientInfo * client, WsXmlNodeH parent, char *resource_uri, const char *nodename, const char *name, CMPIData *data)
{
WsXmlNodeH node = ws_xml_add_child(parent, resource_uri, nodename, NULL);
ws_xml_add_child(node, resource_uri, "name", name);
type2xml(client, node, resource_uri, data->type);
property2xml(client, data, "value", node, resource_uri, 0, 0);
return node;
}
/*
* Convert class or property qualifiers to xml
* client: client
* _class: class
* property_name: NULL for class qualifiers
*/
void
qualifiers2xml(CimClientInfo *client, WsXmlNodeH node, CMPIConstClass *_class, const char *property_name)
{
unsigned int count;
CMPIStatus rc;
if (property_name)
count = _class->ft->getPropertyQualifierCount(_class, property_name, &rc);
else
count = _class->ft->getQualifierCount(_class, &rc);
if (count > 0) {
unsigned int i = 0;
WsXmlNodeH qualifiers = ws_xml_add_child(node, client->resource_uri, "qualifiers", NULL);
while (i < count) {
CMPIString *qualifier_name;
CMPIData data;
if (property_name)
data = _class->ft->getPropertyQualifierAt(_class,
property_name, i++, &qualifier_name, &rc);
else
data = _class->ft->getQualifierAt(_class, i++, &qualifier_name, &rc);
if (rc.rc)
return;
datatype2xml(client, qualifiers, client->resource_uri, "qualifier", CMGetCharPtr(qualifier_name), &data);
CMRelease(qualifier_name);
}
}
}
/*
* Get value of hash node "__cimnamespace"
*
*/
char *
cim_get_namespace_selector(hash_t * keys)
{
char *cim_namespace = NULL;
selector_entry *sentry = NULL;
hnode_t *hn = hash_lookup(keys, (char *) CIM_NAMESPACE_SELECTOR);
if (hn) {
sentry = (selector_entry *) hnode_get(hn);
if(sentry->type == 1) return NULL;
cim_namespace = sentry->entry.text;
hash_delete(keys, hn);
hnode_destroy(hn);
u_free(sentry);
debug("CIM Namespace: %s", cim_namespace);
}
return cim_namespace;
}
static int
cim_add_keys_from_filter_cb(void *objectpath, const char* key,
const char *value)
{
CMPIObjectPath *op = (CMPIObjectPath *)objectpath;
debug("adding selector %s=%s", key, value );
if(strcmp(key, CIM_NAMESPACE_SELECTOR) == 0) //it is __cimnamespace
CMSetNameSpace(op, value);
else
CMAddKey(op, key, value, CMPI_chars);
return 0;
}
static CMPIObjectPath *
cim_epr_to_objectpath(CimClientInfo * client, epr_t *epr)
{
CMPIObjectPath * objectpath = NULL;
char *class = NULL;
if (epr && epr->refparams.uri) {
debug("uri: %s", epr->refparams.uri);
class = strrchr(epr->refparams.uri, '/');
}
if (class) {
class++;
if ((NULL != client) && (NULL != client->cim_namespace))
objectpath = newCMPIObjectPath(client->cim_namespace, class, NULL);
else
objectpath = newCMPIObjectPath(CIM_NAMESPACE, class, NULL);
wsman_epr_selector_cb(epr, cim_add_keys_from_filter_cb, objectpath);
debug( "ObjectPath: %s",
CMGetCharPtr(CMObjectPathToString(objectpath, NULL)));
}
return objectpath;
}
static int
comparef(const void *key1, const void *key2)
{
methodarglist_t * d1 = (methodarglist_t*)key1;
methodarglist_t * d2 = (methodarglist_t*)key2;
return strcmp(d1->key, d2->key);
}
static int
cim_add_args(CimClientInfo * client, CMPIObjectPath *op,
CMPIArgs * argsin)
{
hscan_t hs;
hnode_t *hn;
hash_scan_begin(&hs, client->method_args);
list_t *arglist = NULL;
int res = 0;
debug("cim_add_args:");
while ((hn = hash_scan_next(&hs))) {
if (strcmp(METHOD_ARGS_KEY, (char *)hnode_getkey(hn)) == 0)
arglist = (list_t *)hnode_get(hn);
}
if (NULL != arglist) {
lnode_t *argnode;
methodarglist_t *arraynode = NULL;
methodarglist_t *node_val;
int ii, jj, listcount = list_count(arglist);
// sort the list first then tag arrays
debug("cim_add_args: list count: %u", listcount);
if (0 >= listcount) {
return res; // nothing to do so return
}
list_sort(arglist, comparef);
argnode = list_first(arglist);
arraynode = (methodarglist_t *)argnode->list_data;
argnode = list_next(arglist, argnode);
while (argnode) {
node_val = (methodarglist_t *)argnode->list_data;
if (strcmp(arraynode->key, node_val->key) == 0) {
arraynode->arraycount++;
} else {
arraynode = node_val;
}
argnode = list_next(arglist, argnode);
}
// reiterate the list and add args
argnode = list_first(arglist);
for (ii = 0; ii < listcount; ii++) {
CMPIValue value;
selector_entry *sentry;
node_val = (methodarglist_t *)argnode->list_data;
sentry = (selector_entry *)node_val->data;
if (0 < node_val->arraycount) {
CMPIArray *arraydata = NULL;
lnode_t *t_anode = argnode;
int arraytype = sentry->type, kk;
node_val->arraycount++; // since value of 0 is singleton and value of 1 is actually 2 count in an array
debug("cim_add_args: array key: %s type: %u count: %u", node_val->key, arraytype, node_val->arraycount);
// first verify if array type is the same for all elements in the array.
for (kk = 1; kk < node_val->arraycount; kk++) {
t_anode = list_next(arglist, t_anode);
if (NULL != t_anode) {
selector_entry *t_sentry = (selector_entry *)((methodarglist_t *)t_anode->list_data)->data;
char *key = ((methodarglist_t *)t_anode->list_data)->key;
debug(" %s[0] = %d, %s[%d] = %d", key, sentry->type, key, kk, t_sentry->type);
if (sentry->type != t_sentry->type) {
res = 1;
goto error;
}
}
}
if (0 != arraytype)
arraydata = native_new_CMPIArray(node_val->arraycount, CMPI_ref, NULL);
else
arraydata = native_new_CMPIArray(node_val->arraycount, CMPI_string, NULL);
for (jj = 0; jj < node_val->arraycount; jj++) {
debug("cim_add_args: array %u object: %p", jj, sentry);
if (0 != arraytype) {
value.ref = cim_epr_to_objectpath(client, sentry->entry.eprp);
if (value.ref == NULL) {
res = 1;
goto error;
}
CMSetArrayElementAt(arraydata, jj, &value, CMPI_ref);
} else {
value.string = native_new_CMPIString((char *)sentry->entry.text, NULL);
CMSetArrayElementAt(arraydata, jj, &value, CMPI_string);
}
argnode = list_next(arglist, argnode);
if (NULL != argnode)
sentry = (selector_entry *)((methodarglist_t *)argnode->list_data)->data;
}
value.array = arraydata;
if (0 != arraytype)
CMAddArg(argsin, node_val->key, (char *)&value, CMPI_refA);
else
CMAddArg(argsin, node_val->key, (char *)&value, CMPI_stringA);
ii += (jj - 1);
} else {
debug("cim_add_args: single key: %s type: %u", node_val->key, sentry->type);
if (0 != sentry->type) {
epr_t *eprp = sentry->entry.eprp;
if (eprp == NULL) {
res = 1;
break;
}
debug("epr_t: selectorcount: %u", eprp->refparams.selectorset.count);
value.ref = cim_epr_to_objectpath(client, sentry->entry.eprp);
CMAddArg(argsin, node_val->key, &value, CMPI_ref);
} else {
debug("text: %s", sentry->entry.text);
CMAddArg(argsin, node_val->key, sentry->entry.text, CMPI_chars);
}
argnode = list_next(arglist, argnode);
}
}
} else {
debug("cim_add_args: did not find any argument list");
}
error:
return res;
}
static void
cim_add_keys(CMPIObjectPath * objectpath, hash_t * keys)
{
hscan_t hs;
hnode_t *hn;
selector_entry *sentry;
if (keys == NULL) {
return;
}
hash_scan_begin(&hs, keys);
while ((hn = hash_scan_next(&hs))) {
sentry = (selector_entry *)hnode_get(hn);
debug("in cim_add_keys: key: %s, text: %s", hnode_getkey(hn), sentry->entry.text);
if(sentry->type == 0)
CMAddKey(objectpath, (char *) hnode_getkey(hn),
sentry->entry.text, CMPI_chars);
else {
CMPIValue value;
value.ref = cim_epr_to_objectpath(NULL, sentry->entry.eprp);;
if (NULL != value.ref) {
CMAddKey(objectpath, (char *) hnode_getkey(hn),
&value, CMPI_ref);
}
}
}
}
static int
cim_verify_class_keys(CMPIConstClass * class,
hash_t * keys, WsmanStatus * statusP)
{
CMPIStatus rc;
int count, ccount = 0;
int numproperties, i;
debug("verify class selectors");
if (!keys) {
count = 0;
} else {
count = (int) hash_count(keys);
}
numproperties = class->ft->getPropertyCount(class, NULL);
debug("number of prop in class: %d", numproperties);
for (i = 0; i < numproperties; i++) {
CMPIString *propertyname;
CMPIData data;
class->ft->getPropertyAt(class, i, &propertyname, NULL);
data = class->ft->getPropertyQualifier(class,
CMGetCharPtr(propertyname), "Key", &rc);
if ((data.state != CMPI_nullValue) && (data.value.boolean)) {
ccount++;
}
CMRelease(propertyname);
}
debug("selector count from user: %d, in class definition: %d",
count, ccount);
if (ccount > count) {
statusP->fault_code = WSMAN_INVALID_SELECTORS;
statusP->fault_detail_code =
WSMAN_DETAIL_INSUFFICIENT_SELECTORS;
debug("insuffcient selectors");
goto cleanup;
} else if (ccount < hash_count(keys)) {
statusP->fault_code = WSMAN_INVALID_SELECTORS;
statusP->fault_detail_code =
WSMAN_DETAIL_UNEXPECTED_SELECTORS;
debug("invalid selectors");
goto cleanup;
}
cleanup:
return statusP->fault_code;
}
static int
cim_opcmp(CMPIObjectPath * op1, CMPIObjectPath * op2) {
CMPIStatus rc;
unsigned int i = 0;
unsigned int count = CMGetKeyCount(op2, &rc);
debug("count = %d", count);
char *cv1,*cv2;
int match = 0;
while (i < count) {
CMPIString *name1 = NULL;
CMPIData value1 = CMGetKeyAt(op2, i, &name1, &rc);
if(rc.rc) goto DONE;
i++;
char *p1 = CMGetCharsPtr(name1, &rc);
if(rc.rc)
goto DONE;
CMPIData value2 = CMGetKey(op1, p1, &rc);
if(rc.rc) goto DONE;
cv1 = value2Chars(value1.type, &value1.value);
cv2 = value2Chars(value2.type, &value2.value);
match = strcmp(cv1,cv2);
u_free(cv1);
u_free(cv2);
if(match == 0)
continue;
else
goto DONE;
}
DONE:
CMRelease(op1);
CMRelease(op2);
if(rc.rc || match)
return 1;
else
return 0;
}
static int
cim_verify_keys(CMPIObjectPath * objectpath, hash_t * keys,
WsmanStatus * statusP)
{
CMPIStatus rc;
hscan_t hs;
hnode_t *hn;
int count, opcount;
char *cv = NULL;
debug("verify selectors");
if (!keys) {
count = 0;
} else {
count = (int) hash_count(keys);
}
opcount = CMGetKeyCount(objectpath, &rc);
debug("selector count from user: %d, in object path: %d", count,
opcount);
if (opcount > count) {
statusP->fault_code = WSMAN_INVALID_SELECTORS;
statusP->fault_detail_code = WSMAN_DETAIL_INSUFFICIENT_SELECTORS;
debug("insuffcient selectors");
goto cleanup;
} else if (opcount < hash_count(keys)) {
statusP->fault_code = WSMAN_INVALID_SELECTORS;
debug("invalid selectors");
goto cleanup;
}
hash_scan_begin(&hs, keys);
while ((hn = hash_scan_next(&hs))) {
CMPIData data = CMGetKey(objectpath, (char *) hnode_getkey(hn), &rc);
if (rc.rc != 0) { // key not found
statusP->fault_code = WSMAN_INVALID_SELECTORS;
statusP->fault_detail_code = WSMAN_DETAIL_UNEXPECTED_SELECTORS;
debug("unexpected selectors");
break;
}
selector_entry *sentry = (selector_entry*)hnode_get(hn);
if(sentry->type == 0) {
cv = value2Chars(data.type, &data.value);
if(cv != NULL && strcmp(cv, sentry->entry.text) == 0) {
statusP->fault_code = WSMAN_RC_OK;
statusP->fault_detail_code = WSMAN_DETAIL_OK;
u_free(cv);
}
else {
statusP->fault_code = WSA_DESTINATION_UNREACHABLE;
statusP->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
debug("selector '%s', value: [ %s ] not matched", hnode_getkey(hn), sentry->entry.text);
debug("data.type 0x%04x, cv '%s'", data.type, cv?cv:"<NULL>");
u_free(cv);
break;
}
}
else {
CMPIObjectPath *objectpath_epr = cim_epr_to_objectpath(NULL, sentry->entry.eprp);
CMPIObjectPath *objectpath_epr2 = CMClone(data.value.ref, NULL);
if (cim_opcmp(objectpath_epr2, objectpath_epr) == 0) {
statusP->fault_code = WSMAN_RC_OK;
statusP->fault_detail_code = WSMAN_DETAIL_OK;
u_free(cv);
} else {
statusP->fault_code = WSA_DESTINATION_UNREACHABLE;
statusP->fault_detail_code =
WSMAN_DETAIL_INVALID_RESOURCEURI;
debug("invalid resource_uri %s != %s", cv,
(char *)CMGetCharPtr(CMObjectPathToString(objectpath, NULL)));
u_free(cv);
break;
}
}
}
cleanup:
debug("getKey rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
return statusP->fault_code;
}
static CMPIConstClass *
cim_get_class(CimClientInfo * client,
const char *class,
CMPIFlags flags, WsmanStatus * status)
{
CMPIObjectPath *op;
CMPIConstClass *_class;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
op = newCMPIObjectPath(client->cim_namespace, class, NULL);
_class = cc->ft->getClass(cc, op, flags, NULL, &rc);
debug("getClass() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : "<NULL>");
cim_to_wsman_status(rc, status);
if (op)
CMRelease(op);
return _class;
}
static int
filter_instance(CMPIInstance * instance, WsEnumerateInfo * enumInfo)
{
filter_t *filter = enumInfo->filter;
int i;
int matches = 0;
Selector *ss = filter->selectorset.selectors;
if (ss == NULL) {
debug("epr->refparams.selectors == NULL");
return 0;
}
for (i = 0; i < filter->selectorset.count; i++) {
Selector *s;
s = ss + i;
CMPIData data = instance->ft->getProperty(instance, s->name, NULL);
char *valuestr = value2Chars(data.type, &data.value);
if (valuestr && strcmp(s->value, valuestr) == 0 ) {
matches++;
}
u_free(valuestr);
}
if (matches == filter->selectorset.count)
return 1;
return 0;
}
static void
instance2xml(CimClientInfo * client,
CMPIInstance * instance, char *fragstr,
WsXmlNodeH body, WsEnumerateInfo * enumInfo)
{
int i = 0;
char *class_namespace = NULL;
CMPIObjectPath *objectpath;
CMPIString *classname;
CMPIConstClass *_class = NULL;
char *final_class = NULL;
int numproperties = 0;
int frag_type = 0;
int index;
char *propertystr = NULL;
WsXmlNodeH xmlr = NULL;
objectpath = instance->ft->getObjectPath(instance, NULL);
classname = objectpath->ft->getClassName(objectpath, NULL);
class_namespace = cim_find_namespace_for_class(client, enumInfo,
CMGetCharPtr(classname));
final_class = u_strdup(strrchr(class_namespace, '/') + 1);
if(fragstr) {
xmlr = body;
}
else {
xmlr = ws_xml_add_child(body, class_namespace, final_class, NULL);
}
wsman_get_fragment_type(fragstr, &frag_type, &propertystr, &index);
if (strcmp(client->requested_class, "*") && enumInfo &&
(enumInfo->flags & WSMAN_ENUMINFO_POLY_EXCLUDE )) {
_class = cim_get_class(client, client->requested_class, 0, NULL);
if (_class)
numproperties = _class->ft->getPropertyCount(_class, NULL);
} else {
numproperties = instance->ft->getPropertyCount(instance, NULL);
}
for (i = 0; i < numproperties; i++) {
CMPIString *propertyname;
CMPIData data;
CMPIStatus is_key;
if (strcmp(client->requested_class, "*")
&& enumInfo && (enumInfo->flags & WSMAN_ENUMINFO_POLY_EXCLUDE)) {
_class->ft->getPropertyAt(_class, i, &propertyname,
NULL);
data = instance->ft->getProperty(instance, CMGetCharPtr(propertyname),
NULL);
} else {
data = instance->ft->getPropertyAt(instance, i,
&propertyname,
NULL);
}
if(propertystr && strcmp(propertystr, CMGetCharPtr(propertyname))) {
CMRelease(propertyname);
continue;
}
objectpath->ft->getKey(objectpath, CMGetCharPtr(propertyname), &is_key);
property2xml(client, &data, CMGetCharPtr(propertyname), xmlr,
class_namespace, frag_type, is_key.rc);
CMRelease(propertyname);
}
//ws_xml_dump_node_tree(stdout, r );
struct timeval tv0, tv1;
long long t0, t1;
long long ttime = 0;
gettimeofday(&tv0, NULL);
gettimeofday(&tv1, NULL);
t0 = tv0.tv_sec * 10000000 + tv0.tv_usec;
t1 = tv1.tv_sec * 10000000 + tv1.tv_usec;
ttime += t1 -t0;
if (enumInfo && (enumInfo->flags & WSMAN_ENUMINFO_POLY_EXCLUDE ) ) {
if (_class) {
CMRelease(_class);
}
}
if(propertystr)
u_free(propertystr);
if (classname)
CMRelease(classname);
if (objectpath)
CMRelease(objectpath);
if (final_class)
u_free(final_class);
if (class_namespace)
u_free(class_namespace);
}
/*
* An operation (for a concrete instance) is given only the abstract base class
*
* Enumerate through all instances of the base class, comparing keys to identify
* the matching instance
*
*/
static CMPIObjectPath *
cim_get_op_from_enum(CimClientInfo * client,
WsmanStatus * statusP)
{
CMPIStatus rc;
int match = 0;
CMPIEnumeration *enumeration;
CMPIObjectPath *result_op = NULL;
CMPIArray *enumArr = NULL;
if (client->requested_class)
debug("class available");
CMPIObjectPath *objectpath =
newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
enumeration =
((CMCIClient *) client->cc)->ft->enumInstanceNames(client->cc,
objectpath,
&rc);
debug("enumInstanceNames rc=%d, msg=%s", rc.rc,
(rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc != 0) {
cim_to_wsman_status(rc, statusP);
//statusP->fault_detail_code = WSMAN_DETAIL_INVALID_RESOURCEURI;
if (rc.msg)
CMRelease(rc.msg);
goto cleanup;
}
enumArr = enumeration->ft->toArray(enumeration, NULL);
int n = CMGetArrayCount(enumArr, NULL);
if (n > 0) {
while (enumeration->ft->hasNext(enumeration, NULL)) {
CMPIData data = enumeration->ft->getNext(enumeration,
NULL);
CMPIObjectPath *op = CMClone(data.value.ref, NULL);
CMPIString *opstr = CMObjectPathToString(op, NULL);
debug("objectpath: %s", CMGetCharPtr(opstr));
if (cim_verify_keys(op, client->selectors, statusP) != 0) {
if (opstr)
CMRelease(opstr);
if (op)
CMRelease(op);
continue;
} else {
result_op = CMClone(data.value.ref, NULL);
CMSetNameSpace(result_op,
client->cim_namespace);
match = 1;
if (opstr)
CMRelease(opstr);
if (op)
CMRelease(op);
break;
}
if (opstr)
CMRelease(opstr);
if (op)
CMRelease(op);
}
} else {
statusP->fault_code = WSA_DESTINATION_UNREACHABLE;
statusP->fault_detail_code =
WSMAN_DETAIL_INVALID_RESOURCEURI;
}
debug("fault: %d %d", statusP->fault_code, statusP->fault_detail_code);
cleanup:
if (objectpath)
CMRelease(objectpath);
if (enumeration)
CMRelease(enumeration);
if (match)
return result_op;
else
return NULL;
}
void
cim_enum_instances(CimClientInfo * client,
WsEnumerateInfo * enumInfo,
WsmanStatus * status)
{
CMPIObjectPath *objectpath = NULL;
CMPIEnumeration *enumeration = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
sfcc_enumcontext *enumcontext;
filter_t *filter = NULL;
filter = enumInfo->filter;
if( (enumInfo->flags & WSMAN_ENUMINFO_REF) ||
(enumInfo->flags & WSMAN_ENUMINFO_ASSOC )) {
char *class = NULL;
epr_t *epr;
if (filter) {
epr = (epr_t *)filter->epr;
class = strrchr(epr->refparams.uri, '/') + 1;
objectpath = newCMPIObjectPath(client->cim_namespace,
class, NULL);
wsman_epr_selector_cb(filter->epr,
cim_add_keys_from_filter_cb, objectpath);
debug( "ObjectPath: %s",
CMGetCharPtr(CMObjectPathToString(objectpath, &rc)));
} else {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_OK;
goto cleanup;
}
/*
} else if(enumInfo->flags & WSMAN_ENUMINFO_SELECTOR) {
char *cim_namespace;
cim_namespace = get_cimnamespace_from_selectorset(&filter->selectorset);
if(cim_namespace == NULL)
cim_namespace = client->cim_namespace;
objectpath = newCMPIObjectPath(cim_namespace, client->requested_class, NULL);
wsman_selectorset_cb(&filter->selectorset,
cim_add_keys_from_filter_cb, objectpath);
debug( "ObjectPath: %s",
CMGetCharPtr(CMObjectPathToString(objectpath, &rc)));
*/
} else {
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
}
if (enumInfo->flags & WSMAN_ENUMINFO_REF) {
enumeration = cc->ft->references(cc, objectpath, filter->resultClass,
filter->role, 0, NULL, &rc);
} else if (enumInfo->flags & WSMAN_ENUMINFO_ASSOC) {
enumeration = cc->ft->associators(cc, objectpath, filter->assocClass,
filter->resultClass,
filter->role,
filter->resultRole, 0, NULL, &rc);
} else if (( enumInfo->flags & WSMAN_ENUMINFO_WQL )) {
enumeration = cc->ft->execQuery(cc, objectpath, filter->query, "WQL", &rc);
} else if (( enumInfo->flags & WSMAN_ENUMINFO_CQL )) {
enumeration = cc->ft->execQuery(cc, objectpath, filter->query, "CQL", &rc);
} else if (( enumInfo->flags & WSMAN_ENUMINFO_XPATH )) { /* XPath unsupported in Sfcc */
status->fault_code = WSEN_CANNOT_PROCESS_FILTER;
status->fault_detail_code = WSMAN_DETAIL_NOT_SUPPORTED;
goto cleanup;
} else {
enumeration = cc->ft->enumInstances(cc, objectpath,
CMPI_FLAG_DeepInheritance,
NULL, &rc);
}
debug("enumInstances() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc) {
debug("*** CMCIClient enumInstances() failed");
cim_to_wsman_status(rc, status);
if (rc.msg)
CMRelease(rc.msg);
if (objectpath)
CMRelease(objectpath);
goto cleanup;
}
CMPIArray *enumArr = enumeration->ft->toArray(enumeration, NULL);
CMPIArray *fenumArr = NULL;
if (enumInfo->flags & WSMAN_ENUMINFO_SELECTOR) {
CMPIType t = enumArr->ft->getSimpleType(enumArr, NULL);
fenumArr = newCMPIArray(0, t , NULL);
int idx = 0;
int fidx = 0;
for (idx = 0; idx<enumArr->ft->getSize(enumArr, NULL); idx++) {
CMPIData d = enumArr->ft->getElementAt(enumArr, idx, NULL);
if (filter_instance(d.value.inst, enumInfo)) {
fenumArr->ft->setElementAt(fenumArr, fidx, &d.value, d.type);
fidx++;
}
}
} else {
fenumArr = enumArr;
}
cim_to_wsman_status(rc, status);
if (rc.msg)
CMRelease(rc.msg);
if (!enumArr) {
goto cleanup;
}
enumInfo->totalItems = cim_enum_totalItems(fenumArr);
debug("Total items: %d", enumInfo->totalItems);
enumcontext = u_zalloc(sizeof(sfcc_enumcontext));
enumcontext->ecClient = client;
enumcontext->ecEnumeration = enumeration;
enumInfo->enumResults = fenumArr;
enumInfo->appEnumContext = enumcontext;
if (objectpath)
CMRelease(objectpath);
cleanup:
return;
}
/*
* Get enumeration item as element at enumInfo->index and append it to itemsNode
* return 1 on success
*/
static int
cim_getElementAt(CimClientInfo * client,
WsEnumerateInfo * enumInfo, WsXmlNodeH itemsNode)
{
int retval = 1;
char *fragstr = NULL;
CMPIArray *results = (CMPIArray *) enumInfo->enumResults;
CMPIData data = results->ft->getElementAt(results,
enumInfo->index, NULL);
CMPIInstance *instance = data.value.inst;
CMPIObjectPath *objectpath = instance->ft->getObjectPath(instance, NULL);
CMPIString *classname = objectpath->ft->getClassName(objectpath, NULL);
if ((enumInfo->flags & WSMAN_ENUMINFO_POLY_NONE ) &&
(strcmp(CMGetCharPtr(classname), client->requested_class) != 0)) {
retval = 0;
}
fragstr = wsman_get_fragment_string(client->cntx, client->cntx->indoc);
if(fragstr) {
itemsNode = ws_xml_add_child(itemsNode, XML_NS_WS_MAN, WSM_XML_FRAGMENT,
NULL);
}
if (retval)
instance2xml(client, instance, fragstr, itemsNode, enumInfo);
if (classname)
CMRelease(classname);
if (objectpath)
CMRelease(objectpath);
return retval;
}
/*
* Get enumeration item as WS end point reference at enumInfo->index and append it to itemsNode
* return 1 on success
*
*/
static int
cim_getEprAt(CimClientInfo * client,
WsEnumerateInfo * enumInfo, WsXmlNodeH itemsNode)
{
int retval = 1;
char *uri = NULL;
CMPIArray *results = (CMPIArray *) enumInfo->enumResults;
CMPIData data = results->ft->getElementAt(results,
enumInfo->index, NULL);
CMPIInstance *instance = data.value.inst;
CMPIObjectPath *objectpath = instance->ft->getObjectPath(instance, NULL);
CMPIString *classname = objectpath->ft->getClassName(objectpath, NULL);
if ((enumInfo->flags & WSMAN_ENUMINFO_POLY_NONE)
&& (strcmp(CMGetCharPtr(classname), client->requested_class) != 0)) {
retval = 0;
}
uri = cim_find_namespace_for_class(client, enumInfo, CMGetCharPtr(classname));
if (retval) {
cim_add_epr(client, itemsNode, uri, objectpath);
}
u_free(uri);
if (classname)
CMRelease(classname);
if (objectpath)
CMRelease(objectpath);
return retval;
}
/*
* Get enumeration item as WS end point reference object at enumInfo->index and append it to itemsNode
* return 1 on success
*
*/
static int
cim_getEprObjAt(CimClientInfo * client,
WsEnumerateInfo * enumInfo, WsXmlNodeH itemsNode)
{
int retval = 1;
char *uri = NULL;
CMPIArray *results = (CMPIArray *) enumInfo->enumResults;
CMPIData data =
results->ft->getElementAt(results, enumInfo->index, NULL);
CMPIInstance *instance = data.value.inst;
CMPIObjectPath *objectpath =
instance->ft->getObjectPath(instance, NULL);
CMPIString *classname =
objectpath->ft->getClassName(objectpath, NULL);
if ((enumInfo->flags & WSMAN_ENUMINFO_POLY_NONE) &&
(strcmp(CMGetCharPtr(classname), client->requested_class) != 0)) {
retval = 0;
}
uri = cim_find_namespace_for_class(client, enumInfo, CMGetCharPtr(classname));
if (retval) {
WsXmlNodeH item =
ws_xml_add_child(itemsNode, XML_NS_WS_MAN, WSM_ITEM,
NULL);
instance2xml(client, instance, NULL, item, enumInfo);
cim_add_epr(client, item, uri, objectpath);
}
u_free(uri);
if (classname)
CMRelease(classname);
if (objectpath)
CMRelease(objectpath);
return retval;
}
void
create_instance_from_xml(CMPIInstance * instance,
CMPIConstClass * class,
WsXmlNodeH resource, char *fragstr,
char *resource_uri, WsmanStatus * status)
{
int i;
int fragment_flag;
char *element;
int index;
WsXmlNodeH child = NULL;
char *value = NULL;
CMPIData data;
CMPIObjectPath *objectpath =
instance->ft->getObjectPath(instance, NULL);
CMPIString *classname =
objectpath->ft->getClassName(objectpath, NULL);
int numproperties = 0;
numproperties = class->ft->getPropertyCount(class, NULL);
wsman_get_fragment_type(fragstr, &fragment_flag, &element, &index);
for (i = 0; i < numproperties; i++) {
CMPIString *propertyname;
data = class->ft->getPropertyAt(class,
i, &propertyname,
NULL);
debug("working on property: %s", CMGetCharPtr(propertyname) );
if(fragment_flag == 0) {
child = ws_xml_get_child(resource, 0, resource_uri,
CMGetCharPtr(propertyname));
if (child) {
value = ws_xml_get_node_text(child);
WsXmlAttrH attr =
ws_xml_find_node_attr(child,
XML_NS_SCHEMA_INSTANCE,
XML_NS_SCHEMA_INSTANCE_NIL);
char *attr_val = ws_xml_get_attr_value(attr);
if (attr && attr_val && (strcmp(attr_val, "true") == 0)) {
continue;
}
debug("prop value: %s", value );
if (value) {
xml2property(instance, &data,
CMGetCharPtr(propertyname),
value, resource, resource_uri);
}
} else if (data.type != CMPI_null
&& data.state != CMPI_nullValue) {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code =
WSMAN_DETAIL_MISSING_VALUES;
CMRelease(propertyname);
break;
} else {
warning("cannot handle property");
}
}
else {
if(strcmp(element, CMGetCharPtr(propertyname) ) == 0) {
debug("release %s", element);
CMRelease(propertyname);
break;
}
}
CMRelease(propertyname);
}
if(fragment_flag) {
child = ws_xml_get_child(resource, 0, XML_NS_WS_MAN, WSM_XML_FRAGMENT);
if(i == numproperties) {
status->fault_code = WSMAN_INVALID_SELECTORS;
status->fault_detail_code = WSMAN_DETAIL_UNEXPECTED_SELECTORS;
}
else {
if(fragment_flag == 1) {
child = ws_xml_get_child(resource, 0, NULL, element);
if(child == NULL) {
status->fault_code = WSMAN_INVALID_SELECTORS;
status->fault_detail_code = WSMAN_DETAIL_UNEXPECTED_SELECTORS;
goto cleanup;
}
value = ws_xml_get_node_text(child);
}
else
value = ws_xml_get_node_text(resource);
debug("prop value: %s", value );
if (value) {
xml2property(instance, &data,
element, value, resource, NULL);
}
}
}
cleanup:
if (classname)
CMRelease(classname);
if (objectpath)
CMRelease(objectpath);
if (element)
u_free(element);
return;
}
void
xml2instance(CMPIInstance * instance, WsXmlNodeH body, char *resourceUri)
{
int i, numproperties;
CMPIString *namespace, *classname;
CMPIObjectPath *objectpath = NULL;
WsXmlNodeH r;
objectpath = instance->ft->getObjectPath(instance, NULL);
namespace = objectpath->ft->getNameSpace(objectpath, NULL);
classname =objectpath->ft->getClassName(objectpath, NULL);
numproperties = instance->ft->getPropertyCount(instance, NULL);
r = ws_xml_get_child(body, 0, resourceUri, CMGetCharPtr(classname));
if (numproperties) {
for (i = 0; i < numproperties; i++) {
CMPIString *propertyname;
CMPIData data = instance->ft->getPropertyAt(instance,
i, &propertyname,
NULL);
WsXmlNodeH child = ws_xml_get_child(r, 0,
resourceUri,
(char *)
propertyname->
hdl);
char *value = ws_xml_get_node_text(child);
if (value) {
xml2property(instance, &data,
CMGetCharPtr(propertyname),
value, body, resourceUri);
}
CMRelease(propertyname);
}
}
if (classname)
CMRelease(classname);
if (namespace)
CMRelease(namespace);
if (objectpath)
CMRelease(objectpath);
}
void
cim_add_epr_details(CimClientInfo * client,
WsXmlNodeH resource,
char *resource_uri, CMPIObjectPath * objectpath)
{
int numkeys = 0, i = 0;
char *cv = NULL;
ws_xml_add_child(resource, XML_NS_ADDRESSING, WSA_ADDRESS,
WSA_TO_ANONYMOUS);
numkeys = objectpath->ft->getKeyCount(objectpath, NULL);
WsXmlNodeH refparam = ws_xml_add_child(resource,
XML_NS_ADDRESSING,
WSA_REFERENCE_PARAMETERS,
NULL);
ws_xml_add_child_format(refparam, XML_NS_WS_MAN, WSM_RESOURCE_URI,
"%s", resource_uri);
WsXmlNodeH wsman_selector_set = ws_xml_add_child(refparam,
XML_NS_WS_MAN,
WSM_SELECTOR_SET,
NULL);
if (0 < numkeys) {
CMPIString * cim_namespace = objectpath->ft->getNameSpace(objectpath, NULL);
char *str_namespace = client->cim_namespace;
if (NULL != cim_namespace && NULL != CMGetCharPtr(cim_namespace)) {
str_namespace = CMGetCharPtr(cim_namespace);
}
if (str_namespace != NULL) {
WsXmlNodeH cimns = ws_xml_add_child(wsman_selector_set,
XML_NS_WS_MAN, WSM_SELECTOR,
(char *) str_namespace);
ws_xml_add_node_attr(cimns, NULL, "Name",
CIM_NAMESPACE_SELECTOR);
}
}
for (i = 0; i < numkeys; i++) {
CMPIString *keyname;
CMPIData data =
objectpath->ft->getKeyAt(objectpath, i, &keyname,
NULL);
WsXmlNodeH s = NULL;
if (data.type == CMPI_ref) {
s = ws_xml_add_child(wsman_selector_set,
XML_NS_WS_MAN, WSM_SELECTOR,
NULL);
WsXmlNodeH epr = ws_xml_add_child(s,
XML_NS_ADDRESSING,
WSA_EPR, NULL);
path2xml(client, epr, resource_uri, &data.value);
} else {
char *valuestr =
value2Chars(data.type, &data.value);
s = ws_xml_add_child(wsman_selector_set,
XML_NS_WS_MAN, WSM_SELECTOR,
valuestr);
if (valuestr)
free(valuestr);
}
ws_xml_add_node_attr(s, NULL, WSM_NAME, CMGetCharPtr(keyname));
if (cv)
free(cv);
if (keyname)
CMRelease(keyname);
}
return;
}
void
cim_add_epr(CimClientInfo * client,
WsXmlNodeH resource,
char *resource_uri, CMPIObjectPath * objectpath)
{
WsXmlNodeH epr = ws_xml_add_child(resource,
XML_NS_ADDRESSING, WSA_EPR,
NULL);
cim_add_epr_details(client, epr, resource_uri, objectpath);
return;
}
CMCIClient *
cim_connect_to_cimom(char *cim_host,
char *cim_port,
char *cim_host_userid,
char *cim_host_passwd,
char *frontend,
WsmanStatus * status)
{
CMPIStatus rc;
memset(&rc, 0, sizeof(CMPIStatus)); /* workaround for sfcb bug #2844812 */
if (strcmp(frontend, "SfcbLocal") != 0) {
if (get_cim_ssl())
frontend = "https";
else
frontend = "http";
}
CMCIClient *cimclient = cmciConnect2(cim_host, frontend, cim_port,
cim_host_userid,
cim_host_passwd,
get_cim_verify(),
get_cim_trust_store(),
NULL, /* certFile */
NULL, /* keyFile */
&rc);
if (cimclient == NULL) {
debug( "*** Connection to CIMOM %s://%s:%s failed with %d:%s", frontend, cim_host, cim_port, rc.rc, rc.msg ? CMGetCharPtr(rc.msg) : "?");
} else {
debug("new cimclient: 0x%8x", cimclient);
debug("new cimclient: %d", cimclient->ft->ftVersion);
}
cim_to_wsman_status(rc, status);
return cimclient;
}
void
cim_release_client(CimClientInfo * cimclient)
{
if (cimclient->cc) {
CMRelease((CMCIClient *) cimclient->cc);
}
}
void
release_cmpi_data(CMPIData data)
{
if (data.state == CMPI_nullValue)
return;
debug("release_cmpi_data, type = 0x%04x", data.type);
switch(data.type)
{
case CMPI_string:
debug("release String");
CMRelease(data.value.string);
break;
case CMPI_chars:
debug("free chars");
free (data.value.chars);
break;
case CMPI_instance:
debug("release instance");
CMRelease(data.value.inst);
break;
case CMPI_ref:
debug("release ref");
CMRelease(data.value.ref);
break;
case CMPI_dateTime:
debug("release datetime");
CMRelease(data.value.dateTime);
break;
default:
break;
}
}
/*
* Invoke 'EnumerateClassNames' intrinsic method
*
*/
void
invoke_enumerate_class_names(CimClientInfo *client, WsXmlNodeH body, CMPIStatus *rc)
{
CMPIObjectPath *op = newCMPIObjectPath(client->cim_namespace, "", NULL);
CMCIClient *cc = (CMCIClient *)client->cc;
unsigned long flags = client->flags;
if (client->selectors && hash_lookup(client->selectors, (char *) "DeepInheritance"))
flags |= CMPI_FLAG_DeepInheritance;
CMPIEnumeration *classnames = cc->ft->enumClassNames(cc, op, flags, rc);
debug("invoke_enumerate_class_names");
if (classnames) {
WsXmlNodeH node = ws_xml_add_child(body, client->resource_uri, client->method, NULL);
while (classnames->ft->hasNext(classnames, NULL)) {
CMPIData next = classnames->ft->getNext(classnames, NULL);
char *name = CMGetCharPtr(CMObjectPathToString(next.value.ref, NULL));
ws_xml_add_child(node, client->resource_uri, "name", name);
}
CMRelease(classnames);
}
if (op)
CMRelease(op);
}
/*
* Invoke 'GetClass' intrinsic method
*
*/
void
invoke_get_class(CimClientInfo *client, WsXmlNodeH body, CMPIStatus *rc)
{
CMPIObjectPath *op = newCMPIObjectPath(client->cim_namespace, client->requested_class, NULL);
CMCIClient *cc = (CMCIClient *)client->cc;
CMPIConstClass *_class = cc->ft->getClass(cc, op,
client->flags | (CMPI_FLAG_LocalOnly|CMPI_FLAG_IncludeQualifiers|CMPI_FLAG_IncludeClassOrigin),
NULL, rc);
debug("invoke_get_class");
if (_class) {
char *classname = CMGetCharPtr(_class->ft->getClassName(_class, rc));
unsigned int property_count = _class->ft->getPropertyCount(_class, rc);
/* <body><GetClass>...</GetClass> */
WsXmlNodeH node = ws_xml_add_child(body, client->resource_uri, client->method, NULL);
/* <GetClass><name>name</name> */
ws_xml_add_child(node, client->resource_uri, "name", classname);
debug("getClass: %s", classname);
qualifiers2xml(client, node, _class, NULL);
if (property_count > 0) {
unsigned int i = 0;
/* <GetClass><properties>...</properties> */
WsXmlNodeH properties = ws_xml_add_child(node, client->resource_uri, "properties", NULL);
while (i < property_count) {
CMPIString *property_name;
CMPIData data = _class->ft->getPropertyAt(_class, i++, &property_name, rc);
if (rc->rc)
return;
WsXmlNodeH property = datatype2xml(client, properties, client->resource_uri, "property", CMGetCharPtr(property_name), &data);
qualifiers2xml(client, property, _class, CMGetCharPtr(property_name));
}
}
CMRelease(_class);
}
if (op)
CMRelease(op);
}
void
cim_invoke_method(CimClientInfo * client,
WsContextH cntx, WsXmlNodeH body, WsmanStatus * status)
{
CMPIObjectPath *objectpath;
CMCIClient *cc = (CMCIClient *) client->cc;
WsXmlNodeH method_node = NULL;
if (client->resource_uri
&& strstr(client->resource_uri, XML_NS_CIM_CLASS) != NULL) {
/* Generic CIM uri given (pointing to abstract CIM_xxx class
* enumerate through all instances of this class to
* get the correct instance matching the selectors
*/
objectpath = cim_get_op_from_enum(client, status);
} else {
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
if (objectpath != NULL)
cim_add_keys(objectpath, client->selectors);
}
if (objectpath != NULL) {
CMPIStatus rc;
CMPIArgs *argsin = NULL, *argsout = NULL;
memset(&rc, 0, sizeof(CMPIStatus));
argsin = newCMPIArgs(NULL);
u_free(status->fault_msg);
wsman_status_init(status);
if (client->method_args && hash_count(client->method_args) > 0) {
debug("adding method arguments");
if (0 != cim_add_args(client, objectpath, argsin)) {
status->fault_code = WSMAN_INVALID_PARAMETER;
status->fault_detail_code = WSMAN_DETAIL_INVALID_VALUE;
goto cleanup;
}
}
if (strstr(client->resource_uri, XML_NS_CIM_INTRINSIC) != NULL) {
debug("Instrinsic op ?: %s", client->method);
if (!strcmp(client->method, CIM_ACTION_ENUMERATE_CLASS_NAMES))
invoke_enumerate_class_names(client, body, &rc);
else if (!strcmp(client->method, CIM_ACTION_GET_CLASS))
invoke_get_class(client, body, &rc);
} else {
argsout = newCMPIArgs(NULL);
CMPIData data = cc->ft->invokeMethod(cc, objectpath,
client->method,
argsin, argsout, &rc);
debug("invokeMethod(%s) rc=%d, msg=%s",
client->method, rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : "<NULL>");
method_node = ws_xml_add_empty_child_format(body,
client->resource_uri,
"%s_OUTPUT",
client->method);
if (rc.rc == 0) {
property2xml(client, &data, "ReturnValue",
method_node, client->resource_uri, 0, 1);
}
release_cmpi_data(data);
if (argsout) {
int count = CMGetArgCount(argsout, NULL);
int i = 0;
for (i = 0; i < count; i++) {
CMPIString *argname;
data = CMGetArgAt(argsout, i, &argname, NULL);
property2xml(client, &data,
CMGetCharPtr(argname),
method_node, client->resource_uri, 0, 0);
CMRelease(argname);
}
}
}
cim_to_wsman_status(rc, status);
if (rc.msg)
CMRelease(rc.msg);
cleanup:
if (argsin)
CMRelease(argsin);
if (argsout)
CMRelease(argsout);
}
if (objectpath)
CMRelease(objectpath);
return;
}
void
cim_delete_instance_from_enum(CimClientInfo * client, WsmanStatus * status)
{
CMPIObjectPath *objectpath = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
if (!cc) {
goto cleanup;
}
if ((objectpath = cim_get_op_from_enum(client, status)) != NULL) {
u_free(status->fault_msg);
wsman_status_init(status);
rc = cc->ft->deleteInstance(cc, objectpath);
if (rc.rc != 0) {
cim_to_wsman_status(rc, status);
}
debug("deleteInstance rc=%d, msg=%s", rc.rc,
(rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
}
debug("fault: %d %d", status->fault_code,
status->fault_detail_code);
cleanup:
if (objectpath)
CMRelease(objectpath);
return;
}
void
cim_get_instance_from_enum(CimClientInfo * client,
WsContextH cntx,
WsXmlNodeH body, char *fragstr, WsmanStatus * status)
{
CMPIInstance *instance;
CMPIObjectPath *objectpath;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
if (!cc) {
goto cleanup;
}
if ((objectpath = cim_get_op_from_enum(client, status)) != NULL) {
u_free(status->fault_msg);
wsman_status_init(status);
instance = cc->ft->getInstance(cc, objectpath,
CMPI_FLAG_IncludeClassOrigin,
NULL, &rc);
if (rc.rc == 0) {
if (instance) {
instance2xml(client, instance, fragstr, body, NULL);
}
} else {
cim_to_wsman_status(rc, status);
}
debug("getInstance rc=%d, msg=%s", rc.rc,
(rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (instance)
CMRelease(instance);
}
debug("fault: %d %d", status->fault_code,
status->fault_detail_code);
if (objectpath)
CMRelease(objectpath);
cleanup:
return;
}
void
cim_put_instance(CimClientInfo * client,
WsContextH cntx,
WsXmlNodeH in_body, WsXmlNodeH body, char *fragstr, WsmanStatus * status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *objectpath;
CMPIStatus rc;
WsXmlNodeH resource = NULL;
CMCIClient *cc = (CMCIClient *) client->cc;
CMPIConstClass *class = NULL;
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
if (!objectpath) {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_INVALID_NAMESPACE;
goto cleanup;
}
if (fragstr == NULL) {
resource = ws_xml_get_child(in_body, 0, client->resource_uri,
client->requested_class);
}
else {
resource = ws_xml_get_child(in_body, 0, XML_NS_WS_MAN, WSM_XML_FRAGMENT);
}
if (!resource) {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_INVALID_NAMESPACE;
goto cleanup;
}
cim_add_keys(objectpath, client->selectors);
instance = newCMPIInstance(objectpath, NULL);
if (!instance) {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_INVALID_NAMESPACE;
goto cleanup;
}
class = cim_get_class(client, client->requested_class,
CMPI_FLAG_IncludeQualifiers,
status);
if (class) {
create_instance_from_xml(instance, class, resource,
fragstr, client->resource_uri, status);
CMRelease(class);
}
if (status->fault_code == 0 && instance ) {
CMPIString *opstr = CMObjectPathToString(objectpath, NULL);
debug("objectpath: %s", CMGetCharPtr(opstr) );
rc = cc->ft->setInstance(cc, objectpath, instance, 0, NULL);
debug("modifyInstance() rc=%d, msg=%s", rc.rc,
(rc.msg) ? (char *) CMGetCharPtr(rc.msg) : NULL);
cim_to_wsman_status(rc, status);
if (rc.rc == CMPI_RC_OK) {
// return the current representation of the resource
instance = cc->ft->getInstance(cc, objectpath,
CMPI_FLAG_IncludeClassOrigin,
NULL, &rc);
instance2xml(client, instance, fragstr, body, NULL);
}
if (rc.msg)
CMRelease(rc.msg);
}
cleanup:
if (objectpath)
CMRelease(objectpath);
if (instance)
CMRelease(instance);
return;
}
void
cim_create_instance(CimClientInfo * client,
WsContextH cntx,
WsXmlNodeH in_body,
WsXmlNodeH body, char *fragstr, WsmanStatus * status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *objectpath, *objectpath_r;
CMPIStatus rc;
CMPIConstClass *class;
int fragment_flag;
char *element = NULL;
int index;
WsXmlNodeH resource;
char *resource_xsd = NULL;
WsXmlNodeH child = NULL;
int numproperties = 0, i;
CMCIClient *cc = (CMCIClient *) client->cc;
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
/* now ask the CIMOM for the class definition */
class = cim_get_class(client, client->requested_class,
CMPI_FLAG_IncludeQualifiers, status);
if (!class) {
/* couldn't connect to CIMOM */
status->fault_code = WSA_ENDPOINT_UNAVAILABLE;
status->fault_detail_code = OWSMAN_DETAIL_ENDPOINT_ERROR;
goto cleanup;
}
numproperties = class->ft->getPropertyCount(class, NULL);
debug("cim_create_instance: class %s, %d properties", client->requested_class, numproperties);
if(fragstr == NULL) {
resource = ws_xml_get_child(in_body, 0, client->resource_uri,
client->requested_class);
if(!resource) {
/* cim_data_stubs allows .xsd suffix for the namespace
* follow this convention here.
*/
resource_xsd = u_strdup_printf("%s.xsd", client->resource_uri);
resource = ws_xml_get_child(in_body, 0, resource_xsd,
client->requested_class);
}
}
else {
resource = ws_xml_get_child(in_body, 0, XML_NS_WS_MAN, WSM_XML_FRAGMENT);
}
if (!resource) {
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_INVALID_NAMESPACE;
goto cleanup;
}
wsman_get_fragment_type(fragstr, &fragment_flag, &element, &index);
/*
* Add keys (according to class definition)
*/
for (i = 0; i < numproperties; i++) {
CMPIString *propertyname;
/* retrieve property type (in data) and name (in propertyname) */
CMPIData data = class->ft->getPropertyAt(class, i, &propertyname, NULL);
class->ft->getPropertyQualifier(class, CMGetCharPtr(propertyname), "KEY", &rc);
if (rc.rc == 0
&& fragstr == NULL
&& !ws_xml_get_child(resource, 0,
resource_xsd ? resource_xsd : client->resource_uri,
CMGetCharPtr(propertyname))) {
debug("WXF_INVALID_REPRESENTATION");
debug("No <%s:%s>", resource_xsd ? resource_xsd : client->resource_uri, CMGetCharPtr(propertyname));
status->fault_code = WXF_INVALID_REPRESENTATION;
status->fault_detail_code = WSMAN_DETAIL_MISSING_VALUES;
break;
} else if (rc.rc == 0) {
if(fragstr == NULL) {
child = ws_xml_get_child(resource, 0,
resource_xsd ? resource_xsd : client->resource_uri, CMGetCharPtr(propertyname));
}
else {
if(strcmp(element, CMGetCharPtr(propertyname))) {
CMRelease(propertyname);
continue;
}
if(fragment_flag == 1 || fragment_flag == 3)
child = ws_xml_get_child(resource, 0, NULL, element);
}
/* assemble objectpath, passing value with correct type */
xml2objectpath(objectpath, &data, CMGetCharPtr(propertyname), ws_xml_get_node_text(child));
if(fragstr && strcmp(element, CMGetCharPtr(propertyname)) == 0) {
debug("fragstr, early break");
CMRelease(propertyname);
break;
}
}
CMRelease(propertyname);
}
if(fragstr && i == numproperties) {
status->fault_code = WSMAN_INVALID_SELECTORS;
status->fault_detail_code = WSMAN_DETAIL_UNEXPECTED_SELECTORS;
goto cleanup;
}
/* create a new (empty) instance */
instance = newCMPIInstance(objectpath, NULL);
debug("newCMPIInstance(%s) = %p", CMGetCharPtr(CMObjectPathToString(objectpath, NULL)), instance);
if (!instance) {
debug("newCMPIInstance failed");
goto cleanup;
}
/* write properties to the instance */
create_instance_from_xml(instance, class,
resource, fragstr, client->resource_uri, status);
if (status->fault_code == 0) {
objectpath_r = cc->ft->createInstance(cc, objectpath, instance, &rc);
debug("createInstance() rc=%d, msg=%s", rc.rc,
(rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (objectpath_r) {
WsXmlNodeH epr = ws_xml_add_child(body, XML_NS_TRANSFER,
WXF_RESOURCE_CREATED,
NULL);
cim_add_epr_details(client, epr, client->resource_uri,
objectpath_r);
}
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else {
cim_to_wsman_status(rc, status);
}
if (rc.msg)
CMRelease(rc.msg);
}
cleanup:
if (resource_xsd)
u_free(resource_xsd);
if (class)
CMRelease(class);
if (instance)
CMRelease(instance);
if (objectpath)
CMRelease(objectpath);
if (element)
u_free(element);
return;
}
void
cim_delete_instance(CimClientInfo * client, WsmanStatus * status)
{
CMPIObjectPath *objectpath;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
CMPIConstClass *class =
cim_get_class(client, client->requested_class,
CMPI_FLAG_IncludeQualifiers,
status);
if (!class)
goto cleanup;
cim_verify_class_keys(class, client->selectors, status);
if (status->fault_code != 0)
goto cleanup;
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
cim_add_keys(objectpath, client->selectors);
rc = cc->ft->deleteInstance(cc, objectpath);
/* Print the results */
debug("deleteInstance() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
cim_to_wsman_status(rc, status);
if (rc.msg)
CMRelease(rc.msg);
if (objectpath)
CMRelease(objectpath);
cleanup:
return;
}
CMPIInstance *
cim_get_instance_from_selectors(CimClientInfo * client,
WsContextH cntx, WsmanStatus * status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *objectpath = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
CMPIConstClass *class = cim_get_class(client,
client->requested_class,
CMPI_FLAG_IncludeQualifiers,
status);
if (!class)
goto cleanup;
cim_verify_class_keys(class, client->selectors, status);
if (status->fault_code != 0)
goto cleanup;
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
cim_add_keys(objectpath, client->selectors);
instance = cc->ft->getInstance(cc, objectpath,
CMPI_FLAG_DeepInheritance, NULL,
&rc);
/* Print the results */
debug("getInstance() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
cim_to_wsman_status(rc, status);
if (rc.msg)
CMRelease(rc.msg);
cleanup:
if (objectpath)
CMRelease(objectpath);
if (class)
CMRelease(class);
return instance;
}
CMPIObjectPath *
cim_get_indicationfilter_objectpath_from_selectors(CimClientInfo * client,
WsContextH cntx, WsmanStatus * status)
{
CMPIObjectPath *objectpath = NULL;
CMPIConstClass *class = NULL;
objectpath = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
client->requested_class, NULL);
if(objectpath) {
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *)client->cc;
class = cc->ft->getClass(cc,
objectpath,
CMPI_FLAG_IncludeQualifiers,
NULL,
&rc);
if (!class){
CMRelease(objectpath);
goto cleanup;
}
cim_verify_class_keys(class, client->selectors, status);
if (status->fault_code != 0){
CMRelease(objectpath);
goto cleanup;
}
cim_add_keys(objectpath, client->selectors);
}
cleanup:
if (class)
CMRelease(class);
return objectpath;
}
CMPIObjectPath *
cim_get_objectpath_from_selectors(CimClientInfo * client,
WsContextH cntx, WsmanStatus * status)
{
CMPIObjectPath *objectpath = NULL;
CMPIConstClass *class = cim_get_class(client,
client->requested_class,
CMPI_FLAG_IncludeQualifiers,
status);
if (!class)
goto cleanup;
cim_verify_class_keys(class, client->selectors, status);
if (status->fault_code != 0)
goto cleanup;
objectpath = newCMPIObjectPath(client->cim_namespace,
client->requested_class, NULL);
cim_add_keys(objectpath, client->selectors);
cleanup:
if (class)
CMRelease(class);
return objectpath;
}
void
cim_get_instance(CimClientInfo * client,
WsContextH cntx, WsXmlNodeH body, char *fragstr, WsmanStatus * status)
{
CMPIInstance *instance = cim_get_instance_from_selectors(client, cntx, status);
if(instance) {
instance2xml(client, instance, fragstr, body, NULL);
CMRelease(instance);
}
}
static CMPIObjectPath *
cim_indication_filter_objectpath(CimClientInfo *client,
WsSubscribeInfo *subsInfo, CMPIStatus *rc)
{
CMPIObjectPath *objectpath_filter = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
"CIM_IndicationFilter", rc);
CMAddKey(objectpath_filter, "SystemCreationClassName",
SYSTEMCREATIONCLASSNAME, CMPI_chars);
CMAddKey(objectpath_filter, "SystemName",
SYSTEMNAME, CMPI_chars);
CMAddKey(objectpath_filter, "CreationClassName",
"CIM_IndicationFilter", CMPI_chars);
CMAddKey(objectpath_filter, "Name",
subsInfo->subsId, CMPI_chars);
return objectpath_filter;
}
static CMPIObjectPath
*cim_indication_handler_objectpath(CimClientInfo *client, WsSubscribeInfo *subsInfo, CMPIStatus *rc)
{
CMPIObjectPath *objectpath_handler = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
"CIM_IndicationHandlerCIMXML", rc);
CMAddKey(objectpath_handler, "SystemCreationClassName",
SYSTEMCREATIONCLASSNAME, CMPI_chars);
CMAddKey(objectpath_handler, "SystemName",
SYSTEMNAME, CMPI_chars);
CMAddKey(objectpath_handler, "CreationClassName",
"CIM_IndicationHandlerCIMXML", CMPI_chars);
CMAddKey(objectpath_handler, "Name",
subsInfo->subsId, CMPI_chars);
return objectpath_handler;
}
CMPIObjectPath *
cim_create_indication_filter(CimClientInfo *client, WsSubscribeInfo *subsInfo, WsmanStatus *status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *objectpath = NULL;
CMPIObjectPath *objectpath_r = NULL;
CMPIObjectPath *filter_op = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
objectpath = cim_indication_filter_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
filter_op = CMClone(objectpath, &rc);
CMAddKey(objectpath, "Query",
subsInfo->filter->query, CMPI_chars);
if(subsInfo->flags & WSMAN_SUBSCRIPTION_WQL)
CMAddKey(objectpath, "QueryLanguage",
"WQL",CMPI_chars);
else if(subsInfo->flags & WSMAN_SUBSCRIPTION_CQL)
CMAddKey(objectpath, "QueryLanguage",
"CQL",CMPI_chars);
char *indicationns = subsInfo->cim_namespace;
if(indicationns)
CMAddKey(objectpath, "SourceNamespace",
indicationns, CMPI_chars);
instance = newCMPIInstance(objectpath, NULL);
objectpath_r = cc->ft->createInstance(cc, objectpath, instance, &rc);
cleanup:
/* Print the results */
debug("create CIM_IndicationFilter() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else if(rc.rc != 11){ // an object already exists. We take this erros as success
cim_to_wsman_status(rc, status);
}
if (rc.msg)
CMRelease(rc.msg);
if (objectpath_r)
CMRelease(objectpath_r);
if (objectpath)
CMRelease(objectpath);
if (instance)
CMRelease(instance);
return filter_op;
}
static char *
create_cimxml_listener_path(char *uuid)
{
char path[128];
snprintf(path, 128, "/cimindicationlistener/%s", uuid);
return u_strdup(path);
}
CMPIObjectPath *
cim_create_indication_handler(CimClientInfo *client, WsSubscribeInfo *subsInfo, WsmanStatus *status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *objectpath = NULL;
CMPIObjectPath *objectpath_r = NULL;
CMPIObjectPath *handler_op = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
objectpath = cim_indication_handler_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
handler_op = CMClone(objectpath, &rc);
instance = newCMPIInstance(objectpath, NULL);
char *servicepath = create_cimxml_listener_path(subsInfo->subsId);
char serverpath[128];
#if 0
/* might be a security risk */
snprintf(serverpath, 128, "http://%s:%s@localhost:%s%s", client->username, client->password,
get_server_port(), servicepath);
#else
snprintf(serverpath, 128, "http://localhost:%s%s", get_server_port(), servicepath);
#endif
u_free(servicepath);
CMPIValue value;
value.uint16 = 2;
CMSetProperty(instance, "Destination",
serverpath, CMPI_chars);
CMSetProperty(instance, "PersistenceType",
&value, CMPI_uint16);
objectpath_r = cc->ft->createInstance(cc, objectpath, instance, &rc);
cleanup:
/* Print the results */
debug("create CIM_IndicationHandlerCIMXML() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else if(rc.rc != 11){ // an object already exists. We take this erros as success
cim_to_wsman_status(rc, status);
}
if (rc.msg)
CMRelease(rc.msg);
if (objectpath_r)
CMRelease(objectpath_r);
if (objectpath)
CMRelease(objectpath);
if (instance)
CMRelease(instance);
return handler_op;
}
void
cim_create_indication_subscription(CimClientInfo * client, WsSubscribeInfo *subsInfo, CMPIObjectPath *filter, CMPIObjectPath *handler, WsmanStatus *status)
{
CMPIInstance *instance = NULL;
CMPIObjectPath *instance_r = NULL;
CMPIObjectPath *objectpath = NULL;
CMPIStatus rc;
CMCIClient *cc = (CMCIClient *) client->cc;
// CMPIObjectPath *objectpath_filter = cim_indication_filter_objectpath(client, subsInfo, &rc);
// if(rc.rc) goto cleanup;
// objectpath_handler = cim_indication_handler_objectpath(client, subsInfo, &rc);
// if(rc.rc) goto cleanup;
objectpath = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
"CIM_IndicationSubscription", NULL);
CMPIValue value;
value.ref = filter;
CMAddKey(objectpath, "Filter",
&value, CMPI_ref);
value.ref = handler;
CMAddKey(objectpath, "Handler",
&value, CMPI_ref);
instance = newCMPIInstance(objectpath, NULL);
//set OnFatalErrorPolicy to "Ignore"
value.uint16 = 2;
CMSetProperty(instance, "OnFatalErrorPolicy",
&value, CMPI_uint16);
//enable subscription
value.uint16 = 2;
CMSetProperty(instance, "SubscriptionState",
&value, CMPI_uint16);
if(subsInfo->expires) {
struct timeval tv;
gettimeofday(&tv, NULL);
value.uint64 = subsInfo->expires - tv.tv_sec;
CMSetProperty(instance, "SubscriptionDuration",
&value, CMPI_uint64);
}
//set RepeatNotificationPolicy to None
value.uint16 = 2;
CMSetProperty(instance, "RepeatNotificationPolicy",
&value, CMPI_uint16);
instance_r = cc->ft->createInstance(cc, objectpath, instance, &rc);
/* Print the results */
debug("create CIM_IndicationSubscription() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else if (rc.rc != 11){ // an object already exists. We take this erros as success
cim_to_wsman_status(rc, status);
}
if (rc.msg)
CMRelease(rc.msg);
if (objectpath)
CMRelease(objectpath);
if (instance)
CMRelease(instance);
if (instance_r)
CMRelease(instance_r);
return;
}
void
cim_update_indication_subscription(CimClientInfo *client, WsSubscribeInfo *subsInfo, WsmanStatus *status)
{
CMPIObjectPath *objectpath = NULL;
CMPIInstance *instance = NULL;
CMPIStatus rc;
CMPIObjectPath *objectpath_handler = NULL;
CMCIClient *cc = (CMCIClient *) client->cc;
CMPIObjectPath *objectpath_filter = NULL;
if(subsInfo->flags & WSMAN_SUBSCRIPTION_SELECTORSET)
objectpath_filter = subsInfo->existingfilterOP;
else {
objectpath_filter = cim_indication_filter_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
}
objectpath_handler = cim_indication_handler_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
objectpath = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
"CIM_IndicationSubscription", NULL);
CMPIValue value;
value.ref = objectpath_filter;
CMAddKey(objectpath, "Filter",
&value, CMPI_ref);
value.ref = objectpath_handler;
CMAddKey(objectpath, "Handler",
&value, CMPI_ref);
struct timeval tv;
gettimeofday(&tv, NULL);
value.uint64 = subsInfo->expires - tv.tv_sec;
instance = newCMPIInstance(objectpath, NULL);
CMSetProperty(instance, "subscriptionDuration", &value, CMPI_uint64);
char *properties[] = {"subscriptionDuration",NULL};
cc->ft->setInstance(cc, objectpath, instance, 0, properties);
cleanup:
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else {
cim_to_wsman_status(rc, status);
}
debug("cim_update_indication_subscription() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.msg)
CMRelease(rc.msg);
if (!(subsInfo->flags & WSMAN_SUBSCRIPTION_SELECTORSET) && objectpath_filter)
CMRelease(objectpath_filter);
if (objectpath_handler)
CMRelease(objectpath_handler);
if (instance)
CMRelease(instance);
if (objectpath)
CMRelease(objectpath);
return;
}
void
cim_delete_indication_subscription(CimClientInfo *client, WsSubscribeInfo *subsInfo, WsmanStatus *status)
{
CMPIStatus rc;
CMPIObjectPath *objectpath_subscription = NULL;
CMCIClient *cc = (CMCIClient *) client->cc;
CMPIObjectPath *objectpath_handler = NULL;
CMPIObjectPath *objectpath_filter = NULL;
if(subsInfo->flags & WSMAN_SUBSCRIPTION_SELECTORSET) {
objectpath_filter = subsInfo->existingfilterOP;
}
else{
objectpath_filter = cim_indication_filter_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
}
objectpath_handler = cim_indication_handler_objectpath(client, subsInfo, &rc);
if(rc.rc)
goto cleanup;
objectpath_subscription = newCMPIObjectPath(
get_indication_profile_implementation_ns(),
"CIM_IndicationSubscription", &rc);
if(rc.rc)
goto cleanup;
CMPIValue value;
value.ref = objectpath_filter;
CMAddKey(objectpath_subscription, "Filter",
&value, CMPI_ref);
value.ref = objectpath_handler;
CMAddKey(objectpath_subscription, "Handler",
&value, CMPI_ref);
rc = cc->ft->deleteInstance(cc, objectpath_subscription);
if(rc.rc)
goto cleanup;
if(!(subsInfo->flags & WSMAN_SUBSCRIPTION_SELECTORSET)) {
rc = cc->ft->deleteInstance(cc, objectpath_filter);
if(rc.rc)
goto cleanup;
}
rc = cc->ft->deleteInstance(cc, objectpath_handler);
cleanup:
if (rc.rc == CMPI_RC_ERR_FAILED) {
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
} else {
cim_to_wsman_status(rc, status);
}
debug("cim_delete_indication_subscription() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.msg)
CMRelease(rc.msg);
if (objectpath_filter)
CMRelease(objectpath_filter);
if (objectpath_handler)
CMRelease(objectpath_handler);
if (objectpath_subscription)
CMRelease(objectpath_subscription);
return;
}
void
cim_to_wsman_status(CMPIStatus rc, WsmanStatus * status)
{
if (!status) {
return;
}
switch (rc.rc) {
case CMPI_RC_OK:
status->fault_code = WSMAN_RC_OK;
break;
case CMPI_RC_ERR_INVALID_CLASS:
status->fault_code = WSA_DESTINATION_UNREACHABLE;
status->fault_detail_code =
WSMAN_DETAIL_INVALID_RESOURCEURI;
break;
case CMPI_RC_ERR_FAILED:
if (rc.msg && strcmp(CMGetCharPtr(rc.msg), "CURL error: 7") == 0)
status->fault_code = WSA_DESTINATION_UNREACHABLE;
else
status->fault_code = WSMAN_INTERNAL_ERROR;
break;
case CMPI_RC_ERR_METHOD_NOT_AVAILABLE:
case CMPI_RC_ERR_METHOD_NOT_FOUND:
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
break;
case CMPI_RC_ERR_INVALID_NAMESPACE:
case CMPI_RC_ERR_NOT_FOUND:
status->fault_code = WSA_DESTINATION_UNREACHABLE;
break;
case CMPI_RC_ERR_ACCESS_DENIED:
status->fault_code = WSMAN_ACCESS_DENIED;
break;
case CMPI_RC_ERR_INVALID_PARAMETER:
status->fault_code = WSMAN_INVALID_PARAMETER;
status->fault_detail_code = WSMAN_DETAIL_MISSING_VALUES;
break;
case CMPI_RC_ERR_NOT_SUPPORTED:
status->fault_code = WSA_ACTION_NOT_SUPPORTED;
break;
case CMPI_RC_ERR_CLASS_HAS_CHILDREN:
case CMPI_RC_ERR_CLASS_HAS_INSTANCES:
case CMPI_RC_ERR_INVALID_SUPERCLASS:
case CMPI_RC_ERR_ALREADY_EXISTS:
status->fault_code = WSMAN_ALREADY_EXISTS;
break;
case CMPI_RC_ERR_INVALID_QUERY:
status->fault_code = WSEN_CANNOT_PROCESS_FILTER;
break;
case CMPI_RC_ERR_NO_SUCH_PROPERTY:
case CMPI_RC_ERR_TYPE_MISMATCH:
case CMPI_RC_ERR_QUERY_LANGUAGE_NOT_SUPPORTED:
case CMPI_RC_DO_NOT_UNLOAD:
case CMPI_RC_NEVER_UNLOAD:
case CMPI_RC_ERROR_SYSTEM:
case CMPI_RC_ERROR:
default:
status->fault_code = WSMAN_UNKNOWN;
}
if (rc.msg) {
status->fault_msg = u_strdup(CMGetCharPtr(rc.msg));
}
}
void
cim_release_enum_context(WsEnumerateInfo * enumInfo)
{
if (!(enumInfo && enumInfo->appEnumContext))
return;
debug("releasing enumInfo->appEnumContext");
sfcc_enumcontext *enumcontext = enumInfo->appEnumContext;
CMPIEnumeration *enumeration;
CimClientInfo *client;
enumeration = enumcontext->ecEnumeration;
client = enumcontext->ecClient;
if (enumeration) {
debug("released enumeration");
CMRelease(enumeration);
}
u_free(enumcontext);
}
CimClientInfo *
cim_getclient_from_enum_context(WsEnumerateInfo * enumInfo)
{
CimClientInfo *cimclient = NULL;
if (enumInfo && enumInfo->appEnumContext) {
sfcc_enumcontext *enumcontext =
(sfcc_enumcontext *) enumInfo->appEnumContext;
cimclient = enumcontext->ecClient;
}
return cimclient;
}
CMPIArray *
cim_enum_instancenames(CimClientInfo * client,
char *class_name, WsmanStatus * status)
{
CMPIStatus rc;
CMPIObjectPath *objectpath;
CMPIEnumeration *enumeration;
CMCIClient *cc = (CMCIClient *) client->cc;
objectpath =
newCMPIObjectPath(client->cim_namespace, class_name, NULL);
enumeration = cc->ft->enumInstanceNames(cc, objectpath, &rc);
debug("enumInstanceNames() rc=%d, msg=%s",
rc.rc, (rc.msg) ? CMGetCharPtr(rc.msg) : NULL);
if (rc.rc) {
debug("*** CMCIClient enumInstanceNames() failed");
cim_to_wsman_status(rc, status);
return NULL;
}
CMPIArray *enumArr = enumeration->ft->toArray(enumeration, NULL);
debug("Total enumeration items: %d",
enumArr->ft->getSize(enumArr, NULL));
cim_to_wsman_status(rc, status);
return enumArr;
}
CMPICount
cim_enum_totalItems(CMPIArray * enumArr)
{
return enumArr->ft->getSize(enumArr, NULL);
}
char *
cim_get_property(CMPIInstance * instance, char *property)
{
CMPIStatus rc;
CMPIData data = instance->ft->getProperty(instance, property, &rc);
char *valuestr = NULL;
if (CMIsArray(data)) {
return NULL;
} else {
if (data.type != CMPI_null && data.state != CMPI_nullValue) {
if (data.type != CMPI_ref) {
valuestr =
value2Chars(data.type, &data.value);
}
}
}
return valuestr;
}
char *
cim_get_keyvalue(CMPIObjectPath * objpath, char *keyname)
{
CMPIStatus status;
char *valuestr;
debug("Get key property from objpath");
if (!objpath) {
debug("objpath is NULL");
return "";
}
CMPIData data = objpath->ft->getKey(objpath, keyname, &status);
if (status.rc || CMIsArray(data)) {
return "";
} else {
valuestr = value2Chars(data.type, &data.value);
return valuestr;
}
}
void
cim_get_enum_items(CimClientInfo * client,
WsContextH cntx,
WsXmlNodeH node,
WsEnumerateInfo * enumInfo,
char *namespace,
int maxelements,
unsigned long maxsize)
{
WsXmlNodeH itemsNode;
WsXmlDocH outdoc = NULL;
int c;
int count = 0;
if (node == NULL)
return;
itemsNode = ws_xml_add_child(node, namespace, WSENUM_ITEMS, NULL);
debug("Total items: %d", enumInfo->totalItems);
debug("enum flags: %lu", enumInfo->flags );
outdoc = ws_xml_get_node_doc(node);
if (enumInfo->totalItems > 0) {
if (maxelements <= 0) {
maxelements = -1; /* don't check maxelements */
}
while (enumInfo->index >= 0 &&
enumInfo->index < enumInfo->totalItems) {
if (enumInfo->flags & WSMAN_ENUMINFO_EPR ) {
c = cim_getEprAt(client, enumInfo, itemsNode);
} else if (enumInfo->flags & WSMAN_ENUMINFO_OBJEPR) {
c = cim_getEprObjAt(client, enumInfo, itemsNode);
} else {
c = cim_getElementAt(client, enumInfo, itemsNode);
}
if (!c) {
/* cim_getE... failed */
break;
}
if (check_envelope_size(outdoc, maxsize, enumInfo->encoding)) {
/* last item added to itemsNode exceeded the envelope size */
if (count > 0) {
/* if there's already a partial result,
* remove last child from itemsNode
* and return partial result */
WsXmlNodeH item = xml_parser_node_get(itemsNode, XML_LAST_CHILD);
xml_parser_node_remove(item);
}
/* if the first item already exceeds the envelope size, leave it
* and let the SOAP report an EncodingLimit fault.
*/
break;
}
enumInfo->index++;
count++;
maxelements--;
if (maxelements == 0) {
break;
}
}
enumInfo->index--; /* callee (wsman-soap.c) increments it again */
}
enumInfo->pullResultPtr = outdoc;
}