knife-vsphere 1.2.14 → 1.2.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5568fb262d8a952f210fb7a7100f54bbc4c0c989
4
- data.tar.gz: 2d103c82c324bf3f9577adc8a92583771ce5ccd1
3
+ metadata.gz: ffde4a9240d703c519b66c4d7bddf1a26b5fdc2d
4
+ data.tar.gz: df28bd7b23377431778c93d79a6d04ec358dccbc
5
5
  SHA512:
6
- metadata.gz: 96ccd1409e9573d2c26038163c32bfecb2d3d365d1b2af493ca1d0eb475fcd5f7a2a60a48a656f2d1dd26775da9f692fed192abdfe5281c9c159523cc3ff63a4
7
- data.tar.gz: 9106e7eb45638e26928413b0fc2a6406bb79ab2023515edda7e5c8415e0e686ad137ba5fc54d834df694bb70033707e8bcd37489e7b40920d420ec6d900d72f4
6
+ metadata.gz: bf661f541572092f3a3746cc130ac5d04c7341cffee903e96118aa3ae813f5be37654d6effb654bb39de782ebb64e9a98ba2a59542dd8bf8912b026a2f385680
7
+ data.tar.gz: 7e641d48b040865eace2e255c29f149b2ebc66dcbf1d3af9509a63c230ca202a73bd933dcd5bd5561591eeaf428e7757341b01f608482181e43bc6b864ff2e34
@@ -9,6 +9,10 @@ require 'rbvmomi'
9
9
  require 'base64'
10
10
  require 'filesize'
11
11
 
12
+ PS_ON ||= 'poweredOn'.freeze
13
+ PS_OFF ||= 'poweredOff'.freeze
14
+ PS_SUSPENDED ||= 'suspended'.freeze
15
+
12
16
  # Base class for vsphere knife commands
13
17
  class Chef
14
18
  class Knife
@@ -110,7 +114,7 @@ class Chef
110
114
  end
111
115
 
112
116
  def vim_connection
113
- config[:vim] = RbVmomi::VIM.connect conn_opts
117
+ config[:vim] ||= RbVmomi::VIM.connect conn_opts
114
118
  end
115
119
 
116
120
  def get_password_from_stdin
@@ -183,7 +187,7 @@ class Chef
183
187
 
184
188
  def datacenter
185
189
  dcname = get_config(:vsphere_dc)
186
- traverse_folders_for_dc(config[:vim].rootFolder, dcname) || abort('datacenter not found')
190
+ traverse_folders_for_dc(vim_connection.rootFolder, dcname) || abort('datacenter not found')
187
191
  end
188
192
 
189
193
  def find_folder(folderName)
@@ -373,6 +377,7 @@ class Chef
373
377
  def linux?(config)
374
378
  gid = config.guestId.downcase
375
379
  # This makes the assumption that if it isn't mac or windows it's linux
380
+ # See https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html for values
376
381
  is_linux_bool = !gid.include?('windows') && !gid.include?('darwin')
377
382
  Chef::Log.debug('Identified os as linux.') if is_linux_bool
378
383
  is_linux_bool
@@ -16,14 +16,12 @@ require 'chef/knife/winrm_base'
16
16
  require 'chef/knife/customization_helper'
17
17
  require 'ipaddr'
18
18
 
19
- # Clone an existing template into a new VM, optionally applying a customization specification.
20
- # usage:
21
- # knife vsphere vm clone NewNode UbuntuTemplate --cspec StaticSpec \
22
- # --cips 192.168.0.99/24,192.168.1.99/24 \
23
- # --chostname NODENAME --cdomain NODEDOMAIN
24
19
  class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
25
20
  banner 'knife vsphere vm clone VMNAME (options)'
26
21
 
22
+ AUTO_MAC = 'auto'
23
+ NO_IPS = ''
24
+
27
25
  include Chef::Knife::WinrmBase
28
26
  include CustomizationHelper
29
27
  deps do
@@ -91,11 +89,12 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
91
89
  option :customization_macs,
92
90
  long: '--cmacs CUST_MACS',
93
91
  description: 'Comma-delimited list of MAC addresses for network adapters',
94
- default: 'auto'
92
+ default: AUTO_MAC
95
93
 
96
94
  option :customization_ips,
97
95
  long: '--cips CUST_IPS',
98
- description: 'Comma-delimited list of CIDR IPs for customization'
96
+ description: 'Comma-delimited list of CIDR IPs for customization',
97
+ default: NO_IPS
99
98
 
100
99
  option :customization_dns_ips,
101
100
  long: '--cdnsips CUST_DNS_IPS',
@@ -147,6 +146,10 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
147
146
  long: '--fqdn SERVER_FQDN',
148
147
  description: 'Fully qualified hostname for bootstrapping'
149
148
 
149
+ option :bootstrap_msi_url,
150
+ long: '--bootstrap-msi-url URL',
151
+ description: 'Location of the Chef Client MSI. The default templates will prefer to download from this location.'
152
+
150
153
  option :bootstrap_protocol,
151
154
  long: '--bootstrap-protocol protocol',
152
155
  description: 'Protocol to bootstrap windows servers. options: winrm/ssh',
@@ -311,6 +314,16 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
311
314
  fatal_exit('You must specify a virtual machine name OR use --random-vmname')
312
315
  end
313
316
 
317
+ abort '--template or knife[:source_vm] must be specified' unless config[:source_vm]
318
+
319
+ if get_config(:datastore) && get_config(:datastorecluster)
320
+ abort 'Please select either datastore or datastorecluster'
321
+ end
322
+
323
+ if get_config(:customization_macs) != AUTO_MAC && get_config(:customization_ips) == NO_IPS
324
+ abort('Must specify IP numbers with --cips when specifying MAC addresses with --cmacs, can use "dhcp" as placeholder')
325
+ end
326
+
314
327
  config[:chef_node_name] = vmname unless get_config(:chef_node_name)
315
328
  config[:vmname] = vmname
316
329
 
@@ -321,8 +334,6 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
321
334
 
322
335
  src_folder = find_folder(get_config(:folder)) || dc.vmFolder
323
336
 
324
- abort '--template or knife[:source_vm] must be specified' unless config[:source_vm]
325
-
326
337
  src_vm = find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, config[:source_vm]) ||
327
338
  abort('VM/Template not found')
328
339
 
@@ -395,19 +406,18 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
395
406
  puts 'Waiting for network interfaces to become available...'
396
407
  sleep 2 while vm.guest.net.empty? || !vm.guest.ipAddress
397
408
  ui.info "Found address #{vm.guest.ipAddress}" if log_verbose?
398
- guest_address ||=
399
- config[:fqdn] = if config[:bootstrap_ipv4]
400
- ipv4_address(vm)
401
- elsif config[:fqdn]
402
- get_config(:fqdn)
403
- else
404
- # Use the first IP which is not a link-local address.
405
- # This is the closest thing to vm.guest.ipAddress but
406
- # allows specifying a NIC.
407
- vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect do |addr|
408
- addr.origin != 'linklayer'
409
- end.ipAddress
410
- end
409
+ config[:fqdn] = if config[:bootstrap_ipv4]
410
+ ipv4_address(vm)
411
+ elsif config[:fqdn]
412
+ get_config(:fqdn)
413
+ else
414
+ # Use the first IP which is not a link-local address.
415
+ # This is the closest thing to vm.guest.ipAddress but
416
+ # allows specifying a NIC.
417
+ vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect do |addr|
418
+ addr.origin != 'linklayer'
419
+ end.ipAddress
420
+ end
411
421
  end
412
422
 
413
423
  def wait_for_access(connect_host, connect_port, protocol)
@@ -417,7 +427,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
417
427
  config[:winrm_port] = '5986'
418
428
  end
419
429
  connect_port = get_config(:winrm_port)
420
- print "\n#{ui.color("Waiting for winrm access to become available on #{connect_host}:#{connect_port}",:magenta)}"
430
+ print "\n#{ui.color("Waiting for winrm access to become available on #{connect_host}:#{connect_port}", :magenta)}"
421
431
  print('.') until tcp_test_winrm(connect_host, connect_port) do
422
432
  sleep 10
423
433
  puts('done')
@@ -456,51 +466,47 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
456
466
  end
457
467
  end
458
468
 
459
- # Builds a CloneSpec
460
- def generate_clone_spec(src_config)
461
- rspec = nil
462
- if get_config(:resource_pool)
463
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: find_pool(get_config(:resource_pool)))
464
- else
465
- dc = datacenter
466
- hosts = traverse_folders_for_computeresources(dc.hostFolder)
467
- fatal_exit('No ComputeResource found - Use --resource-pool to specify a resource pool or a cluster') if hosts.empty?
468
- hosts.reject!(&:nil?)
469
- hosts.reject! { |host| host.host.all? { |h| h.runtime.inMaintenanceMode } }
470
- fatal_exit 'All hosts in maintenance mode!' if hosts.empty?
471
-
472
- if get_config(:datastore)
473
- hosts.reject! { |host| !host.datastore.include?(find_datastore(get_config(:datastore))) }
474
- end
469
+ def find_available_hosts
470
+ hosts = traverse_folders_for_computeresources(datacenter.hostFolder)
471
+ fatal_exit('No ComputeResource found - Use --resource-pool to specify a resource pool or a cluster') if hosts.empty?
472
+ hosts.reject!(&:nil?)
473
+ hosts.reject! { |host| host.host.all? { |h| h.runtime.inMaintenanceMode } }
474
+ fatal_exit 'All hosts in maintenance mode!' if hosts.empty?
475
+ if get_config(:datastore)
476
+ hosts.reject! { |host| !host.datastore.include?(find_datastore(get_config(:datastore))) }
477
+ end
475
478
 
476
- fatal_exit "No hosts have the requested Datastore available! #{get_config(:datastore)}" if hosts.empty?
479
+ fatal_exit "No hosts have the requested Datastore available! #{get_config(:datastore)}" if hosts.empty?
477
480
 
478
- if get_config(:datastorecluster)
479
- hosts.reject! { |host| !host.datastore.include?(find_datastorecluster(get_config(:datastorecluster))) }
480
- end
481
+ if get_config(:datastorecluster)
482
+ hosts.reject! { |host| !host.datastore.include?(find_datastorecluster(get_config(:datastorecluster))) }
483
+ end
481
484
 
482
- fatal_exit "No hosts have the requested DatastoreCluster available! #{get_config(:datastorecluster)}" if hosts.empty?
485
+ fatal_exit "No hosts have the requested DatastoreCluster available! #{get_config(:datastorecluster)}" if hosts.empty?
483
486
 
484
- if get_config(:customization_vlan)
485
- vlan_list = get_config(:customization_vlan).split(',')
486
- vlan_list.each do |network|
487
- hosts.reject! { |host| !host.network.include?(find_network(network)) }
488
- end
487
+ if get_config(:customization_vlan)
488
+ vlan_list = get_config(:customization_vlan).split(',')
489
+ vlan_list.each do |network|
490
+ hosts.reject! { |host| !host.network.include?(find_network(network)) }
489
491
  end
492
+ end
490
493
 
491
- fatal_exit "No hosts have the requested Network available! #{get_config(:customization_vlan)}" if hosts.empty?
494
+ fatal_exit "No hosts have the requested Network available! #{get_config(:customization_vlan)}" if hosts.empty?
495
+ hosts
496
+ end
492
497
 
493
- rp = hosts.first.resourcePool
494
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: rp)
495
- end
498
+ # Builds a CloneSpec
499
+ def generate_clone_spec(src_config)
500
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec
496
501
 
497
- if get_config(:linked_clone)
498
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(diskMoveType: :moveChildMostDiskBacking)
499
- end
502
+ rspec.pool = if get_config(:resource_pool)
503
+ find_pool(get_config(:resource_pool))
504
+ else
505
+ hosts = find_available_hosts
506
+ hosts.first.resourcePool
507
+ end
500
508
 
501
- if get_config(:datastore) && get_config(:datastorecluster)
502
- abort 'Please select either datastore or datastorecluster'
503
- end
509
+ rspec.diskMoveType = :moveChildMostDiskBacking if get_config(:linked_clone)
504
510
 
505
511
  if get_config(:datastore)
506
512
  rspec.datastore = find_datastore(get_config(:datastore))
@@ -516,9 +522,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
516
522
  end
517
523
  end
518
524
 
519
- if get_config(:thin_provision)
520
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(transform: :sparse, pool: find_pool(get_config(:resource_pool)))
521
- end
525
+ rspec.transform = :sparse if get_config(:thin_provision)
522
526
 
523
527
  is_template = !get_config(:mark_as_template).nil?
524
528
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: rspec, powerOn: false, template: is_template)
@@ -537,12 +541,8 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
537
541
  clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024
538
542
  end
539
543
 
540
- if get_config(:customization_macs) && !get_config(:customization_ips)
541
- abort('Must specify IP numbers with --cips when specifying MAC addresses with --cmacs, can use "dhcp" as placeholder')
542
- end
543
-
544
- mac_list = if get_config(:customization_macs) == 'auto'
545
- ['auto'] * get_config(:customization_ips).split(',').length
544
+ mac_list = if get_config(:customization_macs) == AUTO_MAC
545
+ [AUTO_MAC] * get_config(:customization_ips).split(',').length
546
546
  else
547
547
  get_config(:customization_macs).split(',')
548
548
  end
@@ -581,21 +581,26 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
581
581
  # not connected to a distibuted switch?
582
582
  card.backing = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(network: network, deviceName: network.name)
583
583
  end
584
- card.macAddress = mac_list[index] if get_config(:customization_macs) && mac_list[index] != 'auto'
584
+ card.macAddress = mac_list[index] if get_config(:customization_macs) && mac_list[index] != AUTO_MAC
585
585
  dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(device: card, operation: 'edit')
586
586
  clone_spec.config.deviceChange.push dev_spec
587
587
  end
588
588
  end
589
589
 
590
- if get_config(:customization_spec)
591
- csi = find_customization(get_config(:customization_spec)) ||
592
- fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")
590
+ cust_spec = if get_config(:customization_spec)
591
+ csi = find_customization(get_config(:customization_spec)) ||
592
+ fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")
593
593
 
594
- cust_spec = csi.spec
595
- else
596
- global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings
597
- identity_settings = RbVmomi::VIM.CustomizationIdentitySettings
598
- cust_spec = RbVmomi::VIM.CustomizationSpec(globalIPSettings: global_ipset, identity: identity_settings)
594
+ csi.spec
595
+ else
596
+ global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings
597
+ identity_settings = RbVmomi::VIM.CustomizationIdentitySettings
598
+ RbVmomi::VIM.CustomizationSpec(globalIPSettings: global_ipset, identity: identity_settings)
599
+ end
600
+
601
+ if get_config(:disable_customization)
602
+ clone_spec.customization = get_config(:customization_spec) ? cust_spec : nil
603
+ return clone_spec
599
604
  end
600
605
 
601
606
  if get_config(:customization_dns_ips)
@@ -612,71 +617,67 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
612
617
  }
613
618
  end
614
619
 
615
- if get_config(:disable_customization)
616
- clone_spec.customization = cust_spec
617
- else
618
- use_ident = !config[:customization_hostname].nil? || !get_config(:customization_domain).nil? || cust_spec.identity.nil?
619
-
620
- if use_ident
621
- hostname = if config[:customization_hostname]
622
- config[:customization_hostname]
623
- else
624
- config[:vmname]
625
- end
626
- if windows?(src_config)
627
- identification = RbVmomi::VIM.CustomizationIdentification(
628
- joinWorkgroup: cust_spec.identity.identification.joinWorkgroup
629
- )
630
- license_file_print_data = RbVmomi::VIM.CustomizationLicenseFilePrintData(
631
- autoMode: cust_spec.identity.licenseFilePrintData.autoMode
632
- )
633
-
634
- user_data = RbVmomi::VIM.CustomizationUserData(
635
- fullName: cust_spec.identity.userData.fullName,
636
- orgName: cust_spec.identity.userData.orgName,
637
- productId: cust_spec.identity.userData.productId,
638
- computerName: RbVmomi::VIM.CustomizationFixedName(name: hostname)
639
- )
640
-
641
- gui_unattended = RbVmomi::VIM.CustomizationGuiUnattended(
642
- autoLogon: cust_spec.identity.guiUnattended.autoLogon,
643
- autoLogonCount: cust_spec.identity.guiUnattended.autoLogonCount,
644
- password: RbVmomi::VIM.CustomizationPassword(
645
- plainText: cust_spec.identity.guiUnattended.password.plainText,
646
- value: cust_spec.identity.guiUnattended.password.value
647
- ),
648
- timeZone: cust_spec.identity.guiUnattended.timeZone
649
- )
650
- runonce = RbVmomi::VIM.CustomizationGuiRunOnce(
651
- commandList: ['cust_spec.identity.guiUnattended.commandList']
652
- )
653
- ident = RbVmomi::VIM.CustomizationSysprep
654
- ident.guiRunOnce = runonce
655
- ident.guiUnattended = gui_unattended
656
- ident.identification = identification
657
- ident.licenseFilePrintData = license_file_print_data
658
- ident.userData = user_data
659
- cust_spec.identity = ident
660
- elsif linux?(src_config)
661
- ident = RbVmomi::VIM.CustomizationLinuxPrep
662
- ident.hostName = RbVmomi::VIM.CustomizationFixedName(name: hostname)
663
-
664
- ident.domain = if get_config(:customization_domain)
665
- get_config(:customization_domain)
666
- else
667
- ''
668
- end
669
- cust_spec.identity = ident
670
- else
671
- ui.error('Customization only supports Linux and Windows currently.')
672
- exit 1
673
- end
620
+ # TODO: why does the domain matter?
621
+ use_ident = config[:customization_hostname] || get_config(:customization_domain) || cust_spec.identity.props.empty?
622
+
623
+ # TODO: How could we not take this? Only if the identity were empty, but that's statically defined as empty above
624
+ if use_ident
625
+ hostname = config[:customization_hostname] || config[:vmname]
626
+
627
+ if windows?(src_config)
628
+ # TODO: This is just copying itself onto itself, isn't it?
629
+ identification = RbVmomi::VIM.CustomizationIdentification(
630
+ joinWorkgroup: cust_spec.identity.identification.joinWorkgroup
631
+ )
632
+ license_file_print_data = RbVmomi::VIM.CustomizationLicenseFilePrintData(
633
+ autoMode: cust_spec.identity.licenseFilePrintData.autoMode
634
+ )
635
+
636
+ user_data = RbVmomi::VIM.CustomizationUserData(
637
+ fullName: cust_spec.identity.userData.fullName,
638
+ orgName: cust_spec.identity.userData.orgName,
639
+ productId: cust_spec.identity.userData.productId,
640
+ computerName: RbVmomi::VIM.CustomizationFixedName(name: hostname)
641
+ )
642
+
643
+ gui_unattended = RbVmomi::VIM.CustomizationGuiUnattended(
644
+ autoLogon: cust_spec.identity.guiUnattended.autoLogon,
645
+ autoLogonCount: cust_spec.identity.guiUnattended.autoLogonCount,
646
+ password: RbVmomi::VIM.CustomizationPassword(
647
+ plainText: cust_spec.identity.guiUnattended.password.plainText,
648
+ value: cust_spec.identity.guiUnattended.password.value
649
+ ),
650
+ timeZone: cust_spec.identity.guiUnattended.timeZone
651
+ )
652
+ runonce = RbVmomi::VIM.CustomizationGuiRunOnce(
653
+ commandList: ['cust_spec.identity.guiUnattended.commandList']
654
+ )
655
+ ident = RbVmomi::VIM.CustomizationSysprep
656
+ ident.guiRunOnce = runonce
657
+ ident.guiUnattended = gui_unattended
658
+ ident.identification = identification
659
+ ident.licenseFilePrintData = license_file_print_data
660
+ ident.userData = user_data
661
+ cust_spec.identity = ident
662
+ elsif linux?(src_config)
663
+ ident = RbVmomi::VIM.CustomizationLinuxPrep
664
+ ident.hostName = RbVmomi::VIM.CustomizationFixedName(name: hostname)
665
+
666
+ ident.domain = if get_config(:customization_domain)
667
+ get_config(:customization_domain)
668
+ else
669
+ ''
670
+ end
671
+ cust_spec.identity = ident
672
+ else
673
+ ui.error('Customization only supports Linux and Windows currently.')
674
+ exit 1
674
675
  end
675
- clone_spec.customization = cust_spec
676
+ end
677
+ clone_spec.customization = cust_spec
676
678
 
677
- if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec)
678
- clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec)
679
- end
679
+ if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec)
680
+ clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec)
680
681
  end
681
682
  clone_spec
682
683
  end
@@ -717,7 +718,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
717
718
  # @param name [String] name of customization
718
719
  # @return [RbVmomi::VIM::CustomizationSpecItem]
719
720
  def find_customization(name)
720
- csm = config[:vim].serviceContent.customizationSpecManager
721
+ csm = vim_connection.serviceContent.customizationSpecManager
721
722
  csm.GetCustomizationSpec(name: name)
722
723
  end
723
724
 
@@ -748,7 +749,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
748
749
  end
749
750
 
750
751
  adapter_map = RbVmomi::VIM.CustomizationAdapterMapping
751
- adapter_map.macAddress = mac if !mac.nil? && (mac != 'auto')
752
+ adapter_map.macAddress = mac if !mac.nil? && (mac != AUTO_MAC)
752
753
  adapter_map.adapter = settings
753
754
  adapter_map
754
755
  end
@@ -789,6 +790,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
789
790
  ui.error('Unsupported Bootstrapping Protocol. Supports : winrm, ssh')
790
791
  exit 1
791
792
  end
793
+ bootstrap.config[:msi_url] = get_config(:bootstrap_msi_url)
792
794
  bootstrap_common_params(bootstrap)
793
795
  end
794
796
 
@@ -802,6 +804,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
802
804
  bootstrap.config[:ssh_port] = get_config(:ssh_port)
803
805
  bootstrap.config[:identity_file] = get_config(:identity_file)
804
806
  bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
807
+ bootstrap.config[:use_sudo_password] = true unless get_config(:ssh_user) == 'root'
805
808
  bootstrap.config[:log_level] = get_config(:log_level)
806
809
  bootstrap_common_params(bootstrap)
807
810
  end
@@ -8,10 +8,6 @@ require 'chef/knife/base_vsphere_command'
8
8
  require 'rbvmomi'
9
9
  require 'netaddr'
10
10
 
11
- PsOn = 'poweredOn'
12
- PsOff = 'poweredOff'
13
- PsSuspended = 'suspended'
14
-
15
11
  # find vms belonging to pool that match criteria, display specified fields
16
12
  class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
17
13
  banner 'knife vsphere vm find'
@@ -95,22 +91,20 @@ class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
95
91
  long: '--full-path',
96
92
  description: 'Show full path'
97
93
 
98
- $stdout.sync = true # smoother output from print
94
+ $stdout.sync = true # smoother output from print
99
95
 
100
96
  def traverse_folders_for_pool_clustercompute(folder, poolname)
101
- # children = folder.children.find_all
102
97
  children = find_all_in_folder(folder, RbVmomi::VIM::ManagedObject)
103
98
  children.each do |child|
104
- if child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ResourcePool
105
- if child.name == poolname then return child
106
- else if child.class == RbVmomi::VIM::Folder || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ResourcePool
107
- pool = traverse_folders_for_pool_clustercompute(child, poolname)
108
- end
109
- end
110
- if pool then return pool end
99
+ next unless child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ResourcePool
100
+ if child.name == poolname
101
+ return child
102
+ elsif child.class == RbVmomi::VIM::Folder || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ResourcePool
103
+ pool = traverse_folders_for_pool_clustercompute(child, poolname)
111
104
  end
105
+ return pool if pool
112
106
  end
113
- return false
107
+ false
114
108
  end
115
109
 
116
110
  def run
@@ -120,125 +114,124 @@ class Chef::Knife::VsphereVmFind < Chef::Knife::BaseVsphereCommand
120
114
  fatal_exit('You must specify a resource pool or cluster name (see knife vsphere pool list)')
121
115
  end
122
116
 
123
- vim = vim_connection
117
+ vim_connection
124
118
  dc = datacenter
125
119
  folder = dc.hostFolder
126
120
 
127
- pool = traverse_folders_for_pool_clustercompute(folder, poolname) or abort "Pool #{poolname} not found"
121
+ pool = traverse_folders_for_pool_clustercompute(folder, poolname) || abort("Pool #{poolname} not found")
128
122
 
129
- if pool.class == RbVmomi::VIM::ResourcePool
130
- vm = pool.vm
131
- else
132
- vm = pool.resourcePool.vm
133
- end
134
-
135
- unless vm.nil?
136
- vm.each do |vmc|
137
- state = case vmc.runtime.powerState
138
- when PsOn
139
- ui.color('on', :green)
140
- when PsOff
141
- ui.color('off', :red)
142
- when PsSuspended
143
- ui.color('suspended', :yellow)
144
- end
145
-
146
- if get_config(:matchname)
147
- next unless vmc.name.include? config[:matchname]
148
- end
149
-
150
- if get_config(:matchtools)
151
- next unless vmc.guest.toolsStatus == config[:matchtools]
152
- end
153
-
154
- next if get_config(:soff) && (vmc.runtime.powerState == PsOn)
155
-
156
- next if get_config(:son) && (vmc.runtime.powerState == PsOff)
157
-
158
- if get_config(:matchip)
159
- if (!vmc.guest.ipAddress.nil? && vmc.guest.ipAddress != '')
160
- next unless vmc.guest.ipAddress.include? config[:matchip]
161
- else
162
- next
123
+ vm = if pool.class == RbVmomi::VIM::ResourcePool
124
+ pool.vm
125
+ else
126
+ pool.resourcePool.vm
163
127
  end
164
- end
165
128
 
166
- unless vmc.guest.guestFullName.nil?
167
- if get_config(:matchos)
168
- next unless vmc.guest.guestFullName.include? config[:matchos]
169
- end
170
- end
171
-
172
- print "#{ui.color("VM Name:", :cyan)} #{vmc.name}\t"
173
- if get_config(:hostname)
174
- print "#{ui.color("Hostname:", :cyan)} #{vmc.guest.hostName}\t"
175
- end
176
-
177
- if get_config(:full_path)
178
- actualname = ''
179
- vmcp = vmc
180
- while vmcp.parent != nil && vmcp.parent.name != 'vm'
181
- actualname.concat("#{vmcp.parent.name}/")
182
- vmcp = vmcp.parent
183
- end
184
- print "#{ui.color("Folder:", :cyan)}"
185
- print "\""
186
- print actualname.split('/').reverse().join('/')
187
- print "\"\t"
188
-
189
- else
190
- print "#{ui.color("Folder", :cyan)}: #{vmc.parent.name}\t"
191
- end
192
-
193
- if get_config(:ip)
194
- print "#{ui.color("IP:", :cyan)} #{vmc.guest.ipAddress}\t"
195
- end
196
- if get_config(:ips)
197
- ipregex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
198
- networks = vmc.guest.net.map { |net| "#{net.network}:" + net.ipConfig.ipAddress.select { |i| i.ipAddress[ipregex] }[0].ipAddress }
199
- print "#{ui.color("IPS:", :cyan)} #{networks.join(",")}\t"
200
- end
201
- if get_config(:os)
202
- print "#{ui.color("OS:", :cyan)} #{vmc.guest.guestFullName}\t"
203
- end
204
- if get_config(:ram)
205
- print "#{ui.color("RAM:", :cyan)} #{vmc.summary.config.memorySizeMB}\t"
206
- end
207
- if get_config(:cpu)
208
- print "#{ui.color("CPU:", :cyan)} #{vmc.summary.config.numCpu}\t"
209
- end
210
- if get_config(:alarms)
211
- print "#{ui.color("Alarms:", :cyan)} #{vmc.summary.overallStatus}\t"
212
- end
213
- print "#{ui.color("State:", :cyan)} #{state}\t"
214
- if get_config(:tools)
215
- print "#{ui.color("Tools:", :cyan)} #{vmc.guest.toolsStatus}\t"
216
- end
217
-
218
- if get_config(:os_disk)
219
- print "#{ui.color("OS Disks:", :cyan)}"
220
- vmc.guest.disk.each do |disc|
221
- print "#{disc.diskPath} #{disc.capacity / 1024 / 1024}MB Free:#{disc.freeSpace / 1024 / 1024}MB |"
222
- end
223
- end
129
+ return if vm.nil?
130
+ vm.each do |vmc|
131
+ state = case vmc.runtime.powerState
132
+ when PS_ON
133
+ ui.color('on', :green)
134
+ when PS_OFF
135
+ ui.color('off', :red)
136
+ when PS_SUSPENDED
137
+ ui.color('suspended', :yellow)
138
+ end
224
139
 
225
- if get_config(:esx_disk)
226
- print "#{ui.color("ESX Disks:", :cyan)}"
227
- vmc.layout.disk.each do |dsc|
228
- print "#{dsc.diskFile} | "
229
- end
230
- end
231
-
232
- if get_config(:snapshots)
233
- unless vmc.snapshot.nil?
234
- print "#{ui.color("Snapshots:", :cyan)}"
235
- vmc.snapshot.rootSnapshotList.each do |snap|
236
- print " #{snap.name}"
237
- end
238
- end
239
- end
240
- puts
140
+ if get_config(:matchname)
141
+ next unless vmc.name.include? config[:matchname]
142
+ end
143
+
144
+ if get_config(:matchtools)
145
+ next unless vmc.guest.toolsStatus == config[:matchtools]
146
+ end
147
+
148
+ next if get_config(:soff) && (vmc.runtime.powerState == PS_ON)
149
+
150
+ next if get_config(:son) && (vmc.runtime.powerState == PS_OFF)
151
+
152
+ if get_config(:matchip)
153
+ if !vmc.guest.ipAddress.nil? && vmc.guest.ipAddress != ''
154
+ next unless vmc.guest.ipAddress.include? config[:matchip]
155
+ else
156
+ next
157
+ end
158
+ end
159
+
160
+ unless vmc.guest.guestFullName.nil?
161
+ if get_config(:matchos)
162
+ next unless vmc.guest.guestFullName.include? config[:matchos]
163
+ end
164
+ end
165
+
166
+ print "#{ui.color('VM Name:', :cyan)} #{vmc.name}\t"
167
+ if get_config(:hostname)
168
+ print "#{ui.color('Hostname:', :cyan)} #{vmc.guest.hostName}\t"
169
+ end
170
+
171
+ if get_config(:full_path)
172
+ actualname = ''
173
+ vmcp = vmc
174
+ while !vmcp.parent.nil? && vmcp.parent.name != 'vm'
175
+ actualname.concat("#{vmcp.parent.name}/")
176
+ vmcp = vmcp.parent
177
+ end
178
+ print ui.color('Folder:', :cyan)
179
+ print '"'
180
+ print actualname.split('/').reverse.join('/')
181
+ print "\"\t"
182
+
183
+ else
184
+ print "#{ui.color('Folder', :cyan)}: #{vmc.parent.name}\t"
185
+ end
186
+
187
+ if get_config(:ip)
188
+ print "#{ui.color('IP:', :cyan)} #{vmc.guest.ipAddress}\t"
189
+ end
190
+ if get_config(:ips)
191
+ ipregex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
192
+ networks = vmc.guest.net.map { |net| "#{net.network}:" + net.ipConfig.ipAddress.select { |i| i.ipAddress[ipregex] }[0].ipAddress }
193
+ print "#{ui.color('IPS:', :cyan)} #{networks.join(',')}\t"
194
+ end
195
+ if get_config(:os)
196
+ print "#{ui.color('OS:', :cyan)} #{vmc.guest.guestFullName}\t"
197
+ end
198
+ if get_config(:ram)
199
+ print "#{ui.color('RAM:', :cyan)} #{vmc.summary.config.memorySizeMB}\t"
200
+ end
201
+ if get_config(:cpu)
202
+ print "#{ui.color('CPU:', :cyan)} #{vmc.summary.config.numCpu}\t"
203
+ end
204
+ if get_config(:alarms)
205
+ print "#{ui.color('Alarms:', :cyan)} #{vmc.summary.overallStatus}\t"
206
+ end
207
+ print "#{ui.color('State:', :cyan)} #{state}\t"
208
+ if get_config(:tools)
209
+ print "#{ui.color('Tools:', :cyan)} #{vmc.guest.toolsStatus}\t"
210
+ end
211
+
212
+ if get_config(:os_disk)
213
+ print ui.color('OS Disks:', :cyan)
214
+ vmc.guest.disk.each do |disc|
215
+ print "#{disc.diskPath} #{disc.capacity / 1024 / 1024}MB Free:#{disc.freeSpace / 1024 / 1024}MB |"
216
+ end
217
+ end
218
+
219
+ if get_config(:esx_disk)
220
+ print ui.color('ESX Disks:', :cyan)
221
+ vmc.layout.disk.each do |dsc|
222
+ print "#{dsc.diskFile} | "
223
+ end
224
+ end
225
+
226
+ if get_config(:snapshots)
227
+ unless vmc.snapshot.nil?
228
+ print ui.color('Snapshots:', :cyan)
229
+ vmc.snapshot.rootSnapshotList.each do |snap|
230
+ print " #{snap.name}"
231
+ end
232
+ end
241
233
  end
234
+ puts
242
235
  end
243
236
  end
244
237
  end
@@ -8,18 +8,14 @@ require 'chef/knife/base_vsphere_command'
8
8
  require 'rbvmomi'
9
9
  require 'netaddr'
10
10
 
11
- PS_ON = 'poweredOn'
12
- PS_OFF = 'poweredOff'
13
- PS_SUSPENDED = 'suspended'
14
-
15
- POWER_STATES = {
16
- PS_ON => 'powered on',
17
- PS_OFF => 'powered off',
18
- PS_SUSPENDED => 'suspended'
19
- }
20
-
21
11
  # Manage power state of a virtual machine
22
12
  class Chef::Knife::VsphereVmState < Chef::Knife::BaseVsphereCommand
13
+ POWER_STATES = {
14
+ PS_ON => 'powered on',
15
+ PS_OFF => 'powered off',
16
+ PS_SUSPENDED => 'suspended'
17
+ }
18
+
23
19
  banner 'knife vsphere vm state VMNAME (options)'
24
20
 
25
21
  common_options
@@ -1,3 +1,3 @@
1
1
  module KnifeVsphere
2
- VERSION = '1.2.14'
2
+ VERSION = '1.2.16'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.14
4
+ version: 1.2.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Pagel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-30 00:00:00.000000000 Z
11
+ date: 2016-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: filesize
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: VMware vSphere Support for Chef's Knife Command
112
126
  email: ezra@cpan.org
113
127
  executables: []