incubator-deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Francesco Vollero <fvoll...@redhat.com>
Subject Re: [PATCH core 1/4] VSphere: Switched from floppy image to CD-ROM ISO Vsphere: Replaced hardware profiles with one highly customizable profile Vsphere: Moved all VSphere helpers to separate file
Date Wed, 20 Jul 2011 12:29:58 GMT
Ack'd. Work for me.

On Tue, Jul 19, 2011 at 04:19:36PM +0200, mfojtik@redhat.com wrote:
> From: Michal Fojtik <mfojtik@redhat.com>
> 
> 
> Signed-off-by: Michal fojtik <mfojtik@redhat.com>
> ---
>  .../deltacloud/drivers/vsphere/vsphere_client.rb   |  113 +++++++++++
>  .../deltacloud/drivers/vsphere/vsphere_driver.rb   |  205 ++++++--------------
>  2 files changed, 170 insertions(+), 148 deletions(-)
>  create mode 100644 server/lib/deltacloud/drivers/vsphere/vsphere_client.rb
> 
> diff --git a/server/lib/deltacloud/drivers/vsphere/vsphere_client.rb b/server/lib/deltacloud/drivers/vsphere/vsphere_client.rb
> new file mode 100644
> index 0000000..f2cc486
> --- /dev/null
> +++ b/server/lib/deltacloud/drivers/vsphere/vsphere_client.rb
> @@ -0,0 +1,113 @@
> +module Deltacloud::Drivers::VSphere
> +
> +  module Helper
> +
> +    # Find a VirtualMachine traversing through all Datastores and Datacenters
> +    #
> +    # This helper will return a Hash: { :datastore => NAME_OF_DS, :instance =>
VM }
> +    # Returning datastore is necesarry for constructing a correct realm for an
> +    # instance
> +    #
> +    def find_vm(credentials, name)
> +      vsphere = new_client(credentials)
> +      safely do
> +        rootFolder = vsphere.serviceInstance.content.rootFolder
> +        vm = {}
> +        rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
> +          dc.datastoreFolder.childEntity.collect do |datastore|
> +            vm[:instance] = datastore.vm.find { |x| x.name == name }
> +            if vm[:instance]
> +              vm[:datastore] = datastore.name
> +              break
> +            end
> +          end
> +          break if [:datastore]
> +        end
> +        vm
> +      end
> +    end
> +
> +    # Find a ResourcePool[1] object associated by given Datastore
> +    # ResourcePool is defined for Datacenter and is used for launching a new
> +    # instance
> +    #
> +    # [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ResourcePool.html
> +    #
> +    def find_resource_pool(credentials, name)
> +      vsphere = new_client(credentials)
> +      safely do
> +        rootFolder = vsphere.serviceInstance.content.rootFolder
> +        dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).select do |dc|
> +          dc.datastoreFolder.childEntity.find { |d| d.name == name }.nil? == false
> +        end.flatten.compact.first
> +        dc.hostFolder.childEntity.collect.first.resourcePool
> +      end
> +    end
> +
> +    # This helper will try to find a Datastore[1] object in all Datacenters.
> +    # Datastore is used to place instance on create to correct place
> +    #
> +    # [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.Datastore.html
> +    #
> +    def find_datastore(credentials, name)
> +      vsphere = new_client(credentials)
> +      safely do
> +        rootFolder = vsphere.serviceInstance.content.rootFolder
> +        rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc|
> +          dc.datastoreFolder.childEntity.find { |d| d.name == name }
> +        end.flatten.compact.first
> +      end
> +    end
> +
> +    # This helper will traverse across all datacenters and datastores and gather
> +    # all virtual machines available on vSphere
> +    #
> +    def list_virtual_machines(credentials)
> +      vsphere = new_client(credentials)
> +      vms = []
> +      rootFolder = vsphere.serviceInstance.content.rootFolder
> +      rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
> +        dc.datastoreFolder.childEntity.collect do |datastore|
> +          vms += datastore.vm.collect { |vm| { :instance => vm, :datastore =>
datastore.name } }
> +        end
> +      end
> +      vms.flatten.compact
> +    end
> +
> +    def map_task_to_instance(task_key, new_instance)
> +      FileUtils::mkdir_p(MAPPER_STORAGE_ROOT) unless File::directory?(MAPPER_STORAGE_ROOT)
> +      File::open(File::join(MAPPER_STORAGE_ROOT, task_key), "w") do |f|
> +        f.puts(YAML::dump(new_instance))
> +      end
> +      new_instance
> +    end
> +
> +    def load_serialized_instance(task_key)
> +      FileUtils::mkdir_p(MAPPER_STORAGE_ROOT) unless File::directory?(MAPPER_STORAGE_ROOT)
> +      YAML::load(File::read(File::join(MAPPER_STORAGE_ROOT, task_key))) rescue nil
> +    end
> +
> +    # Yield all tasks if they are included in mapper storage directory.
> +    def stored_tasks(vsphere)
> +      FileUtils::mkdir_p(MAPPER_STORAGE_ROOT) unless File::directory?(MAPPER_STORAGE_ROOT)
> +      tasks = Dir[File::join(MAPPER_STORAGE_ROOT, '*')].collect { |file| File::basename(file)
}
> +      vsphere.serviceInstance.content.taskManager.recentTask.each do |task|
> +        if tasks.include?(task.info.key)
> +          yield task
> +        else
> +          # If given task is not longer listed in 'recentTasks' delete the
> +          # mapper file
> +          FileUtils::rm_rf(File::join(MAPPER_STORAGE_ROOT, task.info.key))
> +        end
> +      end
> +    end
> +
> +    def extract_architecture(text)
> +      'x86_64' if text.include?('64-bit')
> +      'i386' if text.include?('32-bit')
> +    end
> +
> +
> +  end
> +
> +end
> diff --git a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
> index 8c3c3e0..3a502e0 100644
> --- a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
> +++ b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb
> @@ -15,6 +15,7 @@
>  #
>  
>  require 'deltacloud/base_driver'
> +require 'deltacloud/drivers/vsphere/vsphere_client'
>  require 'rbvmomi'
>  
>  module Deltacloud::Drivers::VSphere
> @@ -23,35 +24,25 @@ module Deltacloud::Drivers::VSphere
>  
>    class VSphereDriver < Deltacloud::BaseDriver
>  
> -    # Set of predefined hardware profiles
> -    define_hardware_profile('small') do
> -      cpu                1
> -      memory             256
> -      architecture       ['x86_64', 'i386']
> -    end
> -
> -    define_hardware_profile('medium') do
> -      cpu                1
> -      memory             512
> -      architecture       ['x86_64', 'i386']
> -    end
> +    include Deltacloud::Drivers::VSphere::Helper
>  
> -    define_hardware_profile('large') do
> -      cpu                2
> -      memory             1024
> -      architecture       ['x86_64', 'i386']
> -    end
> +    feature :instances, :user_data
>  
> -    define_hardware_profile('x-large') do
> -      cpu                4
> -      memory             2048
> -      architecture       ['x86_64', 'i386']
> -    end
> -
> -    # Since user can launch own instance using vSphere tools 
> -    # with customized properties, threat this hardware profile as
> -    # unknown
> -    define_hardware_profile('custom') do
> +    def hardware_profiles(credentials, opts={})
> +      vsphere = new_client(credentials)
> +      safely do
> +        service = vsphere.serviceInstance.content
> +        max_memory, max_cpu_cores = 0, 0
> +        service.rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
> +          max_memory += dc.hostFolder.childEntity.first.summary.effectiveMemory
> +          max_cpu_cores += dc.hostFolder.childEntity.first.summary.numCpuCores
> +        end
> +        [Deltacloud::HardwareProfile::new('default') do
> +          cpu (1..max_cpu_cores)
> +          memory (128..max_memory)
> +          architecture ['x86_64', 'i386']
> +        end]
> +      end
>      end
>  
>      # Configure instance state machine
> @@ -92,10 +83,11 @@ module Deltacloud::Drivers::VSphere
>              :full_name => config[:guestFullName]
>            }
>            image_state = convert_state(:image, image.summary.runtime[:powerState])
> +          image_architecture = extract_architecture(properties[:full_name]) || 'x86_64'
>            Image.new(
>              :id => properties[:name],
>              :name => properties[:name],
> -            :architecture => 'x86_64',  # FIXME: I'm not sure if all templates/VM's
in vSphere are x86_64
> +            :architecture => image_architecture,
>              :owner_id => credentials.user,
>              :description => properties[:full_name],
>              :state => image_state
> @@ -167,7 +159,7 @@ module Deltacloud::Drivers::VSphere
>              :full_name => config[:guestFullName],
>            }
>            instance_state = convert_state(:instance, vm.summary.runtime[:powerState])
> -          instance_profile = InstanceProfile::new(match_hwp_id(:memory => properties[:memory].to_s,
:cpus => properties[:cpus].to_s),
> +          instance_profile = InstanceProfile::new('default',
>                                                    :hwp_cpu => properties[:cpus],
>                                                    :hwp_memory => properties[:memory],
>                                                    :hwp_storage => properties[:storage])
> @@ -212,28 +204,54 @@ module Deltacloud::Drivers::VSphere
>          end
>          relocate = { :pool => resourcePool, :datastore => datastore }
>          relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(relocate)
> -        instance_profile = hardware_profiles(credentials, :id => opts[:hwp_id]).first
> +        # Set extra configuration for VM, like template_id
> +        machine_config = {
> +          :memoryMB => opts[:hwp_memory],
> +          :numCPUs => opts[:hwp_cpu],
> +          :extraConfig => [
> +            { :key => 'template_id', :value => image_id }
> +          ]
> +        }
> +        # If user wants to inject data into instance he need to submit a Base64
> +        # encoded gzipped ISO image.
> +        # This image will be uplaoded to the Datastore given in 'realm_id'
> +        # parameter and them attached to instance.
> +        if opts[:user_data] and not opts[:user_data].empty?
> +          device = vm[:instance].config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom
}.first
> +          if device
> +            # TODO: Upload baked ISO image to the Datastore
> +            device.backing = RbVmomi::VIM.VirtualCdromIsoBackingInfo(:fileName =>
"[#{opts[:realm_id] || vm[:datastore]}] test.iso")
> +            machine_config.merge!({
> +              :deviceChange => [{
> +                :operation => :edit,
> +                :device => device
> +              }]
> +            })
> +          else
> +            raise "Failed to inject data to device because there is no CD-ROM drive
defined in given template"
> +          end
> +        end
>          spec = RbVmomi::VIM.VirtualMachineCloneSpec(
>            :location => relocateSpec,
>            :powerOn => true,
>            :template => false,
> -          :config => RbVmomi::VIM.VirtualMachineConfigSpec(
> -            :memoryMB => instance_profile.memory.value,
> -            :numCPUs => instance_profile.cpu.value,
> -            :extraConfig => [
> -              { :key => 'template_id', :value => image_id }
> -            ]
> -          )
> +          :config => RbVmomi::VIM.VirtualMachineConfigSpec(machine_config)
>          )
> +        instance_profile = InstanceProfile::new('default', :hwp_memory => opts[:hwp_memory],
:hwp_cpu => opts[:hwp_cpu])
>          task = vm[:instance].CloneVM_Task(:folder => vm[:instance].parent, :name
=> opts[:name], :spec => spec)
>          new_instance = Instance::new(
>            :id => opts[:name],
>            :name => opts[:name],
> +          :description => opts[:name],
>            :owner_id => credentials.user,
> +          :image_id => opts[:image_id],
>            :realm_id => opts[:realm_id] || vm[:datastore],
>            :state => 'PENDING',
> -          :instance_profile => InstanceProfile::new(instance_profile.name),
> -          :actions => instance_actions_for( 'PENDING' )
> +          :public_addresses => [],
> +          :private_addresses => [],
> +          :instance_profile => instance_profile,
> +          :actions => instance_actions_for( 'PENDING' ),
> +          :create_image => false
>          )
>          map_task_to_instance(task.info.key, new_instance)
>        end
> @@ -298,105 +316,6 @@ module Deltacloud::Drivers::VSphere
>        endpoint || Deltacloud::Drivers::driver_config[:vsphere][:entrypoints]['default']['default']
>      end
>  
> -    def map_task_to_instance(task_key, new_instance)
> -      FileUtils::mkdir_p(MAPPER_STORAGE_ROOT) unless File::directory?(MAPPER_STORAGE_ROOT)
> -      File::open(File::join(MAPPER_STORAGE_ROOT, task_key), "w") do |f|
> -        f.puts(YAML::dump(new_instance))
> -      end
> -      new_instance
> -    end
> -
> -    def load_serialized_instance(task_key)
> -      YAML::load(File::read(File::join(MAPPER_STORAGE_ROOT, task_key)))
> -    end
> -
> -    # Yield all tasks if they are included in mapper storage directory.
> -    def stored_tasks(vsphere)
> -      FileUtils::mkdir_p(MAPPER_STORAGE_ROOT) unless File::directory?(MAPPER_STORAGE_ROOT)
> -      tasks = Dir[File::join(MAPPER_STORAGE_ROOT, '*')].collect { |file| File::basename(file)
}
> -      vsphere.serviceInstance.content.taskManager.recentTask.each do |task|
> -        if tasks.include?(task.info.key)
> -          yield task
> -        else
> -          # If given task is not longer listed in 'recentTasks' delete the
> -          # mapper file
> -          FileUtils::rm_rf(File::join(MAPPER_STORAGE_ROOT, task.info.key))
> -        end
> -      end
> -    end
> -
> -    # This helper will traverse across all datacenters and datastores and gather
> -    # all virtual machines available on vSphere
> -    #
> -    def list_virtual_machines(credentials)
> -      vsphere = new_client(credentials)
> -      vms = []
> -      rootFolder = vsphere.serviceInstance.content.rootFolder
> -      rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
> -        dc.datastoreFolder.childEntity.collect do |datastore|
> -          vms += datastore.vm.collect { |vm| { :instance => vm, :datastore =>
datastore.name } }
> -        end
> -      end
> -      vms.flatten.compact
> -    end
> -
> -    # This helper will try to find a Datastore[1] object in all Datacenters.
> -    # Datastore is used to place instance on create to correct place
> -    #
> -    # [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.Datastore.html
> -    #
> -    def find_datastore(credentials, name)
> -      vsphere = new_client(credentials)
> -      safely do
> -        rootFolder = vsphere.serviceInstance.content.rootFolder
> -        rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc|
> -          dc.datastoreFolder.childEntity.find { |d| d.name == name }
> -        end.flatten.compact.first
> -      end
> -    end
> -
> -    # Find a ResourcePool[1] object associated by given Datastore
> -    # ResourcePool is defined for Datacenter and is used for launching a new
> -    # instance
> -    #
> -    # [1] http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ResourcePool.html
> -    #
> -    def find_resource_pool(credentials, name)
> -      vsphere = new_client(credentials)
> -      safely do
> -        rootFolder = vsphere.serviceInstance.content.rootFolder
> -        dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).select do |dc|
> -          dc.datastoreFolder.childEntity.find { |d| d.name == name }.nil? == false
> -        end.flatten.compact.first
> -        dc.hostFolder.childEntity.collect.first.resourcePool
> -      end
> -    end
> -
> -    # Find a VirtualMachine traversing through all Datastores and Datacenters
> -    #
> -    # This helper will return a Hash: { :datastore => NAME_OF_DS, :instance =>
VM }
> -    # Returning datastore is necesarry for constructing a correct realm for an
> -    # instance
> -    #
> -    def find_vm(credentials, name)
> -      vsphere = new_client(credentials)
> -      safely do
> -        rootFolder = vsphere.serviceInstance.content.rootFolder
> -        vm = {}
> -        rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).each do |dc|
> -          dc.datastoreFolder.childEntity.collect do |datastore|
> -            vm[:instance] = datastore.vm.find { |x| x.name == name }
> -            if vm[:instance]
> -              vm[:datastore] = datastore.name
> -              break
> -            end
> -          end
> -          break if [:datastore]
> -        end
> -        vm
> -      end
> -    end
> -
>      def convert_realm(datastore)
>        Realm::new(
>          :id => datastore.name,
> @@ -424,16 +343,6 @@ module Deltacloud::Drivers::VSphere
>        new_state
>      end
>  
> -    # Match hardware profile ID against given properties
> -    def match_hwp_id(prop)
> -      return 'small' if prop[:memory] == '256' and prop[:cpus] == '1'
> -      return 'medium' if prop[:memory] == '512' and prop[:cpus] == '1'
> -      return 'large' if prop[:memory] == '1024' and prop[:cpus] == '2'
> -      return 'x-large' if prop[:memory] == '2048' and prop[:cpus] == '4'
> -      'unknown'
> -    end
> -
> -
>    end
>  
>  end
> -- 
> 1.7.4.1
> 

Mime
View raw message