From 1829f977d27209a9b8fcb1e026a971dd74062738 Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Thu, 10 Jun 2010 03:31:08 +0800 Subject: [PATCH] get_network & get_network_ips for Tmrk Ecloud --- lib/fog/vcloud.rb | 9 ++- lib/fog/vcloud/terremark/ecloud.rb | 16 +++-- .../terremark/ecloud/parsers/network.rb | 28 +++++++++ .../terremark/ecloud/parsers/network_ips.rb | 31 +++++++++ .../terremark/ecloud/requests/get_network.rb | 54 ++++++++++++++++ .../ecloud/requests/get_network_ips.rb | 51 +++++++++++++++ .../ecloud/requests/get_network_ips_spec.rb | 54 ++++++++++++++++ .../ecloud/requests/get_network_spec.rb | 63 +++++++++++++++++++ 8 files changed, 299 insertions(+), 7 deletions(-) create mode 100644 lib/fog/vcloud/terremark/ecloud/parsers/network.rb create mode 100644 lib/fog/vcloud/terremark/ecloud/parsers/network_ips.rb create mode 100644 lib/fog/vcloud/terremark/ecloud/requests/get_network.rb create mode 100644 lib/fog/vcloud/terremark/ecloud/requests/get_network_ips.rb create mode 100644 spec/vcloud/terremark/ecloud/requests/get_network_ips_spec.rb create mode 100644 spec/vcloud/terremark/ecloud/requests/get_network_spec.rb diff --git a/lib/fog/vcloud.rb b/lib/fog/vcloud.rb index 14cd21227..d2f350a22 100644 --- a/lib/fog/vcloud.rb +++ b/lib/fog/vcloud.rb @@ -181,7 +181,8 @@ module Fog :dns => "8.8.8.8", :features => [ { :type => :fencemode, :value => "isolated" } - ] + ], + :ips => { "1.2.3.3" => "Broom 1", "1.2.3.4" => "Broom 2", "1.2.3.10" => "Email" } }, { :href => "#{base_url}/network/32", :name => "4.5.6.0/24", @@ -191,7 +192,8 @@ module Fog :dns => "8.8.8.8", :features => [ { :type => :fencemode, :value => "isolated" } - ] + ], + :ips => { } }, ], :vms => [ @@ -241,7 +243,8 @@ module Fog :netmask => "255.255.255.0", :features => [ { :type => :fencemode, :value => "isolated" } - ] + ], + :ips => { "7.8.9.10" => "Master Blaster" } } ], :vms => [ diff --git a/lib/fog/vcloud/terremark/ecloud.rb b/lib/fog/vcloud/terremark/ecloud.rb index aa1de7d9a..aef4ae0a6 100644 --- a/lib/fog/vcloud/terremark/ecloud.rb +++ b/lib/fog/vcloud/terremark/ecloud.rb @@ -44,20 +44,28 @@ module Fog require 'fog/vcloud/terremark/ecloud/parsers/get_public_ips' require 'fog/vcloud/terremark/ecloud/parsers/get_vdc' require 'fog/vcloud/terremark/ecloud/parsers/internet_service' + require 'fog/vcloud/terremark/ecloud/parsers/network' + require 'fog/vcloud/terremark/ecloud/parsers/network_ips' require 'fog/vcloud/terremark/ecloud/requests/add_internet_service' require 'fog/vcloud/terremark/ecloud/requests/configure_internet_service' require 'fog/vcloud/terremark/ecloud/requests/delete_internet_service' require 'fog/vcloud/terremark/ecloud/requests/get_internet_services' + require 'fog/vcloud/terremark/ecloud/requests/get_network' + require 'fog/vcloud/terremark/ecloud/requests/get_network_ips' require 'fog/vcloud/terremark/ecloud/requests/get_public_ip' require 'fog/vcloud/terremark/ecloud/requests/get_public_ips' require 'fog/vcloud/terremark/ecloud/requests/login' require 'fog/vcloud/terremark/ecloud/requests/get_vdc' - Struct.new("TmrkEcloudVdc", :links, :resource_entities, :networks, - :cpu_capacity, :storage_capacity, :memory_capacity, :deployed_vm_quota, :instantiated_vm_quota, - :href, :type, :name, :xmlns, :description) + Struct.new("TmrkEcloudVdc", :links, :resource_entities, :networks, :cpu_capacity, :storage_capacity, + :memory_capacity, :deployed_vm_quota, :instantiated_vm_quota, :href, :type, + :name, :xmlns, :description) Struct.new("TmrkEcloudList", :links) Struct.new("TmrkEcloudPublicIp", :type, :href, :name, :id) - Struct.new("TmrkEcloudInternetService", :type, :href, :id, :name, :public_ip, :port, :protocol, :enabled, :timeout, :description, :url_send_string, :http_header) + Struct.new("TmrkEcloudInternetService", :type, :href, :id, :name, :public_ip, :port, :protocol, + :enabled, :timeout, :description, :url_send_string, :http_header) + Struct.new("TmrkEcloudNetwork", :features, :configuration, :ips_link, :name, :type, :href, :xmlns) + Struct.new("TmrkEcloudNetworkIps", :addresses) + Struct.new("TmrkEcloudNetworkIp", :name, :status, :server) @required = true end if Fog.mocking? diff --git a/lib/fog/vcloud/terremark/ecloud/parsers/network.rb b/lib/fog/vcloud/terremark/ecloud/parsers/network.rb new file mode 100644 index 000000000..1e378124c --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/parsers/network.rb @@ -0,0 +1,28 @@ +module Fog + module Parsers + module Vcloud + module Terremark + module Ecloud + + class Network < Fog::Parsers::Vcloud::Network + + def reset + @response = Struct::TmrkEcloudNetwork.new([]) + end + + def start_element(name,attributes=[]) + super + case name + when "Link" + @response.ips_link = generate_link(attributes) + end + end + + end + end + end + end + end +end + + diff --git a/lib/fog/vcloud/terremark/ecloud/parsers/network_ips.rb b/lib/fog/vcloud/terremark/ecloud/parsers/network_ips.rb new file mode 100644 index 000000000..45f52ace1 --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/parsers/network_ips.rb @@ -0,0 +1,31 @@ +module Fog + module Parsers + module Vcloud + module Terremark + module Ecloud + + class NetworkIps< Fog::Parsers::Vcloud::Base + + def reset + @response = Struct::TmrkEcloudNetworkIps.new([]) + @ip_address = Struct::TmrkEcloudNetworkIp.new + end + + def end_element(name) + case name + when 'Name', 'Status', 'Server' + @ip_address[name.downcase] = @value + when 'IpAddress' + @response.addresses << @ip_address + @ip_address = Struct::TmrkEcloudNetworkIp.new + end + end + + end + end + end + end + end +end + + diff --git a/lib/fog/vcloud/terremark/ecloud/requests/get_network.rb b/lib/fog/vcloud/terremark/ecloud/requests/get_network.rb new file mode 100644 index 000000000..ac9653f0b --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/get_network.rb @@ -0,0 +1,54 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + module Real + + def get_network(network_uri) + request( + :expects => 200, + :method => 'GET', + :parser => Fog::Parsers::Vcloud::Terremark::Ecloud::Network.new, + :uri => network_uri + ) + end + + end + + module Mock + + def get_network(network_uri) + # + # Based off of: + # http://support.theenterprisecloud.com/kb/default.asp?id=546&Lang=1&SID= + # + type = "application/vnd.vmware.vcloud.network+xml" + response = Excon::Response.new + if network = mock_data[:organizations].map { |org| org[:vdcs].map { |vdc| vdc[:networks] } }.flatten.detect { |network| network[:href] == network_uri.to_s } + xml = Builder::XmlMarkup.new + mock_it Fog::Parsers::Vcloud::Terremark::Ecloud::Network.new, 200, + xml.Network(xmlns.merge(:href => network[:href], :name => network[:name], :type => type)) { + xml.Link( :rel => "down", :href => network[:href] + "/ips", :type => "application/xml", :name => "IP Addresses" ) + xml.Configuration { + xml.Gateway(network[:gateway]) + xml.Netmask(network[:netmask]) + } + if network[:features] + xml.Features { + if feature = network[:features].detect { |feature| feature[:type] == :fencemode } + xml.FenceMode(feature[:value]) + end + } + end + }, + { 'Content-Type' => type } + else + mock_error 200, "401 Unauthorized" + end + end + end + end + end + end +end + diff --git a/lib/fog/vcloud/terremark/ecloud/requests/get_network_ips.rb b/lib/fog/vcloud/terremark/ecloud/requests/get_network_ips.rb new file mode 100644 index 000000000..25b95494d --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/get_network_ips.rb @@ -0,0 +1,51 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + module Real + + def get_network_ips(network_ips_uri) + request( + :expects => 200, + :method => 'GET', + :parser => Fog::Parsers::Vcloud::Terremark::Ecloud::NetworkIps.new, + :uri => network_ips_uri + ) + end + + end + + module Mock + require 'ipaddr' + + def get_network_ips(network_ips_uri) + response = Excon::Response.new + if network = mock_data[:organizations].map { |org| org[:vdcs].map { |vdc| vdc[:networks] } }.flatten.detect { |network| network[:href] == network_ips_uri.to_s.gsub(%r:/ips$:,'') } + xml = Builder::XmlMarkup.new + mock_it Fog::Parsers::Vcloud::Terremark::Ecloud::NetworkIps.new, 200, + xml.IpAddresses { + IPAddr.new(network[:name]).to_range.to_a[3..-2].each do |ip| + xml.IpAddress { + xml.Name(ip.to_s) + if network[:ips].has_key?(ip.to_s) + xml.Status("Assigned") + xml.Server(network[:ips][ip.to_s]) + else + xml.Status("Available") + end + } + end + }, + { 'Content-Type' => 'application/vnd.tmrk.ecloud.ipAddressesList+xml' } + else + mock_error 200, "401 Unauthorized" + end + + + end + + end + end + end + end +end diff --git a/spec/vcloud/terremark/ecloud/requests/get_network_ips_spec.rb b/spec/vcloud/terremark/ecloud/requests/get_network_ips_spec.rb new file mode 100644 index 000000000..46db2e1e8 --- /dev/null +++ b/spec/vcloud/terremark/ecloud/requests/get_network_ips_spec.rb @@ -0,0 +1,54 @@ +require "spec_helper" + +describe "Fog::Vcloud, initialized w/ the TMRK Ecloud module", :type => :tmrk_ecloud_request do + subject { @vcloud } + + it { should respond_to :get_network_ips } + + describe "#get_network_ips" do + context "with a valid VDC network ips_uri" do + before { @ips = @vcloud.get_network_ips(URI.parse(@mock_network[:href] + "/ips")) } + subject { @ips } + + it_should_behave_like "all requests" + + its(:headers) { should include "Content-Type" } + specify { subject.headers['Content-Type'].should == "application/vnd.tmrk.ecloud.ipAddressesList+xml" } + + its(:body) { should be_an_instance_of Struct::TmrkEcloudNetworkIps } + + describe "#body" do + describe "#addresses" do + subject { @ips.body.addresses } + + it { should have(252).addresses } + + describe "one we know is assigned" do + let(:address) { subject[0] } + + specify { address.status.should == "Assigned" } + specify { address.server.should == "Broom 1" } + specify { address.name.should == "1.2.3.3" } + + end + + describe "one we know is not assigned" do + let(:address) { subject[100] } + + specify { address.status.should == "Available" } + specify { address.server.should == nil } + specify { address.name.should == "1.2.3.103" } + + end + + end + end + end + + context "with a network ips uri that doesn't exist" do + subject { lambda { @vcloud.get_network_ips(URI.parse('https://www.fakey.c/piv8vc99')) } } + + it_should_behave_like "a request for a resource that doesn't exist" + end + end +end diff --git a/spec/vcloud/terremark/ecloud/requests/get_network_spec.rb b/spec/vcloud/terremark/ecloud/requests/get_network_spec.rb new file mode 100644 index 000000000..0f5ca34f6 --- /dev/null +++ b/spec/vcloud/terremark/ecloud/requests/get_network_spec.rb @@ -0,0 +1,63 @@ +require "spec_helper" + +describe Fog::Vcloud, :type => :tmrk_ecloud_request do + subject { @vcloud } + + it { should respond_to :get_network } + + describe :get_network, :type => :vcloud_request do + context "with a valid network uri" do + before { @network = @vcloud.get_network(URI.parse(@mock_network[:href])) } + subject { @network } + + it_should_behave_like "all requests" + + its(:headers) { should include "Content-Type" } + its(:body) { should be_an_instance_of Struct::TmrkEcloudNetwork } + + describe :headers do + let(:header) { @network.headers["Content-Type"] } + specify { header.should == "application/vnd.vmware.vcloud.network+xml" } + end + + describe :body do + subject { @network.body } + + it_should_behave_like "it has a vcloud v0.8 xmlns" + + its(:configuration) { should be_an_instance_of Struct::VcloudNetworkConfiguration } + its(:features) { should be_an_instance_of Array } + its(:ips_link) { should be_an_instance_of Struct::VcloudLink } + its(:href) { should == URI.parse("https://fakey.com/api/v0.8/network/31") } + its(:type) { should == "application/vnd.vmware.vcloud.network+xml" } + its(:name) { should == @mock_network[:name] } + + describe :configuration do + subject { @network.body.configuration } + + its(:gateway) { should == "1.2.3.1" } + its(:netmask) { should == "255.255.255.0" } + end + + describe :ips_link do + subject { @network.body.ips_link } + its(:href) { should == URI.parse(@mock_network[:href] + "/ips") } + its(:rel) { should == "down" } + its(:type) { should == "application/xml" } + its(:name) { should == "IP Addresses" } + end + + describe "FenceMode Feature" do + subject { @network.body.features.detect { |feature| feature.is_a?(Struct::VcloudNetworkFenceMode) } } + its(:mode) { should == "isolated" } + end + + end + end + context "with a network uri that doesn't exist" do + subject { lambda { @vcloud.get_network(URI.parse('https://www.fakey.com/api/v0.8/network/999')) } } + it_should_behave_like "a request for a resource that doesn't exist" + end + end +end +