net_app_manageability 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.
@@ -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
+ }