knife-lpar 0.0.3

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,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "knife-lpar/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "knife-lpar"
8
+ spec.version = Knife::Lpar::VERSION
9
+ spec.authors = ["Scott Hain"]
10
+ spec.email = ["shain@chef.io"]
11
+ spec.summary = %q{LPAR creation}
12
+ spec.description = spec.summary
13
+ spec.homepage = "http://github.com/chef/knife-lpar"
14
+ spec.license = "Apache 2.0"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "net-ssh", "~> 2.6"
22
+ end
@@ -0,0 +1,57 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014-2016 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "io/console"
19
+ require "net/ssh"
20
+
21
+ class Chef
22
+ class Knife
23
+ module LparBase
24
+
25
+ # I hate this name but I'm not thinking of anything better right now.
26
+ def print_with_output(message, output = nil)
27
+ if output.nil? || output.empty?
28
+ ui.info message
29
+ else
30
+ ui.info message + " - " + output
31
+ end
32
+ end
33
+
34
+ def run_remote_command(ssh, command)
35
+ return_val = nil
36
+ ssh.exec! command do |ch, stream, data|
37
+ if stream == :stdout
38
+ return_val = data.chomp
39
+ else
40
+ # some exception is in order I think
41
+ ui.error "Something went wrong:"
42
+ ui.error data.to_s
43
+ exit 1
44
+ end
45
+ end
46
+ return_val
47
+ end
48
+
49
+ # quick and dirty password prompt, because I'm cool like that
50
+ def get_password
51
+ print "Enter root password for HMC: "
52
+ STDIN.noecho(&:gets).chomp
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,247 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014-2016 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef/knife"
19
+ require "chef/knife/lpar_base"
20
+
21
+ class Chef
22
+ class Knife
23
+ class LparCreate < Knife
24
+ include Chef::Knife::LparBase
25
+
26
+ banner "knife lpar create HMC [options]"
27
+
28
+ option :name,
29
+ :short => "-n NAME",
30
+ :long => "--name",
31
+ :description => "LPAR Name"
32
+
33
+ option :profile,
34
+ :short => "-p PROFILE",
35
+ :long => "--profile",
36
+ :description => "LPAR Profile Name"
37
+
38
+ option :virtual_server,
39
+ :short => "-v SERVER",
40
+ :long => "--virtual-server",
41
+ :description => "Virtual Server Name"
42
+
43
+ option :vios,
44
+ :long => "--vios NAME",
45
+ :description => "Virtual I/O Server LPAR Name"
46
+
47
+ option :min_mem,
48
+ :long => "--min-mem MEM",
49
+ :description => "Minimum Memory in mb (default 1024)",
50
+ :default => 1024
51
+
52
+ option :desired_mem,
53
+ :long => "--desired-mem MEM",
54
+ :description => "Desired Memory in mb (default 4096)",
55
+ :default => 4096
56
+
57
+ option :max_mem,
58
+ :long => "--max-mem MEM",
59
+ :description => "Max Memory in mb (default 16384)",
60
+ :default => 16384
61
+
62
+ option :min_procs,
63
+ :long => "--min-procs PROCS",
64
+ :description => "Minimum number of Processors (default 1)",
65
+ :default => 1
66
+
67
+ option :desired_procs,
68
+ :long => "--desired-procs PROCS",
69
+ :description => "Desired number of Processors (default 2)",
70
+ :default => 2
71
+
72
+ option :max_procs,
73
+ :long => "--max-procs PROCS",
74
+ :description => "Max number of Processors (default 4)",
75
+ :default => 4
76
+
77
+ option :min_proc_units,
78
+ :long => "--min-proc_units UNITS",
79
+ :description => "Minimum number of processor units (default 1)",
80
+ :default => 1
81
+
82
+ option :desired_proc_units,
83
+ :long => "--desired-proc_units UNITS",
84
+ :description => "Desired number of processor units (default 2)",
85
+ :default => 2
86
+
87
+ option :max_proc_units,
88
+ :long => "--max-proc_units UNITS",
89
+ :description => "Max number of processor units (default 4)",
90
+ :default => 4
91
+
92
+ option :help,
93
+ :long => "--help",
94
+ :description => "Prints this menu"
95
+
96
+ option :disk_name,
97
+ :long => "--disk-name DISK",
98
+ :description => "Disk image name (e.g. AIX_6_1_vol1)"
99
+
100
+ #
101
+ # Run the plugin
102
+ #
103
+ def run
104
+ read_and_validate_params
105
+ @password = get_password
106
+ create_lpar
107
+ end
108
+
109
+ #
110
+ # Reads the input parameters and validates them.
111
+ # Will exit if it encounters an error
112
+ #
113
+ def read_and_validate_params
114
+ if @name_args.length < 1
115
+ show_usage
116
+ exit 1
117
+ end
118
+
119
+ if config[:name].nil? ||
120
+ config[:vios].nil? ||
121
+ config[:virtual_server].nil? ||
122
+ config[:disk_name].nil?
123
+ show_usage
124
+ exit 1
125
+ end
126
+
127
+ if config[:profile].nil?
128
+ config[:profile] = config[:name]
129
+ end
130
+ end
131
+
132
+ def create_lpar
133
+ Net::SSH.start(@name_args[0], "hscroot", :password => @password) do |ssh|
134
+ # some background checks
135
+ # check for existing lpar with name
136
+ ui.info "Searching for existing lpar with name: #{config[:name]}"
137
+ command = "lssyscfg -m #{config[:virtual_server]} -F name -r lpar | grep #{config[:name]}"
138
+ output = run_remote_command(ssh, command)
139
+ unless output.nil?
140
+ ui.fatal "An lpar already exists with the name #{config[:name]}"
141
+ exit 1
142
+ end
143
+ ui.info "lpar not found, creation imminent"
144
+
145
+ # find the last vscsi device number
146
+ ui.info "Looking for next device number in sequence"
147
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"lsdev -type disk -virtual -field name\" | tail -1"
148
+ last_vscsi = run_remote_command(ssh, command)
149
+ ui.info "Found existing device - #{last_vscsi}"
150
+
151
+ # use the vscsi number to find the actual physical ID so we can find which vios slot it's in
152
+ ui.info "Finding vios mapping for device - #{last_vscsi}"
153
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"lsdev -dev #{last_vscsi} -field physloc -fmt \\\":\\\"\""
154
+ last_vscsi_phy_loc = run_remote_command(ssh, command)
155
+ prev_loc = last_vscsi_phy_loc.match('.*-C(\d+)-.*')[1]
156
+ ui.info "Found vios mapping #{prev_loc}"
157
+ new_virt_loc = prev_loc.to_i + 1
158
+ ui.info "Will use new mapping #{new_virt_loc}"
159
+
160
+ # create the new lpar
161
+ ui.info "Creating new lpar #{config[:name]}"
162
+ command = "mksyscfg -m #{config[:virtual_server]} -r lpar \
163
+ -i \"name=#{config[:name]}, \
164
+ profile_name=#{config[:profile]}, \
165
+ lpar_env=aixlinux, \
166
+ min_mem=#{config[:min_mem]}, \
167
+ desired_mem=#{config[:desired_mem]}, \
168
+ max_mem=#{config[:max_mem]}, \
169
+ proc_mode=shared, \
170
+ min_procs=#{config[:min_procs]}, \
171
+ desired_procs=#{config[:desired_procs]}, \
172
+ max_procs=#{config[:max_procs]}, \
173
+ min_proc_units=#{config[:min_proc_units]}, \
174
+ desired_proc_units=#{config[:desired_proc_units]}, \
175
+ max_proc_units=#{config[:max_proc_units]}, \
176
+ sharing_mode=uncap, uncap_weight=128, \
177
+ boot_mode=norm, max_virtual_slots=10, \
178
+ \\\"virtual_eth_adapters=3/0/1//0/0\\\", \
179
+ \\\"virtual_scsi_adapters=2/client//#{config[:vios]}/#{new_virt_loc}/1\\\"\""
180
+ output = run_remote_command(ssh, command)
181
+ ui.info "Creation Successful"
182
+
183
+ # now we have to figure out what LPAR we just created
184
+ ui.info "Finding vhost name"
185
+ command = "lssyscfg -m #{config[:virtual_server]} --filter \"lpar_names=#{config[:name]}\" -F lpar_id -r lpar"
186
+ output = run_remote_command(ssh, command)
187
+ # and of course it doesn't match, 0 based vs 1 based counting
188
+ vhost = output.to_i - 1
189
+ vhost_name = "vhost#{vhost}"
190
+ ui.info "#{config[:name]} is #{vhost_name}"
191
+
192
+ # Add the virtual io server vscsi mapping
193
+ ui.info "Mapping #{new_virt_loc} between #{config[:vios]} and #{config[:name]}"
194
+ command = "chhwres -r virtualio -m #{config[:virtual_server]} -o a -p #{config[:vios]} --rsubtype scsi -s #{new_virt_loc} -a \"adapter_type=server, remote_lpar_name=#{config[:name]}, remote_slot_num=2\""
195
+ output = run_remote_command(ssh, command)
196
+ ui.info "Mapping Successful"
197
+
198
+ # make a file backed optical drive
199
+ ui.info "Creating virtual file backed optical device"
200
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"mkvdev -fbo -vadapter #{vhost_name}\""
201
+ vopt_name = run_remote_command(ssh, command).split(" ")[0]
202
+ ui.info "Created device #{vopt_name}"
203
+
204
+ # load the iso
205
+ ui.info "Loading disk in optical drive"
206
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"loadopt -vtd #{vopt_name} -disk #{config[:disk_name]}\""
207
+ output = run_remote_command(ssh, command)
208
+ ui.info "Loading Successful"
209
+
210
+ # create logical volume
211
+ ui.info "Creating logical volume"
212
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"mklv -lv #{config[:name]} rootvg 50G\""
213
+ lv_name = run_remote_command(ssh, command)
214
+ ui.info "Created logical volume #{lv_name}"
215
+
216
+ # attach it
217
+ ui.info "Attaching lv to lpar"
218
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"mkvdev -vdev #{config[:name]} -vadapter #{vhost_name}\""
219
+ vtscsi_name = run_remote_command(ssh, command).split(" ")[0]
220
+ ui.info "Attach Successful as #{vtscsi_name}"
221
+
222
+ # save the virtual io server profile
223
+ ui.info "Activating virtual io server profile"
224
+ command = "mksyscfg -r prof -m #{config[:virtual_server]} -o save -p #{config[:vios]} -n `lssyscfg -r lpar -m #{config[:virtual_server]} --filter \"lpar_names=#{config[:vios]}\" -F curr_profile` --force"
225
+ output = run_remote_command(ssh, command)
226
+ ui.info "Activation Successful"
227
+
228
+ # reload the lpar so it knows it has new devices
229
+ ui.info "Reload virtual io server to re-read devices"
230
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"cfgdev\""
231
+ output = run_remote_command(ssh, command)
232
+ ui.info "Reload Successful"
233
+
234
+ # could start it up here, we'll see
235
+ ui.info "Boot lpar in SMS mode"
236
+ command = "chsysstate -r lpar -m #{config[:virtual_server]} -o on -f #{config[:profile]} -b sms -n #{config[:name]}"
237
+ output = run_remote_command(ssh, command)
238
+ unless output.nil?
239
+ ui.info output.to_s
240
+ end
241
+ ui.info "Boot Successful"
242
+ end
243
+ end
244
+
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,168 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014-2016 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef/knife"
19
+ require "chef/knife/lpar_base"
20
+
21
+ class Chef
22
+ class Knife
23
+ class LparDelete < Knife
24
+ include Chef::Knife::LparBase
25
+
26
+ banner "knife lpar delete HMC [options]"
27
+
28
+ option :name,
29
+ :short => "-n NAME",
30
+ :long => "--name",
31
+ :description => "LPAR Name"
32
+
33
+ option :virtual_server,
34
+ :short => "-v SERVER",
35
+ :long => "--virtual-server",
36
+ :description => "Virtual Server Name"
37
+
38
+ option :vios,
39
+ :long => "--vios NAME",
40
+ :description => "Virtual I/O Server LPAR Name"
41
+
42
+ option :help,
43
+ :long => "--help",
44
+ :description => "Prints this menu"
45
+
46
+ #
47
+ # Run the plugin
48
+ #
49
+ def run
50
+ read_and_validate_params
51
+ @password = get_password
52
+ delete_lpar
53
+ end
54
+
55
+ #
56
+ # Reads the input parameters and validates them.
57
+ # Will exit if it encounters an error
58
+ #
59
+ def read_and_validate_params
60
+ if @name_args.length < 1
61
+ show_usage
62
+ exit 1
63
+ end
64
+
65
+ if config[:name].nil? ||
66
+ config[:vios].nil? ||
67
+ config[:virtual_server].nil?
68
+ show_usage
69
+ exit 1
70
+ end
71
+ end
72
+
73
+ def delete_lpar
74
+ Net::SSH.start(@name_args[0], "hscroot", :password => @password) do |ssh|
75
+ # some background checks
76
+
77
+ # check for existing lpar with name
78
+ ui.info "Verifying #{config[:name]} exists"
79
+ command = "lssyscfg -m #{config[:virtual_server]} -F name -r lpar --filter \"lpar_names=#{config[:name]}\""
80
+ output = run_remote_command(ssh, command)
81
+ unless output.eql? config[:name]
82
+ ui.fatal output
83
+ Kernel.exit(1)
84
+ end
85
+
86
+ # Check to see if it's running
87
+ ui.info "Verifying #{config[:name]} is not running"
88
+ command = "lssyscfg -m #{config[:virtual_server]} -F state -r lpar --filter \"lpar_names=#{config[:name]}\""
89
+ output = run_remote_command(ssh, command)
90
+ unless output.eql? "Not Activated"
91
+ ui.fatal output
92
+ Kernel.exit(1)
93
+ end
94
+
95
+ # first let's find the host mapping
96
+ ui.info "Searching for host mapping"
97
+ command = "lssyscfg -m #{config[:virtual_server]} --filter \"lpar_names=#{config[:name]}\" -F lpar_id -r lpar"
98
+ output = run_remote_command(ssh, command)
99
+ # and of course it doesn't match, 0 based vs 1 based counting
100
+ vhost = output.to_i - 1
101
+ vhost_name = "vhost#{vhost}"
102
+ print_with_output("Found host id of #{output} - mapping to #{vhost_name}", nil)
103
+
104
+ # mapping for the drive
105
+ ui.info "Searching for vscsi mapping"
106
+ command = "lssyscfg -m #{config[:virtual_server]} -r prof --filter \"lpar_names=#{config[:name]}\" -F virtual_scsi_adapters"
107
+ output = run_remote_command(ssh, command)
108
+ vscsi_id = output.match('.*\/.*\/.*\/.*\/(.*)\/.*')[1]
109
+ print_with_output("Found vscsi mapping #{vscsi_id}", output)
110
+
111
+ # find the mapping for the vopt
112
+ ui.info "Searching for vtopt mapping"
113
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"lsmap -vadapter #{vhost_name} -type file_opt -field vtd -fmt \\\":\\\"\""
114
+ vtopt_id = run_remote_command(ssh, command)
115
+ print_with_output("Found vtopt mapping #{vtopt_id}", output)
116
+
117
+ # find lv mapping
118
+ ui.info "Searching for logical volume mapping"
119
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"lsmap -vadapter #{vhost_name} -type lv -field vtd -fmt \\\":\\\"\""
120
+ lv_id = run_remote_command(ssh, command)
121
+ print_with_output("Found lv mapping #{lv_id}", output)
122
+
123
+ # find lv backing device
124
+ ui.info "Searching for lv backing device"
125
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"lsmap -vadapter #{vhost_name} -type lv -field backing -fmt \\\":\\\"\""
126
+ backing_device = run_remote_command(ssh, command)
127
+ print_with_output("Found device #{backing_device}")
128
+
129
+ # now delete the file backed optical drive mapping
130
+ ui.info "Removing #{vtopt_id}"
131
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"rmvdev -vtd #{vtopt_id}\""
132
+ output = run_remote_command(ssh, command)
133
+ print_with_output("#{vtopt_id} Removed", output)
134
+
135
+ # now delete the vtscsi device
136
+ ui.info "Removing vscsi #{lv_id}"
137
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"rmvdev -vtd #{lv_id}\""
138
+ output = run_remote_command(ssh, command)
139
+ print_with_output("#{lv_id} Removed", output)
140
+
141
+ # now delete the logical volume
142
+ ui.info "Removing lv #{backing_device}"
143
+ command = "viosvrcmd -m #{config[:virtual_server]} -p #{config[:vios]} -c \"rmlv -f #{backing_device}\""
144
+ output = run_remote_command(ssh, command)
145
+ print_with_output("#{backing_device} Removed", output)
146
+
147
+ # now that we know the id, let's remove it from the virtual io server
148
+ ui.info "Removing vtscsi mapping from vios"
149
+ command = "chhwres -r virtualio -m #{config[:virtual_server]} -o r -p #{config[:vios]} --rsubtype scsi -s #{vscsi_id}"
150
+ output = run_remote_command(ssh, command)
151
+ print_with_output("Mapping Removed", output)
152
+
153
+ # save the virtual io server profile
154
+ ui.info "Saving updated vios profile on #{config[:vios]}"
155
+ command = "mksyscfg -r prof -m #{config[:virtual_server]} -o save -p #{config[:vios]} -n `lssyscfg -r lpar -m #{config[:virtual_server]} --filter \"lpar_names=#{config[:vios]}\" -F curr_profile` --force"
156
+ output = run_remote_command(ssh, command)
157
+ print_with_output("Profile Saved", output)
158
+
159
+ # now remove the lpar completely
160
+ ui.info "Removing #{config[:name]} completely"
161
+ command = "rmsyscfg -r lpar -m #{config[:virtual_server]} -n #{config[:name]}"
162
+ output = run_remote_command(ssh, command)
163
+ print_with_output("#{config[:name]} Terminated", output)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end