diff --git a/lib/fog/vcloud.rb b/lib/fog/vcloud.rb index 684f473f5..f8b1bb4ee 100644 --- a/lib/fog/vcloud.rb +++ b/lib/fog/vcloud.rb @@ -73,6 +73,12 @@ module Fog end end + def xmlns + { "xmlns" => "http://www.vmware.com/vcloud/v0.8", + "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", + "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema" } + end + def reload @connections.each_value { |k,v| v.reset if v } end @@ -343,12 +349,6 @@ module Fog @login_uri = get_login_uri end - def xmlns - { "xmlns" => "http://www.vmware.com/vcloud/v0.8", - "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", - "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema" } - end - def mock_it(status, mock_data, mock_headers = {}) response = Excon::Response.new diff --git a/lib/fog/vcloud/terremark/ecloud.rb b/lib/fog/vcloud/terremark/ecloud.rb index 8c10a9cde..7ba914a47 100644 --- a/lib/fog/vcloud/terremark/ecloud.rb +++ b/lib/fog/vcloud/terremark/ecloud.rb @@ -7,6 +7,8 @@ module Fog model_path 'fog/vcloud/terremark/ecloud/models' model :catalog_item model :catalog + model :firewall_acl + model :firewall_acls model :internet_service model :internet_services model :ip @@ -27,6 +29,7 @@ module Fog request_path 'fog/vcloud/terremark/ecloud/requests' request :add_internet_service request :add_node + request :clone_vapp request :configure_internet_service request :configure_network request :configure_network_ip @@ -38,6 +41,8 @@ module Fog request :get_catalog request :get_catalog_item request :get_customization_options + request :get_firewall_acls + request :get_firewall_acl request :get_internet_services request :get_network request :get_network_ip @@ -50,7 +55,9 @@ module Fog request :get_task request :get_task_list request :get_vapp + request :get_vapp_template request :get_vdc + request :instantiate_vapp_template request :power_off request :power_on request :power_reset diff --git a/lib/fog/vcloud/terremark/ecloud/models/firewall_acl.rb b/lib/fog/vcloud/terremark/ecloud/models/firewall_acl.rb new file mode 100644 index 000000000..d4bd5c281 --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/models/firewall_acl.rb @@ -0,0 +1,28 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + class FirewallAcl < Fog::Vcloud::Model + + identity :href, :Href + + ignore_attributes :xmlns, :xmlns_i + + attribute :name, :aliases => :Name + attribute :id, :aliases => :Id + attribute :protocol, :aliases => :Protocol + attribute :source, :aliases => :Source + attribute :destination, :aliases => :Destination + attribute :permission, :aliases => :Permission + attribute :port_start, :aliases => :PortStart + attribute :port_end, :aliases => :PortEnd + attribute :port_type, :aliases => :PortType + attribute :type, :aliases => :Type + + end + end + end + end +end + + diff --git a/lib/fog/vcloud/terremark/ecloud/models/firewall_acls.rb b/lib/fog/vcloud/terremark/ecloud/models/firewall_acls.rb new file mode 100644 index 000000000..24cba598c --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/models/firewall_acls.rb @@ -0,0 +1,31 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + class FirewallAcls < Fog::Vcloud::Collection + + model Fog::Vcloud::Terremark::Ecloud::FirewallAcl + + attribute :href, :aliases => :Href + + def all + if data = connection.get_firewall_acls(href).body[:FirewallAcl] + data = [ data ] if data.is_a?(Hash) + load(data) + end + end + + def get(uri) + if data = connection.get_firewall_acl(uri).body + new(data) + end + rescue Fog::Errors::NotFound + nil + end + + end + end + end + end +end diff --git a/lib/fog/vcloud/terremark/ecloud/models/internet_services.rb b/lib/fog/vcloud/terremark/ecloud/models/internet_services.rb index f5d3adc96..288501607 100644 --- a/lib/fog/vcloud/terremark/ecloud/models/internet_services.rb +++ b/lib/fog/vcloud/terremark/ecloud/models/internet_services.rb @@ -21,7 +21,7 @@ module Fog end end - # Optimize later, no need to get_internet_services again + # Optimize later, no need to get_internet_services again? def get(uri) internet_services = connection.get_internet_services(href).body[:InternetService] internet_services = [ internet_services ] if internet_services.is_a?(Hash) diff --git a/lib/fog/vcloud/terremark/ecloud/models/server.rb b/lib/fog/vcloud/terremark/ecloud/models/server.rb index 807fd72bc..142b0c617 100644 --- a/lib/fog/vcloud/terremark/ecloud/models/server.rb +++ b/lib/fog/vcloud/terremark/ecloud/models/server.rb @@ -91,7 +91,7 @@ module Fog def memory { :amount => memory_mess[:VirtualQuantity].to_i, - :units => memory_mess[:VirtualQuantityUnits] } + :units => memory_mess[:AllocationUnits] } end def memory=(amount) @@ -132,17 +132,14 @@ module Fog end def reload - super reset_tracking + super end def save if new_record? - requires :name - puts "NOOP" - return false - #result = connection.instantiate_vapp_template( stuff ) - #merge_attributes(result.body) + #Lame ... + raise RuntimeError, "Should not be here" else if on? if @changed @@ -159,7 +156,6 @@ module Fog def reset_tracking @disk_change = false @changed = false - true end def _compose_vapp_data diff --git a/lib/fog/vcloud/terremark/ecloud/models/servers.rb b/lib/fog/vcloud/terremark/ecloud/models/servers.rb index 7f72082c0..0baf3e345 100644 --- a/lib/fog/vcloud/terremark/ecloud/models/servers.rb +++ b/lib/fog/vcloud/terremark/ecloud/models/servers.rb @@ -5,6 +5,8 @@ module Fog class Servers < Fog::Vcloud::Collection + undef_method :create + model Fog::Vcloud::Terremark::Ecloud::Server attribute :href, :aliases => :Href @@ -21,6 +23,15 @@ module Fog nil end + def create( catalog_item_uri, options ) + options[:vdc_uri] = href + options[:cpus] ||= 1 + options[:memory] ||= 512 + data = connection.instantiate_vapp_template( catalog_item_uri, options ).body + object = new(data) + object + end + private def _resource_entities diff --git a/lib/fog/vcloud/terremark/ecloud/models/vdc.rb b/lib/fog/vcloud/terremark/ecloud/models/vdc.rb index f5399cfc9..893c1b91a 100644 --- a/lib/fog/vcloud/terremark/ecloud/models/vdc.rb +++ b/lib/fog/vcloud/terremark/ecloud/models/vdc.rb @@ -20,15 +20,11 @@ module Fog attribute :instantiated_vm_quota def public_ips - load_unless_loaded! - @public_ips ||= Fog::Vcloud::Terremark::Ecloud::PublicIps.new( :connection => connection, - :href => other_links.detect { |link| link[:type] == "application/vnd.tmrk.ecloud.publicIpsList+xml" }[:href] ) + @public_ips ||= collection_based_on_type("application/vnd.tmrk.ecloud.publicIpsList+xml") end def internet_services - @internet_services ||= Fog::Vcloud::Terremark::Ecloud::InternetServices. - new( :connection => connection, - :href => href.to_s.gsub('vdc','extensions/vdc') + "/internetServices" ) + @internet_services ||= collection_based_on_type("application/vnd.tmrk.ecloud.internetServicesList+xml") end def networks @@ -50,11 +46,32 @@ module Fog end def catalog - @catalog ||= Fog::Vcloud::Terremark::Ecloud::Catalog. - new( :connection => connection, - :href => href + "/catalog" ) + @catalog ||= collection_based_on_type("application/vnd.vmware.vcloud.catalog+xml") end + def firewall_acls + @firewall_acls ||= collection_based_on_type("application/vnd.tmrk.ecloud.firewallAclsList+xml") + end + + private + + def collection_based_on_type(type) + load_unless_loaded! + if link = other_links.detect { |link| link[:type] == type } + case type + when "application/vnd.tmrk.ecloud.publicIpsList+xml" + Fog::Vcloud::Terremark::Ecloud::PublicIps + when "application/vnd.tmrk.ecloud.internetServicesList+xml" + Fog::Vcloud::Terremark::Ecloud::InternetServices + when "application/vnd.vmware.vcloud.catalog+xml" + Fog::Vcloud::Terremark::Ecloud::Catalog + when "application/vnd.tmrk.ecloud.firewallAclsList+xml" + Fog::Vcloud::Terremark::Ecloud::FirewallAcls + end.new( :connection => connection, :href => link[:href] ) + else + [ ] + end + end end end end diff --git a/lib/fog/vcloud/terremark/ecloud/requests/clone_vapp.rb b/lib/fog/vcloud/terremark/ecloud/requests/clone_vapp.rb new file mode 100644 index 000000000..3ca12515e --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/clone_vapp.rb @@ -0,0 +1,50 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + module Real + + def validate_clone_vapp_options(options) + valid_opts = [:name, :poweron] + unless valid_opts.all? { |opt| options.keys.include?(opt) } + raise ArgumentError.new("Required data missing: #{(valid_opts - options.keys).map(&:inspect).join(", ")}") + end + end + + def generate_clone_vapp_request(uri, options) + xml = Builder::XmlMarkup.new + xml.CloneVAppParams(xmlns.merge!(:name => options[:name], :deploy => "true", :powerOn => options[:poweron])) { + xml.VApp( :href => uri, :type => "application/vnd.vmware.vcloud.vApp+xml", + :xmlns => "http://www.vmware.com/vcloud/v0.8") + } + end + + def clone_vapp(vdc_uri, vapp_uri, options = {}) + unless options.has_key?(:poweron) + options[:poweron] = "false" + end + + validate_clone_vapp_options(options) + + request( + :body => generate_clone_vapp_request(vapp_uri, options), + :expects => 202, + :headers => {'Content-Type' => 'application/vnd.vmware.vcloud.cloneVAppParams+xml'}, + :method => 'POST', + :uri => vdc_uri + '/action/clonevapp', + :parse => true + ) + end + end + + module Mock + def clone_vapp(vdc_uri, vapp_uri, customization_data) + validate_customization_data(customization_data) + Fog::Mock.not_implemented + end + end + end + end + end +end diff --git a/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acl.rb b/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acl.rb new file mode 100644 index 000000000..37c9573df --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acl.rb @@ -0,0 +1,18 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + module Real + basic_request :get_firewall_acl + end + + module Mock + def get_firewall_acl(firewall_acl_uri) + Fog::Mock.not_implemented + end + end + end + end + end +end diff --git a/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acls.rb b/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acls.rb new file mode 100644 index 000000000..02a4f6ed6 --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/get_firewall_acls.rb @@ -0,0 +1,18 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + module Real + basic_request :get_firewall_acls + end + + module Mock + def get_firewall_acls(firewall_acls_uri) + Fog::Mock.not_implemented + end + end + end + end + end +end diff --git a/lib/fog/vcloud/terremark/ecloud/requests/get_vapp_template.rb b/lib/fog/vcloud/terremark/ecloud/requests/get_vapp_template.rb new file mode 100644 index 000000000..d49827038 --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/get_vapp_template.rb @@ -0,0 +1,18 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + module Real + basic_request :get_vapp_template + end + + module Mock + def get_vapp_template(templace_uri) + Fog::Mock.not_implemented + end + end + end + end + end +end diff --git a/lib/fog/vcloud/terremark/ecloud/requests/instantiate_vapp_template.rb b/lib/fog/vcloud/terremark/ecloud/requests/instantiate_vapp_template.rb new file mode 100644 index 000000000..02475ed53 --- /dev/null +++ b/lib/fog/vcloud/terremark/ecloud/requests/instantiate_vapp_template.rb @@ -0,0 +1,100 @@ +module Fog + module Vcloud + module Terremark + module Ecloud + + module Real + + def validate_instantiate_vapp_template_options(catalog_item_uri, options) + valid_opts = [:name, :vdc_uri, :network_uri, :cpus, :memory, :row, :group] + unless valid_opts.all? { |opt| options.keys.include?(opt) } + raise ArgumentError.new("Required data missing: #{(valid_opts - options.keys).map(&:inspect).join(", ")}") + end + + # Figure out the template_uri + catalog_item = get_catalog_item( catalog_item_uri ).body + catalog_item[:Entity] = [ catalog_item[:Entity] ] if catalog_item[:Entity].is_a?(Hash) + catalog_item[:Link] = [ catalog_item[:Link] ] if catalog_item[:Link].is_a?(Hash) + + options[:template_uri] = begin + catalog_item[:Entity].detect { |entity| entity[:type] == "application/vnd.vmware.vcloud.vAppTemplate+xml" }[:href] + rescue + raise RuntimeError.new("Unable to locate template uri for #{catalog_item_uri}") + end + + customization_options = begin + customization_href = catalog_item[:Link].detect { |link| link[:type] == "application/vnd.tmrk.ecloud.catalogItemCustomizationParameters+xml" }[:href] + get_customization_options( customization_href ).body + rescue + raise RuntimeError.new("Unable to get customization options for #{catalog_item_uri}") + end + + # Check to see if we can set the password + if options[:password] and customization_options[:CustomizePassword] == "false" + raise ArgumentError.new("This catalog item (#{catalog_item_uri}) does not allow setting a password.") + end + + # According to the docs if CustomizePassword is "true" then we NEED to set a password + if customization_options[:CustomizePassword] == "true" and ( options[:password].nil? or options[:password].empty? ) + raise ArgumentError.new("This catalog item (#{catalog_item_uri}) requires a :password to instantiate.") + end + end + + def generate_instantiate_vapp_template_request(options) + xml = Builder::XmlMarkup.new + xml.InstantiateVAppTemplateParams(xmlns.merge!(:name => options[:name], :"xml:lang" => "en")) { + xml.VAppTemplate(:href => options[:template_uri]) + xml.InstantiationParams { + xml.ProductSection( :"xmlns:q1" => "http://www.vmware.com/vcloud/v0.8", :"xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1") { + if options[:password] + xml.Property( :xmlns => "http://schemas.dmtf.org/ovf/envelope/1", :"ovf:key" => "password", :"ovf:value" => options[:password] ) + end + xml.Property( :xmlns => "http://schemas.dmtf.org/ovf/envelope/1", :"ovf:key" => "row", :"ovf:value" => options[:row] ) + xml.Property( :xmlns => "http://schemas.dmtf.org/ovf/envelope/1", :"ovf:key" => "group", :"ovf:value" => options[:group] ) + } + xml.VirtualHardwareSection( :"xmlns:q1" => "http://www.vmware.com/vcloud/v0.8" ) { + # # of CPUS + xml.Item( :xmlns => "http://schemas.dmtf.org/ovf/envelope/1" ) { + xml.InstanceID(1, :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + xml.ResourceType(3, :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + xml.VirtualQuantity(options[:cpus], :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + } + # Memory + xml.Item( :xmlns => "http://schemas.dmtf.org/ovf/envelope/1" ) { + xml.InstanceID(2, :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + xml.ResourceType(4, :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + xml.VirtualQuantity(options[:memory], :xmlns => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData") + } + } + xml.NetworkConfigSection { + xml.NetworkConfig { + xml.NetworkAssociation( :href => options[:network_uri] ) + } + } + } + } + end + + def instantiate_vapp_template(catalog_item_uri, options = {}) + validate_instantiate_vapp_template_options(catalog_item_uri, options) + + request( + :body => generate_instantiate_vapp_template_request(options), + :expects => 200, + :headers => {'Content-Type' => 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'}, + :method => 'POST', + :uri => options[:vdc_uri] + '/action/instantiatevAppTemplate', + :parse => true + ) + end + end + + module Mock + def instantiate_vapp_template(vdc_uri) + Fog::Mock.not_implemented + end + end + end + end + end +end