rbvppc 1.0.1
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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +302 -0
- data/Rakefile +8 -0
- data/documentation/hmc.odt +0 -0
- data/documentation/lpar.odt +0 -0
- data/documentation/lun.odt +0 -0
- data/documentation/network.odt +0 -0
- data/documentation/nim.odt +0 -0
- data/documentation/vio.odt +0 -0
- data/documentation/vnic.odt +0 -0
- data/documentation/vscsi.odt +0 -0
- data/examples/add_disk_any_size_to_lpar.rb +46 -0
- data/examples/add_disk_specifing_size_to_lpar.rb +47 -0
- data/examples/remove_disks_and_delete_lpar.rb +35 -0
- data/examples/remove_disks_from_lpar.rb +33 -0
- data/examples/test_lpar_build.rb +83 -0
- data/lib/rbvppc/command_failure.rb +18 -0
- data/lib/rbvppc/connectable_server.rb +95 -0
- data/lib/rbvppc/hmc.rb +892 -0
- data/lib/rbvppc/lpar.rb +1140 -0
- data/lib/rbvppc/lun.rb +23 -0
- data/lib/rbvppc/network.rb +54 -0
- data/lib/rbvppc/nim.rb +442 -0
- data/lib/rbvppc/version.rb +10 -0
- data/lib/rbvppc/vio.rb +720 -0
- data/lib/rbvppc/vnic.rb +34 -0
- data/lib/rbvppc/vscsi.rb +36 -0
- data/lib/rbvppc.rb +28 -0
- data/rbvppc.gemspec +26 -0
- metadata +117 -0
data/lib/rbvppc/lun.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Authors: Christopher M Wood (<woodc@us.ibm.com>)
|
|
3
|
+
# John F Hutchinson (<jfhutchi@us.ibm.com)
|
|
4
|
+
# © Copyright IBM Corporation 2015.
|
|
5
|
+
#
|
|
6
|
+
# LICENSE: MIT (http://opensource.org/licenses/MIT)
|
|
7
|
+
#
|
|
8
|
+
class Lun
|
|
9
|
+
attr_reader :name, :pvid, :size_in_mb
|
|
10
|
+
def initialize(name,pvid, size_in_mb)
|
|
11
|
+
@name = name
|
|
12
|
+
#@serial_number = serial_number
|
|
13
|
+
@pvid = pvid
|
|
14
|
+
@size_in_mb = size_in_mb.to_i
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
#Override == to test equality of two disk's PVIDs??
|
|
19
|
+
def ==(other_lun)
|
|
20
|
+
return self.pvid == other_lun.pvid
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Authors: Christopher M Wood (<woodc@us.ibm.com>)
|
|
3
|
+
# John F Hutchinson (<jfhutchi@us.ibm.com)
|
|
4
|
+
# © Copyright IBM Corporation 2015.
|
|
5
|
+
#
|
|
6
|
+
# LICENSE: MIT (http://opensource.org/licenses/MIT)
|
|
7
|
+
#
|
|
8
|
+
class Network
|
|
9
|
+
attr_accessor :ip_address, :is_primary, :subnet_mask, :gateway, :dns, :given_name, :vlan_id
|
|
10
|
+
|
|
11
|
+
def initialize(options_hash)
|
|
12
|
+
#Test for the explicitly required parameters
|
|
13
|
+
raise StandardError.new("A Network cannot be defined without a IP Address") if options_hash[:ip_address].nil?
|
|
14
|
+
raise StandardError.new("A Network cannot be defined without a Subnet Mask") if options_hash[:subnet_mask].nil?
|
|
15
|
+
raise StandardError.new("A Network cannot be defined without specifying if it is the primary network or not") if options_hash[:is_primary].nil? or (options_hash[:is_primary] != "false" and options_hash[:is_primary] != "true")
|
|
16
|
+
raise StandardError.new("A Network cannot be defined without specifying a VLAN ID") if options_hash[:vlan_id].nil?
|
|
17
|
+
|
|
18
|
+
#Test for optional parameters
|
|
19
|
+
warn ("Warning: Gateway not defined") if options_hash[:gateway].nil?
|
|
20
|
+
warn ("Warning: DNS not defined") if options_hash[:dns].nil?
|
|
21
|
+
warn ("Warning: Given Name not defined") if options_hash[:given_name].nil?
|
|
22
|
+
|
|
23
|
+
#Parameters
|
|
24
|
+
@ip_address = options_hash[:ip_address]
|
|
25
|
+
@is_primary = options_hash[:is_primary]
|
|
26
|
+
@subnet_mask = options_hash[:subnet_mask]
|
|
27
|
+
@gateway = options_hash[:gateway]
|
|
28
|
+
@dns = options_hash[:dns]
|
|
29
|
+
@given_name = options_hash[:given_name]
|
|
30
|
+
@vlan_id = options_hash[:vlan_id]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update_dns(new_dns,old_dns=nil)
|
|
34
|
+
if old_dns.nil?
|
|
35
|
+
if new_dns.is_array?
|
|
36
|
+
@dns = new_dns
|
|
37
|
+
else
|
|
38
|
+
@dns = [new_dns]
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
#find index of old_entry in @dns
|
|
42
|
+
i = @dns.index(old_dns)
|
|
43
|
+
@dns[i] = new_entry
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def update_gateway(new_gateway)
|
|
48
|
+
@gateway = new_gateway
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def update_given_name(new_name)
|
|
52
|
+
@vlan_id = new_name
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/rbvppc/nim.rb
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Authors: Christopher M Wood (<woodc@us.ibm.com>)
|
|
3
|
+
# John F Hutchinson (<jfhutchi@us.ibm.com)
|
|
4
|
+
# © Copyright IBM Corporation 2015.
|
|
5
|
+
#
|
|
6
|
+
# LICENSE: MIT (http://opensource.org/licenses/MIT)
|
|
7
|
+
#
|
|
8
|
+
=begin
|
|
9
|
+
|
|
10
|
+
Assumptions:
|
|
11
|
+
-We will adopt the following naming convention to find/use/manage bosinst_data (BID) for a client LPAR:
|
|
12
|
+
LPAR Name = "lpar123" => BID Name = "lpar123_bid"
|
|
13
|
+
|
|
14
|
+
-All BID objects are assumed to be stored in /darwin of the NIM (for now)
|
|
15
|
+
|
|
16
|
+
TO-DO:
|
|
17
|
+
-Some functions that uses client_lpar as an input contains commented out versions of lines
|
|
18
|
+
citing client_lpar.name instead of just client_lpar. Use these lines when we convert the functions
|
|
19
|
+
to use LPAR obects and not just pass names.
|
|
20
|
+
=end
|
|
21
|
+
|
|
22
|
+
require_relative 'connectable_server'
|
|
23
|
+
|
|
24
|
+
class Nim < ConnectableServer
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
#Execute commands on NIM, outputting the full command
|
|
28
|
+
#with puts first.
|
|
29
|
+
def execute_cmd(command)
|
|
30
|
+
puts "#{command}" if debug
|
|
31
|
+
super "#{command}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#list all defined objects of a specific type
|
|
35
|
+
#acceptable types are (standalone,ent,lpp_source,mksysb,spot,fb_script,script,bosinst_data,ent)
|
|
36
|
+
def list_objtype(type)
|
|
37
|
+
case type
|
|
38
|
+
when "standalone","ent","lpp_source","mksysb","spot","fb_script","script","bosinst_data"
|
|
39
|
+
output = execute_cmd "lsnim -t #{type}"
|
|
40
|
+
else
|
|
41
|
+
raise StandardError.new("Unknown type of NIM Object passed")
|
|
42
|
+
end
|
|
43
|
+
objects = []
|
|
44
|
+
output.each_line do |line|
|
|
45
|
+
line.chomp!
|
|
46
|
+
columns = line.split(/[[:blank:]]+/)
|
|
47
|
+
objects.push(columns[0]) if !columns[0].empty?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
return objects
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#Is the NIM Client defined?
|
|
54
|
+
def client_defined?(client_lpar)
|
|
55
|
+
#lsnim -Z lpar_name_here 2>/dev/null | awk '(NR==2) {print $1}' | awk -F: '{print $2}'
|
|
56
|
+
#result = execute_cmd "lsnim -Z #{client_lpar} 2>/dev/null | " +
|
|
57
|
+
result = execute_cmd "lsnim -Z #{client_lpar.name} 2>/dev/null | " +
|
|
58
|
+
"awk '(NR==2) {print $1}' | awk -F: '{print $2}'"
|
|
59
|
+
return result.chomp == "machines"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#Define the NIM Client
|
|
63
|
+
def define_client(client_lpar)
|
|
64
|
+
if client_defined?(client_lpar)
|
|
65
|
+
remove_client(client_lpar)
|
|
66
|
+
end
|
|
67
|
+
execute_cmd %Q{nim -o define -t standalone -a if1="find_net #{client_lpar.hostname} #{client_lpar.get_mac_address}" -a cable_type1="N/A" -a platform=chrp -a comments="Built by Darwin" -a net_settings1="auto auto" -a connect="shell" -a netboot_kernel=#{master_netboot_kernel} #{client_lpar.name}}
|
|
68
|
+
#execute_cmd %Q{nim -o define -t standalone -a if1="find_net #{hostname} #{mac}" -a cable_type1="N/A" -a platform=chrp -a comments="Built by Darwin" -a net_settings1="auto auto" -a connect="shell" -a netboot_kernel=#{master_netboot_kernel} #{client_lpar}}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#Pull the netboot_kernel attribute from NIM master object
|
|
72
|
+
def master_netboot_kernel
|
|
73
|
+
result = execute_cmd "lsnim -l master | awk '{if ($1 ~ /netboot_kernel/) print $3}'"
|
|
74
|
+
return result.chomp
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#Returns the IP address of the NIM master as a String
|
|
78
|
+
def get_master_ip
|
|
79
|
+
niminfo_line = execute_cmd("cat /etc/niminfo | grep NIM_MASTER_HOSTNAME")
|
|
80
|
+
hostname = niminfo_line.split("=")[1].chomp
|
|
81
|
+
|
|
82
|
+
ipaddr_line = execute_cmd("host #{hostname}")
|
|
83
|
+
ip = ipaddr_line.split(" is ")[1].chomp
|
|
84
|
+
|
|
85
|
+
if ip.empty?
|
|
86
|
+
raise StandardError.new("Unable to determine the NIM Master's IP Address")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
return ip
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#Reset a NIM client
|
|
93
|
+
def reset_client(client_lpar)
|
|
94
|
+
execute_cmd "nim -F -o reset #{client_lpar.name}"
|
|
95
|
+
#execute_cmd "nim -F -o reset #{client_lpar}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
#Deallocates any/all NIM resources from the client manchine
|
|
99
|
+
def deallocate_resources(client_lpar)
|
|
100
|
+
execute_cmd "nim -o deallocate -a subclass=all #{client_lpar.name}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#Remove a NIM client
|
|
104
|
+
def remove_client(client_lpar)
|
|
105
|
+
deallocate_resources(client_lpar)
|
|
106
|
+
execute_cmd "nim -F -o remove #{client_lpar.name}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
#Check the install status of a NIM client
|
|
110
|
+
#Returns current Cstate attribute of NIM client
|
|
111
|
+
def check_install_status(client_lpar)
|
|
112
|
+
#lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info nim_client_name
|
|
113
|
+
result = execute_cmd "lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info #{client_lpar.name}"
|
|
114
|
+
#result = execute_cmd "lsnim -Z -a Cstate -a Mstate -a Cstate_result -a info #{client_lpar}"
|
|
115
|
+
result.each_line do |line|
|
|
116
|
+
line.match(/#{client_lpar.name}/) do |m|
|
|
117
|
+
#line.match(/#{client_lpar}/) do |m|
|
|
118
|
+
#Cstate is the 2nd column of the : delimited output
|
|
119
|
+
cstate = line.split(/:/)[1]
|
|
120
|
+
return cstate
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
return nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
#Return an array of names of mksysbs that exist on this NIM
|
|
127
|
+
def list_images
|
|
128
|
+
list_objtype("mksysb")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
#Capture a mksysb image from a NIM client
|
|
132
|
+
def capture_image(source_lpar,mksysb_name,path)
|
|
133
|
+
#Pull mksysb from a NIM client, give it a name and place it in some location on the NIM
|
|
134
|
+
execute_cmd "nim -o define -t mksysb -F -a server=master -a location=#{path} -a source=#{source_lpar.name} -a mk_image=yes -a mksysb_flags=XAe #{mksysb_name}"
|
|
135
|
+
|
|
136
|
+
#Create SPOT resource from this mksysb, giving it a name and a location on the NIM to store it
|
|
137
|
+
extract_spot(mksysb_name)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
#Add a mksysb image to this NIM based on the name given and
|
|
141
|
+
#the local file path of the mksysb file on the NIM.
|
|
142
|
+
#Returns the name of the image that is created.
|
|
143
|
+
def add_image(file_path,mksysb_name)
|
|
144
|
+
#Check to make sure a mksysb with this name doesn't already exist
|
|
145
|
+
images = list_images
|
|
146
|
+
if images.include?(mksysb_name)
|
|
147
|
+
raise StandardError.new("A mksysb with the specified name #{mksysb_name} already exists, please specify another name")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
#Add image to the NIM
|
|
151
|
+
execute_cmd "nim -o define -t mksysb -F -a server=master -a location=#{file_path} -a mksysb_flags=XAe #{mksysb_name}"
|
|
152
|
+
|
|
153
|
+
#Extract a SPOT from this mksysb
|
|
154
|
+
extract_spot(mksysb_name)
|
|
155
|
+
|
|
156
|
+
return mksysb_name
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
#Removes a mksysb from the NIM that identifies with the name specified.
|
|
160
|
+
#Attempts to remove the SPOT that was extracted from this mksysb first.
|
|
161
|
+
def remove_image(mksysb_name)
|
|
162
|
+
#Find if this mksysb actually exists on the NIM
|
|
163
|
+
images = list_images
|
|
164
|
+
if !images.include?(mksysb_name)
|
|
165
|
+
warn "#{mksysb_name} does not exist on this NIM."
|
|
166
|
+
return
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
#Find and remove the SPOT for this mksysb
|
|
170
|
+
spot_name = get_spot(mksysb_name)
|
|
171
|
+
if !spot_name.nil?
|
|
172
|
+
remove_spot(spot_name)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
#Remove the mksysb from the NIM (along with it's mksysb file)
|
|
176
|
+
execute_cmd("nim -o remove -a rm_image=yes #{mksysb_name}")
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
#Deploy mksysb image to NIM client
|
|
180
|
+
def deploy_image(client_lpar, mksysb_name, firstboot_script = nil, lpp_source = nil)
|
|
181
|
+
|
|
182
|
+
bosinst_data_obj = client_lpar.name+"_bid"
|
|
183
|
+
|
|
184
|
+
#Create a NIM Client and a bosinst_data object if they don't
|
|
185
|
+
#already exist for this LPAR.
|
|
186
|
+
define_client(client_lpar) if !client_defined?(client_lpar)
|
|
187
|
+
create_bid(client_lpar) if !bid_exists?(client_lpar)
|
|
188
|
+
|
|
189
|
+
if !lpp_source.nil?
|
|
190
|
+
#TODO: Do something different if an lpp_source is specified...
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
#Get the SPOT to use for this image deployment
|
|
194
|
+
spot_name = get_spot(mksysb_name)
|
|
195
|
+
if spot_name.nil?
|
|
196
|
+
#Extract the spot from this mksysb and use it
|
|
197
|
+
spot_name = extract_spot(mksysb_name)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
command = "nim -o bos_inst -a source=mksysb -a mksysb=#{mksysb_name} -a bosinst_data=#{bosinst_data_obj} -a no_nim_client=no " +
|
|
201
|
+
"-a accept_licenses=yes -a boot_client=no"
|
|
202
|
+
command += " -a spot=#{spot_name}" if !spot_name.nil?
|
|
203
|
+
command += " -a fb_script=#{firstboot_script}" if !firstboot_script.nil?
|
|
204
|
+
command += " -a lpp_source=#{lpp_source}" if !lpp_source.nil?
|
|
205
|
+
command += " #{client_lpar.name}"
|
|
206
|
+
#NIM command to start a remote mksysb install on NIM client
|
|
207
|
+
execute_cmd(command)
|
|
208
|
+
|
|
209
|
+
#Then, in order to actually start the install the HMC needs to netboot the LPAR
|
|
210
|
+
#Should that be called from here or just utilized separately from the HMC object?
|
|
211
|
+
#Maybe yeild to a block that should call the HMC LPAR netboot?
|
|
212
|
+
#Then upon returning to this function, we poll the NIM client for Cstate statuses
|
|
213
|
+
#until the build is finished?
|
|
214
|
+
network_name = get_lpar_network_name(client_lpar)
|
|
215
|
+
gateway = get_network_gateway(network_name)
|
|
216
|
+
subnetmask = get_network_subnetmask(network_name)
|
|
217
|
+
nim_ip = get_master_ip
|
|
218
|
+
|
|
219
|
+
yield(nim_ip,gateway,subnetmask)
|
|
220
|
+
|
|
221
|
+
#Implemented nicer looking progress message for BOS installs
|
|
222
|
+
print "Waiting for BOS install for #{client_lpar.name} to finish..."
|
|
223
|
+
print "." until bos_install_finished?(client_lpar)
|
|
224
|
+
puts "done"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
#Used in populating the BOS Install status message
|
|
228
|
+
#Returns true of the specified lpar is done with is BOS build.
|
|
229
|
+
#Sleeps for 15 seconds and returns false if otherwise.
|
|
230
|
+
def bos_install_finished?(lpar)
|
|
231
|
+
if check_install_status(lpar).match(/ready for a NIM operation/i)
|
|
232
|
+
return true
|
|
233
|
+
else
|
|
234
|
+
sleep 15
|
|
235
|
+
return false
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
#Returns the filesystem location of the mksysb with the specified name
|
|
240
|
+
def get_mksysb_location(mksysb_name)
|
|
241
|
+
execute_cmd("lsnim -l #{mksysb_name} | awk '{if ($1 ~ /location/) print $3}'").chomp
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
#Returns the name of the SPOT extracted from the supplied mksysb
|
|
246
|
+
def get_spot(mksysb_name)
|
|
247
|
+
spot = execute_cmd("lsnim -l #{mksysb_name} | awk '{if ($1 ~ /extracted_spot/) print $3}'").chomp
|
|
248
|
+
if spot.empty?
|
|
249
|
+
return nil
|
|
250
|
+
else
|
|
251
|
+
return spot
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
#Extracts a SPOT from the mksysb image name specified.
|
|
256
|
+
#places the SPOT in a directory location adjacent to
|
|
257
|
+
#where the mksysb resides
|
|
258
|
+
#If a spot already exists for this mksysb, it's name is
|
|
259
|
+
#simply returned.
|
|
260
|
+
def extract_spot(mksysb_name)
|
|
261
|
+
#Find out if this mksysb exists on the NIM
|
|
262
|
+
if !list_objtype("mksysb").include?(mksysb_name)
|
|
263
|
+
#Mksysb not found - error out?
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
spot_name = mksysb_name+"_spot"
|
|
267
|
+
#Find out if a SPOT already exists for this mksysb
|
|
268
|
+
#if so, just return that name.
|
|
269
|
+
temp_name = get_spot(mksysb_name)
|
|
270
|
+
if !temp_name.nil?
|
|
271
|
+
return temp_name
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
#Get the location of this mksysb
|
|
275
|
+
mksysb_loc = get_mksysb_location(mksysb_name)
|
|
276
|
+
|
|
277
|
+
#Make sure the mksysb location is non-null
|
|
278
|
+
raise StandardError.new("Cannot locate where the image #{mksysb_name} exists on this NIM") if mksysb_loc.nil?
|
|
279
|
+
|
|
280
|
+
#Split the mksysb location on '/', pop the mksysb name and directory it resides
|
|
281
|
+
#in off of the array and push "spot" and the spot name onto the array to end up placing
|
|
282
|
+
#the SPOT in ../spot/spot_name
|
|
283
|
+
split_mksysb_path = mksysb_loc.split("/")
|
|
284
|
+
split_mksysb_path.pop
|
|
285
|
+
split_mksysb_path.pop
|
|
286
|
+
split_mksysb_path.push("spot")
|
|
287
|
+
split_mksysb_path.push(mksysb_name+"_spot")
|
|
288
|
+
spot_path = split_mksysb_path.join("/")
|
|
289
|
+
|
|
290
|
+
#Make a SPOT from this mksysb with the name <mksysb_name>_spot
|
|
291
|
+
execute_cmd("nim -o define -t spot -a server=master -a source=#{mksysb_name} -a location=#{spot_path} -a auto_expand=yes #{spot_name}")
|
|
292
|
+
|
|
293
|
+
#Return the name of the SPOT.
|
|
294
|
+
return spot_name
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
#Removes a SPOT object from a NIM based on the name
|
|
298
|
+
def remove_spot(spot_name)
|
|
299
|
+
execute_cmd("nim -Fo remove #{spot_name}")
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
#Creates a bosinst_data object for the client_lpar specified
|
|
303
|
+
def create_bid(client_lpar)
|
|
304
|
+
if bid_exists?(client_lpar)
|
|
305
|
+
#Force remove the BID and then continue to create a new one.
|
|
306
|
+
remove_bid(client_lpar)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
#Use heredoc to populate the bosinst_data file in a multiline string
|
|
310
|
+
bid_contents = <<-EOS
|
|
311
|
+
# bosinst_data file created for #{client_lpar.name}
|
|
312
|
+
|
|
313
|
+
CONSOLE = Default
|
|
314
|
+
RECOVER_DEVICES = no
|
|
315
|
+
INSTALL_METHOD = overwrite
|
|
316
|
+
PROMPT = no
|
|
317
|
+
EXISTING_SYSTEM_OVERWRITE = any
|
|
318
|
+
ACCEPT_LICENSES = yes
|
|
319
|
+
|
|
320
|
+
locale:
|
|
321
|
+
BOSINST_LANG = en_US
|
|
322
|
+
CULTURAL_CONVENTION = en_US
|
|
323
|
+
MESSAGES = en_US
|
|
324
|
+
KEYBOARD = en_US
|
|
325
|
+
EOS
|
|
326
|
+
|
|
327
|
+
#Create bid contents file on NIM
|
|
328
|
+
execute_cmd "mkdir -p /darwin; echo '#{bid_contents}' > /darwin/#{client_lpar.name}_bid"
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
#Define the BID object
|
|
332
|
+
execute_cmd "nim -o define -t bosinst_data -a location=/darwin/#{client_lpar.name}_bid -a server=master #{client_lpar.name}_bid"
|
|
333
|
+
|
|
334
|
+
#Return the name of the BID created
|
|
335
|
+
return "#{client_lpar.name}_bid"
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
#Remove the NIM BID object for a client LPAR
|
|
339
|
+
def remove_bid(client_lpar)
|
|
340
|
+
execute_cmd "nim -F -o remove #{client_lpar.name}_bid"
|
|
341
|
+
#execute_cmd "nim -F -o remove #{client_lpar}_bid"
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
#Checks if BID object exists on NIM for the Client LPAR
|
|
345
|
+
def bid_exists?(client_lpar)
|
|
346
|
+
defined_bids = list_objtype("bosinst_data")
|
|
347
|
+
defined_bids.each do |obj_name|
|
|
348
|
+
#Iterate through array elements returned by list_objtype
|
|
349
|
+
#and check if any of them line up with the BID name for our LPAR
|
|
350
|
+
if (obj_name == "#{client_lpar.name}_bid")
|
|
351
|
+
#if (obj_name == "#{client_lpar}_bid")
|
|
352
|
+
return true
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
return false
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
#Find NIM interface settings for client LPAR
|
|
359
|
+
def get_lpar_network_name(client_lpar)
|
|
360
|
+
output = execute_cmd "lsnim -Z -a if1 #{client_lpar.name}"
|
|
361
|
+
nim_network=""
|
|
362
|
+
output.each_line do |line|
|
|
363
|
+
line.chomp!
|
|
364
|
+
if line.match(/^#{client_lpar.name}/)
|
|
365
|
+
network_args = line.split(/:/)
|
|
366
|
+
nim_network = network_args[1]
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
return nim_network
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
#Find Gateway IP for NIM network
|
|
373
|
+
def get_network_gateway(network_name)
|
|
374
|
+
output = execute_cmd "lsnim -Z -a net_addr -a snm -a routing #{network_name}"
|
|
375
|
+
output.each_line do |line|
|
|
376
|
+
line.chomp!
|
|
377
|
+
if line.match(/^#{network_name}/)
|
|
378
|
+
network_fields = line.split(/:/)
|
|
379
|
+
return network_fields[-1]
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
#Find Subnet mask for NIM network
|
|
385
|
+
def get_network_subnetmask(network_name)
|
|
386
|
+
output = execute_cmd "lsnim -Z -a net_addr -a snm -a routing #{network_name}"
|
|
387
|
+
output.each_line do |line|
|
|
388
|
+
line.chomp!
|
|
389
|
+
if line.match(/^#{network_name}/)
|
|
390
|
+
network_fields = line.split(/:/)
|
|
391
|
+
return network_fields[2]
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
#Add a NIM network object using the given name, network address,
|
|
397
|
+
#subnet mask, gateway
|
|
398
|
+
def add_network(network_name,network_addr,snm,gw)
|
|
399
|
+
#Ensure that network with this address doesn't already exist
|
|
400
|
+
raise StandardError.new("Network #{network_name} already exists on this NIM") if network_exists?(network_name,network_addr)
|
|
401
|
+
|
|
402
|
+
#Execute NIM command to create the network
|
|
403
|
+
#It is assumed that the network addess and the gateway are the same
|
|
404
|
+
execute_cmd("nim -o define -t ent -a net_addr=#{network_addr} -a snm=#{snm} #{network_name}")
|
|
405
|
+
|
|
406
|
+
#Add default route to the specified gateway
|
|
407
|
+
add_default_route(network_name,gw)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
#Remove a NIM network given it's name and/or it's
|
|
411
|
+
#network address
|
|
412
|
+
def remove_network(network_name,network_addr=nil)
|
|
413
|
+
#Ensure that the network to remove is actually defined currently
|
|
414
|
+
raise StandardError.new("Network #{network_name} does not exist on this NIM to be removed") if !network_exists?(network_name,network_addr)
|
|
415
|
+
|
|
416
|
+
#Run command that removes this network from the NIM
|
|
417
|
+
execute_cmd("nim -Fo remove #{network_name}")
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
#Returns true if a network object exists on the NIM
|
|
421
|
+
#with either the specified name or network address.
|
|
422
|
+
#Returns false otherwise.
|
|
423
|
+
def network_exists?(network_name,network_addr=nil)
|
|
424
|
+
network_names = list_objtype("ent")
|
|
425
|
+
if network_names.include?(network_name)
|
|
426
|
+
return true
|
|
427
|
+
end
|
|
428
|
+
network_names.each do |net_name|
|
|
429
|
+
address = execute_cmd("lsnim -l #{net_name} | awk '{if ($1 ~ /net_addr/) print $3}'").chomp
|
|
430
|
+
if address == network_addr
|
|
431
|
+
return true
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
return false
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def add_default_route(network_name,gateway)
|
|
439
|
+
#TODO: Add more robust creation/management of NIM network routes, if necessary
|
|
440
|
+
execute_cmd("nim -o change -a routing1='default #{gateway}' #{network_name}")
|
|
441
|
+
end
|
|
442
|
+
end
|