[rackspace|compute_v2] adds virtual interfaces support

This commit is contained in:
Kyle Rames 2014-03-04 11:51:26 -06:00
parent 76c470ffbb
commit ba63870629
10 changed files with 338 additions and 1 deletions

View File

@ -44,19 +44,28 @@ module Fog
recognizes :rackspace_compute_url
model_path 'fog/rackspace/models/compute_v2'
model :server
collection :servers
model :flavor
collection :flavors
model :image
collection :images
model :attachment
collection :attachments
model :network
collection :networks
model :key_pair
collection :key_pairs
model :virtual_interface
collection :virtual_interfaces
request_path 'fog/rackspace/requests/compute_v2'
request :list_servers
request :get_server
@ -106,6 +115,10 @@ module Fog
request :delete_keypair
request :get_keypair
request :list_virtual_interfaces
request :create_virtual_interface
request :delete_virtual_interface
class Mock < Fog::Rackspace::Service
include Fog::Rackspace::MockData
@ -174,7 +187,7 @@ module Fog
end
def request_id_header
"X-Compute-Request-Id"
"x-compute-request-id"
end
def region

View File

@ -579,6 +579,10 @@ module Fog
retry
end
def virtual_interfaces
@virtual_interfaces ||= Fog::Compute::RackspaceV2::VirtualInterfaces.new :server => self, :service => service
end
private
def adminPass=(new_admin_pass)

View File

@ -0,0 +1,87 @@
require 'fog/core/collection'
require 'fog/rackspace/models/compute_v2/virtual_interface'
module Fog
module Compute
class RackspaceV2
class VirtualInterface < Fog::Model
# @!attribute [r] id
# @return [String] The virtual interface id
identity :id
# @!attribute [r] mac_address
# @return [String] The Media Access Control (MAC) address for the virtual interface.
# A MAC address is a unique identifier assigned to network interfaces for communications on the physical network segment.
attribute :mac_address
# @!attribute [r] ip_addresses
# @return [Array<Hash>] returns an array of hashes containing information about allocated ip addresses and their associated networks
# @example
# [
# {
# "address": "2001:4800:7810:0512:d87b:9cbc:ff04:850c",
# "network_id": "ba122b32-dbcc-4c21-836e-b701996baeb3",
# "network_label": "public"
# },
# {
# "address": "64.49.226.149",
# "network_id": "ba122b32-dbcc-4c21-836e-b701996baeb3",
# "network_label": "public"
# }
# ]
attribute :ip_addresses
# Saves the virtual interface.
# This method can only create a virtual interface. Attempting to update interface will result an exception
# @return [Boolean] true if virtual interface has been saved
def save(attributes = {})
if persisted?
raise Fog::Errors::Error.new("This virtual interface has already been created and it cannot be updated")
else
create
end
true
end
# Creates Virtual interface for server
# * requires attributes: :network
# @return [Boolean] returns true if virtual network interface is being created
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @example To create a virtual interface;
# my_server.virtual_interfaces.create :network => my_network
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/api_create_virtual_interface.html
def create
data = service.create_virtual_interface(server_id, network_id)
merge_attributes(data.body['virtual_interfaces'].first)
end
# Destroy the virtual interface
# @return [Boolean] returns true if virtual interface has been destroyed
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/delete_virt_interface_api.html
def destroy
service.delete_virtual_interface(server_id, id)
true
end
private
def server_id
attributes[:server].is_a?(Server) ? attributes[:server].id : attributes[:server]
end
def network_id
attributes[:network].is_a?(Network) ? attributes[:network].id : attributes[:network]
end
end
end
end
end

View File

@ -0,0 +1,46 @@
require 'fog/core/collection'
require 'fog/rackspace/models/compute_v2/virtual_interface'
require 'fog/rackspace/models/compute_v2/server'
module Fog
module Compute
class RackspaceV2
class VirtualInterfaces < Fog::Collection
model Fog::Compute::RackspaceV2::VirtualInterface
attr_reader :server
def server=(obj)
if obj.is_a?(Server)
@server = obj
else
@server = Fog::Compute::RackspaceV2::Server.new :id => obj, :service => service
end
end
# Returns list of virtual interfaces for a server
# @return [Fog::Compute::RackspaceV2::Servers] Retrieves a list virtual interfaces for server.
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @note Fog's current implementation only returns 1000 servers
# @note The filter parameter on the method is just to maintain compatability with other providers that support filtering.
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Servers-d1e2078.html
# @see Fog::Compute::RackspaceV2::Server#virtual_interfaces
def all
raise "Please access this collection via Server#virtual_interfaces" unless self.server
data = service.list_virtual_interfaces(server.id).body['virtual_interfaces']
objects = load(data)
objects.each {|obj| obj.attributes[:server] = self.server}
objects
end
def new(attributes = {})
super({ :server => server }.merge(attributes))
end
end
end
end
end

View File

@ -0,0 +1,32 @@
module Fog
module Compute
class RackspaceV2
class Real
# Creates virtual interface for a server
# @param [String] server_id The server id to create the virtual interface on
# @param [String] network_id The network id to attach the virtual interface to
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/api_create_virtual_interface.html
def create_virtual_interface(server_id, network_id)
data = {
:virtual_interface => {
:network_id => network_id
}
}
request(
:expects => [200],
:method => 'POST',
:path => "/servers/#{server_id}/os-virtual-interfacesv2",
:body => Fog::JSON.encode(data)
)
end
end
end
end
end

View File

@ -0,0 +1,25 @@
module Fog
module Compute
class RackspaceV2
class Real
# Deletes virtual interface from server
# @param [String] server_id The server id that contains the virtual interface
# @param [String] interface_id The id of the virtual interface
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/delete_virt_interface_api.html
def delete_virtual_interface(server_id, interface_id)
request(
:expects => [200],
:method => 'DELETE',
:path => "/servers/#{server_id}/os-virtual-interfacesv2/#{interface_id}"
)
end
end
end
end
end

View File

@ -0,0 +1,24 @@
module Fog
module Compute
class RackspaceV2
class Real
# Lists virtual interfaces for a server
# @param [String] server_id
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
# @raise [Fog::Compute::RackspaceV2::ServiceError]
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/list_virt_interfaces.html
def list_virtual_interfaces(server_id)
request(
:expects => [200],
:method => 'GET',
:path => "/servers/#{server_id}/os-virtual-interfacesv2"
)
end
end
end
end
end

View File

@ -0,0 +1,33 @@
Shindo.tests('Fog::Compute::RackspaceV2 | virtual_interface', ['rackspace']) do
service = Fog::Compute::RackspaceV2.new
net_options = {
:label => "fog_network_#{Time.now.to_i.to_s}",
:cidr => '192.168.0.0/24'
}
server_options = {
:name => "fog_server_#{Time.now.to_i.to_s}",
:flavor_id => rackspace_test_flavor_id(service),
:image_id => rackspace_test_image_id(service)
}
tests('virtual_interface') do
pending if Fog.mocking?
begin
@server = service.servers.create server_options
@network = service.networks.create net_options
@server.wait_for { ready? }
model_tests(@server.virtual_interfaces, {:network => @network}, false)
ensure
if @server
@server.destroy
# wait_for_server_deletion(@server) if @server
delete_test_network(@network) if @network
end
end
end
end

View File

@ -0,0 +1,24 @@
Shindo.tests('Fog::Compute::RackspaceV2 | virtual_interfaces', ['rackspace']) do
service = Fog::Compute::RackspaceV2.new
options = {
:name => "fog_server_#{Time.now.to_i.to_s}",
:flavor_id => rackspace_test_flavor_id(service),
:image_id => rackspace_test_image_id(service)
}
tests('virtual_interfaces') do
pending if Fog.mocking?
begin
@server = service.servers.create options
@server.wait_for { ready? }
tests('#virtual_interfaces').succeeds do
@server.virtual_interfaces.all
end
ensure
@server.destroy if @server
end
end
end

View File

@ -0,0 +1,49 @@
Shindo.tests('Fog::Compute::RackspaceV2 | virtual_interface_tests', ['rackspace']) do
@service = Fog::Compute.new(:provider => 'Rackspace', :version => 'V2')
virtual_interface_format = {
"virtual_interfaces"=> [{
"ip_addresses"=> [{
"network_id"=> String,
"network_label"=> String,
"address"=> String
}],
"id"=> String,
"mac_address"=> String
}]
}
begin
unless Fog.mocking?
network_id = nil
@server = @service.servers.create(:name => "fog_virtual_interface_test_#{Time.now.to_i.to_s}",
:flavor_id => rackspace_test_flavor_id(@service),
:image_id => rackspace_test_image_id(@service))
@server.wait_for { ready? }
@network = @service.networks.create(:label => "fog_#{Time.now.to_i.to_s}", :cidr => '192.168.0.0/24')
end
tests('success') do
pending if Fog.mocking?
tests('#create_virtual_interface').formats(virtual_interface_format) do
response = @service.create_virtual_interface @server.id, @network.id
body = response.body
@virtual_network_interface_id = body["virtual_interfaces"].first["id"]
body
end
tests('#list_virtual_interfaces').formats(virtual_interface_format) do
@service.list_virtual_interfaces(@server.id).body
end
tests('#delete_virtual_interfaces').succeeds do
@service.delete_virtual_interface(@server.id, @virtual_network_interface_id)
end
end
ensure
@server.destroy if @server
delete_test_network @network
end
end