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