sfcc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +4 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +28 -0
- data/README.rdoc +60 -0
- data/Rakefile +32 -0
- data/TODO.rdoc +28 -0
- data/ext/sfcc/cim_class.c +274 -0
- data/ext/sfcc/cim_class.h +12 -0
- data/ext/sfcc/cim_client.c +862 -0
- data/ext/sfcc/cim_client.h +12 -0
- data/ext/sfcc/cim_enumeration.c +65 -0
- data/ext/sfcc/cim_enumeration.h +12 -0
- data/ext/sfcc/cim_instance.c +357 -0
- data/ext/sfcc/cim_instance.h +12 -0
- data/ext/sfcc/cim_object_path.c +419 -0
- data/ext/sfcc/cim_object_path.h +12 -0
- data/ext/sfcc/cim_string.c +64 -0
- data/ext/sfcc/cim_string.h +12 -0
- data/ext/sfcc/extconf.rb +8 -0
- data/ext/sfcc/sfcc.c +344 -0
- data/ext/sfcc/sfcc.h +87 -0
- data/lib/sfcc.rb +174 -0
- data/test/helper.rb +32 -0
- data/test/test_sfcc.rb +69 -0
- data/test/test_sfcc_cim_class.rb +53 -0
- data/test/test_sfcc_cim_client.rb +151 -0
- data/test/test_sfcc_cim_enumeration.rb +24 -0
- data/test/test_sfcc_cim_instance.rb +89 -0
- data/test/test_sfcc_cim_object_path.rb +85 -0
- metadata +152 -0
data/ext/sfcc/sfcc.c
ADDED
@@ -0,0 +1,344 @@
|
|
1
|
+
|
2
|
+
#include <stdarg.h>
|
3
|
+
|
4
|
+
#include "sfcc.h"
|
5
|
+
|
6
|
+
#include <CimClientLib/cmci.h>
|
7
|
+
#include <CimClientLib/native.h>
|
8
|
+
#include <CimClientLib/cmcimacs.h>
|
9
|
+
|
10
|
+
#include "cim_string.h"
|
11
|
+
#include "cim_object_path.h"
|
12
|
+
#include "cim_enumeration.h"
|
13
|
+
#include "cim_class.h"
|
14
|
+
#include "cim_instance.h"
|
15
|
+
#include "cim_client.h"
|
16
|
+
|
17
|
+
VALUE mSfcc;
|
18
|
+
VALUE mSfccCim;
|
19
|
+
|
20
|
+
void Init_sfcc()
|
21
|
+
{
|
22
|
+
/**
|
23
|
+
* SBLIM sfcc ruby API
|
24
|
+
*/
|
25
|
+
mSfcc = rb_define_module("Sfcc");
|
26
|
+
/**
|
27
|
+
* SBLIM sfcc CIMC API
|
28
|
+
*/
|
29
|
+
mSfccCim= rb_define_module_under(mSfcc, "Cim");
|
30
|
+
|
31
|
+
init_cim_string();
|
32
|
+
init_cim_object_path();
|
33
|
+
init_cim_enumeration();
|
34
|
+
init_cim_class();
|
35
|
+
init_cim_instance();
|
36
|
+
init_cim_client();
|
37
|
+
}
|
38
|
+
|
39
|
+
static VALUE sfcc_status_exception(CMPIStatus status)
|
40
|
+
{
|
41
|
+
switch (status.rc)
|
42
|
+
{
|
43
|
+
case CMPI_RC_ERR_FAILED:
|
44
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorFailed"));
|
45
|
+
case CMPI_RC_ERR_ACCESS_DENIED:
|
46
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorAcessDenied"));
|
47
|
+
case CMPI_RC_ERR_INVALID_NAMESPACE:
|
48
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorInvalidNamespace"));
|
49
|
+
case CMPI_RC_ERR_INVALID_PARAMETER:
|
50
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorInvalidParameter"));
|
51
|
+
case CMPI_RC_ERR_INVALID_CLASS:
|
52
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorInvalidClass"));
|
53
|
+
case CMPI_RC_ERR_NOT_FOUND:
|
54
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorNotFound"));
|
55
|
+
case CMPI_RC_ERR_NOT_SUPPORTED:
|
56
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorNotSupported"));
|
57
|
+
case CMPI_RC_ERR_CLASS_HAS_CHILDREN:
|
58
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorClassHasChildren"));
|
59
|
+
case CMPI_RC_ERR_CLASS_HAS_INSTANCES:
|
60
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorClassHasInstances"));
|
61
|
+
case CMPI_RC_ERR_INVALID_SUPERCLASS:
|
62
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorInvalidSuperClass"));
|
63
|
+
case CMPI_RC_ERR_ALREADY_EXISTS:
|
64
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorAlreadyExists"));
|
65
|
+
case CMPI_RC_ERR_NO_SUCH_PROPERTY:
|
66
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorNoSuchProperty"));
|
67
|
+
case CMPI_RC_ERR_TYPE_MISMATCH:
|
68
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorTypeMismatch"));
|
69
|
+
case CMPI_RC_ERR_QUERY_LANGUAGE_NOT_SUPPORTED:
|
70
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorQueryLanguageNotSupported"));
|
71
|
+
case CMPI_RC_ERR_INVALID_QUERY:
|
72
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorInvalidQuery"));
|
73
|
+
case CMPI_RC_ERR_METHOD_NOT_AVAILABLE:
|
74
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorMethodNotAvailable"));
|
75
|
+
case CMPI_RC_ERR_METHOD_NOT_FOUND:
|
76
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorMethodNotFound"));
|
77
|
+
case CMPI_RC_DO_NOT_UNLOAD:
|
78
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorDoNotUnload"));
|
79
|
+
case CMPI_RC_NEVER_UNLOAD:
|
80
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorNeverUnload"));
|
81
|
+
case CMPI_RC_ERROR_SYSTEM:
|
82
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorSystem"));
|
83
|
+
case CMPI_RC_ERROR:
|
84
|
+
return rb_const_get(mSfccCim, rb_intern("ErrorRcError"));
|
85
|
+
case CMPI_RC_OK:
|
86
|
+
default:
|
87
|
+
return Qnil;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
void sfcc_rb_raise_if_error(CMPIStatus status, const char *msg, ...)
|
92
|
+
{
|
93
|
+
static char *error_separator = " : ";
|
94
|
+
va_list arg_list;
|
95
|
+
va_start(arg_list, msg);
|
96
|
+
size_t size = 0;
|
97
|
+
char *error = NULL;
|
98
|
+
|
99
|
+
if (!status.rc)
|
100
|
+
return;
|
101
|
+
|
102
|
+
size = sizeof(msg) + sizeof(error_separator);
|
103
|
+
if (status.msg)
|
104
|
+
size = size + sizeof(status.msg->ft->getCharPtr(status.msg, NULL));
|
105
|
+
error = (char *)malloc(size*sizeof(char *));
|
106
|
+
strcpy(error, msg);
|
107
|
+
if (status.msg) {
|
108
|
+
strcat(error, " : ");
|
109
|
+
strcat(error, status.msg->ft->getCharPtr(status.msg, NULL));
|
110
|
+
}
|
111
|
+
rb_raise(sfcc_status_exception(status), error, arg_list);
|
112
|
+
free(error);
|
113
|
+
}
|
114
|
+
|
115
|
+
char ** sfcc_value_array_to_string_array(VALUE array)
|
116
|
+
{
|
117
|
+
char **ret;
|
118
|
+
int i = 0;
|
119
|
+
|
120
|
+
if ( !NIL_P(array) && RARRAY_LEN(array) > 0 ) {
|
121
|
+
ret = (char**) malloc(RARRAY_LEN(array)*sizeof(char*));
|
122
|
+
for (; i < RARRAY_LEN(array); ++i)
|
123
|
+
ret[i] = StringValuePtr(*(RARRAY_PTR(array) + i));
|
124
|
+
}
|
125
|
+
else
|
126
|
+
ret = NULL;
|
127
|
+
|
128
|
+
return ret;
|
129
|
+
}
|
130
|
+
|
131
|
+
VALUE sfcc_cimdata_to_value(CMPIData data)
|
132
|
+
{
|
133
|
+
CMPIString *cimstr = NULL;
|
134
|
+
VALUE rbval;
|
135
|
+
CMPIStatus status;
|
136
|
+
|
137
|
+
if (data.type & CMPI_ARRAY) {
|
138
|
+
int k = 0;
|
139
|
+
int n = 0;
|
140
|
+
VALUE rbarray = rb_ary_new();
|
141
|
+
|
142
|
+
if (!data.value.array)
|
143
|
+
return rb_ary_new();
|
144
|
+
|
145
|
+
n = data.value.array->ft->getSize(data.value.array, &status);
|
146
|
+
if (!status.rc) {
|
147
|
+
for (k = 0; k < n; ++k) {
|
148
|
+
CMPIData element = data.value.array->ft->getElementAt(data.value.array, k, NULL);
|
149
|
+
rb_ary_push(rbarray, sfcc_cimdata_to_value(element));
|
150
|
+
}
|
151
|
+
return rbarray;
|
152
|
+
}
|
153
|
+
sfcc_rb_raise_if_error(status, "Can't retrieve array size");
|
154
|
+
return Qnil;
|
155
|
+
}
|
156
|
+
else if (data.type & CMPI_ENC) {
|
157
|
+
switch (data.type) {
|
158
|
+
case CMPI_instance:
|
159
|
+
return data.value.inst ? Sfcc_wrap_cim_instance(data.value.inst->ft->clone(data.value.inst, NULL)) : Qnil;
|
160
|
+
case CMPI_class:
|
161
|
+
return data.value.cls ? Sfcc_wrap_cim_class(data.value.cls->ft->clone(data.value.cls, NULL)) : Qnil;
|
162
|
+
case CMPI_ref:
|
163
|
+
return data.value.ref ? Sfcc_wrap_cim_object_path(data.value.ref->ft->clone(data.value.ref, NULL)) : Qnil;
|
164
|
+
case CMPI_args:
|
165
|
+
return data.value.args ? sfcc_cimargs_to_hash(data.value.args) : Qnil;
|
166
|
+
case CMPI_filter:
|
167
|
+
return Qnil;
|
168
|
+
case CMPI_numericString:
|
169
|
+
case CMPI_booleanString:
|
170
|
+
case CMPI_dateTimeString:
|
171
|
+
case CMPI_classNameString:
|
172
|
+
break;
|
173
|
+
case CMPI_string:
|
174
|
+
return data.value.string ? rb_str_new2((char*)data.value.string->ft->getCharPtr(data.value.string, NULL)) : Qnil;
|
175
|
+
case CMPI_charsptr:
|
176
|
+
return data.value.chars ? rb_str_new((char*)data.value.dataPtr.ptr, data.value.dataPtr.length) : Qnil;
|
177
|
+
case CMPI_dateTime:
|
178
|
+
cimstr = data.value.dateTime ? CMGetStringFormat(data.value.dateTime,NULL) : NULL;
|
179
|
+
rbval = cimstr ? rb_str_new2(cimstr->ft->getCharPtr(cimstr, NULL)) : Qnil;
|
180
|
+
if (cimstr) CMRelease(cimstr);
|
181
|
+
return rbval;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
else if (data.type & CMPI_SIMPLE) {
|
185
|
+
switch (data.type) {
|
186
|
+
case CMPI_boolean: return data.value.boolean ? Qtrue : Qfalse;
|
187
|
+
case CMPI_char16: return UINT2NUM(data.value.char16);
|
188
|
+
}
|
189
|
+
}
|
190
|
+
else if (data.type & CMPI_INTEGER) {
|
191
|
+
switch (data.type) {
|
192
|
+
case CMPI_uint8: return UINT2NUM(data.value.uint8);
|
193
|
+
case CMPI_sint8: return INT2NUM(data.value.sint8);
|
194
|
+
case CMPI_uint16: return UINT2NUM(data.value.uint16);
|
195
|
+
case CMPI_sint16: return INT2NUM(data.value.sint16);
|
196
|
+
case CMPI_uint32: return UINT2NUM(data.value.uint32);
|
197
|
+
case CMPI_sint32: return INT2NUM(data.value.sint32);
|
198
|
+
case CMPI_uint64: return UINT2NUM(data.value.uint64);
|
199
|
+
case CMPI_sint64: return INT2NUM(data.value.sint64);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
else if (data.type & CMPI_REAL) {
|
203
|
+
switch (data.type) {
|
204
|
+
case CMPI_real32: return LONG2NUM(data.value.real32);
|
205
|
+
case CMPI_real64: return LONG2NUM(data.value.real64);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
else if (data.type & CMPI_null ) {
|
209
|
+
return Qnil;
|
210
|
+
}
|
211
|
+
rb_raise(rb_eTypeError, "unsupported data data type %d", data.type);
|
212
|
+
return Qnil;
|
213
|
+
}
|
214
|
+
|
215
|
+
/* callback to add each hash element to a CMPIArgs */
|
216
|
+
static int hash_to_cimargs_iterator(VALUE key, VALUE value, VALUE extra)
|
217
|
+
{
|
218
|
+
CMPIStatus status;
|
219
|
+
CMPIData data;
|
220
|
+
CMPIArgs *args = (CMPIArgs *)extra;
|
221
|
+
VALUE key_str = rb_funcall(key, rb_intern("to_s"), 0);
|
222
|
+
char *key_cstr = StringValuePtr(key_str);
|
223
|
+
data = sfcc_value_to_cimdata(value);
|
224
|
+
status = args->ft->addArg(args, key_cstr, &data.value, data.type);
|
225
|
+
|
226
|
+
if ( !status.rc ) {
|
227
|
+
return ST_CONTINUE;
|
228
|
+
}
|
229
|
+
|
230
|
+
sfcc_rb_raise_if_error(status, "Can't add argument '%s'", StringValuePtr(key));
|
231
|
+
return ST_STOP;
|
232
|
+
}
|
233
|
+
|
234
|
+
CMPIArgs *sfcc_hash_to_cimargs(VALUE hash)
|
235
|
+
{
|
236
|
+
CMPIArgs *args;
|
237
|
+
args = newCMPIArgs(NULL);
|
238
|
+
rb_hash_foreach(hash, hash_to_cimargs_iterator, (VALUE)args);
|
239
|
+
return args;
|
240
|
+
}
|
241
|
+
|
242
|
+
VALUE sfcc_cimargs_to_hash(CMPIArgs *args)
|
243
|
+
{
|
244
|
+
CMPIArgs *ptr = NULL;
|
245
|
+
int i = 0;
|
246
|
+
int n = 0;
|
247
|
+
VALUE hash;
|
248
|
+
CMPIString *argname;
|
249
|
+
CMPIData argdata;
|
250
|
+
CMPIStatus status;
|
251
|
+
char *argname_cstr = NULL;
|
252
|
+
|
253
|
+
//Data_Get_Struct(args, CMPIArgs, ptr);
|
254
|
+
ptr = args;
|
255
|
+
if (!ptr) {
|
256
|
+
rb_raise(rb_eRuntimeError, "Can't retrieve args pointer");
|
257
|
+
return Qnil;
|
258
|
+
}
|
259
|
+
n = ptr->ft->getArgCount(ptr, NULL);
|
260
|
+
hash = rb_hash_new();
|
261
|
+
|
262
|
+
for (; i < n; ++i) {
|
263
|
+
argname = NULL;
|
264
|
+
argdata = ptr->ft->getArgAt(ptr, i, &argname, &status);
|
265
|
+
if (!status.rc && argdata.state == CMPI_goodValue ) {
|
266
|
+
argname_cstr = argname->ft->getCharPtr(argname, &status);
|
267
|
+
if (!argname_cstr) {
|
268
|
+
rb_raise(rb_eRuntimeError, "Can't retrieve argument name");
|
269
|
+
return Qnil;
|
270
|
+
}
|
271
|
+
|
272
|
+
if (!status.rc) {
|
273
|
+
rb_hash_aset(hash, rb_funcall(rb_str_new2(argname_cstr), rb_intern("to_sym"), 0), sfcc_cimdata_to_value(argdata));
|
274
|
+
}
|
275
|
+
else {
|
276
|
+
sfcc_rb_raise_if_error(status, "Can't retrieve argument name");
|
277
|
+
return Qnil;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
else {
|
281
|
+
sfcc_rb_raise_if_error(status, "Can't retrieve argument");
|
282
|
+
return Qnil;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
return hash;
|
286
|
+
}
|
287
|
+
|
288
|
+
CMPIData sfcc_value_to_cimdata(VALUE value)
|
289
|
+
{
|
290
|
+
CMPIData data;
|
291
|
+
memset(&data, 0, sizeof(CMPIData));
|
292
|
+
data.state = CMPI_goodValue;
|
293
|
+
data.type = CMPI_null;
|
294
|
+
|
295
|
+
switch (TYPE(value))
|
296
|
+
{
|
297
|
+
case T_NIL:
|
298
|
+
data.type = CMPI_null;
|
299
|
+
data.state = CMPI_nullValue;
|
300
|
+
break;
|
301
|
+
case T_STRING:
|
302
|
+
data.type = CMPI_string;
|
303
|
+
data.value.string = newCMPIString(StringValuePtr(value), NULL);
|
304
|
+
break;
|
305
|
+
case T_TRUE:
|
306
|
+
data.type = CMPI_boolean;
|
307
|
+
data.value.boolean = 1;
|
308
|
+
break;
|
309
|
+
case T_FALSE:
|
310
|
+
data.type = CMPI_boolean;
|
311
|
+
data.value.boolean = 0;
|
312
|
+
break;
|
313
|
+
case T_FIXNUM:
|
314
|
+
data.type = CMPI_sint64;
|
315
|
+
data.value.Long = NUM2INT(value);
|
316
|
+
break;
|
317
|
+
/* not yet supported
|
318
|
+
case T_BIGNUM:
|
319
|
+
break;
|
320
|
+
case T_FLOAT:
|
321
|
+
break;
|
322
|
+
case T_ARRAY:
|
323
|
+
break;
|
324
|
+
case T_HASH:
|
325
|
+
break;
|
326
|
+
case T_SYMBOL:
|
327
|
+
*/
|
328
|
+
case T_DATA:
|
329
|
+
default:
|
330
|
+
if (CLASS_OF(value) == cSfccCimString) {
|
331
|
+
Data_Get_Struct(value, CMPIString, data.value.string);
|
332
|
+
data.type = CMPI_string;
|
333
|
+
}
|
334
|
+
else {
|
335
|
+
data.state = CMPI_badValue;
|
336
|
+
data.type = CMPI_null;
|
337
|
+
VALUE cname = rb_funcall(rb_funcall(value, rb_intern("class"), 0), rb_intern("to_s"), 0);
|
338
|
+
const char *class_name = StringValuePtr(cname);
|
339
|
+
rb_raise(rb_eTypeError, "unsupported data data type: %s", class_name);
|
340
|
+
return data;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
return data;
|
344
|
+
}
|
data/ext/sfcc/sfcc.h
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
#ifndef RUBY_SFCC_NATIVE
|
3
|
+
#define RUBY_SFCC_NATIVE
|
4
|
+
|
5
|
+
#include <assert.h>
|
6
|
+
|
7
|
+
/*
|
8
|
+
#include <cimc/cimc.h>
|
9
|
+
#include <cimc/cimcdt.h>
|
10
|
+
#include <cimc/cimcft.h>
|
11
|
+
*/
|
12
|
+
#include <CimClientLib/cmci.h>
|
13
|
+
#include <CimClientLib/cmcidt.h>
|
14
|
+
#include <CimClientLib/cmcift.h>
|
15
|
+
#include <CimClientLib/native.h>
|
16
|
+
#include <CimClientLib/cmcimacs.h>
|
17
|
+
|
18
|
+
#include "ruby.h"
|
19
|
+
#include "st.h"
|
20
|
+
#include <unistd.h>
|
21
|
+
#include <stdlib.h>
|
22
|
+
|
23
|
+
extern VALUE mSfcc;
|
24
|
+
extern VALUE mSfccCim;
|
25
|
+
|
26
|
+
/*
|
27
|
+
#define SFCC_DEC_REFCOUNT(x) \
|
28
|
+
do { \
|
29
|
+
int refc = ((CIMCObject*)x)->refCount; \
|
30
|
+
printf("dec X: %d rf: %d\n", (int)x, refc); \
|
31
|
+
--((CIMCObject*)x)->refCount; \
|
32
|
+
if (refc <= 0) \
|
33
|
+
x->ft->release(x); \
|
34
|
+
free(x); \
|
35
|
+
} while (0);
|
36
|
+
*/
|
37
|
+
|
38
|
+
#define SFCC_DEC_REFCOUNT(x) \
|
39
|
+
x->ft->release(x);
|
40
|
+
|
41
|
+
/*
|
42
|
+
#define SFCC_INC_REFCOUNT(x) \
|
43
|
+
do { \
|
44
|
+
int refc = ((CIMCObject*)x)->refCount; \
|
45
|
+
printf("inc X: %d rf: %d\n", (int) x, refc); \
|
46
|
+
++((CIMCObject*)x)->refCount; \
|
47
|
+
} while (0);
|
48
|
+
*/
|
49
|
+
|
50
|
+
#define SFCC_INC_REFCOUNT(x) (void)(0);
|
51
|
+
|
52
|
+
/**
|
53
|
+
* raises a ruby exception if the status is an error
|
54
|
+
* whenever possible, adds the custom message if not null
|
55
|
+
*/
|
56
|
+
void sfcc_rb_raise_if_error(CMPIStatus status, const char *msg, ...);
|
57
|
+
|
58
|
+
/**
|
59
|
+
* allocates a string array where each string points to the
|
60
|
+
* str pointer of the value
|
61
|
+
*
|
62
|
+
* you need to deallocate the array yourself. But don't deallocate
|
63
|
+
* the elements.
|
64
|
+
*/
|
65
|
+
inline char ** sfcc_value_array_to_string_array(VALUE array);
|
66
|
+
|
67
|
+
/**
|
68
|
+
* converts a ruby hash to a CIM args object
|
69
|
+
*/
|
70
|
+
inline CMPIArgs* sfcc_hash_to_cimargs(VALUE hash);
|
71
|
+
|
72
|
+
/**
|
73
|
+
* converts a CIM args object to a hash
|
74
|
+
*/
|
75
|
+
inline VALUE sfcc_cimargs_to_hash(CMPIArgs *args);
|
76
|
+
|
77
|
+
/**
|
78
|
+
* converts CMPIData to ruby VALUE
|
79
|
+
*/
|
80
|
+
inline VALUE sfcc_cimdata_to_value(CMPIData data);
|
81
|
+
|
82
|
+
/**
|
83
|
+
* convert ruby VALUE to CMPIData
|
84
|
+
*/
|
85
|
+
inline CMPIData sfcc_value_to_cimdata(VALUE value);
|
86
|
+
|
87
|
+
#endif
|
data/lib/sfcc.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
|
2
|
+
require "sfcc.so" # native
|
3
|
+
require 'enumerator'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Sfcc
|
7
|
+
|
8
|
+
VERSION = "0.1.0"
|
9
|
+
|
10
|
+
module Flags
|
11
|
+
LocalOnly = 1
|
12
|
+
DeepInheritance = 2
|
13
|
+
IncludeQualifiers = 4
|
14
|
+
IncludeClassOrigin = 8
|
15
|
+
end
|
16
|
+
|
17
|
+
module Cim
|
18
|
+
|
19
|
+
# Base class for errors
|
20
|
+
class Error < RuntimeError; end
|
21
|
+
|
22
|
+
# A general error occurred that is not covered by a more specific error code
|
23
|
+
class ErrorFailed < Sfcc::Cim::Error; end
|
24
|
+
# Access to a CIM resource was not available to the client
|
25
|
+
class ErrorAccessDenied < Sfcc::Cim::Error; end
|
26
|
+
# The target namespace does not exist
|
27
|
+
class ErrorInvalidNamespace < Sfcc::Cim::Error; end
|
28
|
+
# One or more parameter values passed to the method were invalid
|
29
|
+
class ErrorInvalidParameter < Sfcc::Cim::Error; end
|
30
|
+
# The specified Class does not exist
|
31
|
+
class ErrorInvalidClass < Sfcc::Cim::Error; end
|
32
|
+
# The requested object could not be found
|
33
|
+
class ErrorNotFound < Sfcc::Cim::Error; end
|
34
|
+
# The requested operation is not supported
|
35
|
+
class ErrorNotSupported < Sfcc::Cim::Error; end
|
36
|
+
# Operation cannot be carried out on this class since it has subclasses
|
37
|
+
class ErrorClassHasChildren < Sfcc::Cim::Error; end
|
38
|
+
# Operation cannot be carried out on this class since it has instances
|
39
|
+
class ErrorClassHasInstances < Sfcc::Cim::Error; end
|
40
|
+
# Operation cannot be carried out since the specified superclass does not exist
|
41
|
+
class ErrorInvalidSuperClass < Sfcc::Cim::Error; end
|
42
|
+
# Operation cannot be carried out because an object already exists
|
43
|
+
class ErrorAlreadyExists < Sfcc::Cim::Error; end
|
44
|
+
# The specified Property does not exist
|
45
|
+
class ErrorNoSuchProperty < Sfcc::Cim::Error; end
|
46
|
+
# The value supplied is incompatible with the type
|
47
|
+
class ErrorTypeMisMatch < Sfcc::Cim::Error; end
|
48
|
+
# The query language is not recognized or supported
|
49
|
+
class ErrorQueryLanguageNotSupported < Sfcc::Cim::Error; end
|
50
|
+
# The query is not valid for the specified query language
|
51
|
+
class ErrorInvalidQuery < Sfcc::Cim::Error; end
|
52
|
+
# The extrinsic Method could not be executed
|
53
|
+
class ErrorMethodNotAvailable < Sfcc::Cim::Error; end
|
54
|
+
# The specified extrinsic Method does not exist
|
55
|
+
class ErrorMethodNotFound < Sfcc::Cim::Error; end
|
56
|
+
|
57
|
+
class ErrorDoNotUnload < RuntimeError; end
|
58
|
+
class ErrorErrorSystem < RuntimeError; end
|
59
|
+
class ErrorRcError < RuntimeError; end
|
60
|
+
|
61
|
+
class Client
|
62
|
+
# Client.connect(:host => "localhost",
|
63
|
+
# :scheme => "http",
|
64
|
+
# :port => 5988,
|
65
|
+
# :user => "root",
|
66
|
+
# :password => "foo") do |client|
|
67
|
+
# # do something with client
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# client is both returned and passed to the given block.
|
71
|
+
#
|
72
|
+
# Alternatively you can pass a uri:
|
73
|
+
#
|
74
|
+
# client = Client.connect(uri)
|
75
|
+
#
|
76
|
+
def self.connect(args={})
|
77
|
+
params = {}
|
78
|
+
uri = nil
|
79
|
+
case args
|
80
|
+
when Hash
|
81
|
+
params.merge!(args)
|
82
|
+
when String
|
83
|
+
uri = URI.parse(arg)
|
84
|
+
when URI
|
85
|
+
params[:host] = uri.host
|
86
|
+
params[:scheme] = uri.scheme
|
87
|
+
params[:port] = uri.port
|
88
|
+
params[:user] = uri.user
|
89
|
+
params[:password] = uri.password
|
90
|
+
end
|
91
|
+
|
92
|
+
native_connect(params[:host],
|
93
|
+
params[:scheme],
|
94
|
+
params[:port],
|
95
|
+
params[:user],
|
96
|
+
params[:password]);
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Class
|
101
|
+
# properties => Hash
|
102
|
+
#
|
103
|
+
# return a hash with all properties
|
104
|
+
def properties
|
105
|
+
ret = {}
|
106
|
+
each_property { |key, value| ret[key] = value }
|
107
|
+
ret
|
108
|
+
end
|
109
|
+
|
110
|
+
# qualifiers => Hash
|
111
|
+
#
|
112
|
+
# return a hash with all qualifiers
|
113
|
+
def qualifiers
|
114
|
+
ret = {}
|
115
|
+
each_qualifier { |key, value| ret[key] = value }
|
116
|
+
ret
|
117
|
+
end
|
118
|
+
|
119
|
+
# property_qualifiers(property_name) => Hash
|
120
|
+
#
|
121
|
+
# return a hash with all qualifiers for +property_name+
|
122
|
+
def property_qualifiers(property_name)
|
123
|
+
ret = {}
|
124
|
+
each_property_qualifier(property_name) { |key, value| ret[key] = value }
|
125
|
+
ret
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
class Instance
|
131
|
+
# properties => Hash
|
132
|
+
#
|
133
|
+
# return a hash with all properties
|
134
|
+
def properties
|
135
|
+
ret = {}
|
136
|
+
each_property { |key, value| ret[key] = value }
|
137
|
+
ret
|
138
|
+
end
|
139
|
+
|
140
|
+
# qualifiers => Hash
|
141
|
+
#
|
142
|
+
# return a hash with all qualifiers
|
143
|
+
def qualifiers
|
144
|
+
ret = {}
|
145
|
+
each_qualifier { |key, value| ret[key] = value }
|
146
|
+
ret
|
147
|
+
end
|
148
|
+
|
149
|
+
# property_qualifiers(property_name) => Hash
|
150
|
+
#
|
151
|
+
# return a hash with all qualifiers for +property_name+
|
152
|
+
def property_qualifiers(property_name)
|
153
|
+
ret = {}
|
154
|
+
each_property_qualifier(property_name) { |key, value| ret[key] = value }
|
155
|
+
ret
|
156
|
+
end
|
157
|
+
|
158
|
+
# returns the string representation of
|
159
|
+
# the object path for this instance
|
160
|
+
def to_s
|
161
|
+
object_path.to_s
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class ObjectPath
|
166
|
+
end
|
167
|
+
|
168
|
+
class Enumeration
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
%w(../lib ../ext).each do |path|
|
7
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), path)))
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'sfcc'
|
12
|
+
|
13
|
+
class SfccTestCase < Test::Unit::TestCase
|
14
|
+
ASSETS = File.expand_path(File.join(File.dirname(__FILE__), 'assets'))
|
15
|
+
|
16
|
+
unless RUBY_VERSION >= '1.9'
|
17
|
+
undef :default_test
|
18
|
+
end
|
19
|
+
|
20
|
+
def cimom_running?
|
21
|
+
`ps -e`.each_line do |line|
|
22
|
+
return true if line =~ /sfcbd/
|
23
|
+
end
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_cim_client
|
28
|
+
@client = Sfcc::Cim::Client.connect('http://root@localhost:5988')
|
29
|
+
# @client = Sfcc::Cim::Client.connect(:host => 'localhost', :scheme => 'http', :user => 'root', :port => '5988')
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/test/test_sfcc.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
class BasicTest < SfccTestCase
|
5
|
+
|
6
|
+
context "a running CIMOM with no auth" do
|
7
|
+
setup do
|
8
|
+
setup_cim_client
|
9
|
+
end
|
10
|
+
|
11
|
+
should "be running" do
|
12
|
+
assert cimom_running?
|
13
|
+
end
|
14
|
+
|
15
|
+
should "be of class Client" do
|
16
|
+
assert_kind_of(Sfcc::Cim::Client, @client)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "a new object path for root/cimv2" do
|
20
|
+
setup do
|
21
|
+
@op = Sfcc::Cim::ObjectPath.new("root/cimv2", "")
|
22
|
+
end
|
23
|
+
|
24
|
+
should "be of class ObjectPath" do
|
25
|
+
assert_kind_of(Sfcc::Cim::ObjectPath, @op)
|
26
|
+
end
|
27
|
+
|
28
|
+
should "allow for query" do
|
29
|
+
result = @client.query(@op, "select * from CIM_ComputerSystem", "wql")
|
30
|
+
result.each do |instance|
|
31
|
+
puts instance
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "class names" do
|
36
|
+
setup do
|
37
|
+
@class_names = @client.class_names(@op, Sfcc::Flags::DeepInheritance)
|
38
|
+
end
|
39
|
+
|
40
|
+
should "be a Cimc::Enumeration" do
|
41
|
+
assert_kind_of(Sfcc::Cim::Enumeration, @class_names)
|
42
|
+
end
|
43
|
+
|
44
|
+
should "include CIM_ManagedElement" do
|
45
|
+
assert !@class_names.select { |x| x.to_s == "CIM_ManagedElement" }.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
should "have every element of type Sfcc::Cim::ObjectPath" do
|
49
|
+
@class_names.each { |n| assert_kind_of(Sfcc::Cim::ObjectPath, n) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "classes" do
|
54
|
+
setup do
|
55
|
+
@classes = @client.classes(@op, Sfcc::Flags::DeepInheritance)
|
56
|
+
end
|
57
|
+
|
58
|
+
should "be a Cimc::Enumeration" do
|
59
|
+
assert_kind_of(Sfcc::Cim::Enumeration, @classes)
|
60
|
+
end
|
61
|
+
|
62
|
+
should "have every alement of type Cimc::Class" do
|
63
|
+
@classes.each { |c| assert_kind_of(Sfcc::Cim::Class, c) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|