knife-vsphere 0.1.3 → 0.1.4

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.
@@ -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