knife-vsphere 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -55,21 +55,18 @@ class Chef
55
55
  :description => "The Datacenter to create the VM in"
56
56
 
57
57
  option :path,
58
- :short => "-P SOAP_PATH",
59
58
  :long => "--path SOAP_PATH",
60
59
  :description => "The SOAP endpoint path",
61
60
  :proc => Proc.new { |p| Chef::Config[:knife][:path] = p },
62
61
  :default => "/sdk"
63
62
 
64
63
  option :port,
65
- :short => "-p PORT",
66
64
  :long => "--port PORT",
67
65
  :description => "The VI SDK port number to use",
68
66
  :proc => Proc.new { |p| Chef::Config[:knife][:port] = p },
69
67
  :default => 443
70
68
 
71
69
  option :use_ssl,
72
- :short => "-s USE_SSL",
73
70
  :long => "--ssl USE_SSL",
74
71
  :description => "Whether to use SSL connection",
75
72
  :default => true
@@ -17,73 +17,117 @@
17
17
  require 'chef/knife'
18
18
  require 'chef/knife/VsphereBaseCommand'
19
19
  require 'rbvmomi'
20
+ require 'netaddr'
20
21
 
21
- class Chef
22
- class Knife
23
- class VsphereVmClone < VsphereBaseCommand
22
+ class Chef::Knife::VsphereVmClone < Chef::Knife::VsphereBaseCommand
24
23
 
25
- banner "knife vsphere vm clone (options)"
24
+ banner "knife vsphere vm clone (options)"
26
25
 
27
- get_common_options
26
+ get_common_options
28
27
 
29
- option :template,
30
- :short => "-t TEMPLATE",
31
- :long => "--template TEMPLATE",
32
- :description => "The template to create the VM from"
33
-
34
- option :vmname,
35
- :short => "-N VMNAME",
36
- :long => "--vmname VMNAME",
37
- :description => "The name for the new virtual machine"
28
+ option :template,
29
+ :short => "-t TEMPLATE",
30
+ :long => "--template TEMPLATE",
31
+ :description => "The template to create the VM from"
32
+
33
+ option :vmname,
34
+ :short => "-N VMNAME",
35
+ :long => "--vmname VMNAME",
36
+ :description => "The name for the new virtual machine"
38
37
 
39
- option :customization_spec,
40
- :long => "--cspec CUSTOMIZATION_SPEC",
41
- :description => "The name of any customization specification to apply"
38
+ option :customization_spec,
39
+ :long => "--cspec CUSTOMIZATION_SPEC",
40
+ :description => "The name of any customization specification to apply"
42
41
 
43
- def run
42
+ option :customization_ips,
43
+ :long => "--cips CUSTOMIZATION_IPS",
44
+ :description => "A comma-delimited list of CIDR notation static IPs to be mapped in order for "+
45
+ "any applied customization specification that expects IP addresses"
44
46
 
45
- $stdout.sync = true
46
-
47
- vim = get_vim_connection
48
47
 
49
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
50
- dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
51
48
 
52
- hosts = find_all_in_folders(dc.hostFolder, RbVmomi::VIM::ComputeResource)
53
- rp = hosts.first.resourcePool
54
49
 
55
- template = config[:template] or abort "source template name required"
56
- vmname = config[:vmname] or abort "destination vm name required"
50
+ def run
51
+
52
+ $stdout.sync = true
57
53
 
58
- src_vm = find_in_folders(dc.vmFolder, RbVmomi::VIM::VirtualMachine, template) or
59
- abort "VM/Template not found"
54
+ template = config[:template] or abort "source template name required"
55
+ vmname = config[:vmname] or abort "destination vm name required"
56
+
57
+ vim = get_vim_connection
60
58
 
61
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => rp)
59
+ dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
60
+ dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
62
61
 
63
-
64
- spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec,
65
- :powerOn => false,
66
- :template => false)
62
+ hosts = find_all_in_folders(dc.hostFolder, RbVmomi::VIM::ComputeResource)
63
+ rp = hosts.first.resourcePool
67
64
 
68
- if config[:customization_spec]
69
- cs = find_customization(vim, config[:customization_spec]) or
70
- abort "failed to find customization specification named #{config[:customization_spec]}"
71
- spec.customization = cs.spec
72
- end
65
+ src_vm = find_in_folders(dc.vmFolder, RbVmomi::VIM::VirtualMachine, template) or
66
+ abort "VM/Template not found"
73
67
 
74
- task = src_vm.CloneVM_Task(:folder => src_vm.parent, :name => vmname, :spec => spec)
75
- puts "Cloning template #{template} to new VM #{vmname}"
76
- task.wait_for_completion
77
- puts "Finished creating virtual machine #{vmname}"
68
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => rp)
78
69
 
79
- end
70
+
71
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec,
72
+ :powerOn => false,
73
+ :template => false)
80
74
 
81
- def find_customization(vim, name)
82
- csm = vim.serviceContent.customizationSpecManager
83
- csm.GetCustomizationSpec(:name => name)
75
+ if config[:customization_spec]
76
+ csi = find_customization(vim, config[:customization_spec]) or
77
+ abort "failed to find customization specification named #{config[:customization_spec]}"
78
+
79
+ if config[:customization_ips]
80
+ csi.spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i) }
84
81
  end
85
82
 
83
+ clone_spec.customization = csi.spec
84
+
85
+ end
86
+
87
+ task = src_vm.CloneVM_Task(:folder => src_vm.parent, :name => vmname, :spec => clone_spec)
88
+ puts "Cloning template #{template} to new VM #{vmname}"
89
+ task.wait_for_completion
90
+ puts "Finished creating virtual machine #{vmname}"
91
+ end
92
+
86
93
 
94
+ # Retrieves a CustomizationSpecItem that matches the supplied name
95
+ # @param vim [Connection] VI Connection to use
96
+ # @param name [String] name of customization
97
+ # @return [RbVmomi::VIM::CustomizationSpecItem]
98
+ def find_customization(vim, name)
99
+ csm = vim.serviceContent.customizationSpecManager
100
+ csm.GetCustomizationSpec(:name => name)
101
+ end
102
+
103
+ # Generates a CustomizationAdapterMapping (currently only single IPv4 address) object
104
+ # @param ip [String] Any static IP address to use, otherwise DHCP
105
+ # @param gw [String] If static, the gateway for the interface, otherwise network address + 1 will be used
106
+ # @return [RbVmomi::VIM::CustomizationIPSettings]
107
+ def generate_adapter_map (ip=nil, gw=nil, dns1=nil, dns2=nil, domain=nil)
108
+
109
+ settings = RbVmomi::VIM.CustomizationIPSettings
110
+
111
+ if ip.nil?
112
+ settings.ip = RbVmomi::VIM::CustomizationDhcpIpGenerator
113
+ else
114
+ cidr_ip = NetAddr::CIDR.create(ip)
115
+ settings.ip = RbVmomi::VIM::CustomizationFixedIp(:ipAddress => cidr_ip.ip)
116
+ settings.subnetMask = cidr_ip.netmask_ext
117
+
118
+ # TODO - want to confirm gw/ip are in same subnet?
119
+ if [gw.nil?]
120
+ settings.gateway = [cidr_ip.network(:Objectify => true).next_ip]
121
+ else
122
+ gw_cidr = NetAddr::CIDR.create(gw)
123
+ settings.gateway = [gw_cidr.ip]
124
+ end
87
125
  end
126
+
127
+ adapter_map = RbVmomi::VIM.CustomizationAdapterMapping
128
+ adapter_map.adapter = settings
129
+ adapter_map
130
+ #end
88
131
  end
132
+
89
133
  end
@@ -44,11 +44,11 @@ class Chef
44
44
  dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
45
45
 
46
46
  vm = find_in_folders(dc.vmFolder, RbVmomi::VIM::VirtualMachine, vmname) or
47
- abort "VM not found"
47
+ abort "VM #{vmname} not found"
48
48
 
49
49
  vm.PowerOffVM_Task.wait_for_completion unless vm.runtime.powerState == "poweredOff"
50
- vm.UnregisterVM
51
- puts "Finished unregistering virtual machine #{vmname}"
50
+ vm.Destroy_Task
51
+ puts "Deleted virtual machine #{vmname}"
52
52
 
53
53
  end
54
54
  end
@@ -0,0 +1,99 @@
1
+ #
2
+ # Author:: Ezra Pagel (<ezra@cpan.org>)
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
+ require 'chef/knife'
18
+ require 'chef/knife/VsphereBaseCommand'
19
+ require 'rbvmomi'
20
+ require 'netaddr'
21
+
22
+ PsOn = 'poweredOn'
23
+ PsOff = 'poweredOff'
24
+ PsSuspended = 'suspended'
25
+
26
+ PowerStates = {
27
+ PsOn => 'powered on',
28
+ PsOff => 'powered off',
29
+ PsSuspended => 'suspended'
30
+ }
31
+
32
+ class Chef::Knife::VsphereVmState < Chef::Knife::VsphereBaseCommand
33
+
34
+ banner "knife vsphere vm state (options)"
35
+
36
+ get_common_options
37
+
38
+ option :vmname,
39
+ :short => "-N VMNAME",
40
+ :long => "--vmname VMNAME",
41
+ :description => "The name for the new virtual machine"
42
+
43
+ option :state,
44
+ :short => "-s STATE",
45
+ :long => "--state STATE",
46
+ :description => "The power state to transition the VM into; one of on|off|suspended"
47
+
48
+ def run
49
+
50
+ $stdout.sync = true
51
+
52
+ vmname = config[:vmname] or abort "destination vm name required"
53
+
54
+ vim = get_vim_connection
55
+
56
+ dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
57
+ dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
58
+
59
+ hosts = find_all_in_folders(dc.hostFolder, RbVmomi::VIM::ComputeResource)
60
+ rp = hosts.first.resourcePool
61
+
62
+ vm = find_in_folders(dc.vmFolder, RbVmomi::VIM::VirtualMachine, vmname) or
63
+ abort "VM #{vmname} not found"
64
+
65
+ state = vm.runtime.powerState
66
+
67
+ if config[:state].nil?
68
+ puts "VM #{vmname} is currently " + PowerStates[vm.runtime.powerState]
69
+ else
70
+
71
+ case config[:state]
72
+ when 'on'
73
+ if state == PsOn
74
+ puts "Virtual machine #{vmname} was already powered on"
75
+ else
76
+ vm.PowerOnVM_Task.wait_for_completion
77
+ puts "Powered on virtual machine #{vmname}"
78
+ end
79
+ when 'off'
80
+ if state == PsOff
81
+ puts "Virtual machine #{vmname} was already powered off"
82
+ else
83
+ vm.PowerOffVM_Task.wait_for_completion
84
+ puts "Powered off virtual machine #{vmname}"
85
+ end
86
+ when 'suspend'
87
+ if state == PowerStates['suspended']
88
+ puts "Virtual machine #{vmname} was already suspended"
89
+ else
90
+ vm.SuspendVM_Task.wait_for_completion
91
+ puts "Suspended virtual machine #{vmname}"
92
+ end
93
+ when 'reset'
94
+ vm.ResetVM_Task.wait_for_completion
95
+ puts "Reset virtual machine #{vmname}"
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,4 +1,4 @@
1
1
  module KnifeVsphere
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 3
10
- version: 0.1.3
9
+ - 4
10
+ version: 0.1.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ezra Pagel
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-30 00:00:00 -05:00
18
+ date: 2011-07-05 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -64,6 +64,7 @@ files:
64
64
  - lib/chef/knife/vsphere_vm_clone.rb
65
65
  - lib/chef/knife/vsphere_vm_delete.rb
66
66
  - lib/chef/knife/vsphere_vm_list.rb
67
+ - lib/chef/knife/vsphere_vm_state.rb
67
68
  - lib/chef/knife/VsphereBaseCommand.rb
68
69
  - lib/knife-vsphere/version.rb
69
70
  has_rdoc: true