Return-Path: X-Original-To: apmail-incubator-deltacloud-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-deltacloud-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E70194637 for ; Fri, 17 Jun 2011 09:33:31 +0000 (UTC) Received: (qmail 38999 invoked by uid 500); 17 Jun 2011 09:33:31 -0000 Delivered-To: apmail-incubator-deltacloud-dev-archive@incubator.apache.org Received: (qmail 38924 invoked by uid 500); 17 Jun 2011 09:33:31 -0000 Mailing-List: contact deltacloud-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: deltacloud-dev@incubator.apache.org Delivered-To: mailing list deltacloud-dev@incubator.apache.org Received: (qmail 38916 invoked by uid 99); 17 Jun 2011 09:33:30 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Jun 2011 09:33:30 +0000 X-ASF-Spam-Status: No, hits=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of mfojtik@redhat.com designates 209.132.183.28 as permitted sender) Received: from [209.132.183.28] (HELO mx1.redhat.com) (209.132.183.28) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Jun 2011 09:33:26 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5H9X3Rv020913 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 17 Jun 2011 05:33:04 -0400 Received: from dhcp-2-126.brq.redhat.com (dhcp-2-126.brq.redhat.com [10.34.2.126]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p5H9WwQA012854 for ; Fri, 17 Jun 2011 05:33:03 -0400 From: mfojtik@redhat.com To: deltacloud-dev@incubator.apache.org Subject: [PATCH core 2/2] Added Datastore object as Realm so Instances could be now placed in different locations inside Datacenter. Date: Fri, 17 Jun 2011 11:33:34 +0200 Message-Id: <1308303214-15980-3-git-send-email-mfojtik@redhat.com> In-Reply-To: <1308303214-15980-1-git-send-email-mfojtik@redhat.com> References: <1308303214-15980-1-git-send-email-mfojtik@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 From: Michal Fojtik Signed-off-by: Michal fojtik --- .../deltacloud/drivers/vsphere/vsphere_driver.rb | 154 ++++++++++++++------ 1 files changed, 107 insertions(+), 47 deletions(-) diff --git a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb index 52835c9..3a59ee2 100644 --- a/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +++ b/server/lib/deltacloud/drivers/vsphere/vsphere_driver.rb @@ -78,12 +78,13 @@ module Deltacloud::Drivers::VSphere if opts[:id] template_vms = [ find_vm(credentials, opts[:id]) ].compact else - template_vms = list_virtual_machines(credentials).select { |vm| vm.summary.config[:template] } + template_vms = list_virtual_machines(credentials).select { |vm| vm[:instance].summary.config[:template] } end - img_arr = template_vms.collect do |image| + img_arr = template_vms.collect do |image_hash| # Since all calls to vm are threaten as SOAP calls, reduce them using # local variable. + image, realm = image_hash[:instance], image_hash[:datastore] config = image.summary.config instance_state = convert_state(:instance, image.summary.runtime[:powerState]) properties = { @@ -109,23 +110,23 @@ module Deltacloud::Drivers::VSphere def create_image(credentials, opts={}) vsphere = new_client(credentials) safely do - find_vm(credentials, opts[:id]).MarkAsTemplate + find_vm(credentials, opts[:id])[:instance].MarkAsTemplate end - image(credentials, :id => opts[:id]) + images(credentials, :id => opts[:id]) end # List all datacenters managed by the vSphere or vCenter entrypoint. def realms(credentials, opts=nil) vsphere = new_client(credentials) safely do - rootFolder = vsphere.serviceInstance.content.rootFolder - rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc| - Realm.new( - :id => dc.name, - :name => dc.name, - :limit => :unlimited, - :state => convert_state(:datacenter, dc.configStatus) - ) + if opts and opts[:id] + datastore = find_datastore(credentials, opts[:id]) + [convert_realm(datastore)] + else + rootFolder = vsphere.serviceInstance.content.rootFolder + rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect do |dc| + dc.datastoreFolder.childEntity.collect { |datastore| convert_realm(datastore) } + end.flatten end end end @@ -139,14 +140,14 @@ module Deltacloud::Drivers::VSphere if opts[:id] machine_vms = [ find_vm(credentials, opts[:id]) ].compact else - machine_vms = list_virtual_machines(credentials).select { |vm| !vm.summary.config[:template] } + machine_vms = list_virtual_machines(credentials).select { |vm| !vm[:instance].summary.config[:template] } end end - realm_id = realms(credentials).first.id safely do - inst_arr = machine_vms.collect do |vm| + inst_arr = machine_vms.collect do |vm_hash| # Since all calls to vm are threaten as SOAP calls, reduce them using # local variable. + vm, realm_id = vm_hash[:instance], vm_hash[:datastore] config = vm.summary.config next unless config next unless vm.summary.storage @@ -186,34 +187,43 @@ module Deltacloud::Drivers::VSphere vsphere = new_client(credentials) safely do rootFolder = vsphere.serviceInstance.content.rootFolder - # FIXME: This will consume first datacenter and ignore 'realm' property - dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect.first - vm = dc.find_vm(image_id) - resource_pool = dc.hostFolder.childEntity.collect.first.resourcePool - relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool) - # NOTE: 'powerOn' attribute will force machine to start after clone operation - # 'template' attribute will mark VM as a template if set to true + vm = find_vm(credentials, opts[:image_id]) + # Find correct ResourcePool and Datastore where a new VM will be + # located + if opts and opts[:realm_id] + resourcePool = find_resource_pool(credentials, opts[:realm_id]) + datastore = find_datastore(credentials, opts[:realm_id]) + else + resourcePool = find_resource_pool(credentials, vm[:datastore]) + datastore = find_datastore(credentials, opts[:datastore]) + end + relocate = { :pool => resourcePool, :datastore => datastore } + relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(relocate) + instance_profile = hardware_profiles(credentials, :id => opts[:hwp_id]).first spec = RbVmomi::VIM.VirtualMachineCloneSpec( :location => relocateSpec, :powerOn => true, :template => false, :config => RbVmomi::VIM.VirtualMachineConfigSpec( - :memoryMB => 256, - :numCPUs => 1 + :memoryMB => instance_profile.memory.value, + :numCPUs => instance_profile.cpu.value ) ) - # NOTE: This operation may take a very long time (about 1m) to complete + # + # WARNING: This operation may take a very long time (about 1m) to complete + # + # TODO: Use mapper? + # puts "Cloning template #{image_id} to #{opts[:name]}..." - vm.CloneVM_Task(:folder => vm.parent, :name => opts[:name], :spec => spec).wait_for_completion + vm[:instance].CloneVM_Task(:folder => vm[:instance].parent, :name => opts[:name], :spec => spec).wait_for_completion puts "Cloning complete!" - # Since task itself is not returning anything, construct Instance from things we already have Instance::new( :id => opts[:name], :name => opts[:name], :owner_id => credentials.user, - :realm_id => dc.name, + :realm_id => opts[:realm_id] || vm[:datastore], :state => 'PENDING', - :instance_profile => InstanceProfile::new('default'), + :instance_profile => InstanceProfile::new(instance_profile.name), :actions => instance_actions_for( 'PENDING' ) ) end @@ -221,23 +231,23 @@ module Deltacloud::Drivers::VSphere # Reboot an instance, given its id. def reboot_instance(credentials, id) - find_vm(credentials, id).ResetVM_Task + find_vm(credentials, id)[:instance].ResetVM_Task end # Start an instance, given its id. def start_instance(credentials, id) - find_vm(credentials, id).PowerOnVM_Task + find_vm(credentials, id)[:instance].PowerOnVM_Task end # Stop an instance, given its id. def stop_instance(credentials, id) - find_vm(credentials, id).PowerOffVM_Task + find_vm(credentials, id)[:instance].PowerOffVM_Task end # Destroy an instance, given its id. Note that this will destory all # instance data. def destroy_instance(credentials, id) - find_vm(credentials, id).Destroy_Task.wait_for_completion + find_vm(credentials, id)[:instance].Destroy_Task.wait_for_completion end exceptions do @@ -276,31 +286,87 @@ module Deltacloud::Drivers::VSphere endpoint || Deltacloud::Drivers::driver_config[:vsphere][:entrypoints]['default']['default'] 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| - vms += dc.vmFolder.childEntity.collect do |ent| - if ent.class.name == 'RbVmomi::VIM::Folder' - ent.childEntity.grep(RbVmomi::VIM::VirtualMachine).collect - else - ent - end + 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 - dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).collect.first - dc.find_vm(name) + 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, + :name => datastore.name, + :limit => datastore.summary.freeSpace, + :state => datastore.summary.accessible ? 'AVAILABLE' : 'UNAVAILABLE' + ) + end + def convert_state(object, state) new_state = '' if object == :image @@ -316,12 +382,6 @@ module Deltacloud::Drivers::VSphere else 'PENDING' end end - if object == :datacenter - new_state = case state - when 'gray', 'green' then 'AVAILABLE' - else 'UNAVAILABLE' - end - end new_state end -- 1.7.4.1