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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +76 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/examples/api_example.rb +7 -0
- data/examples/client_example.rb +45 -0
- data/examples/create_volume.rb +96 -0
- data/examples/list_aggregates.rb +20 -0
- data/examples/list_volumes.rb +20 -0
- data/examples/lun_info.rb +29 -0
- data/examples/nfs_root_hosts.rb +51 -0
- data/examples/provision_nas_datastore_via_manageiq.rb +147 -0
- data/ext/net_app_manageability/extconf.rb +20 -0
- data/ext/net_app_manageability/net_app_manageability.c +543 -0
- data/lib/net_app_manageability.rb +10 -0
- data/lib/net_app_manageability/api.rb +10 -0
- data/lib/net_app_manageability/api/error.rb +6 -0
- data/lib/net_app_manageability/client.rb +104 -0
- data/lib/net_app_manageability/client_stub.rb +24 -0
- data/lib/net_app_manageability/error.rb +4 -0
- data/lib/net_app_manageability/nam_array.rb +11 -0
- data/lib/net_app_manageability/nam_hash.rb +42 -0
- data/lib/net_app_manageability/ontap_method_map.rb +641 -0
- data/lib/net_app_manageability/types.rb +4 -0
- data/lib/net_app_manageability/version.rb +3 -0
- data/net_app_manageability.gemspec +35 -0
- metadata +136 -0
@@ -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
|
+
}
|