ruby-libvirt 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/libvirt/common.c CHANGED
@@ -2,6 +2,7 @@
2
2
  * common.c: Common utilities for the ruby libvirt bindings
3
3
  *
4
4
  * Copyright (C) 2007,2010 Red Hat Inc.
5
+ * Copyright (C) 2013 Chris Lalancette <clalancette@gmail.com>
5
6
  *
6
7
  * This library is free software; you can redistribute it and/or
7
8
  * modify it under the terms of the GNU Lesser General Public
@@ -26,68 +27,65 @@
26
27
  #include <libvirt/libvirt.h>
27
28
  #include <libvirt/virterror.h>
28
29
  #include "common.h"
30
+ #include "connect.h"
29
31
 
30
32
  struct rb_exc_new2_arg {
31
33
  VALUE error;
32
34
  char *msg;
33
35
  };
34
36
 
35
- static VALUE rb_exc_new2_wrap(VALUE arg) {
37
+ static VALUE ruby_libvirt_exc_new2_wrap(VALUE arg)
38
+ {
36
39
  struct rb_exc_new2_arg *e = (struct rb_exc_new2_arg *)arg;
37
40
 
38
41
  return rb_exc_new2(e->error, e->msg);
39
42
  }
40
43
 
41
- VALUE rb_ary_new2_wrap(VALUE arg) {
44
+ VALUE ruby_libvirt_ary_new2_wrap(VALUE arg)
45
+ {
42
46
  return rb_ary_new2(*((int *)arg));
43
47
  }
44
48
 
45
- VALUE rb_ary_push_wrap(VALUE arg) {
46
- struct rb_ary_push_arg *e = (struct rb_ary_push_arg *)arg;
49
+ VALUE ruby_libvirt_ary_push_wrap(VALUE arg)
50
+ {
51
+ struct ruby_libvirt_ary_push_arg *e = (struct ruby_libvirt_ary_push_arg *)arg;
47
52
 
48
53
  return rb_ary_push(e->arr, e->value);
49
54
  }
50
55
 
51
- VALUE rb_str_new2_wrap(VALUE arg) {
52
- char **str = (char **)arg;
53
-
54
- return rb_str_new2(*str);
55
- }
56
-
57
- VALUE rb_ary_entry_wrap(VALUE arg) {
58
- struct rb_ary_entry_arg *e = (struct rb_ary_entry_arg *)arg;
56
+ VALUE ruby_libvirt_ary_store_wrap(VALUE arg)
57
+ {
58
+ struct ruby_libvirt_ary_store_arg *e = (struct ruby_libvirt_ary_store_arg *)arg;
59
59
 
60
- return rb_ary_entry(e->arr, e->elem);
61
- }
60
+ rb_ary_store(e->arr, e->index, e->elem);
62
61
 
63
- VALUE rb_ary_new_wrap(VALUE arg) {
64
- return rb_ary_new();
62
+ return Qnil;
65
63
  }
66
64
 
67
- VALUE rb_str_new_wrap(VALUE arg) {
68
- struct rb_str_new_arg *e = (struct rb_str_new_arg *)arg;
65
+ VALUE ruby_libvirt_str_new2_wrap(VALUE arg)
66
+ {
67
+ char **str = (char **)arg;
69
68
 
70
- return rb_str_new(e->val, e->size);
69
+ return rb_str_new2(*str);
71
70
  }
72
71
 
73
- VALUE rb_iv_set_wrap(VALUE arg) {
74
- struct rb_iv_set_arg *e = (struct rb_iv_set_arg *)arg;
72
+ VALUE ruby_libvirt_str_new_wrap(VALUE arg)
73
+ {
74
+ struct ruby_libvirt_str_new_arg *e = (struct ruby_libvirt_str_new_arg *)arg;
75
75
 
76
- return rb_iv_set(e->klass, e->member, e->value);
76
+ return rb_str_new(e->val, e->size);
77
77
  }
78
78
 
79
- VALUE rb_class_new_instance_wrap(VALUE arg) {
80
- struct rb_class_new_instance_arg *e = (struct rb_class_new_instance_arg *)arg;
81
-
82
- return rb_class_new_instance(e->argc, e->argv, e->klass);
83
- }
79
+ VALUE ruby_libvirt_hash_aset_wrap(VALUE arg)
80
+ {
81
+ struct ruby_libvirt_hash_aset_arg *e = (struct ruby_libvirt_hash_aset_arg *)arg;
84
82
 
85
- VALUE rb_string_value_cstr_wrap(VALUE arg) {
86
- return (VALUE)rb_string_value_cstr((VALUE *)arg);
83
+ return rb_hash_aset(e->hash, rb_str_new2(e->name), e->val);
87
84
  }
88
85
 
89
- /* Error handling */
90
- VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
86
+ void ruby_libvirt_raise_error_if(const int condition, VALUE error,
87
+ const char *method, virConnectPtr conn)
88
+ {
91
89
  VALUE ruby_errinfo;
92
90
  virErrorPtr err;
93
91
  char *msg;
@@ -95,15 +93,23 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
95
93
  struct rb_exc_new2_arg arg;
96
94
  int exception = 0;
97
95
 
98
- if (conn == NULL)
96
+ if (!condition) {
97
+ return;
98
+ }
99
+
100
+ if (conn == NULL) {
99
101
  err = virGetLastError();
100
- else
102
+ }
103
+ else {
101
104
  err = virConnGetLastError(conn);
105
+ }
102
106
 
103
- if (err != NULL && err->message != NULL)
107
+ if (err != NULL && err->message != NULL) {
104
108
  rc = asprintf(&msg, "Call to %s failed: %s", method, err->message);
105
- else
109
+ }
110
+ else {
106
111
  rc = asprintf(&msg, "Call to %s failed", method);
112
+ }
107
113
 
108
114
  if (rc < 0) {
109
115
  /* there's not a whole lot we can do here; try to raise an
@@ -113,10 +119,12 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
113
119
 
114
120
  arg.error = error;
115
121
  arg.msg = msg;
116
- ruby_errinfo = rb_protect(rb_exc_new2_wrap, (VALUE)&arg, &exception);
122
+ ruby_errinfo = rb_protect(ruby_libvirt_exc_new2_wrap, (VALUE)&arg,
123
+ &exception);
117
124
  free(msg);
118
- if (exception)
125
+ if (exception) {
119
126
  rb_jump_tag(exception);
127
+ }
120
128
 
121
129
  rb_iv_set(ruby_errinfo, "@libvirt_function_name", rb_str_new2(method));
122
130
 
@@ -124,80 +132,347 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
124
132
  rb_iv_set(ruby_errinfo, "@libvirt_code", INT2NUM(err->code));
125
133
  rb_iv_set(ruby_errinfo, "@libvirt_component", INT2NUM(err->domain));
126
134
  rb_iv_set(ruby_errinfo, "@libvirt_level", INT2NUM(err->level));
127
- if (err->message != NULL)
135
+ if (err->message != NULL) {
128
136
  rb_iv_set(ruby_errinfo, "@libvirt_message",
129
137
  rb_str_new2(err->message));
138
+ }
130
139
  }
131
140
 
132
- return ruby_errinfo;
141
+ rb_exc_raise(ruby_errinfo);
133
142
  };
134
143
 
135
- char *get_string_or_nil(VALUE arg)
144
+ char *ruby_libvirt_get_cstring_or_null(VALUE arg)
136
145
  {
137
- if (TYPE(arg) == T_NIL)
146
+ if (TYPE(arg) == T_NIL) {
138
147
  return NULL;
139
- else if (TYPE(arg) == T_STRING)
148
+ }
149
+ else if (TYPE(arg) == T_STRING) {
140
150
  return StringValueCStr(arg);
141
- else
142
- rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)"); return NULL;
151
+ }
152
+ else {
153
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)");
154
+ }
155
+
156
+ return NULL;
143
157
  }
144
158
 
145
- VALUE generic_new(VALUE klass, void *ptr, VALUE conn,
146
- RUBY_DATA_FUNC free_func) {
159
+ VALUE ruby_libvirt_new_class(VALUE klass, void *ptr, VALUE conn,
160
+ RUBY_DATA_FUNC free_func)
161
+ {
147
162
  VALUE result;
148
163
  result = Data_Wrap_Struct(klass, NULL, free_func, ptr);
149
164
  rb_iv_set(result, "@connection", conn);
150
165
  return result;
151
166
  }
152
167
 
153
- int is_symbol_or_proc(VALUE handle) {
168
+ int ruby_libvirt_is_symbol_or_proc(VALUE handle)
169
+ {
154
170
  return ((strcmp(rb_obj_classname(handle), "Symbol") == 0) ||
155
171
  (strcmp(rb_obj_classname(handle), "Proc") == 0));
156
172
  }
157
173
 
158
- /* this is an odd function, because it has massive side-effects. The first
159
- * tip that something is weird here should be the triple-starred list.
174
+ /* this is an odd function, because it has massive side-effects.
160
175
  * The intended usage of this function is after a list has been collected
161
176
  * from a libvirt list function, and now we want to make an array out of it.
162
177
  * However, it is possible that the act of creating an array causes an
163
178
  * exception, which would lead to a memory leak of the values we got from
164
179
  * libvirt. Therefore, this function not only wraps all of the relevant
165
- * calls with rb_protect, it also frees every individual entry in list
166
- * along with list itself.
180
+ * calls with rb_protect, it also frees every individual entry in list after
181
+ * it is done with it. Freeing list itself is left to the callers.
167
182
  */
168
- VALUE gen_list(int num, char ***list) {
183
+ VALUE ruby_libvirt_generate_list(int num, char **list)
184
+ {
169
185
  VALUE result;
170
186
  int exception = 0;
171
187
  int i, j;
172
- struct rb_ary_push_arg arg;
188
+ struct ruby_libvirt_ary_store_arg arg;
173
189
 
174
- result = rb_protect(rb_ary_new2_wrap, (VALUE)&num, &exception);
190
+ i = 0;
191
+
192
+ result = rb_protect(ruby_libvirt_ary_new2_wrap, (VALUE)&num, &exception);
175
193
  if (exception) {
176
- for (i = 0; i < num; i++)
177
- free((*list)[i]);
178
- xfree(*list);
179
- rb_jump_tag(exception);
194
+ goto exception;
180
195
  }
181
196
  for (i = 0; i < num; i++) {
182
197
  arg.arr = result;
183
- arg.value = rb_protect(rb_str_new2_wrap, (VALUE)&((*list)[i]),
184
- &exception);
198
+ arg.index = i;
199
+ arg.elem = rb_protect(ruby_libvirt_str_new2_wrap, (VALUE)&(list[i]),
200
+ &exception);
185
201
  if (exception) {
186
- for (j = i; j < num; j++)
187
- xfree((*list)[j]);
188
- xfree(*list);
189
- rb_jump_tag(exception);
202
+ goto exception;
190
203
  }
191
- rb_protect(rb_ary_push_wrap, (VALUE)&arg, &exception);
204
+ rb_protect(ruby_libvirt_ary_store_wrap, (VALUE)&arg, &exception);
192
205
  if (exception) {
193
- for (j = i; j < num; j++)
194
- xfree((*list)[j]);
195
- xfree(*list);
196
- rb_jump_tag(exception);
206
+ goto exception;
197
207
  }
198
- xfree((*list)[i]);
208
+ xfree(list[i]);
199
209
  }
200
- xfree(*list);
201
210
 
202
211
  return result;
212
+
213
+ exception:
214
+ for (j = i; j < num; j++) {
215
+ xfree(list[j]);
216
+ }
217
+ rb_jump_tag(exception);
218
+
219
+ /* not needed, but here to shut the compiler up */
220
+ return Qnil;
221
+ }
222
+
223
+ void ruby_libvirt_typed_params_to_hash(void *voidparams, int i, VALUE hash)
224
+ {
225
+ virTypedParameterPtr params = (virTypedParameterPtr)voidparams;
226
+ VALUE val;
227
+
228
+ switch (params[i].type) {
229
+ case VIR_TYPED_PARAM_INT:
230
+ val = INT2NUM(params[i].value.i);
231
+ break;
232
+ case VIR_TYPED_PARAM_UINT:
233
+ val = UINT2NUM(params[i].value.ui);
234
+ break;
235
+ case VIR_TYPED_PARAM_LLONG:
236
+ val = LL2NUM(params[i].value.l);
237
+ break;
238
+ case VIR_TYPED_PARAM_ULLONG:
239
+ val = ULL2NUM(params[i].value.ul);
240
+ break;
241
+ case VIR_TYPED_PARAM_DOUBLE:
242
+ val = rb_float_new(params[i].value.d);
243
+ break;
244
+ case VIR_TYPED_PARAM_BOOLEAN:
245
+ val = (params[i].value.b == 0) ? Qfalse : Qtrue;
246
+ break;
247
+ case VIR_TYPED_PARAM_STRING:
248
+ val = rb_str_new2(params[i].value.s);
249
+ break;
250
+ default:
251
+ rb_raise(rb_eArgError, "Invalid parameter type");
252
+ }
253
+
254
+ rb_hash_aset(hash, rb_str_new2(params[i].field), val);
255
+ }
256
+
257
+ VALUE ruby_libvirt_get_parameters(VALUE d, unsigned int flags, void *opaque,
258
+ unsigned int typesize,
259
+ char *(*nparams_cb)(VALUE d,
260
+ unsigned int flags,
261
+ void *opaque,
262
+ int *nparams),
263
+ char *(*get_cb)(VALUE d, unsigned int flags,
264
+ void *voidparams,
265
+ int *nparams, void *opaque),
266
+ void (*hash_set)(void *voidparams, int i,
267
+ VALUE result))
268
+ {
269
+ int nparams = 0;
270
+ void *params;
271
+ VALUE result;
272
+ char *errname;
273
+ int i;
274
+
275
+ errname = nparams_cb(d, flags, opaque, &nparams);
276
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
277
+ ruby_libvirt_connect_get(d));
278
+
279
+ result = rb_hash_new();
280
+
281
+ if (nparams == 0) {
282
+ return result;
283
+ }
284
+
285
+ params = alloca(typesize * nparams);
286
+
287
+ errname = get_cb(d, flags, params, &nparams, opaque);
288
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
289
+ ruby_libvirt_connect_get(d));
290
+
291
+ for (i = 0; i < nparams; i++) {
292
+ hash_set(params, i, result);
293
+ }
294
+
295
+ return result;
296
+ }
297
+
298
+ VALUE ruby_libvirt_get_typed_parameters(VALUE d, unsigned int flags,
299
+ void *opaque,
300
+ char *(*nparams_cb)(VALUE d,
301
+ unsigned int flags,
302
+ void *opaque,
303
+ int *nparams),
304
+ char *(*get_cb)(VALUE d,
305
+ unsigned int flags,
306
+ void *params,
307
+ int *nparams,
308
+ void *opaque))
309
+ {
310
+ return ruby_libvirt_get_parameters(d, flags, opaque,
311
+ sizeof(virTypedParameter), nparams_cb,
312
+ get_cb,
313
+ ruby_libvirt_typed_params_to_hash);
314
+ }
315
+
316
+ void ruby_libvirt_assign_hash_and_flags(VALUE in, VALUE *hash, VALUE *flags)
317
+ {
318
+ if (TYPE(in) == T_HASH) {
319
+ *hash = in;
320
+ *flags = INT2NUM(0);
321
+ }
322
+ else if (TYPE(in) == T_ARRAY) {
323
+ if (RARRAY_LEN(in) != 2) {
324
+ rb_raise(rb_eArgError, "wrong number of arguments (%ld for 1 or 2)",
325
+ RARRAY_LEN(in));
326
+ }
327
+ *hash = rb_ary_entry(in, 0);
328
+ *flags = rb_ary_entry(in, 1);
329
+ }
330
+ else {
331
+ rb_raise(rb_eTypeError, "wrong argument type (expected Hash or Array)");
332
+ }
333
+ }
334
+
335
+ int ruby_libvirt_typed_parameter_assign(VALUE key, VALUE val, VALUE in)
336
+ {
337
+ struct ruby_libvirt_parameter_assign_args *args = (struct ruby_libvirt_parameter_assign_args *)in;
338
+ char *keyname;
339
+ unsigned int i;
340
+ int found;
341
+
342
+ keyname = StringValueCStr(key);
343
+
344
+ found = 0;
345
+ for (i = 0; i < args->num_allowed; i++) {
346
+ if (strcmp(args->allowed[i].name, keyname) == 0) {
347
+ args->params[args->i].type = args->allowed[i].type;
348
+ switch (args->params[args->i].type) {
349
+ case VIR_TYPED_PARAM_INT:
350
+ args->params[i].value.i = NUM2INT(val);
351
+ break;
352
+ case VIR_TYPED_PARAM_UINT:
353
+ args->params[i].value.ui = NUM2UINT(val);
354
+ break;
355
+ case VIR_TYPED_PARAM_LLONG:
356
+ args->params[i].value.l = NUM2LL(val);
357
+ break;
358
+ case VIR_TYPED_PARAM_ULLONG:
359
+ args->params[args->i].value.ul = NUM2ULL(val);
360
+ break;
361
+ case VIR_TYPED_PARAM_DOUBLE:
362
+ args->params[i].value.d = NUM2DBL(val);
363
+ break;
364
+ case VIR_TYPED_PARAM_BOOLEAN:
365
+ args->params[i].value.b = (val == Qtrue) ? 1 : 0;
366
+ break;
367
+ case VIR_TYPED_PARAM_STRING:
368
+ args->params[args->i].value.s = StringValueCStr(val);
369
+ break;
370
+ default:
371
+ rb_raise(rb_eArgError, "Invalid parameter type");
372
+ }
373
+ strncpy(args->params[args->i].field, keyname,
374
+ VIR_TYPED_PARAM_FIELD_LENGTH);
375
+ (args->i)++;
376
+ found = 1;
377
+ break;
378
+ }
379
+ }
380
+
381
+ if (!found) {
382
+ rb_raise(rb_eArgError, "Unknown key %s", keyname);
383
+ }
384
+
385
+ return ST_CONTINUE;
386
+ }
387
+
388
+ VALUE ruby_libvirt_set_typed_parameters(VALUE d, VALUE input,
389
+ unsigned int flags, void *opaque,
390
+ struct ruby_libvirt_typed_param *allowed,
391
+ unsigned int num_allowed,
392
+ char *(*set_cb)(VALUE d,
393
+ unsigned int flags,
394
+ virTypedParameterPtr params,
395
+ int nparams,
396
+ void *opaque))
397
+ {
398
+ char *errname;
399
+ struct ruby_libvirt_parameter_assign_args args;
400
+ unsigned long hashsize;
401
+
402
+ /* make sure input is a hash */
403
+ Check_Type(input, T_HASH);
404
+
405
+ hashsize = RHASH_SIZE(input);
406
+
407
+ if (hashsize == 0) {
408
+ return Qnil;
409
+ }
410
+
411
+ args.allowed = allowed;
412
+ args.num_allowed = num_allowed;
413
+ args.params = alloca(sizeof(virTypedParameter) * hashsize);
414
+ args.i = 0;
415
+
416
+ rb_hash_foreach(input, ruby_libvirt_typed_parameter_assign, (VALUE)&args);
417
+
418
+ errname = set_cb(d, flags, args.params, args.i, opaque);
419
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
420
+ ruby_libvirt_connect_get(d));
421
+
422
+ return Qnil;
423
+ }
424
+
425
+ unsigned int ruby_libvirt_value_to_uint(VALUE in)
426
+ {
427
+ if (NIL_P(in)) {
428
+ return 0;
429
+ }
430
+
431
+ return NUM2UINT(in);
432
+ }
433
+
434
+ int ruby_libvirt_value_to_int(VALUE in)
435
+ {
436
+ if (NIL_P(in)) {
437
+ return 0;
438
+ }
439
+
440
+ return NUM2INT(in);
441
+ }
442
+
443
+ unsigned long ruby_libvirt_value_to_ulong(VALUE in)
444
+ {
445
+ if (NIL_P(in)) {
446
+ return 0;
447
+ }
448
+
449
+ return NUM2ULONG(in);
450
+ }
451
+
452
+ unsigned long long ruby_libvirt_value_to_ulonglong(VALUE in)
453
+ {
454
+ if (NIL_P(in)) {
455
+ return 0;
456
+ }
457
+
458
+ return NUM2ULL(in);
459
+ }
460
+
461
+ int ruby_libvirt_get_maxcpus(virConnectPtr conn)
462
+ {
463
+ int maxcpu = -1;
464
+ virNodeInfo nodeinfo;
465
+
466
+ #if HAVE_VIRNODEGETCPUMAP
467
+ maxcpu = virNodeGetCPUMap(conn, NULL, NULL, 0);
468
+ #endif
469
+ if (maxcpu < 0) {
470
+ /* fall back to nodeinfo */
471
+ ruby_libvirt_raise_error_if(virNodeGetInfo(conn, &nodeinfo) < 0,
472
+ e_RetrieveError, "virNodeGetInfo", conn);
473
+
474
+ maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
475
+ }
476
+
477
+ return maxcpu;
203
478
  }