sfcc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|