net_app_manageability 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,147 @@
1
+ require 'net_app_manageability'
2
+ require 'logger'
3
+ # require '../VMwareWebService/MiqVim'
4
+ # require '../VMwareWebService/MiqVimBroker'
5
+
6
+ GB = 1024 * 1024 * 1024
7
+
8
+ NAS_SERVER = raise "please define"
9
+ NAS_USERNAME = ""
10
+ NAS_PASSWORD = ""
11
+
12
+ VIM_SERVER = raise "please define"
13
+ VIM_USERNAME = ""
14
+ VIM_PASSWORD = ""
15
+
16
+ CONTAINING_AGGR = "aggr1"
17
+ NEW_VOLUME = "api_test_vol1"
18
+ VOL_SIZE_GB = 10
19
+ NFS_PATH = "/vol/#{NEW_VOLUME}"
20
+
21
+ TARGET_HOSTS = raise "please define array of host names"
22
+ LOCAL_PATH = NEW_VOLUME.tr('_', '-') # Datastore names cannot contain underscores
23
+ ACCESS_MODE = "readWrite"
24
+
25
+ broker = MiqVimBroker.new(:client)
26
+ vim = broker.getMiqVim(VIM_SERVER, VIM_USERNAME, VIM_PASSWORD)
27
+
28
+ puts "vim.class: #{vim.class}"
29
+ puts "#{vim.server} is #{(vim.isVirtualCenter? ? 'VC' : 'ESX')}"
30
+ puts "API version: #{vim.apiVersion}"
31
+ puts
32
+
33
+ puts "Connecting to NAS server: #{NAS_SERVER}..."
34
+ netapp_client = NetAppManageability::Client.new do
35
+ server NAS_SERVER
36
+ auth_style NetAppManageability::Client::NA_STYLE_LOGIN_PASSWORD
37
+ username NAS_USERNAME
38
+ password NAS_PASSWORD
39
+ end
40
+ puts "done."
41
+ puts
42
+
43
+ #
44
+ # Ensure the volume doesn't already exist.
45
+ #
46
+ puts "Checking to see if volume #{NEW_VOLUME} already exists..."
47
+ err = false
48
+ begin
49
+ netapp_client.volume_list_info(:volume, NEW_VOLUME)
50
+ err = true
51
+ rescue
52
+ # Ignore expected failure
53
+ end
54
+ raise "Volume #{NEW_VOLUME} already exists" if err
55
+ puts "Volume #{NEW_VOLUME} does not exist"
56
+ puts
57
+
58
+ #
59
+ # Make sure there's enough free space in the aggregate for the new volume.
60
+ #
61
+ puts "Checking space on containing aggregate: #{CONTAINING_AGGR}"
62
+ rv = netapp_client.aggr_list_info(:aggregate, CONTAINING_AGGR)
63
+ aggr_free_space = rv.aggregates.aggr_info.size_available.to_i
64
+ raise "Insufficient free space in #{CONTAINING_AGGR}: #{aggr_free_space}" if aggr_free_space < VOL_SIZE_GB * GB
65
+ puts "Containing aggregate: #{CONTAINING_AGGR} has sufficient free space"
66
+ puts
67
+
68
+ #
69
+ # The creation of the volume will result in the creation a qtree entry for its root.
70
+ # If we want to base a VMware datastore on the volume's NFS share, the security style of
71
+ # its corresponding qtree must not be 'ntfs'.
72
+ #
73
+ # Unfortunately, the API doesn't provide a way to specify this value or change it after the fact.
74
+ # The security style is always set to the value of the 'wafl.default_security_style' option.
75
+ # So we must ensure that this value is set to either 'unix' or 'mixed' before the volume is created.
76
+ #
77
+ rv = netapp_client.options_get(:name, 'wafl.default_security_style')
78
+ if rv.value == "ntfs"
79
+ puts "Default security style is ntfs, resetting it to mixed"
80
+ netapp_client.options_set do
81
+ name 'wafl.default_security_style'
82
+ value 'mixed'
83
+ end
84
+ end
85
+
86
+ #
87
+ # Create the volume within the given aggregate.
88
+ #
89
+ puts "Creating volume: #{NEW_VOLUME} in aggregate: #{CONTAINING_AGGR} on NAS server: #{NAS_SERVER}..."
90
+ rv = netapp_client.volume_create do
91
+ containing_aggr_name CONTAINING_AGGR
92
+ volume NEW_VOLUME
93
+ space_reserve "none"
94
+ size "#{VOL_SIZE_GB}g"
95
+ end
96
+ puts "done."
97
+ puts
98
+
99
+ puts "Updating rules for export: #{NEW_VOLUME}..."
100
+ #
101
+ # Get the export rules for the new volume's NFS share.
102
+ #
103
+ rv = netapp_client.nfs_exportfs_list_rules(:pathname, NFS_PATH)
104
+
105
+ #
106
+ # Ensure the target hosts have root access to the share.
107
+ #
108
+ rules = rv.rules
109
+ rules.exports_rule_info.root = NetAppManageability::NAMHash.new do
110
+ exports_hostname_info NetAppManageability::NAMArray.new do
111
+ TARGET_HOSTS.each do |rh|
112
+ push NetAppManageability::NAMHash.new { name rh }
113
+ end
114
+ end
115
+ end
116
+
117
+ #
118
+ # Update the export rules with the root access host list.
119
+ #
120
+ rv = netapp_client.nfs_exportfs_modify_rule do
121
+ persistent true
122
+ rule rules
123
+ end
124
+ puts "done."
125
+ puts
126
+
127
+ #
128
+ # Attach the new NFS share as a datastore on each of the desired hosts.
129
+ #
130
+ TARGET_HOSTS.each do |th|
131
+ begin
132
+ miqHost = vim.getVimHost(th)
133
+ puts "Got object for host: #{miqHost.name}"
134
+ rescue => err
135
+ puts "Could not find host: #{th}"
136
+ next
137
+ end
138
+
139
+ miqDss = miqHost.datastoreSystem
140
+
141
+ puts
142
+ puts "Creating datastore: #{LOCAL_PATH} on host: #{th}..."
143
+ miqDss.createNasDatastore(NAS_SERVER, NFS_PATH, LOCAL_PATH, ACCESS_MODE)
144
+ miqHost.release
145
+ puts "done."
146
+ puts
147
+ end
@@ -0,0 +1,20 @@
1
+ require 'mkmf'
2
+
3
+ if Gem.win_platform?
4
+ $LDFLAGS = "-static"
5
+ # $DLDFLAGS = $DLDFLAGS.split(',').delete_if {|f| f == "--export-all"}.join(',')
6
+
7
+ libs = %w(ws2_32 libadt libxml libeay32 ssleay32 odbc32 odbccp32 libnetapp)
8
+
9
+ sdk_base = "C:/netapp-manageability-sdk/netapp-manageability-sdk-4.0P1"
10
+ dir_config("netapp-manageability-sdk", nil, File.join(sdk_base, "lib/nt"))
11
+ else
12
+ libs = %w(z xml pthread nsl m crypto ssl dl rt adt netapp)
13
+
14
+ dir_config("netapp-manageability-sdk")
15
+ end
16
+
17
+ have_header("netapp_api.h")
18
+ libs.each { |lib| have_library(lib) }
19
+
20
+ create_makefile("net_app_manageability/net_app_manageability")
@@ -0,0 +1,543 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <stdarg.h>
4
+
5
+ #include "ruby.h"
6
+
7
+ #ifdef HAVE_NETAPP_API_H
8
+ #include "netapp_api.h"
9
+
10
+ static void marshal_args(na_elem_t *elem, VALUE rObj);
11
+
12
+ static const char *module_name = "NetAppManageability";
13
+ static const char *class_name = "API";
14
+ static const char *exception_name = "Error";
15
+ static const char *hash_class_name = "NAMHash";
16
+
17
+ static VALUE mNetAppManageability;
18
+ static VALUE cAPI;
19
+ static VALUE rb_eAPIError;
20
+ static VALUE cNAMHash;
21
+
22
+ static ID id_to_s;
23
+ static ID id_logger;
24
+ static ID id_verbose;
25
+ static ID id_wire_dump;
26
+ static ID id_info;
27
+ static ID id_debug;
28
+
29
+ /*
30
+ * Create a class constant based on the given object-like macro.
31
+ */
32
+ #define INTDEF2CONST(klass, intdef) \
33
+ rb_define_const(klass, #intdef, INT2NUM(intdef))
34
+
35
+ #define INT2BOOL(v) \
36
+ (v ? Qtrue : Qfalse)
37
+
38
+ #define LOG_VERBOSE \
39
+ (RTEST(rb_funcall(cAPI, id_verbose, 0)) ? id_info : id_debug)
40
+
41
+ #define WIRE_DUMP \
42
+ (RTEST(rb_funcall(cAPI, id_wire_dump, 0)))
43
+
44
+ static void
45
+ server_free(void *p) {
46
+ (void)na_server_close((na_server_t *)p);
47
+ }
48
+
49
+ static VALUE
50
+ obj_to_s(VALUE obj) {
51
+ return rb_funcall(obj, id_to_s, 0);
52
+ }
53
+
54
+ static void
55
+ rb_log(ID level, const char *fmt, ...) {
56
+ va_list ap;
57
+ VALUE logger;
58
+ char *p, *np;
59
+ int n, size = 128;
60
+
61
+ logger = rb_funcall(cAPI, id_logger, 0);
62
+ if (logger == Qnil) {
63
+ return;
64
+ }
65
+
66
+ if ((p = malloc(size)) == NULL) {
67
+ return;
68
+ }
69
+
70
+ va_start(ap, fmt);
71
+ n = vsnprintf(p, size, fmt, ap);
72
+ va_end(ap);
73
+
74
+ if (n >= size) {
75
+ size = n + 1;
76
+ if ((np = realloc(p, size)) == NULL) {
77
+ free(p);
78
+ return;
79
+ }
80
+ p = np;
81
+
82
+ va_start(ap, fmt);
83
+ vsnprintf(p, size, fmt, ap);
84
+ va_end(ap);
85
+ }
86
+
87
+ rb_funcall(logger, level, 1, rb_str_new2(p));
88
+ free(p);
89
+ }
90
+
91
+ /*
92
+ * The "server_open" class method.
93
+ */
94
+ static VALUE
95
+ server_open(VALUE rSelf, VALUE rServer, VALUE rMajor, VALUE rMinor) {
96
+ int cMajor;
97
+ int cMinor;
98
+ char *cServer;
99
+ na_server_t *s;
100
+
101
+ cServer = StringValuePtr(rServer);
102
+ cMajor = NUM2UINT(rMajor);
103
+ cMinor = NUM2UINT(rMinor);
104
+
105
+ rb_log(LOG_VERBOSE, "%s.server_open [calling]: server = %s, major = %d, minor = %d", class_name, cServer, cMajor, cMinor);
106
+ if ((s = na_server_open(cServer, cMajor, cMinor)) == NULL) {
107
+ rb_raise(rb_eAPIError, "%s.server_open: could not open connection to server %s", class_name, cServer);
108
+ }
109
+ rb_log(LOG_VERBOSE, "%s.server_open [returned]: server = %s, major = %d, minor = %d", class_name, cServer, cMajor, cMinor);
110
+ return Data_Wrap_Struct(rSelf, 0, server_free, s);
111
+ }
112
+
113
+ /*
114
+ * The "server_get_style" class method.
115
+ */
116
+ static VALUE
117
+ server_get_style(VALUE rSelf, VALUE rServer) {
118
+ na_server_t *s;
119
+ na_style_t rv;
120
+
121
+ Data_Get_Struct(rServer, na_server_t, s);
122
+ rb_log(LOG_VERBOSE, "%s.server_get_style [calling]", class_name);
123
+ rv = na_server_get_style(s);
124
+ rb_log(LOG_VERBOSE, "%s.server_get_style [returned]: style = %d", class_name, rv);
125
+ return INT2NUM(rv);
126
+ }
127
+
128
+ /*
129
+ * The "server_get_transport_type" class method.
130
+ */
131
+ static VALUE
132
+ server_get_transport_type(VALUE rSelf, VALUE rServer) {
133
+ na_server_t *s;
134
+ na_server_transport_t rv;
135
+
136
+ Data_Get_Struct(rServer, na_server_t, s);
137
+ rb_log(LOG_VERBOSE, "%s.na_server_get_transport_type [calling]", class_name);
138
+ rv = na_server_get_transport_type(s);
139
+ rb_log(LOG_VERBOSE, "%s.na_server_get_transport_type [returned]: type = %d", class_name, rv);
140
+ return INT2NUM(rv);
141
+ }
142
+
143
+ /*
144
+ * The "server_get_port" class method.
145
+ */
146
+ static VALUE
147
+ server_get_port(VALUE rSelf, VALUE rServer) {
148
+ na_server_t *s;
149
+ int rv;
150
+
151
+ Data_Get_Struct(rServer, na_server_t, s);
152
+ rb_log(LOG_VERBOSE, "%s.server_get_port [calling]", class_name);
153
+ rv = na_server_get_port(s);
154
+ rb_log(LOG_VERBOSE, "%s.server_get_port [returned]: port = %d", class_name, rv);
155
+ return INT2NUM(rv);
156
+ }
157
+
158
+ /*
159
+ * The "server_get_timeout" class method.
160
+ */
161
+ static VALUE
162
+ server_get_timeout(VALUE rSelf, VALUE rServer) {
163
+ na_server_t *s;
164
+ int rv;
165
+
166
+ Data_Get_Struct(rServer, na_server_t, s);
167
+ rb_log(LOG_VERBOSE, "%s.server_get_timeout [calling]", class_name);
168
+ rv = na_server_get_timeout(s);
169
+ rb_log(LOG_VERBOSE, "%s.server_get_timeout [returned]: timeout = %d", class_name, rv);
170
+ return INT2NUM(rv);
171
+ }
172
+
173
+ /*
174
+ * The "server_style" class method.
175
+ */
176
+ static VALUE
177
+ server_style(VALUE rSelf, VALUE rServer, VALUE rStyle) {
178
+ na_server_t *s;
179
+ na_style_t cStyle;
180
+
181
+ cStyle = NUM2UINT(rStyle);
182
+ Data_Get_Struct(rServer, na_server_t, s);
183
+ rb_log(LOG_VERBOSE, "%s.server_style [calling]: style = %d", class_name, cStyle);
184
+ na_server_style(s, cStyle);
185
+ rb_log(LOG_VERBOSE, "%s.server_style [returned]", class_name);
186
+ return Qnil;
187
+ }
188
+
189
+ /*
190
+ * The "server_set_debugstyle" class method.
191
+ */
192
+ static VALUE
193
+ server_set_debugstyle(VALUE rSelf, VALUE rServer, VALUE rStyle) {
194
+ na_server_t *s;
195
+ na_style_t cStyle;
196
+
197
+ cStyle = NUM2UINT(rStyle);
198
+ Data_Get_Struct(rServer, na_server_t, s);
199
+ rb_log(LOG_VERBOSE, "%s.na_server_set_debugstyle [calling]: style = %d", class_name, cStyle);
200
+ na_server_set_debugstyle(s, cStyle);
201
+ rb_log(LOG_VERBOSE, "%s.na_server_set_debugstyle [returned]", class_name);
202
+ return Qnil;
203
+ }
204
+
205
+ /*
206
+ * The "server_set_server_type" class method.
207
+ */
208
+ static VALUE
209
+ server_set_server_type(VALUE rSelf, VALUE rServer, VALUE rType) {
210
+ na_server_t *s;
211
+ int cType, rv;
212
+
213
+ cType = NUM2UINT(rType);
214
+ Data_Get_Struct(rServer, na_server_t, s);
215
+ rb_log(LOG_VERBOSE, "%s.server_set_server_type [calling]: type = %d", class_name, cType);
216
+ rv = na_server_set_server_type(s, cType);
217
+ rb_log(LOG_VERBOSE, "%s.server_set_server_type [returned]: rv = %d", class_name, rv);
218
+ return INT2BOOL(rv);
219
+ }
220
+
221
+ /*
222
+ * The "server_set_transport_type" class method.
223
+ */
224
+ static VALUE
225
+ server_set_transport_type(VALUE rSelf, VALUE rServer, VALUE rType) {
226
+ na_server_t *s;
227
+ int cType, rv;
228
+
229
+ cType = NUM2UINT(rType);
230
+ Data_Get_Struct(rServer, na_server_t, s);
231
+ rb_log(LOG_VERBOSE, "%s.server_set_transport_type [calling]: type = %d", class_name, cType);
232
+ rv = na_server_set_transport_type(s, cType, 0);
233
+ rb_log(LOG_VERBOSE, "%s.server_set_transport_type [returned]: rv = %d", class_name, rv);
234
+ return INT2BOOL(rv);
235
+ }
236
+
237
+ /*
238
+ * The "server_set_port" class method.
239
+ */
240
+ static VALUE
241
+ server_set_port(VALUE rSelf, VALUE rServer, VALUE rPort) {
242
+ na_server_t *s;
243
+ int cPort, rv;
244
+
245
+ cPort = NUM2UINT(rPort);
246
+ Data_Get_Struct(rServer, na_server_t, s);
247
+ rb_log(LOG_VERBOSE, "%s.server_set_port [calling]: port = %d", class_name, cPort);
248
+ rv = na_server_set_port(s, cPort);
249
+ rb_log(LOG_VERBOSE, "%s.server_set_port [returned]: rv = %d", class_name, rv);
250
+ return INT2BOOL(rv);
251
+ }
252
+
253
+ /*
254
+ * The "server_set_timeout" class method.
255
+ */
256
+ static VALUE
257
+ server_set_timeout(VALUE rSelf, VALUE rServer, VALUE rTimeout) {
258
+ na_server_t *s;
259
+ int cTimeout, rv;
260
+
261
+ cTimeout = NUM2UINT(rTimeout);
262
+ Data_Get_Struct(rServer, na_server_t, s);
263
+ rb_log(LOG_VERBOSE, "%s.server_set_timeout [calling]: timeout = %d", class_name, cTimeout);
264
+ rv = na_server_set_timeout(s, cTimeout);
265
+ rb_log(LOG_VERBOSE, "%s.server_set_timeout [returned]: rv = %d", class_name, rv);
266
+ return INT2BOOL(rv);
267
+ }
268
+
269
+ /*
270
+ * The "server_adminuser" class method.
271
+ */
272
+ static VALUE
273
+ server_adminuser(VALUE rSelf, VALUE rServer, VALUE rLogin, VALUE rPwd) {
274
+ na_server_t *s;
275
+ char *cLogin;
276
+ char *cPwd;
277
+ int rv;
278
+
279
+ cLogin = StringValuePtr(rLogin);
280
+ cPwd = StringValuePtr(rPwd);
281
+ Data_Get_Struct(rServer, na_server_t, s);
282
+ rb_log(LOG_VERBOSE, "%s.server_adminuser [calling]: login = %s", class_name, cLogin);
283
+ rv = na_server_adminuser(s, cLogin, cPwd);
284
+ rb_log(LOG_VERBOSE, "%s.server_adminuser [returned]: rv = %d", class_name, rv);
285
+ return INT2BOOL(rv);
286
+ }
287
+
288
+ typedef struct {
289
+ char *key;
290
+ na_elem_t *elem;
291
+ } array_iter_arg_t;
292
+
293
+ static VALUE
294
+ array_iter_func(VALUE ae, array_iter_arg_t *aia) {
295
+ na_elem_t *ce;
296
+
297
+ ce = na_elem_new(aia->key);
298
+ na_child_add(aia->elem, ce);
299
+ marshal_args(ce, ae);
300
+
301
+ return Qnil;
302
+ }
303
+
304
+ static int
305
+ hash_iter_func(VALUE rKey, VALUE val, na_elem_t *elem) {
306
+ char *cKey;
307
+ na_elem_t *ce;
308
+
309
+ if (TYPE(rKey) == T_SYMBOL) {
310
+ VALUE tv = obj_to_s(rKey);
311
+ cKey = StringValuePtr(tv);
312
+ }
313
+ else if (TYPE(rKey) == T_STRING) {
314
+ cKey = StringValuePtr(rKey);
315
+ }
316
+ else {
317
+ rb_raise(rb_eTypeError, "%s.hash_iter_func: hash key must be a string or symbol", class_name);
318
+ }
319
+
320
+ if (TYPE(val) == T_ARRAY) {
321
+ array_iter_arg_t aia;
322
+ aia.key = cKey;
323
+ aia.elem = elem;
324
+ rb_iterate(rb_each, val, array_iter_func, (VALUE)&aia);
325
+ return 0;
326
+ }
327
+
328
+ ce = na_elem_new(cKey);
329
+ na_child_add(elem, ce);
330
+ marshal_args(ce, val);
331
+
332
+ return 0;
333
+ }
334
+
335
+ static void
336
+ marshal_args(na_elem_t *elem, VALUE rObj) {
337
+ VALUE rsv;
338
+ char *csv;
339
+
340
+ switch ( TYPE(rObj) ) {
341
+ case T_NIL:
342
+ return;
343
+
344
+ case T_HASH:
345
+ rb_hash_foreach(rObj, hash_iter_func, (VALUE)elem);
346
+ break;
347
+
348
+ case T_ARRAY:
349
+ break;
350
+
351
+ case T_STRING:
352
+ csv = StringValuePtr(rObj);
353
+ na_elem_set_content(elem, csv);
354
+ break;
355
+
356
+ case T_FIXNUM:
357
+ case T_BIGNUM:
358
+ case T_TRUE:
359
+ case T_FALSE:
360
+ rsv = obj_to_s(rObj);
361
+ csv = StringValuePtr(rsv);
362
+ na_elem_set_content(elem, csv);
363
+ break;
364
+
365
+ default:
366
+ rb_raise(rb_eTypeError, "%s.marshal_args: Type = %d, not valid value", class_name, TYPE(rObj));
367
+ break;
368
+ }
369
+ }
370
+
371
+ static VALUE
372
+ nam_hash_new(void) {
373
+ return rb_class_new_instance(0, 0, cNAMHash);
374
+ }
375
+
376
+ static VALUE
377
+ unmarshal_elem(na_elem_t *elem) {
378
+ na_elem_t *ce;
379
+ na_elem_iter_t iter;
380
+ VALUE rv, hv, ta, cn;
381
+
382
+ if (!na_elem_has_children(elem)) {
383
+ return rb_str_new2(na_elem_get_content(elem));
384
+ }
385
+
386
+ rv = nam_hash_new();
387
+
388
+ for (iter = na_child_iterator(elem); (ce = na_iterator_next(&iter)) != NULL;) {
389
+ cn = rb_str_new2(na_elem_get_name(ce));
390
+
391
+ if ((hv = rb_hash_aref(rv, cn)) == Qnil) {
392
+ rb_hash_aset(rv, cn, unmarshal_elem(ce));
393
+ continue;
394
+ }
395
+
396
+ if (TYPE(hv) != T_ARRAY) {
397
+ ta = rb_ary_new();
398
+ rb_ary_push(ta, hv);
399
+ rb_hash_aset(rv, cn, ta);
400
+ }
401
+ else {
402
+ ta = hv;
403
+ }
404
+ rb_ary_push(ta, unmarshal_elem(ce));
405
+ }
406
+ return rv;
407
+ }
408
+
409
+ typedef struct {
410
+ na_server_t *s;
411
+ na_elem_t *in;
412
+ na_elem_t *out;
413
+ VALUE rArgs;
414
+ char *cCmd;
415
+ } invoke_protect_arg_t;
416
+
417
+ static VALUE
418
+ invoke_protect(VALUE arg) {
419
+ char *xml;
420
+
421
+ invoke_protect_arg_t *ipap = (invoke_protect_arg_t *)arg;
422
+
423
+ ipap->in = na_elem_new(ipap->cCmd);
424
+ marshal_args(ipap->in, ipap->rArgs);
425
+
426
+ if (WIRE_DUMP && ((xml = na_elem_sprintf(ipap->in)) != NULL)) {
427
+ rb_log(LOG_VERBOSE, "%s.server_invoke: REQUEST START", class_name);
428
+ rb_log(LOG_VERBOSE, "%s", xml);
429
+ rb_log(LOG_VERBOSE, "%s.server_invoke: REQUEST END", class_name);
430
+ na_free(xml);
431
+ }
432
+
433
+ ipap->out = na_server_invoke_elem(ipap->s, ipap->in);
434
+
435
+ if (WIRE_DUMP && ((xml = na_elem_sprintf(ipap->out)) != NULL)) {
436
+ rb_log(LOG_VERBOSE, "%s.server_invoke: RESPONSE START", class_name);
437
+ rb_log(LOG_VERBOSE, "%s", xml);
438
+ rb_log(LOG_VERBOSE, "%s.server_invoke: RESPONSE END", class_name);
439
+ na_free(xml);
440
+ }
441
+
442
+ if (na_results_status(ipap->out) != NA_OK) {
443
+ rb_raise(rb_eAPIError, "%s.server_invoke: Error %d: %s", class_name,
444
+ na_results_errno(ipap->out),
445
+ na_results_reason(ipap->out));
446
+ }
447
+ return unmarshal_elem(ipap->out);
448
+ }
449
+
450
+ /*
451
+ * The "server_invoke" class method.
452
+ */
453
+ static VALUE
454
+ server_invoke(VALUE rSelf, VALUE rServer, VALUE rCmd, VALUE rArgs) {
455
+ invoke_protect_arg_t ipa;
456
+ VALUE rv;
457
+ int exception;
458
+
459
+ ipa.rArgs = rArgs;
460
+ ipa.in = NULL;
461
+ ipa.out = NULL;
462
+ ipa.cCmd = StringValuePtr(rCmd);
463
+ Data_Get_Struct(rServer, na_server_t, ipa.s);
464
+
465
+ rb_log(LOG_VERBOSE, "%s.server_invoke [calling]: command = %s", class_name, ipa.cCmd);
466
+ rv = rb_protect(invoke_protect, (VALUE)&ipa, &exception);
467
+ rb_log(LOG_VERBOSE, "%s.server_invoke [returned]: command = %s", class_name, ipa.cCmd);
468
+
469
+ if (ipa.in != NULL) na_elem_free(ipa.in);
470
+ if (ipa.out != NULL) na_elem_free(ipa.out);
471
+
472
+ if (exception) {
473
+ rb_jump_tag(exception);
474
+ }
475
+ return rv;
476
+ }
477
+ #endif
478
+
479
+ /*
480
+ * Initialize the class.
481
+ */
482
+ void Init_net_app_manageability() {
483
+ #ifdef HAVE_NETAPP_API_H
484
+ char err[256];
485
+
486
+ mNetAppManageability = rb_const_get(rb_cObject, rb_intern(module_name));
487
+ cAPI = rb_const_get(mNetAppManageability, rb_intern(class_name));
488
+
489
+ /*
490
+ * Define class methods.
491
+ */
492
+ rb_define_singleton_method(cAPI, "server_open", server_open, 3);
493
+ rb_define_singleton_method(cAPI, "server_get_style", server_get_style, 1);
494
+ rb_define_singleton_method(cAPI, "server_get_transport_type", server_get_transport_type, 1);
495
+ rb_define_singleton_method(cAPI, "server_get_port", server_get_port, 1);
496
+ rb_define_singleton_method(cAPI, "server_get_timeout", server_get_timeout, 1);
497
+ rb_define_singleton_method(cAPI, "server_style", server_style, 2);
498
+ rb_define_singleton_method(cAPI, "server_set_debugstyle", server_set_debugstyle, 2);
499
+ rb_define_singleton_method(cAPI, "server_set_server_type", server_set_server_type, 2);
500
+ rb_define_singleton_method(cAPI, "server_set_transport_type", server_set_transport_type, 2);
501
+ rb_define_singleton_method(cAPI, "server_set_port", server_set_port, 2);
502
+ rb_define_singleton_method(cAPI, "server_set_timeout", server_set_timeout, 2);
503
+ rb_define_singleton_method(cAPI, "server_adminuser", server_adminuser, 3);
504
+ rb_define_singleton_method(cAPI, "server_invoke", server_invoke, 3);
505
+
506
+ /*
507
+ * Create constants in this class based on values defined in netapp_api.h
508
+ */
509
+ INTDEF2CONST(cAPI, NA_STYLE_LOGIN_PASSWORD);
510
+ INTDEF2CONST(cAPI, NA_STYLE_RPC);
511
+ INTDEF2CONST(cAPI, NA_STYLE_HOSTSEQUIV);
512
+
513
+ INTDEF2CONST(cAPI, NA_SERVER_TRANSPORT_HTTP);
514
+ INTDEF2CONST(cAPI, NA_SERVER_TRANSPORT_HTTPS);
515
+
516
+ INTDEF2CONST(cAPI, NA_SERVER_TYPE_FILER);
517
+ INTDEF2CONST(cAPI, NA_SERVER_TYPE_NETCACHE);
518
+ INTDEF2CONST(cAPI, NA_SERVER_TYPE_AGENT);
519
+ INTDEF2CONST(cAPI, NA_SERVER_TYPE_DFM);
520
+ INTDEF2CONST(cAPI, NA_SERVER_TYPE_CLUSTER);
521
+
522
+ INTDEF2CONST(cAPI, NA_NO_DEBUG);
523
+ INTDEF2CONST(cAPI, NA_PRINT_DONT_PARSE);
524
+ INTDEF2CONST(cAPI, NA_DONT_PRINT_DONT_PARSE);
525
+
526
+ rb_eAPIError = rb_const_get(cAPI, rb_intern(exception_name));
527
+ cNAMHash = rb_const_get(mNetAppManageability, rb_intern(hash_class_name));
528
+
529
+ id_to_s = rb_intern("to_s");
530
+ id_logger = rb_intern("logger");
531
+ id_verbose = rb_intern("verbose");
532
+ id_wire_dump = rb_intern("wire_dump");
533
+ id_info = rb_intern("info");
534
+ id_debug = rb_intern("debug");
535
+
536
+ /*
537
+ * Initialize the library.
538
+ */
539
+ if (!na_startup(err, sizeof(err))) {
540
+ rb_raise(rb_eAPIError, "Error in na_startup: %s", err);
541
+ }
542
+ #endif
543
+ }