From: Michal Fojtik <[email protected]> --- .../drivers/rackspace/rackspace_client.rb | 130 -------------- .../drivers/rackspace/rackspace_driver.rb | 180 +++++++++++--------- server/lib/deltacloud/models/instance.rb | 2 + server/views/instances/show.html.haml | 9 + 4 files changed, 109 insertions(+), 212 deletions(-) delete mode 100644 server/lib/deltacloud/drivers/rackspace/rackspace_client.rb
diff --git a/server/lib/deltacloud/drivers/rackspace/rackspace_client.rb b/server/lib/deltacloud/drivers/rackspace/rackspace_client.rb deleted file mode 100644 index d803302..0000000 --- a/server/lib/deltacloud/drivers/rackspace/rackspace_client.rb +++ /dev/null @@ -1,130 +0,0 @@ -# -# Copyright (C) 2009, 2010 Red Hat, Inc. -# -# 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 "net/http" -require "net/https" -require 'rubygems' -require 'json' - -# -# author: Michael Neale -# TODO: catch generic errors in JSON response and throw (probably) -# -module Deltacloud - module Drivers - module Rackspace - -class RackspaceClient - - @@AUTH_API = URI.parse('https://auth.api.rackspacecloud.com/v1.0') - - def initialize(username, auth_key) - http = Net::HTTP.new(@@AUTH_API.host,@@AUTH_API.port) - http.use_ssl = true - authed = http.get(@@AUTH_API.path, {'X-Auth-User' => username, 'X-Auth-Key' => auth_key}) - if authed.is_a?(Net::HTTPUnauthorized) - raise Deltacloud::AuthException, "Failed to authenticate to Rackspace" - elsif !authed.is_a?(Net::HTTPSuccess) - backend_error!(resp) - end - @auth_token = authed.header['X-Auth-Token'] - @service_uri = URI.parse(authed.header['X-Server-Management-Url']) - @service = Net::HTTP.new(@service_uri.host, @service_uri.port) - @service.use_ssl = true - end - - def list_flavors - JSON.parse(get('/flavors/detail'))['flavors'] - end - - def list_images - JSON.parse(get('/images/detail'))['images'] - end - - def list_servers - JSON.parse(get('/servers/detail'))['servers'] - end - - - def load_server_details( server_id ) - JSON.parse(get("/servers/#{server_id}"))['server'] - end - - - def start_server(image_id, flavor_id, name) - json = { :server => { :name => name, - :imageId => image_id.to_i, - :flavorId => flavor_id.to_i }}.to_json - # FIXME: The response has the root password in 'adminPass'; we somehow - # need to communicate this back since it's the only place where we can - # get it from - JSON.parse(post("/servers", json, headers).body)["server"] - end - - def delete_server(server_id) - delete("/servers/#{server_id}", headers) - end - - def reboot_server(server_id) - json = { :reboot => { :type => :SOFT }}.to_json - post("/servers/#{server_id}/action", json, headers) - end - - - def headers - {"Accept" => "application/json", "X-Auth-Token" => @auth_token, "Content-Type" => "application/json"} - end - - private - def get(path) - resp = @service.get(@service_uri.path + path, {"Accept" => "application/json", "X-Auth-Token" => @auth_token}) - unless resp.is_a?(Net::HTTPSuccess) - backend_error!(resp) - end - resp.body - end - - def post(path, json, headers) - resp = @service.post(@service_uri.path + path, json, headers) - unless resp.is_a?(Net::HTTPSuccess) - backend_error!(resp) - end - resp - end - - def delete(path, headers) - resp = @service.delete(@service_uri.path + path, headers) - unless resp.is_a?(Net::HTTPSuccess) - backend_error!(resp) - end - resp - end - - def backend_error!(resp) - json = JSON.parse(resp.body) - cause = json.keys[0] - code = json[cause]["code"] - message = json[cause]["message"] - details = json[cause]["details"] - raise Deltacloud::BackendError.new(code, cause, message, details) - end - -end - end - end -end diff --git a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb index 8d743aa..028b63a 100644 --- a/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +++ b/server/lib/deltacloud/drivers/rackspace/rackspace_driver.rb @@ -17,8 +17,8 @@ # under the License. require 'deltacloud/base_driver' -require 'deltacloud/drivers/rackspace/rackspace_client' require 'cloudfiles' +require 'cloudservers' module Deltacloud module Drivers @@ -27,20 +27,21 @@ module Deltacloud class RackspaceDriver < Deltacloud::BaseDriver feature :instances, :user_name + feature :instances, :authentication_password def supported_collections DEFAULT_COLLECTIONS + [ :buckets ] end - def hardware_profiles(credentials, opts = nil) - racks = new_client( credentials ) - results="" + def hardware_profiles(credentials, opts = {}) + rs = new_client( credentials ) + results = [] safely do - results = racks.list_flavors.map do |flav| - HardwareProfile.new(flav["id"].to_s) do + results = rs.list_flavors.collect do |f| + HardwareProfile.new(f[:id].to_s) do architecture 'x86_64' - memory flav["ram"].to_i - storage flav["disk"].to_i + memory f[:ram].to_i + storage f[:disk].to_i end end end @@ -48,22 +49,21 @@ class RackspaceDriver < Deltacloud::BaseDriver end def images(credentials, opts=nil) - racks = new_client( credentials ) - results="" + rs = new_client(credentials) + results = [] safely do - results = racks.list_images.map do |img| - Image.new( { - :id=>img["id"].to_s, - :name=>img["name"], - :description => img["name"] + " " + img["status"] + "", - :owner_id=>"root", - :architecture=>'x86_64' - } ) + results = rs.list_images.collect do |img| + Image.new( + :id => img[:id].to_s, + :name => img[:name], + :description => img[:name], + :owner_id => credentials.user, + :state => img[:status], + :architecture => 'x86_64' + ) end end - results.sort_by{|e| [e.description]} - results = filter_on( results, :id, opts ) - results + filter_on( results, :id, opts ) end #rackspace does not at this stage have realms... its all US/TX, all the time (at least at time of writing) @@ -75,67 +75,102 @@ class RackspaceDriver < Deltacloud::BaseDriver } )] end - def reboot_instance(credentials, id) - racks = new_client(credentials) + # + # create instance. Default to flavor 1 - really need a name though... + # In rackspace, all flavors work with all images. + # + def create_instance(credentials, image_id, opts) + rs = new_client( credentials ) + result = nil safely do - racks.reboot_server(id) + server = rs.create_server(:name => opts[:name] || Time.now.to_s, + :imageId => image_id.to_i, + :flavorId => opts[:hwp_id].to_i || hardware_profiles(credentials).first.id.to_i) + result = convert_instance_after_create(server, credentials.user, server.adminPass) end - Instance.new( { - :id => id, - :state => "RUNNING", - :actions => instance_actions_for( "RUNNING" ), - } ) + result end - def stop_instance(credentials, id) - destroy_instance(credentials, id) + def reboot_instance(credentials, instance_id) + rs = new_client(credentials) + safely do + server = rs.get_server(instance_id.to_i) + server.reboot! + convert_instance_after_create(server, credentials.user) + end end - def destroy_instance(credentials, id) - racks = new_client(credentials) + def destroy_instance(credentials, instance_id) + rs = new_client(credentials) safely do - racks.delete_server(id) + server = rs.get_server(instance_id.to_i) + server.delete! + convert_instance_after_create(server, credentials.user) end - Instance.new( { - :id => id, - :state => "STOPPED", - :actions => instance_actions_for( "STOPPED" ), - } ) end + alias_method :stop_instance, :destroy_instance + + def convert_instance_after_create(server, user_name, password='') + inst = Instance.new( + :id => server.id.to_s, + :realm_id => 'us', + :owner_id => user_name, + :description => server.name, + :name => server.name, + :state => (server.status == 'ACTIVE') ? 'RUNNING' : 'PENDING', + :architecture => 'x86_64', + :image_id => server.imageId.to_s, + :instance_profile => InstanceProfile::new(server.flavorId.to_s), + :public_addresses => server.addresses[:public], + :private_addresses => server.addresses[:private], + :username => 'root', + :password => password ? password : nil + ) + inst.actions = instance_actions_for(inst.state) + inst + end - # - # create instance. Default to flavor 1 - really need a name though... - # In rackspace, all flavors work with all images. - # - def create_instance(credentials, image_id, opts) - racks = new_client( credentials ) - hwp_id = opts[:hwp_id] || 1 - name = Time.now.to_s - if (opts[:name]) then name = opts[:name] end - safely do - return convert_srv_to_instance(racks.start_server(image_id, hwp_id, name)) - end + def convert_instance(server, user_name = '') + inst = Instance.new( + :id => server[:id].to_s, + :realm_id => 'us', + :owner_id => user_name, + :description => server[:name], + :name => server[:name], + :state => (server[:status] == 'ACTIVE') ? 'RUNNING' : 'PENDING', + :architecture => 'x86_64', + :image_id => server[:imageId].to_s, + :instance_profile => InstanceProfile::new(server[:flavorId].to_s), + :public_addresses => server[:addresses][:public], + :private_addresses => server[:addresses][:private] + ) + inst.actions = instance_actions_for(inst.state) + inst end # # Instances # - def instances(credentials, opts=nil) - racks = new_client(credentials) - instances = [] + def instances(credentials, opts={}) + + rs = new_client(credentials) + insts = [] + safely do - if (opts.nil?) - instances = racks.list_servers.map do |srv| - convert_srv_to_instance(srv) - end + if opts[:id] + server = rs.get_server(opts[:id].to_i) + insts << convert_instance_after_create(server, credentials.user) else - instances << convert_srv_to_instance(racks.load_server_details(opts[:id])) + insts = rs.list_servers_detail.collect do |server| + convert_instance(server, credentials.user) + end end end - instances = filter_on( instances, :id, opts ) - instances = filter_on( instances, :state, opts ) - instances + + insts = filter_on( insts, :id, opts ) + insts = filter_on( insts, :state, opts ) + insts end def valid_credentials?(credentials) @@ -149,14 +184,10 @@ class RackspaceDriver < Deltacloud::BaseDriver define_instance_states do start.to( :pending ) .on( :create ) - pending.to( :running ) .automatically - running.to( :running ) .on( :reboot ) running.to( :shutting_down ) .on( :stop ) - shutting_down.to( :stopped ) .automatically - stopped.to( :finish ) .automatically end @@ -290,25 +321,10 @@ class RackspaceDriver < Deltacloud::BaseDriver private - def convert_srv_to_instance(srv) - inst = Instance.new(:id => srv["id"].to_s, - :owner_id => "root", - :realm_id => "us") - inst.name = srv["name"] - inst.state = srv["status"] == "ACTIVE" ? "RUNNING" : "PENDING" - inst.actions = instance_actions_for(inst.state) - inst.image_id = srv["imageId"].to_s - inst.instance_profile = InstanceProfile.new(srv["flavorId"].to_s) - if srv["addresses"] - inst.public_addresses = srv["addresses"]["public"] - inst.private_addresses = srv["addresses"]["private"] - end - inst - end def new_client(credentials) safely do - return RackspaceClient.new(credentials.user, credentials.password) + CloudServers::Connection.new(:username => credentials.user, :api_key => credentials.password) end end diff --git a/server/lib/deltacloud/models/instance.rb b/server/lib/deltacloud/models/instance.rb index 467d93f..6345590 100644 --- a/server/lib/deltacloud/models/instance.rb +++ b/server/lib/deltacloud/models/instance.rb @@ -30,6 +30,8 @@ class Instance < BaseModel attr_accessor :launch_time attr_accessor :keyname attr_accessor :authn_error + attr_accessor :username + attr_accessor :password def to_s name diff --git a/server/views/instances/show.html.haml b/server/views/instances/show.html.haml index 0a6e115..76d77ba 100644 --- a/server/views/instances/show.html.haml +++ b/server/views/instances/show.html.haml @@ -36,6 +36,15 @@ %dt Private Addresses %dd = @instance.private_addresses.collect { |address| "<div>#{address}</div>" }.join + - if @instance.password + %di + %dt Username + %dd + = @instance.username + %di + %dt Password + %dd + = @instance.password %di %dt %dd -- 1.7.4
