You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2011/02/14 13:48:50 UTC
[PATCH core] Revamped using 'cloudservers' gem (thanks Rackspace!)
From: Michal Fojtik <mf...@redhat.com>
---
.../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