Hi Marios,

for testing, have you tried running the driver with Fog's "mock" mode ?
A useful test is to start deltacloudd and then run 'rake spec' from the
client/ directory.

On Fri, 2010-04-23 at 21:38 +0100, [email protected] wrote:
> From: marios <[email protected]>
>  create mode 100644 server/lib/deltacloud/drivers/tmark/fog/bin.rb
>  create mode 100644 server/lib/deltacloud/drivers/tmark/fog/collection.rb
>  create mode 100644 server/lib/deltacloud/drivers/tmark/fog/connection.rb
>  create mode 100644 server/lib/deltacloud/drivers/tmark/fog/credentials.rb
> ...

First off, you shouldn't copy the files from fog into deltacloud - it'll
be hell to incorporate bugfixes etc.

I suspect that you did that because you rely on unreleased code in fog -
if that's the case, it's much better to say 'You need a git checkout of
fog, and include the directory xyz in your RUBYLIB env var'

> diff --git a/server/lib/deltacloud/drivers/tmark/vcloudexpress_driver.rb 
> b/server/lib/deltacloud/drivers/tmark/vcloudexpress_driver.rb
> new file mode 100644
> index 0000000..c72caf8
> --- /dev/null
> +++ b/server/lib/deltacloud/drivers/tmark/vcloudexpress_driver.rb
> @@ -0,0 +1,287 @@
> +# Copyright (C) 2010  Red Hat, Inc.
> +#
> +# This library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# This library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with this library; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
> USA
> +#
> +# @author: marios
> +# This driver uses the fog library (Geemus - Wesley Beary) to talk to 
> terremark... see 
> +#                                   http://github.com/geemus/fog
> +# see terremark vcloud express api at: 
> +# 
> https://community.vcloudexpress.terremark.com/en-us/product_docs/w/wiki/d-complete-vcloud-express-api-document.aspx
> +#
> +# 23 April 2010
> +#
> +require 'deltacloud/base_driver'
> +require 'deltacloud/drivers/tmark/fog/terremark'
> +begin
> +  require 'excon'
> +  require 'nokogiri'
> +rescue LoadError
> +  puts "ERROR: please ensure excon and nokogiri gems installed. (1. gem 
> install excon , 2. gem install nokogiri)"
> +  exit(1)
> +end

No need to catch the LoadError here - the 'normal' Ruby error message
should tell people what they need. In addition, we'll need to document
those requirements separately on the website and in some prominent file
in git (README maybe ? Or a new file server/DRIVERS)

> +module Deltacloud
> +  module Drivers
> +    module Tmark
> +      
> +class VCloudExpressDriver < Deltacloud::BaseDriver
> +  
> +#--
> +# HARDWARE PROFILES
> +#--
> +  define_hardware_profile 'terremark_hardware_profile' do
> +    cpu   [1,2,4,8]
> +    memory  [512, 1024, 2048, 4096, 8192]
> +    storage [1..500]
> +  end
> +  #storage_disks [1..15]
> +  def hardware_profiles(credentials, opts = nil)
> +    hw_profiles = HardwareProfile.new('terremark_hardware_profile') do
> +      cpu     [1,2,4,8]
> +      memory  [512, 1024, 2048, 4096, 8192]
> +      storage [1..500]
> +    end
> +    hw_profiles = filter_hardware_profiles(hw_profiles, opts)
> +  end

You don't need the 'def hardware_profiles' - define_hardware_profile
already takes care of everything. You only need to override
hardware_profiles if the list of HWP changes dynamically, since
define_hardware_profile defines the profiles statically.

Also, I would call the HWP something simpler, like 'default'.
  
> +#--
> +# IMAGES
> +#--
> +#aka "vapp_templates"
> +  def images(credentials, opts=nil)
> +      theImages = []

No CamelCase, please; 'the_images' or 'result' is much better.

> +      safely do
> +        terremark_client = new_client(credentials)
> +        #get Organization ... get vDC id ... get Catalog ... list vapp 
> templates
> +        vdc_id = terremark_client.default_vdc_id
> +        catalogItems = 
> terremark_client.get_catalog(vdc_id).body['CatalogItems']
> +        catalogItems.each{|catalog_item|
> +          current_item_id = catalog_item['href'].split('/').last.to_i

Does Terremark really not give you the id in any other way than parsing
a URL ? That's very annoying and somewhat nasty.

> +          current_item = 
> terremark_client.get_catalog_item(current_item_id).body['Entity']
> +            if(current_item['type'] == 
> 'application/vnd.vmware.vcloud.vAppTemplate+xml')

What are the entries that do not have that tortuous media type ? Is it
ok to just drop them on the floor silently ?

> +#--
> +# CREATE INSTANCE
> +#--  
> +#launch a vapp template. Needs a name, ram, no. cpus, id of vapp_template
> +  def create_instance(credentials, image_id, opts)
> +    vapp_opts = {} #assemble options to pass to 
> Fog::Terremark::Real.instantiate_vapp_template
> +    terremark_hwp = hardware_profiles(credentials, opts) #sanity check 
> values against the defaults
hardware_profiles returns an array. You probably want
'hardware_profiles(credentials)[0]'

> +    vapp_opts['name'] = "inst_#{rand.to_s.slice(2..8)}" if 
> opts['name'].nil?#e.g. "inst_7394507"
> +    vapp_opts['name'] ||= opts['name']

This is more idiomatic if you write it as

       vapp_opts['name'] = opts['name'] || "inst#{Time.now.to_i}"

(it's also better to use Time.now to make the likelihood of collisions
smaller)

> +    vapp_opts['vapp_template'] = image_id
> +    vapp_opts['cpus'] = (terremark_hwp.cpu.include?(opts[:hwp_cpu])? 
> opts[:hwp_cpu]: 1 )
> +    vapp_opts['memory'] = (terremark_hwp.memory.include?(opts[:hwp_memory])? 
> opts[:hwp_memory]: 512)

You should raise an error if they pass in completely nonsensical values
for hwp_cpu, i.e. if terremark_hwp.cpu.include?(opts[:hwp_cpu]) is false

To generate a 400 response, you should raise a
Deltacloud::Validation::Failure

> +    safely do
> +      terremark_client = new_client(credentials)
> +      vapp_id = 
> terremark_client.instantiate_vapp_template(vapp_opts['name'], 
> vapp_opts).body['href'].split('/').last.to_i
> +      new_vapp = terremark_client.get_vapp(vapp_id)

I am not terribly happy with this, since we could successfully create
the vapp, then fail to get the details for the vapp, and the client
would not find out what went wrong.

The problem is more with the general API, than with the driver. To avoid
the extra call, we'd need to only return the location of the new
instance - for now, just stick a big FIXME comment in the code above.
It's something we need to sort out at the API level.

> +#--
> +# DESTROY INSTANCE
> +#--
> +#shuts down... in terremark need to do a futher delete to get rid of a vapp 
> entirely
> +  def destroy_instance(credentials, id)
> +    safely do
> +      terremark_client = new_client(credentials)
> +      terremark_client.shutdown(id) 
> +      #shutdown power POST https://{Terremark URI}/vapp/{vApp 
> ID}/power/action/powerOff
> +      #delete the vapp DELETE https://{Terremark URI}/vapp/{vApp ID} 
> +      #terremark_client.delete_vapp(id)
> +    end
> +  end

Your state machine rightly says that destroy can only be performed on a
stopped instance. IOW, destroy should just do the DELETE on the vapp -
calling it on a running instance should just be an error; I'd hope that
the backend cloud reports it. We do need to catch and report these
errors in the API.
  
David


_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel

Reply via email to