Class: Chef::Knife::VsphereVmClone
- Inherits:
-
BaseVsphereCommand
- Object
- Bootstrap
- BaseVsphereCommand
- Chef::Knife::VsphereVmClone
- Defined in:
- lib/chef/knife/vsphere_vm_clone.rb
Overview
VsphereVmClone extends the BaseVspherecommand
Instance Attribute Summary collapse
-
#server_name ⇒ Object
(also: #host_descriptor)
Returns the value of attribute server_name.
Instance Method Summary collapse
- #all_the_hosts ⇒ Object
- #create_delta_disk(src_vm) ⇒ Object
-
#customization_plugin ⇒ KnifeVspherePlugin
Loads the customization plugin if one was specified.
- #find_available_hosts ⇒ Object
-
#find_customization(name) ⇒ RbVmomi::VIM::CustomizationSpecItem
Retrieves a CustomizationSpecItem that matches the supplied name.
- #find_host(host_name) ⇒ Object
-
#generate_adapter_map(ip = nil, gw = nil, mac = nil) ⇒ RbVmomi::VIM::CustomizationIPSettings
Generates a CustomizationAdapterMapping (currently only single IPv4 address) object.
-
#generate_clone_spec(src_config) ⇒ Object
Builds a CloneSpec.
- #guest_address(vm) ⇒ Object
- #ipv4_address(vm) ⇒ Object
-
#plugin_create_instance! ⇒ TrueClass
Create the server that we will bootstrap, if necessary.
-
#plugin_finalize ⇒ void
Perform any teardown or cleanup necessary by the plugin.
-
#plugin_setup! ⇒ TrueClass
Perform any setup necessary by the plugin.
-
#plugin_validate_options! ⇒ TrueClass
If options are valid or exits.
- #run ⇒ Object
- #tcp_test_ssh(hostname, connection_port) ⇒ Object
- #tcp_test_winrm(hostname, port) ⇒ Object
- #validate_name_args! ⇒ Object
- #vm_is_waiting_for_ip?(vm) ⇒ Boolean
- #wait_for_access(connect_host, connect_port, protocol) ⇒ Object
Methods inherited from BaseVsphereCommand
#choose_datastore, common_options, #conn_opts, #datacenter, #fatal_exit, #find_all_in_folder, #find_datastore, #find_datastorecluster, #find_datastores_regex, #find_device, #find_folder, #find_in_folder, #find_network, #find_pool, #find_pool_folder, #find_pools_and_clusters, #get_config, #get_password_from_stdin, #get_path_to_object, #linux?, #number_to_human_size, #password, #tcp_test_port, #tcp_test_port_vm, #traverse_folders_for_computeresources, #traverse_folders_for_dc, #traverse_folders_for_pools, #vim_connection, #windows?
Instance Attribute Details
#server_name ⇒ Object Also known as: host_descriptor
Returns the value of attribute server_name.
264 265 266 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 264 def server_name @server_name end |
Instance Method Details
#all_the_hosts ⇒ Object
475 476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 475 def all_the_hosts hosts = traverse_folders_for_computeresources(datacenter.hostFolder) all_hosts = [] hosts.each do |host| if host.is_a? RbVmomi::VIM::ClusterComputeResource all_hosts.concat(host.host) else all_hosts.push host end end all_hosts end |
#create_delta_disk(src_vm) ⇒ Object
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 422 def create_delta_disk(src_vm) disks = src_vm.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk) disks.select { |disk| disk.backing.parent.nil? }.each do |disk| spec = { deviceChange: [ { operation: :remove, device: disk, }, { operation: :add, fileOperation: :create, device: disk.dup.tap do |new_disk| new_disk.backing = new_disk.backing.dup new_disk.backing.fileName = "[#{disk.backing.datastore.name}]" new_disk.backing.parent = disk.backing end, }, ], } src_vm.ReconfigVM_Task(spec: spec).wait_for_completion end end |
#customization_plugin ⇒ KnifeVspherePlugin
Loads the customization plugin if one was specified
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 697 def customization_plugin if @customization_plugin.nil? cplugin_path = get_config(:customization_plugin) if cplugin_path if File.exist? cplugin_path require cplugin_path else abort "Customization plugin could not be found at #{cplugin_path}" end if Object.const_defined? "KnifeVspherePlugin" @customization_plugin = Object.const_get("KnifeVspherePlugin").new cplugin_data = get_config(:customization_plugin_data) if cplugin_data if @customization_plugin.respond_to?(:data=) @customization_plugin.data = cplugin_data else abort "Customization plugin has no :data= accessor to receive the --cplugin-data argument. Define both or neither." end end else abort "KnifeVspherePlugin class is not defined in #{cplugin_path}" end end end @customization_plugin end |
#find_available_hosts ⇒ Object
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 446 def find_available_hosts hosts = traverse_folders_for_computeresources(datacenter.hostFolder) fatal_exit("No ComputeResource found - Use --resource-pool to specify a resource pool or a cluster") if hosts.empty? hosts.reject!(&:nil?) hosts.reject! { |host| host.host.all? { |h| h.runtime.inMaintenanceMode } } fatal_exit "All hosts in maintenance mode!" if hosts.empty? if get_config(:datastore) hosts.reject! { |host| !host.datastore.include?(find_datastore(get_config(:datastore))) } end fatal_exit "No hosts have the requested Datastore available! #{get_config(:datastore)}" if hosts.empty? if get_config(:datastorecluster) hosts.reject! { |host| !host.datastore.include?(find_datastorecluster(get_config(:datastorecluster))) } end fatal_exit "No hosts have the requested DatastoreCluster available! #{get_config(:datastorecluster)}" if hosts.empty? if get_config(:customization_vlan) vlan_list = get_config(:customization_vlan).split(",") vlan_list.each do |network| hosts.reject! { |host| !host.network.include?(find_network(network)) } end end fatal_exit "No hosts have the requested Network available! #{get_config(:customization_vlan)}" if hosts.empty? hosts end |
#find_customization(name) ⇒ RbVmomi::VIM::CustomizationSpecItem
Retrieves a CustomizationSpecItem that matches the supplied name
729 730 731 732 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 729 def find_customization(name) csm = vim_connection.serviceContent.customizationSpecManager csm.GetCustomizationSpec(name: name) end |
#find_host(host_name) ⇒ Object
488 489 490 491 492 493 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 488 def find_host(host_name) host = all_the_hosts.find { |host| host.name == host_name } raise "Can't find #{host_name}. I found #{all_the_hosts.map(&:name)}" unless host host end |
#generate_adapter_map(ip = nil, gw = nil, mac = nil) ⇒ RbVmomi::VIM::CustomizationIPSettings
Generates a CustomizationAdapterMapping (currently only single IPv4 address) object
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 738 def generate_adapter_map(ip = nil, gw = nil, mac = nil) settings = RbVmomi::VIM.CustomizationIPSettings if ip.nil? || ip.casecmp("dhcp") == 0 settings.ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new else ip_addr = IPAddr.new(ip) ip_string, _length = ip.split("/") settings.ip = RbVmomi::VIM::CustomizationFixedIp(ipAddress: ip_string) settings.subnetMask = ip_addr.netmask # TODO: want to confirm gw/ip are in same subnet? # Only set gateway on first IP. if config[:customization_ips].split(",").first == ip if gw.nil? next_ip = IPAddr.new(ip_addr.to_i + 1, Socket::AF_INET).to_s settings.gateway = [next_ip] else gw_string, _length = gw.split("/") settings.gateway = [gw_string] end end end adapter_map = RbVmomi::VIM.CustomizationAdapterMapping adapter_map.macAddress = mac if !mac.nil? && (mac != AUTO_MAC) adapter_map.adapter = settings adapter_map end |
#generate_clone_spec(src_config) ⇒ Object
Builds a CloneSpec
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 496 def generate_clone_spec(src_config) rspec = RbVmomi::VIM.VirtualMachineRelocateSpec case when get_config(:host) rspec.host = find_host(get_config(:host)) hosts = find_available_hosts rspec.pool = hosts.first.resourcePool when get_config(:resource_pool) rspec.pool = find_pool(get_config(:resource_pool)) else hosts = find_available_hosts rspec.pool = hosts.first.resourcePool end rspec.diskMoveType = :moveChildMostDiskBacking if get_config(:linked_clone) if get_config(:datastore) rspec.datastore = find_datastore(get_config(:datastore)) end if get_config(:datastorecluster) dsc = find_datastorecluster(get_config(:datastorecluster)) dsc.childEntity.each do |store| if rspec.datastore.nil? || rspec.datastore.summary[:freeSpace] < store.summary[:freeSpace] rspec.datastore = store end end end rspec.transform = :sparse if get_config(:thin_provision) is_template = !get_config(:mark_as_template).nil? clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: rspec, powerOn: false, template: is_template) clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(deviceChange: []) if get_config(:annotation) clone_spec.config.annotation = get_config(:annotation) end if get_config(:customization_cpucount) clone_spec.config.numCPUs = get_config(:customization_cpucount) end if get_config(:customization_corespersocket) clone_spec.config.numCoresPerSocket = get_config(:customization_corespersocket) end if get_config(:customization_memory) clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024 end if get_config(:customization_memory_reservation) clone_spec.config.memoryAllocation = RbVmomi::VIM.ResourceAllocationInfo reservation: Integer(Float(get_config(:customization_memory_reservation)) * 1024) end mac_list = if get_config(:customization_macs) == AUTO_MAC [AUTO_MAC] * get_config(:customization_ips).split(",").length else get_config(:customization_macs).split(",") end if get_config(:customization_sw_uuid) unless get_config(:customization_vlan) abort("Must specify VLANs with --cvlan when specifying switch UUIDs with --sw-uuids") end swuuid_list = if get_config(:customization_sw_uuid) == "auto" ["auto"] * get_config(:customization_ips).split(",").length else get_config(:customization_sw_uuid).split(",").map { |swuuid| swuuid.gsub(/((\w+\s+){7})(\w+)\s+(.+)/, '\1\3-\4') } end end if get_config(:customization_vlan) vlan_list = get_config(:customization_vlan).split(",") sw_uuid = get_config(:customization_sw_uuid) networks = vlan_list.map { |vlan| find_network(vlan, sw_uuid) } cards = src_config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard) networks.each_with_index do |network, index| card = cards[index] || abort("Can't find source network card to customize for vlan #{vlan_list[index]}") begin if get_config(:customization_sw_uuid) && (swuuid_list[index] != "auto") switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection( switchUuid: swuuid_list[index], portgroupKey: network.key ) else switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection( switchUuid: network.config.distributedVirtualSwitch.uuid, portgroupKey: network.key ) end card.backing.port = switch_port rescue # not connected to a distibuted switch? card.backing = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(network: network, deviceName: network.name) end card.macAddress = mac_list[index] if get_config(:customization_macs) && mac_list[index] != AUTO_MAC dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(device: card, operation: "edit") clone_spec.config.deviceChange.push dev_spec end end cust_spec = if get_config(:customization_spec) csi = find_customization(get_config(:customization_spec)) || fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}") csi.spec else global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings identity_settings = RbVmomi::VIM.CustomizationIdentitySettings RbVmomi::VIM.CustomizationSpec(globalIPSettings: global_ipset, identity: identity_settings) end if get_config(:disable_customization) clone_spec.customization = get_config(:customization_spec) ? cust_spec : nil return clone_spec end if get_config(:customization_dns_ips) cust_spec.globalIPSettings.dnsServerList = get_config(:customization_dns_ips).split(",") end if get_config(:customization_dns_suffixes) cust_spec.globalIPSettings.dnsSuffixList = get_config(:customization_dns_suffixes).split(",") end if config[:customization_ips] != NO_IPS cust_spec.nicSettingMap = config[:customization_ips].split(",").map.with_index { |cust_ip, index| generate_adapter_map(cust_ip, get_config(:customization_gw), mac_list[index]) } end # TODO: why does the domain matter? use_ident = config[:customization_hostname] || get_config(:customization_domain) || cust_spec.identity.props.empty? # TODO: How could we not take this? Only if the identity were empty, but that's statically defined as empty above if use_ident hostname = config[:customization_hostname] || vmname if windows?(src_config) # We should get here with the customizations set, either by a plugin or a --cspec fatal_exit "Windows clones need a customization identity. Try passing a --cspec or making a --cplugin" if cust_spec.identity.props.empty? identification = identification_for_spec(cust_spec) if cust_spec.identity.licenseFilePrintData license_file_print_data = RbVmomi::VIM.CustomizationLicenseFilePrintData( autoMode: cust_spec.identity.licenseFilePrintData.autoMode ) end # optional param user_data = RbVmomi::VIM.CustomizationUserData( fullName: cust_spec.identity.userData.fullName, orgName: cust_spec.identity.userData.orgName, productId: cust_spec.identity.userData.productId, computerName: RbVmomi::VIM.CustomizationFixedName(name: hostname) ) gui_unattended = RbVmomi::VIM.CustomizationGuiUnattended( autoLogon: cust_spec.identity.guiUnattended.autoLogon, autoLogonCount: cust_spec.identity.guiUnattended.autoLogonCount, password: RbVmomi::VIM.CustomizationPassword( plainText: cust_spec.identity.guiUnattended.password.plainText, value: cust_spec.identity.guiUnattended.password.value ), timeZone: cust_spec.identity.guiUnattended.timeZone ) runonce = RbVmomi::VIM.CustomizationGuiRunOnce( commandList: ["cust_spec.identity.guiUnattended.commandList"] ) ident = RbVmomi::VIM.CustomizationSysprep ident.guiRunOnce = runonce ident.guiUnattended = gui_unattended ident.identification = identification ident.licenseFilePrintData = license_file_print_data ident.userData = user_data cust_spec.identity = ident elsif linux?(src_config) ident = RbVmomi::VIM.CustomizationLinuxPrep ident.hostName = RbVmomi::VIM.CustomizationFixedName(name: hostname) ident.domain = (get_config(:customization_domain) || "") cust_spec.identity = ident else ui.error("Customization only supports Linux and Windows currently.") exit 1 end end clone_spec.customization = cust_spec if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec) clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec) end clone_spec end |
#guest_address(vm) ⇒ Object
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 383 def guest_address(vm) puts "Waiting for network interfaces to become available..." sleep 2 while vm.guest.net.empty? || !vm.guest.ipAddress ui.info "Found address #{vm.guest.ipAddress}" if log_verbose? config[:fqdn] = if config[:bootstrap_ipv4] ipv4_address(vm) elsif config[:fqdn] get_config(:fqdn) else # Use the first IP which is not a link-local address. # This is the closest thing to vm.guest.ipAddress but # allows specifying a NIC. vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect do |addr| addr.origin != "linklayer" end.ipAddress end end |
#ipv4_address(vm) ⇒ Object
369 370 371 372 373 374 375 376 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 369 def ipv4_address(vm) puts "Waiting for a valid IPv4 address..." # Multiple reboots occur during guest customization in which a link-local # address is assigned. As such, we need to wait until a routable IP address # becomes available. This is most commonly an issue with Windows instances. sleep 2 while vm_is_waiting_for_ip?(vm) vm.guest.net[bootstrap_nic_index].ipAddress.detect { |addr| IPAddr.new(addr).ipv4? } end |
#plugin_create_instance! ⇒ TrueClass
Create the server that we will bootstrap, if necessary
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to call out to an API to build an instance of the server we wish to bootstrap
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 273 def plugin_create_instance! config[:chef_node_name] = vmname unless get_config(:chef_node_name) vim = vim_connection vim.serviceContent.virtualDiskManager dc = datacenter src_vm = get_vm_by_name(get_config(:source_vm), get_config(:folder)) || fatal_exit("Could not find template #{get_config(:source_vm)}") create_delta_disk(src_vm) if get_config(:linked_clone) clone_spec = generate_clone_spec(src_vm.config) cust_folder = config[:dest_folder] || get_config(:folder) dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder) task = src_vm.CloneVM_Task(folder: dest_folder, name: vmname, spec: clone_spec) puts "Cloning template #{get_config(:source_vm)} to new VM #{vmname}" pp clone_spec if log_verbose? begin task.wait_for_completion rescue RbVmomi::Fault => e fault = e.fault if fault.class == RbVmomi::VIM::NicSettingMismatch abort "There is a mismatch in the number of NICs on the template (#{fault.numberOfNicsInVM}) and what you've passed on the command line with --cips (#{fault.numberOfNicsInSpec}). The VM has been cloned but not customized." elsif fault.class == RbVmomi::VIM::DuplicateName ui.info "VM already exists, proceeding to bootstrap" else raise e end end puts "Finished creating virtual machine #{vmname}" if customization_plugin && customization_plugin.respond_to?(:reconfig_vm) target_vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM could not be found in #{dest_folder}") customization_plugin.reconfig_vm(target_vm) end return if get_config(:mark_as_template) if get_config(:power) || get_config(:bootstrap) vm = get_vm_by_name(vmname, cust_folder) || fatal_exit("VM #{vmname} not found") begin vm.PowerOnVM_Task.wait_for_completion rescue RbVmomi::Fault => e raise e unless e.fault.class == RbVmomi::VIM::InvalidPowerState # Ignore if it's already turned on end puts "Powered on virtual machine #{vmname}" end return unless get_config(:bootstrap) protocol = get_config(:bootstrap_protocol) if windows?(src_vm.config) protocol ||= "winrm" connect_port ||= 5985 unless config[:disable_customization] # Wait for customization to complete puts "Waiting for customization to complete..." CustomizationHelper.wait_for_sysprep(vm, vim, Integer(get_config(:sysprep_timeout)), 10) puts "Customization Complete" end connect_host = guest_address(vm) self.server_name = connect_host Chef::Log.debug("Connect Host for winrm Bootstrap: #{connect_host}") wait_for_access(connect_host, connect_port, protocol) else connect_host = guest_address(vm) self.server_name = connect_host connect_port ||= 22 Chef::Log.debug("Connect Host for SSH Bootstrap: #{connect_host}") protocol ||= "ssh" wait_for_access(connect_host, connect_port, protocol) end end |
#plugin_finalize ⇒ void
This method returns an undefined value.
Perform any teardown or cleanup necessary by the plugin
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to display a message or perform any cleanup
365 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 365 def plugin_finalize; end |
#plugin_setup! ⇒ TrueClass
Perform any setup necessary by the plugin
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to create connection objects
358 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 358 def plugin_setup!; end |
#plugin_validate_options! ⇒ TrueClass
Returns If options are valid or exits.
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 247 def unless using_supplied_hostname? ^ using_random_hostname? show_usage fatal_exit("You must specify a virtual machine name OR use --random-vmname") end abort "--template or knife[:source_vm] must be specified" unless config[:source_vm] if get_config(:datastore) && get_config(:datastorecluster) abort "Please select either datastore or datastorecluster" end if get_config(:customization_macs) != AUTO_MAC && get_config(:customization_ips) == NO_IPS abort('Must specify IP numbers with --cips when specifying MAC addresses with --cmacs, can use "dhcp" as placeholder') end end |
#run ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 216 def run check_license plugin_setup! validate_name_args! validate_protocol! validate_first_boot_attributes! validate_winrm_transport_opts! winrm_warn_no_ssl_verification warn_on_short_session_timeout plugin_create_instance! return unless get_config(:bootstrap) $stdout.sync = true connect! register_client content = render_template bootstrap_path = upload_bootstrap(content) perform_bootstrap(bootstrap_path) plugin_finalize ensure connection.del_file!(bootstrap_path) if connection && bootstrap_path end |
#tcp_test_ssh(hostname, connection_port) ⇒ Object
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 768 def tcp_test_ssh(hostname, connection_port) tcp_socket = TCPSocket.new(hostname, connection_port) readable = IO.select([tcp_socket], nil, nil, 5) if readable = tcp_socket.gets if .nil? || .empty? false else Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{}") yield true end else false end rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError Chef::Log.debug("ssh failed to connect: #{hostname}") sleep 2 false rescue Errno::EPERM, Errno::ETIMEDOUT Chef::Log.debug("ssh timed out: #{hostname}") false rescue Errno::ECONNRESET Chef::Log.debug("ssh reset its connection: #{hostname}") sleep 2 false ensure tcp_socket && tcp_socket.close end |
#tcp_test_winrm(hostname, port) ⇒ Object
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 798 def tcp_test_winrm(hostname, port) tcp_socket = TCPSocket.new(hostname, port) yield true rescue SocketError sleep 2 false rescue Errno::ETIMEDOUT false rescue Errno::EPERM false rescue Errno::ECONNREFUSED sleep 2 false rescue Errno::EHOSTUNREACH sleep 2 false rescue Errno::ENETUNREACH sleep 2 false ensure tcp_socket && tcp_socket.close end |
#validate_name_args! ⇒ Object
367 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 367 def validate_name_args!; end |
#vm_is_waiting_for_ip?(vm) ⇒ Boolean
378 379 380 381 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 378 def vm_is_waiting_for_ip?(vm) first_ip_address = vm.guest.net[bootstrap_nic_index].ipConfig.ipAddress.detect { |addr| IPAddr.new(addr.ipAddress).ipv4? } first_ip_address.nil? || first_ip_address.origin == ORIGIN_IS_REAL_NIC end |
#wait_for_access(connect_host, connect_port, protocol) ⇒ Object
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/chef/knife/vsphere_vm_clone.rb', line 401 def wait_for_access(connect_host, connect_port, protocol) if winrm? if get_config(:winrm_ssl) && get_config(:connection_port) == "5985" config[:connection_port] = "5986" end connect_port = get_config(:connection_port) print "\n#{ui.color("Waiting for winrm access to become available on #{connect_host}:#{connect_port}", :magenta)}" print(".") until tcp_test_winrm(connect_host, connect_port) do sleep 10 puts("done") end else print "\n#{ui.color("Waiting for sshd access to become available on #{connect_host}:#{connect_port}", :magenta)}" print(".") until tcp_test_ssh(connect_host, connect_port) do sleep 10 puts("done") end end connect_port end |