You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by Francesco Vollero <fv...@redhat.com> on 2013/04/11 17:41:50 UTC

[PATCH core] core: fixed the variable name in xml view

Signed-off-by: Francesco Vollero <fv...@redhat.com>
---
 .../deltacloud/drivers/upcloud/upcloud_driver.rb   | 350 +++++++++++++++++++++
 server/views/firewalls/show.xml.haml               |   2 +-
 2 files changed, 351 insertions(+), 1 deletion(-)
 create mode 100644 server/lib/deltacloud/drivers/upcloud/upcloud_driver.rb

diff --git a/server/lib/deltacloud/drivers/upcloud/upcloud_driver.rb b/server/lib/deltacloud/drivers/upcloud/upcloud_driver.rb
new file mode 100644
index 0000000..d210032
--- /dev/null
+++ b/server/lib/deltacloud/drivers/upcloud/upcloud_driver.rb
@@ -0,0 +1,350 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'restclient'
+
+module Deltacloud
+  module Drivers
+    module Upcloud
+      class UpcloudDriver < Deltacloud::BaseDriver
+
+        feature :instances, :user_name, :authentication_key
+        feature :images, :owner_id
+
+        define_instance_states do
+          start.to( :pending )          .on( :create )
+          pending.to( :running )        .automatically
+          running.to( :running )        .on( :reboot )
+          running.to( :stopping )       .on( :stop )
+          running.to( :finish )         .on( :destroy )
+          stopped.to( :running )        .on( :start )
+          stopped.to( :finish)          .on( :destroy )
+          stopping.to( :stopped )       .automatically
+          stopped.to( :finish )         .automatically
+          error.from(:running, :pending, :stopping)
+        end
+
+        define_hardware_profile('default')
+
+        def hardware_profiles(credentials, opts={})
+          do_client = new_client(credentials)
+          results = []
+          safely do
+            if opts[:id]
+              size = do_client.get("sizes/#{opts[:id]}")["size"]
+              results << hardware_profile_from(size)
+            else
+              do_client.get("sizes")["sizes"].each do |s|
+                size = do_client.get("sizes/#{s['id']}")["size"]
+                results << hardware_profile_from(size)
+              end
+            end
+            filter_hardware_profiles(results, opts)
+          end
+        end
+
+        def hardware_profile_ids(credentials)
+          do_client = new_client(credentials)
+          hwps = []
+          safely do
+            do_client.get("sizes")["sizes"].each do |s|
+              hwps << HardwareProfile.new(s["id"].to_s)
+            end
+          end
+          hwps
+        end
+
+        def realms(credentials, opts={})
+          safely do
+            realms = new_client(credentials).get('regions')['regions'].map do |r|
+              Realm.new(
+                :id => r['id'].to_s,
+                :name => r['name'],
+                :state => 'AVAILABLE',
+                :limit => :unlimited
+              )
+            end
+            filter_on(realms, opts, :id)
+          end
+        end
+
+        # By default images will return list of 'all' images available
+        # to launch.
+        # With 'owner_id' you can filter them using 'global' and 'my_images'
+        # values to get less images.
+        #
+        def images(credentials, opts={})
+          hwps = hardware_profile_ids(credentials)
+          unless opts[:id]
+            filter = opts[:owner_id] ? { :filter => "my_images" } : {}
+            img_arr = safely do
+              new_client(credentials).get('images', filter)['images'].map do |i|
+                convert_image(hwps, i)
+              end
+            end
+            filter_on( img_arr, :architecture, opts )
+          else
+            safely do
+              [convert_image(
+                hwps,
+                new_client(credentials).get('images/%s' % opts[:id])['image']
+              )]
+            end
+          end
+        end
+
+        # You can only destroy images you own.
+        #
+        def destroy_image(credentials, image_id)
+          safely do
+            new_client(credentials).get('images/%s/destroy', image_id)
+          end
+        end
+
+        def instances(credentials, opts={})
+          inst_arr = safely do
+            new_client(credentials).get('droplets')['droplets'].map do |i|
+              convert_instance(credentials.user, i)
+            end
+          end
+          filter_on inst_arr, :state, opts
+        end
+
+        def instance(credentials, opts={})
+          safely do
+            convert_instance(
+              credentials.user,
+              new_client(credentials).get("droplets/#{opts[:id]}")["droplet"]
+            )
+          end
+        end
+
+        def create_instance(credentials, image_id, opts={})
+          safely do
+            client = new_client(credentials)
+            args = { :image_id => image_id }
+            # Defaults to first realm if realm_id not set
+            opts[:realm_id] ||= '1'
+            args.merge!(:region_id => opts[:realm_id])
+            # Defaults to first size if hwp_id not set
+            opts[:hwp_id] ||= '66'
+            args.merge!(:size_id => opts[:hwp_id])
+            # Default to 'inst-timestamp if name is not set'
+            opts[:name] ||= "inst-#{Time.now.to_i}"
+            args.merge!(:name => opts[:name])
+            args.merge!(:ssh_key_ids => opts[:keyname]) if opts[:keyname]
+            convert_instance(
+              credentials.user,
+              client.get("droplets/new", args)['droplet']
+            )
+          end
+        end
+
+        def destroy_instance(credentials, instance_id)
+          safely do
+            new_client(credentials).get("droplets/#{instance_id}/destroy/")
+          end
+        end
+
+        def stop_instance(credentials, instance_id)
+          safely do
+            new_client(credentials).get("droplets/#{instance_id}/shutdown")
+          end
+        end
+
+        def start_instance(credentials, instance_id)
+          safely do
+            new_client(credentials).get("droplets/#{instance_id}/power_on/")
+          end
+        end
+
+        def reboot_instance(credentials, instance_id)
+          safely do
+            new_client(credentials).get("droplets/#{instance_id}/reboot/")
+          end
+        end
+
+        def keys(credentials, opts={})
+          client = new_client(credentials)
+          safely do
+            client.get('ssh_keys')['ssh_keys'].map do |k|
+              convert_key(k)
+            end
+          end
+        end
+
+        def key(credentials, opts={})
+          client = new_client(credentials)
+          safely do
+            convert_key(client.get("ssh_keys/#{opts[:id]}")["ssh_key"])
+          end
+        end
+
+        def destroy_key(credentials, opts={})
+          client = new_client(credentials)
+          original_key = key(credentials, opts)
+          safely do
+            client.get("ssh_keys/#{opts[:id]}/destroy")
+            original_key.state = 'deleted'
+            original_key
+          end
+        end
+
+        def create_key(credentials, opts={})
+          client = new_client(credentials)
+          convert_key(
+            client.get(
+              "ssh_keys/new",
+              :name => opts[:key_name],
+              :ssh_pub_key => opts[:public_key])['ssh_key']
+          )
+        end
+
+        exceptions do
+
+          on (/ERROR Unable to verify credentials.*/) do
+            status 401
+          end
+
+          on(/InternalServerError/) do
+            status 502
+          end
+
+          on(/No .*Found/) do
+            status 404
+          end
+
+          on(/An invalid/) do
+            status 400
+          end
+
+        end
+
+        def valid_credentials?(credentials)
+          begin
+            hardware_profile_ids(credentials)
+          rescue  Deltacloud::Exceptions::AuthenticationFailure
+            return false
+          rescue => e
+            safely { raise e }
+          end
+          true
+        end
+
+        private
+
+        class Client
+
+          API_URL = "https://api.upcloud.com/1.0/"
+          attr_reader :credentials
+
+          def initialize(credentials)
+            @credentials = credentials
+            @resource = RestClient::Resource.new(API_URL)
+          end
+
+          def get(uri, opts={})
+            opts.merge!(
+              :client_id => credentials.user,
+              :api_key => credentials.password
+            )
+            result = @resource[uri].get(:params => opts)
+            json_result = JSON::parse(result)
+            if json_result['status'] != 'OK'
+              p result
+              error_message = json_result['error_message'] || "#{json_result['status']} #{json_result['description']}"
+              raise error_message
+            end
+            json_result
+          end
+
+        end
+
+        def new_client(credentials)
+          Client.new(credentials)
+        end
+
+        def extract_arch_from_name(name)
+          return 'x86_64' if name.include? 'x64'
+          return 'i386' if name.include? 'x32'
+        end
+
+        def convert_key(k)
+          Key.new(
+            :id => k['id'],
+            :name => k['name'],
+            :credential_type => :key,
+            :pem_rsa_key => k['ssh_pub_key'],
+            :state => 'available'
+          )
+        end
+
+        def convert_state(status)
+          case status
+            when 'started' then 'RUNNING'
+            when 'new' then 'PENDING'
+            when 'error', 'stopped', 'maintenance'  then 'STOPPED'
+            else status.upcase
+          end
+        end
+
+        def convert_instance(user, i)
+          state = convert_state(i['status'] || 'pending')
+          address = i['ip_address'].nil? ?
+            [] : [InstanceAddress.new(i['ip_address'])]
+
+          Instance.new(
+            :id => i['id'].to_s,
+            :name => i['name'],
+            :image_id => i['image_id'],
+            :realm_id => i['region_id'],
+            :instance_profile => InstanceProfile.new(i['size_id']),
+            :state => state,
+            :public_addresses => address,
+            :private_addresses => [],
+            :owner_id => user,
+            :create_image => false,
+            :actions => instance_actions_for(state)
+          )
+        end
+
+        def convert_image(hwps, i)
+          Image.new(
+            :id => i['id'].to_s,
+            :name => i['name'],
+            :description => i['distribution'],
+            :owner_id => 'global',
+            :state => 'AVAILABLE',
+            :architecture => extract_arch_from_name(i['name']),
+            :hardware_profiles => hwps
+          )
+        end
+
+        #{"cost_per_hour"=>0.00744, "cpu"=>1, "disk"=>20, "id"=>66, "memory"=>512, "name"=>"512MB"}
+        def hardware_profile_from(size)
+          hwp = HardwareProfile.new(size["id"].to_s) do
+            architecture 'x86_64'
+            memory size["memory"]
+            storage size["disk"]
+            cpu size["cpu"]
+          end
+          hwp.name=size["name"]
+          return hwp
+        end
+
+      end
+    end
+  end
+end
diff --git a/server/views/firewalls/show.xml.haml b/server/views/firewalls/show.xml.haml
index d7c2bb7..c6b4ff1 100644
--- a/server/views/firewalls/show.xml.haml
+++ b/server/views/firewalls/show.xml.haml
@@ -2,7 +2,7 @@
 %firewall{:href => firewall_url(firewall.id), :id => firewall.id}
   %actions
     %link{ :rel => :destroy, :href => destroy_firewall_url(firewall.id), :method => :delete}
-    %link{ :rel => :update, :href => "#{firewall_url(firewall_name)}/rules", :method => :post}
+    %link{ :rel => :update, :href => "#{firewall_url(firewall.id)}/rules", :method => :post}
   - firewall.attributes.select{ |attr| attr != :id && attr!= :rules}.each do |attribute|
     - haml_tag("#{attribute}".tr('-', '_'), :<) do
       - if [:name, :description].include?(attribute)
-- 
1.8.1.4