<commit_before>module Fog
  module Compute
    class Vsphere
      module Shared
        private
        def vm_clone_check_options(options)
          default_options = {
            'force'        => false,
            'linked_clone' => false,
            'nic_type' => 'VirtualE1000',
          }
          options = default_options.merge(options)
          options["storage_pod"] = nil if options["storage_pod"] == ''
          # Backwards compat for "path" option
          options["template_path"] ||= options["path"]
          options["path"] ||= options["template_path"]
          required_options = %w{ datacenter template_path name }
          required_options.each do |param|
            raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
          end
          raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"])
          raise Fog::Compute::Vsphere::NotFound, "Template #{options["template_path"]} Doesn't Exist!" unless get_virtual_machine(options["template_path"], options["datacenter"])
          if options.key?('storage_pod') && !options['storage_pod'].nil? && !get_raw_storage_pod(options['storage_pod'], options['datacenter'])
            raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options["storage_pod"]} Doesn't Exist!"
          end
          options
        end
      end

      class Real
        include Shared

        # Clones a VM from a template or existing machine on your vSphere
        # Server.
        #
        # ==== Parameters
        # * options<~Hash>:
        #   * 'datacenter'<~String> - *REQUIRED* Datacenter name your cloning
        #     in. Make sure this datacenter exists, should if you're using
        #     the clone function in server.rb model.
        #   * 'template_path'<~String> - *REQUIRED* The path to the machine you
        #     want to clone FROM. Relative to Datacenter (Example:
        #     "FolderNameHere/VMNameHere")
        #   * 'name'<~String> - *REQUIRED* The VMName of the Destination
        #   * 'dest_folder'<~String> - Destination Folder of where 'name' will
        #     be placed on your cluster. Relative Path to Datacenter E.G.
        #     "FolderPlaceHere/anotherSub Folder/onemore"
        #   * 'power_on'<~Boolean> - Whether to power on machine after clone.
        #     Defaults to true.
        #   * 'wait'<~Boolean> - Whether the method should wait for the virtual
        #     machine to finish cloning before returning information from
        #     vSphere. Broken right now as you cannot return a model of a serer
        #     that isn't finished cloning. Defaults to True
        #   * 'resource_pool'<~Array> - The resource pool on your datacenter
        #     cluster you want to use. Only works with clusters within same
        #     same datacenter as where you're cloning from. Datacenter grabbed
        #     from template_path option.
        #     Example: ['cluster_name_here','resource_pool_name_here']
        #   * 'datastore'<~String> - The datastore you'd like to use.
        #       (datacenterObj.datastoreFolder.find('name') in API)
        #   * 'storage_pod'<~String> - The storage pod / datastore cluster you'd like to use.
        #   * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html
        #   * 'numCPUs'<~Integer> - the number of Virtual CPUs of the Destination VM
        #   * 'numCoresPerSocket'<~Integer> - the number of cores per socket of the Destination VM
        #   * 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB
        #   * customization_spec<~Hash>: Options are marked as required if you
        #     use this customization_spec. 
        #     As defined https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
        #     * encryptionKey <~array of bytes> Used to encrypt/decrypt password
        #     * globalIPSettings expects a hash, REQUIRED
        #     * identity expects a hash, REQUIRED - either LinuxPrep, Sysprep or SysprepText
        #     * nicSettingMap expects an array
        #     * options expects a hash
        #     * All options can be parsed using a yaml template with cloudinit_to_customspec.rb
        #      
        #     OLD Values still supported:
        #     This only support cloning and setting DHCP on the first interface
        #     * 'domain'<~String> - *REQUIRED* This is put into
        #       /etc/resolve.conf (we hope)
        #     * 'hostname'<~String> - Hostname of the Guest Os - default is
        #       options['name']
        #     * 'hw_utc_clock'<~Boolean> - *REQUIRED* Is hardware clock UTC?
        #       Default true
        #     * 'time_zone'<~String> - *REQUIRED* Only valid linux options
        #       are valid - example: 'America/Denver'
        #     * 'interfaces' <~Array> - interfaces object to apply to
        #        the template when cloning: overrides the
        #        network_label, network_adapter_device_key and nic_type attributes
        #     * 'volumes' <~Array> - volumes object to apply to
        #        the template when cloning: this allows to resize the
        #        existing disks as well as add or remove them. The
        #        resizing is applied only when the size is bigger then the
        #        in size in the template
        def vm_clone(options = {})
          # Option handling
          options = vm_clone_check_options(options)

          # Added for people still using options['path']
          template_path = options['path'] || options['template_path']

          # Options['template_path']<~String>
          # Added for people still using options['path']
          template_path = options['path'] || options['template_path']
          # Now find the template itself using the efficient find method
          vm_mob_ref = get_vm_ref(template_path, options['datacenter'])

          # Options['dest_folder']<~String>
          # Grab the destination folder object if it exists else use cloned mach
          dest_folder_path = options.fetch('dest_folder','/') # default to root path ({dc_name}/vm/)
          dest_folder = get_raw_vmfolder(dest_folder_path, options['datacenter'])

          # Options['resource_pool']<~Array>
          # Now find _a_ resource pool to use for the clone if one is not specified
          if ( options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] != 'Resources')
            cluster_name = options['resource_pool'][0]
            pool_name = options['resource_pool'][1]
            resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter'])
          elsif ( vm_mob_ref.resourcePool == nil )
            # If the template is really a template then there is no associated resource pool,
            # so we need to find one using the template's parent host or cluster
            esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
            # The parent of the ESX host itself is a ComputeResource which has a resourcePool
            resource_pool = esx_host.parent.resourcePool
            cluster_name = nil
          end
          # If the vm given did return a valid resource pool, default to using it for the clone.
          # Even if specific pools aren't implemented in this environment, we will still get back
          # at least the cluster or host we can pass on to the clone task
          # This catches if resource_pool option is set but comes back nil and if resourcePool is
          # already set.
          resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool

          # Options['host']<~String>
          # The target host for the virtual machine. Optional.
          if options.key?('host') && !options['host'].empty? && !cluster_name.nil?<commit_msg>Do not fail when cloning from template to different cluster (#70)<commit_after>module Fog
  module Compute
    class Vsphere
      module Shared
        private
        def vm_clone_check_options(options)
          default_options = {
            'force'        => false,
            'linked_clone' => false,
            'nic_type' => 'VirtualE1000',
          }
          options = default_options.merge(options)
          options["storage_pod"] = nil if options["storage_pod"] == ''
          # Backwards compat for "path" option
          options["template_path"] ||= options["path"]
          options["path"] ||= options["template_path"]
          required_options = %w{ datacenter template_path name }
          required_options.each do |param|
            raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
          end
          raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"])
          raise Fog::Compute::Vsphere::NotFound, "Template #{options["template_path"]} Doesn't Exist!" unless get_virtual_machine(options["template_path"], options["datacenter"])
          if options.key?('storage_pod') && !options['storage_pod'].nil? && !get_raw_storage_pod(options['storage_pod'], options['datacenter'])
            raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options["storage_pod"]} Doesn't Exist!"
          end
          options
        end
      end

      class Real
        include Shared

        # Clones a VM from a template or existing machine on your vSphere
        # Server.
        #
        # ==== Parameters
        # * options<~Hash>:
        #   * 'datacenter'<~String> - *REQUIRED* Datacenter name your cloning
        #     in. Make sure this datacenter exists, should if you're using
        #     the clone function in server.rb model.
        #   * 'template_path'<~String> - *REQUIRED* The path to the machine you
        #     want to clone FROM. Relative to Datacenter (Example:
        #     "FolderNameHere/VMNameHere")
        #   * 'name'<~String> - *REQUIRED* The VMName of the Destination
        #   * 'dest_folder'<~String> - Destination Folder of where 'name' will
        #     be placed on your cluster. Relative Path to Datacenter E.G.
        #     "FolderPlaceHere/anotherSub Folder/onemore"
        #   * 'power_on'<~Boolean> - Whether to power on machine after clone.
        #     Defaults to true.
        #   * 'wait'<~Boolean> - Whether the method should wait for the virtual
        #     machine to finish cloning before returning information from
        #     vSphere. Broken right now as you cannot return a model of a serer
        #     that isn't finished cloning. Defaults to True
        #   * 'resource_pool'<~Array> - The resource pool on your datacenter
        #     cluster you want to use. Only works with clusters within same
        #     same datacenter as where you're cloning from. Datacenter grabbed
        #     from template_path option.
        #     Example: ['cluster_name_here','resource_pool_name_here']
        #   * 'datastore'<~String> - The datastore you'd like to use.
        #       (datacenterObj.datastoreFolder.find('name') in API)
        #   * 'storage_pod'<~String> - The storage pod / datastore cluster you'd like to use.
        #   * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html
        #   * 'numCPUs'<~Integer> - the number of Virtual CPUs of the Destination VM
        #   * 'numCoresPerSocket'<~Integer> - the number of cores per socket of the Destination VM
        #   * 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB
        #   * customization_spec<~Hash>: Options are marked as required if you
        #     use this customization_spec. 
        #     As defined https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
        #     * encryptionKey <~array of bytes> Used to encrypt/decrypt password
        #     * globalIPSettings expects a hash, REQUIRED
        #     * identity expects a hash, REQUIRED - either LinuxPrep, Sysprep or SysprepText
        #     * nicSettingMap expects an array
        #     * options expects a hash
        #     * All options can be parsed using a yaml template with cloudinit_to_customspec.rb
        #      
        #     OLD Values still supported:
        #     This only support cloning and setting DHCP on the first interface
        #     * 'domain'<~String> - *REQUIRED* This is put into
        #       /etc/resolve.conf (we hope)
        #     * 'hostname'<~String> - Hostname of the Guest Os - default is
        #       options['name']
        #     * 'hw_utc_clock'<~Boolean> - *REQUIRED* Is hardware clock UTC?
        #       Default true
        #     * 'time_zone'<~String> - *REQUIRED* Only valid linux options
        #       are valid - example: 'America/Denver'
        #     * 'interfaces' <~Array> - interfaces object to apply to
        #        the template when cloning: overrides the
        #        network_label, network_adapter_device_key and nic_type attributes
        #     * 'volumes' <~Array> - volumes object to apply to
        #        the template when cloning: this allows to resize the
        #        existing disks as well as add or remove them. The
        #        resizing is applied only when the size is bigger then the
        #        in size in the template
        def vm_clone(options = {})
          # Option handling
          options = vm_clone_check_options(options)

          # Added for people still using options['path']
          template_path = options['path'] || options['template_path']

          # Options['template_path']<~String>
          # Added for people still using options['path']
          template_path = options['path'] || options['template_path']
          # Now find the template itself using the efficient find method
          vm_mob_ref = get_vm_ref(template_path, options['datacenter'])

          # Options['dest_folder']<~String>
          # Grab the destination folder object if it exists else use cloned mach
          dest_folder_path = options.fetch('dest_folder','/') # default to root path ({dc_name}/vm/)
          dest_folder = get_raw_vmfolder(dest_folder_path, options['datacenter'])

          # Options['resource_pool']<~Array>
          # Now find _a_ resource pool to use for the clone if one is not specified
          if ( options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] != 'Resources')
            cluster_name = options['resource_pool'][0]
            pool_name = options['resource_pool'][1]
            resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter'])
          elsif ( options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] == 'Resources')
            cluster_name = options['resource_pool'][0]
            pool_name = options['resource_pool'][1]
            resource_pool = get_raw_resource_pool(nil, cluster_name, options['datacenter'])
          elsif ( vm_mob_ref.resourcePool == nil )
            # If the template is really a template then there is no associated resource pool,
            # so we need to find one using the template's parent host or cluster
            esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
            # The parent of the ESX host itself is a ComputeResource which has a resourcePool
            resource_pool = esx_host.parent.resourcePool
            cluster_name = nil
          end
          # If the vm given did return a valid resource pool, default to using it for the clone.
          # Even if specific pools aren't implemented in this environment, we will still get back
          # at least the cluster or host we can pass on to the clone task
          # This catches if resource_pool option is set but comes back nil and if resourcePool is
          # already set.
          resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool

          # Options['host']<~String>
          # The target host for the virtual machine. Optional.
          if options.key?('host') && !options['host'].empty? && !cluster_name.nil?
{'fraction_non_alphanumeric': 0.09718623847683316, 'fraction_numerical': 0.0018075555823341568, 'mean_word_length': 2.4407131011608625, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 61, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '664712', 'n_tokens_mistral': 4571, 'n_tokens_neox': 4455, 'n_words': 1412}