diff --git a/README.md b/README.md index ae66567..3f11a99 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,45 @@ -## Ruby VCloud SDK is a gem to simplify making vCloud Director API calls. +#Ruby VCloud SDK + +Ruby VCloud SDK is a gem to simplify making vCloud Director API calls. Copyright (c) VMware, Inc. +## Object Structure + + + + Client |-> VDC |-> Vapp |-> Vm |-> Nic + | | | | + | | | |-> Internal Disk + | | | | + | | | |-> Disk + | | | | + | | | |-> Vapp + | | | + | | |-> Network + | | + | |-> Network |-> IpRanges + | | + | |-> Disk |-> Vm + | | + | |-> Resources + | | + | |-> Edge Gateway |-> IpRanges + | | + | |-> Vdc Storage Profile + | + |-> Catalog |-> Catalog Item |-> Template Vapp |-> Envelope + | | + | |-> OVF Directory + | + |-> RightRecord + | + |-> Session |-> Connection + ## Object Model - Client - + +#### Client + ------ find_vdc_by_name parameters: name (String): name of VDC @@ -55,7 +90,8 @@ Copyright (c) VMware, Inc. throws: 'RestClient::BadRequest' for un-expected errors - VDC +#### VDC + --- storage_profiles returns: array of storage profile objects @@ -102,6 +138,15 @@ Copyright (c) VMware, Inc. 'ObjectNotFoundError' when vapp with the name does not exist 'RestClient::BadRequest' for un-expected errors + find_vapp_by_id + parameters: + id (String): id of vapp + returns: + vapp object matching id + throws: + 'ObjectNotFoundError' when vapp with the id does not exist + 'RestClient::BadRequest' for un-expected errors + vapp_exists? parameters: name (String): name of vapp @@ -202,7 +247,8 @@ Copyright (c) VMware, Inc. 'CloudError' when any disk deletion failure occurs 'RestClient::BadRequest' for un-expected errors - Catalog +#### Catalog + ------- items returns: array of catalog item objects @@ -299,7 +345,8 @@ Copyright (c) VMware, Inc. 'ApiError' when instantiating vapp template task is not successful 'RestClient::BadRequest' for un-expected error - Network +#### Network + ------- ip_ranges returns: IpRanges object @@ -311,7 +358,17 @@ Copyright (c) VMware, Inc. throws: 'RestClient::BadRequest' for un-expected errors - VApp +#### VApp + ---- + + id + returns: vApp's id + + name + returns: vApp's name + + status: + returns: vApp's status delete returns: nil @@ -332,6 +389,15 @@ Copyright (c) VMware, Inc. 'VappSuspendedError' if VApp is suspended 'RestClient::BadRequest' for un-expected errors + reboot + returns: vApp object + + reset + returns: vApp object + + suspend: + returns: vApp object + recompose_from_vapp_template parameters: catalog_name (String): name of catalog @@ -403,7 +469,31 @@ Copyright (c) VMware, Inc. 'ObjectNotFoundError' when network with the name does not exist 'RestClient::BadRequest' for un-expected errors - VM + create_snapshot + parameters: + snapshot_hash (Hash): hash with :name and :description + returns: nil + throws: + + remove_snapshot + returns: nil + throws: + + revert_snapshot + returns: nil + throws: + +#### VM + --- + + id + returns: VM's id + + status + returns: VM's status + + href + returns: VM's href vcpu: returns: number of virtual cpus of VM @@ -434,6 +524,9 @@ Copyright (c) VMware, Inc. 'CloudError' when the memory size is less than or equal to 0 'RestClient::BadRequest' for un-expected errors + ip_address + returns: The IP address(es) of the VM + nics returns: array of NIC objects throws: @@ -479,6 +572,17 @@ Copyright (c) VMware, Inc. 'VmSuspendedError' if VM is suspended 'RestClient::BadRequest' for un-expected errors + reboot + returns: VM object + + reset + returns: VM object + + suspend: + returns: VM object + + undeploy: + insert_media parameters: catalog_name (String): name of catalog @@ -522,6 +626,9 @@ Copyright (c) VMware, Inc. 'ObjectNotFoundError' if specified nic index does not exist 'RestClient::BadRequest' for un-expected errors + install_vmtools + returns: nil + product_section_properties returns: array of hash values representing properties of product section of VM @@ -563,14 +670,16 @@ Copyright (c) VMware, Inc. 'ObjectNotFoundError' if no disk matching the given name 'RestClient::BadRequest' for un-expected errors - VdcStorageProfile +#### VdcStorageProfile + ----------------- available_storage returns: integer number of available storage in MB, i.e. storageLimitMB - storageUsedMB -1 if 'storageLimitMB' is 0 - EdgeGateway +#### EdgeGateway + ----------- public_ips: returns: IpRanges object @@ -579,19 +688,20 @@ Copyright (c) VMware, Inc. ## Example + VCloud_SDK is straightforward to use. Here is an example of creating vApp from vApp template. 1. Create vCloud client object - client = VCloudSdk::Client.new(url, username, password) + `client = VCloudSdk::Client.new(url, username, password)` Note that the parameter 'username' should be the VDC user_name@organization_name. For example, - the VDC user name is admin, the organization name is myorg, then the 'username' parameter + the VDC user name is admin, the organization name is myorg, then the 'username' parameter here should be admin@myorg. - + 2. Find the catalog where the vapp template is stored - catalog = client.find_catalog_by_name(catalog_name) + `catalog = client.find_catalog_by_name(catalog_name)` 3. Create vApp from that vapp template - vapp = instantiate_vapp_template(vapp_template_name, vdc_name, vapp_name) + `vapp = catalog.instantiate_vapp_template(vapp_template_name, vdc_name, vapp_name)` \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/catalog.rb b/lib/ruby_vcloud_sdk/catalog.rb index 5ec0e24..c009b6d 100644 --- a/lib/ruby_vcloud_sdk/catalog.rb +++ b/lib/ruby_vcloud_sdk/catalog.rb @@ -12,7 +12,7 @@ def initialize(session, link) @link = link end - def name + def name admin_xml.name end @@ -132,18 +132,34 @@ def upload_vapp_template( find_vapp_template_by_name(template_name) end + def find_vapp_template_by_id(uuid) + ##CUTRE + link = nil + admin_xml.catalog_items.each do |item_link| + link = item_link if uuid == item_link[:id] + end + fail ObjectNotFoundError, "Catalog Item '#{uuid}' is not found" if link.nil? + + item = VCloudSdk::CatalogItem.new(@session, link) + check_item_type(item, Xml::MEDIA_TYPE[:VAPP_TEMPLATE]) + item + + end + def find_vapp_template_by_name(name) find_item(name, Xml::MEDIA_TYPE[:VAPP_TEMPLATE]) end def instantiate_vapp_template(template_name, vdc_name, vapp_name, - description = nil, disk_locality = nil, network_config = nil) + description = nil, disk_locality = nil, network_config = nil, vm_params = nil) - instantiate_vapp_params = create_instantiate_vapp_params( - template_name, vapp_name, description, disk_locality, network_config) + catalog_item = find_vapp_template_by_name(template_name) + vm_link = catalog_item.vapp_template.vm_link - vdc = find_vdc_by_name vdc_name + instantiate_vapp_params = create_instantiate_vapp_params( + template_name, vapp_name, description, disk_locality, network_config,vm_params,vm_link) + vdc = find_vdc_by_name vdc_name vapp = connection.post(vdc.instantiate_vapp_template_link, instantiate_vapp_params) vapp.running_tasks.each do |task| @@ -330,7 +346,7 @@ def retrieve_vapp_template_xml_node(template_name) end def create_instantiate_vapp_params(template_name, - vapp_name, description, disk_locality, network_config) + vapp_name, description, disk_locality, network_config,vm_params,vm_link) source_vapp_template = retrieve_vapp_template_xml_node(template_name) @@ -346,6 +362,9 @@ def create_instantiate_vapp_params(template_name, instantiate_vapp_params.linked_clone = false instantiate_vapp_params.set_locality = locality_spec( source_vapp_template, disk_locality) + + disk = vm_params.first + instantiate_vapp_params.disk_size(disk[:id],disk[:size],vm_link) instantiate_vapp_params end diff --git a/lib/ruby_vcloud_sdk/catalog_item.rb b/lib/ruby_vcloud_sdk/catalog_item.rb index fee1cf6..70a7880 100644 --- a/lib/ruby_vcloud_sdk/catalog_item.rb +++ b/lib/ruby_vcloud_sdk/catalog_item.rb @@ -1,26 +1,91 @@ require_relative "session" require_relative "infrastructure" +require_relative "template_vapp" module VCloudSdk - # Represents the calalog item in calalog. + + ############################################################################## + # This class represents a catalog item in catalog. + # It can be a vApp Template or media&other, + ############################################################################## class CatalogItem include Infrastructure + ############################################################################ + # Initializes a Catalog Item object associated with a vCloud Session and the + # the catalog item's link + # @param session [Session] The client's session + # @param link [String] The xml representation of catalog item + ############################################################################ def initialize(session, link) @session = session @link = link end - def name + ############################################################################ + # Return the name of the Catalog Item object + # @return [String] The name of the catalog item + ############################################################################ + def name entity_xml.entity[:name] end - def type + ############################################################################ + # Return the identifier of the Catalog Item object + # @return [String] The identifier of the catalog item + ############################################################################ + def id + id = entity_xml.urn + id.split(":")[3] + end + + ############################################################################ + # Return the description of the Catalog Item object + # @return [String] The description of the catalog item + ############################################################################ + def description + entity_xml.description + end + + ############################################################################ + # Return the vApp template id of the Catalog Item object + # @return [String] The vApp template id of the catalog item + ############################################################################ + def vapp_template_id + entity_xml.entity[:href].split("/")[5] + end + + ############################################################################ + # Return the type of the Catalog Item object. It can be: + # @return [String] The type of the catalog item + ############################################################################ + def type entity_xml.entity[:type] end + def size + entity_xml.size + end + + ############################################################################ + # Return the vCloud href of the Catalog Item object. + # @return [String] The href of the catalog item + ############################################################################ def href entity_xml.entity[:href] end + + def vapp_template + VCloudSdk::TemplateVapp.new(@session, entity_xml.entity[:href]) + end + + ############################################################################ + # Return the date of creation of the Catalog Item object. + # @return [String] The creation date of the catalog item + ############################################################################ + def date + entity_xml.date + end end + ############################################################################## end diff --git a/lib/ruby_vcloud_sdk/client.rb b/lib/ruby_vcloud_sdk/client.rb index 87b1cea..606ecd8 100644 --- a/lib/ruby_vcloud_sdk/client.rb +++ b/lib/ruby_vcloud_sdk/client.rb @@ -6,6 +6,10 @@ module VCloudSdk + ################################################################################ + # This class represents a vCloud connection and an associated client + # The connection is associated to the vCloud API. + ################################################################################ class Client include Infrastructure @@ -13,8 +17,19 @@ class Client public :find_vdc_by_name, :catalogs, :list_catalogs, :catalog_exists?, :find_catalog_by_name, - :vdc_exists? + :vdc_exists?, :vdcs + ############################################################################## + # Initializes the Client and creates a Session to vCloud API. + # @param url [String] The url of vCloud host [http://api.example.com] + # @param username [String] The username of vCloud account [username@org_name] + # @param password [String] The password for vCloud user. + # @param options [Hash] The options (RETRIES, TIME_LIMIT_SEC,DELAY) for + # the session.Use 'options = {}' for default options. + # See session.rb for more info. + # @param logger [Logger] Optional.The logger for the connection. It manages + # response messages.By default STDOUT + ############################################################################## def initialize(url, username, password, options = {}, logger = nil) @url = url Config.configure(logger: logger || Logger.new(STDOUT)) @@ -23,6 +38,12 @@ def initialize(url, username, password, options = {}, logger = nil) Config.logger.info("Successfully connected.") end + ############################################################################## + # Creates a catalog for the organization. + # @param name [String] The catalog's name. + # @param description [String] The catalog's description. + # @return [Catalog] The new created catalog. + ############################################################################## def create_catalog(name, description = "") catalog = Xml::WrapperFactory.create_instance("AdminCatalog") catalog.name = name @@ -33,6 +54,11 @@ def create_catalog(name, description = "") find_catalog_by_name name end + ############################################################################## + # Deletes the catalog identified with "name" for the organization. + # @param name [String] The catalog's name to delete + # @return [Catalog] The deleted catalog + ############################################################################## def delete_catalog_by_name(name) catalog = find_catalog_by_name(name) catalog.delete_all_items @@ -40,6 +66,10 @@ def delete_catalog_by_name(name) self end + ############################################################################## + # Returns Right Records. + # @return [Right Record] an array of Right Record. + ############################################################################## def right_records right_records = connection.get("/api/admin/rights/query").right_records @@ -48,5 +78,5 @@ def right_records end end end - + ################################################################################ end diff --git a/lib/ruby_vcloud_sdk/cpu.rb b/lib/ruby_vcloud_sdk/cpu.rb index 971cf20..0f4c543 100644 --- a/lib/ruby_vcloud_sdk/cpu.rb +++ b/lib/ruby_vcloud_sdk/cpu.rb @@ -1,10 +1,19 @@ module VCloudSdk + ################################################################################ + # This class represents the CPU resource of the Virtual Data Center. + ################################################################################ class CPU - attr_reader :available_cores + attr_reader :available_cores, :limit_cores - def initialize(available_cores) + ############################################################################## + # Initialize a CPU resource of the VDC. + # @param available_cores [String] The cores not used in the VDC. + # @param limit_cores [String] The maximum cores to use in the VDC. + ############################################################################## + def initialize(available_cores,limit_cores) @available_cores = available_cores + @limit_cores = limit_cores end end diff --git a/lib/ruby_vcloud_sdk/edge_gateway.rb b/lib/ruby_vcloud_sdk/edge_gateway.rb index a4725df..9b96b7d 100644 --- a/lib/ruby_vcloud_sdk/edge_gateway.rb +++ b/lib/ruby_vcloud_sdk/edge_gateway.rb @@ -3,16 +3,139 @@ require_relative "ip_ranges" module VCloudSdk + + ############################################################################## + # This class represents a Edge Gateway in the Virtual Data Center. + ############################################################################## class EdgeGateway include Infrastructure extend Forwardable def_delegator :entity_xml, :name + ############################################################################ + # Initializes a EdgeGateway object associated with a vCloud Session and the + # the Edge Gateway's link + # @param session [Session] The client's session + # @param link [String] The xml representation of the Edge Gateway + ############################################################################ def initialize(session, link) - @session = session - @link = link + @session = session + @link = link + end + + ############################################################################ + # Add Firewall rules to the Edge Gateyay. + # @param rules [Array] Array of Hashes representing the rules to be added. + # :name [String] The name of the rule. + # :ip_src [String] The source IP or "Any". + # :ip_dest [String] The destination IP or "Any". + # :port_src [String] The source Port or "Any". + # :port_dest [String] The destination IP or "Any". + # :prot [String] "TCP","UDP", "TCP & UDP", "ICMP", + # "ANY" . + # :action [String] The action to be applied.It can be + # "allow" or "deny". + # :enabled [String] To enable or disable the rule. + # The options are "true" or "false". + # + # @return [EdgeGateway] The Edge Gateway object. + ############################################################################ + def add_fw_rules(rules) + link = entity_xml.configure_services_link + payload = entity_xml.add_fw_rules(rules) + + task = connection.post(link, + payload.configure_services, + Xml::ADMIN_MEDIA_TYPE[:EDGE_SERVICES_CONFIG]) + monitor_task(task) + self + end + + ############################################################################ + # Remove the Firewall rules with IPs destination passed as an argument + # @param ips [Array] Array of IPs destination addresses + # @return [EdgeGateway] The Edge Gateway object. + ############################################################################ + def remove_fw_rules(ips) + link = entity_xml.configure_services_link + payload = entity_xml.remove_fw_rules(ips) + + task = connection.post(link, + payload.configure_services, + Xml::ADMIN_MEDIA_TYPE[:EDGE_SERVICES_CONFIG]) + monitor_task(task) + self + end + def ent + entity_xml + end + ############################################################################ + # Add Nat rules to the Edge Gateyay. + # @param rules [Array] Array of Hashes representing the rules to be added. + # :description [String] Description about the rule. + # :rule_type [String] "SNAT" or "DNAT". + # :enabled [String] "true" or "false". + # :interface [String] The name of the uplink network. + # :original_ip [String] The original IP or "Any". + # :original_port [String] The translated IP,"Any" or range ("startIP"-"finalIP"). + # :translated_ip [String] The destination IP or "Any". + # :translated_port [String] + # :protocol [String] + # + # @return [EdgeGateway] The Edge Gateway object. + ############################################################################ + def add_nat_rules(rules) + link = entity_xml.configure_services_link + payload = entity_xml.add_nat_rules(rules) + + task = connection.post(link, + payload.configure_services, + Xml::ADMIN_MEDIA_TYPE[:EDGE_SERVICES_CONFIG]) + monitor_task(task) + self + end + + ############################################################################ + # Remove the Nat rules with the VM IPs passed as an argument + # @param ips [Array] Array of IPs addresses + # @return [EdgeGateway] The Edge Gateway object. + ############################################################################ + def remove_nat_rules(ips) + link = entity_xml.configure_services_link + payload = entity_xml.remove_nat_rules(ips) + + task = connection.post(link, + payload.configure_services, + Xml::ADMIN_MEDIA_TYPE[:EDGE_SERVICES_CONFIG]) + monitor_task(task) + self end + + def public_net_name + uplink_gateway_interface = entity_xml + .gateway_interfaces + .find { |g| g.interface_type == "uplink" } + return uplink_gateway_interface.get_nodes("Name").first.content + + end + + def public_ip_net + uplink_gateway_interface = entity_xml + .gateway_interfaces + .find { |g| g.interface_type == "uplink" } + + ip_address = uplink_gateway_interface.get_nodes("IpAddress").first.content.split(".") + netmask = uplink_gateway_interface.get_nodes("Netmask").first.content.split(".") + + ip_net = "" + ip_net << (ip_address[0].to_i & netmask[0].to_i).to_s << "." + ip_net << (ip_address[1].to_i & netmask[1].to_i).to_s << "." + ip_net << (ip_address[2].to_i & netmask[2].to_i).to_s << "." + ip_net << (ip_address[3].to_i & netmask[3].to_i).to_s + + return ip_net + end def public_ip_ranges uplink_gateway_interface = entity_xml diff --git a/lib/ruby_vcloud_sdk/envelope.rb b/lib/ruby_vcloud_sdk/envelope.rb new file mode 100644 index 0000000..c7ba785 --- /dev/null +++ b/lib/ruby_vcloud_sdk/envelope.rb @@ -0,0 +1,45 @@ +require_relative "infrastructure" + +module VCloudSdk + + ############################################################################## + # This class represents a catalog item in catalog. + # It can be a vApp Template or media&other, + ############################################################################## + class Envelope + include Infrastructure + + + ############################################################################ + # Initializes a Catalog Item object associated with a vCloud Session and the + # the catalog item's link + # @param session [Session] The client's session + # @param link [String] The xml representation of catalog item + ############################################################################ + def initialize(session, link) + @session = session + @link = link + end + + def ent + entity_xml + end + + def os + entity_xml.operating_system + end + + def disks + hardware_section = entity_xml.hardware_section + internal_disks = [] + hardware_section.hard_disks.each do |disk| + disk_link = disk.host_resource.attribute("disk") + if disk_link.nil? + internal_disks << VCloudSdk::InternalDisk.new(disk) + end + end + internal_disks + end + end + ############################################################################## +end diff --git a/lib/ruby_vcloud_sdk/infrastructure.rb b/lib/ruby_vcloud_sdk/infrastructure.rb index 98fe0fe..cc69b26 100644 --- a/lib/ruby_vcloud_sdk/infrastructure.rb +++ b/lib/ruby_vcloud_sdk/infrastructure.rb @@ -1,6 +1,9 @@ module VCloudSdk - # Shared functions by classes such as Client, Catalog and VDC - # Make sure instance variable @session is available + + ############################################################################################### + # This module defines the shared functions by classes such as Client, Catalog and VDC + # Make sure instance variable @session is available + ############################################################################################### module Infrastructure ERROR_STATUSES = [Xml::TASK_STATUS[:ABORTED], Xml::TASK_STATUS[:ERROR], Xml::TASK_STATUS[:CANCELED]] @@ -8,18 +11,41 @@ module Infrastructure private + ############################################################################################# + # Returns the Virtual Data Center identified by name. + # @return [VDC] The VDC. + ############################################################################################# def find_vdc_by_name(name) vdc_link = @session.org.vdc_link(name) fail ObjectNotFoundError, "VDC #{name} not found" unless vdc_link VCloudSdk::VDC.new(@session, vdc_link) end + ############################################################################################# + # Obtain if the VDC identified by name exists. + # @return [Boolean] If the VDC identified by name exists, returns "True". + ############################################################################################# def vdc_exists?(name) @session.org.vdcs.any? do |vdc| vdc.name == name end end + ############################################################################################# + # Returns the list of VDC existing. + # @return [VDC] The array of VDC. + ############################################################################################# + def vdcs + @session.org.vdcs.map do |vdc_link| + VCloudSdk::VDC.new(@session, vdc_link) + end + + end + + ############################################################################################# + # Returns the Network identified by name. + # @return [Network] The network returned. + ############################################################################################# def find_network_by_name(name) @session.org.networks.each do |network_link| if network_link.name == name @@ -30,30 +56,50 @@ def find_network_by_name(name) fail ObjectNotFoundError, "Network '#{name}' is not found" end + ############################################################################################# + # Obtain if the network identified by name exists. + # @return [Boolean] If the network identified by name exists, returns "True". + ############################################################################################# def network_exists?(name) @session.org.networks.any? do |network| network.name == name end end + ############################################################################################# + # Returns the list of catalogs. + # @return [Catalog] The array of existing catalogs. + ############################################################################################# def catalogs @session.org.catalogs.map do |catalog_link| VCloudSdk::Catalog.new(@session, catalog_link) end end + ############################################################################################# + # Returns the name's list of Networks created in the Virtual Data Center. + # @return [String] The array of Network's names. + ############################################################################################# def list_catalogs @session.org.catalogs.map do |catalog_link| catalog_link.name end end + ############################################################################################# + # Obtain if the catalog identified by name exists. + # @return [Boolean] If the catalog identified by name exists, returns "True". + ############################################################################################# def catalog_exists?(name) @session.org.catalogs.any? do |catalog| catalog.name == name end end + ############################################################################################# + # Returns the catalog identified by name. + # @return [Catalog] The catalog returned. + ############################################################################################# def find_catalog_by_name(name) @session.org.catalogs.each do |catalog_link| if catalog_link.name == name @@ -64,10 +110,17 @@ def find_catalog_by_name(name) fail ObjectNotFoundError, "Catalog '#{name}' is not found" end + ############################################################################################# + # Returns the object's connection. + # @return [Connection] The connection returned. + ############################################################################################# def connection @session.connection end + ############################################################################################# + # Monitores the task passed as a argument. + ############################################################################################# def monitor_task( task, time_limit = @session.time_limit[:default], @@ -124,23 +177,39 @@ def monitor_task( "Task #{task.operation} did not complete within limit of #{time_limit} seconds." end + ############################################################################################# + # Obtain if the task has progressed or not. + # @return [Boolean] If the task has progressed, returns "True". + ############################################################################################# def task_progressed?(current_task, prev_progress, prev_status) (current_task.progress && (current_task.progress != prev_progress)) || (current_task.status && (current_task.status != prev_status)) end + ############################################################################################# + # Obtain if the task has succeeded or not. + # @return [Boolean] If the task has succeeded, returns "True". + ############################################################################################# def task_is_success(current_task, success = SUCCESS_STATUS) success.find do |s| s.downcase == current_task.status.downcase end end + ############################################################################################# + # Obtain if the task has an error or not. + # @return [Boolean] If the task has an error, returns "True". + ############################################################################################# def task_has_error(current_task, error_statuses = ERROR_STATUSES) error_statuses.find do |s| s.downcase == current_task.status.downcase end end + ############################################################################################# + # Returns the object's XML representation. + # @return [String] The XML representation of the object. + ############################################################################################# def entity_xml connection.get(@link) end @@ -154,4 +223,5 @@ def wait_for_running_tasks(subject, subject_display) end end end + ############################################################################################### end diff --git a/lib/ruby_vcloud_sdk/internal_disk.rb b/lib/ruby_vcloud_sdk/internal_disk.rb index a849782..9df4994 100644 --- a/lib/ruby_vcloud_sdk/internal_disk.rb +++ b/lib/ruby_vcloud_sdk/internal_disk.rb @@ -1,9 +1,10 @@ module VCloudSdk class InternalDisk - attr_reader :name, :capacity, :bus_type, :bus_sub_type + attr_reader :id, :name, :capacity, :bus_type, :bus_sub_type def initialize(entity_xml) + @id = entity_xml.disk_id @name = entity_xml.element_name @capacity = entity_xml.host_resource.attribute("capacity").to_s.to_i @bus_type = entity_xml.host_resource.attribute("busType").to_s diff --git a/lib/ruby_vcloud_sdk/memory.rb b/lib/ruby_vcloud_sdk/memory.rb index 7fede01..e9b5522 100644 --- a/lib/ruby_vcloud_sdk/memory.rb +++ b/lib/ruby_vcloud_sdk/memory.rb @@ -1,10 +1,19 @@ module VCloudSdk + ################################################################################ + # This class represents the Memory resource of the Virtual Data Center. + ################################################################################ class Memory - attr_reader :available_mb + attr_reader :available_mb, :limit_mb - def initialize(available_mb) + ############################################################################## + # Initialize a Memory resource of the VDC. + # @param available_mb [String] The amount memory not used in the VDC in MB + # @param limit_mb [String] The amount memory to use in the VDC in MB + ############################################################################## + def initialize(available_mb,limit_mb) @available_mb = available_mb + @limit_mb = limit_mb end end diff --git a/lib/ruby_vcloud_sdk/network.rb b/lib/ruby_vcloud_sdk/network.rb index 865b37e..f908b9e 100644 --- a/lib/ruby_vcloud_sdk/network.rb +++ b/lib/ruby_vcloud_sdk/network.rb @@ -2,21 +2,74 @@ require_relative "ip_ranges" module VCloudSdk + + ###################################################################################### + # This class represents a virtual Network in the virtual data center. + ###################################################################################### class Network include Infrastructure extend Forwardable def_delegator :entity_xml, :name - + + #################################################################################### + # Initializes a vApp object associated with a vCloud Session and the Network's link. + # @param session [Session] The client's session. + # @param link [String] The vCloud link of the network. + #################################################################################### def initialize(session, link) @session = session @link = link end + #################################################################################### + # Returns the identifier of the Network (uuid). + # @return [String] The identifier of the Network. + #################################################################################### + def id + @link.href.split("/")[5] + end + + def ent + entity_xml + end + + #################################################################################### + # Returns the description of the Network. + # @return [String] The identifier of the Network. + #################################################################################### + def description + entity_xml.description + end + + def gateway + entity_xml.gateway + end + + def netmask + entity_xml.netmask + end + + #################################################################################### + # Returns the fence mode of the Network. + # @return [String] The fence mode of the Network. + #################################################################################### + def fence_mode + entity_xml.fence_mode + end + + #################################################################################### + # Returns the vCloud link of the Network. + # @return [String] The vCloud link of the Network. + #################################################################################### def href @link end + #################################################################################### + # Returns array of IpRanges objects of the Network + # @return [IpRanges] an array of IpRanges + #################################################################################### def ip_ranges entity_xml .ip_scope @@ -27,6 +80,10 @@ def ip_ranges end end + #################################################################################### + # Returns the list of allocated ips of the Network + # @return [String] an array of allocated ip addresses + #################################################################################### def allocated_ips allocated_addresses = connection.get(entity_xml.allocated_addresses_link) allocated_addresses.ip_addresses.map do |i| @@ -34,4 +91,5 @@ def allocated_ips end end end + ###################################################################################### end diff --git a/lib/ruby_vcloud_sdk/network_config.rb b/lib/ruby_vcloud_sdk/network_config.rb index 591b5d8..64d8996 100644 --- a/lib/ruby_vcloud_sdk/network_config.rb +++ b/lib/ruby_vcloud_sdk/network_config.rb @@ -7,9 +7,10 @@ def initialize( network_name, vapp_net_name = nil, fence_mode = Xml::FENCE_MODES[:BRIDGED]) - @network_name = network_name - @vapp_net_name = vapp_net_name - @fence_mode = fence_mode + + @network_name = network_name + @vapp_net_name = vapp_net_name + @fence_mode = fence_mode end end diff --git a/lib/ruby_vcloud_sdk/nic.rb b/lib/ruby_vcloud_sdk/nic.rb index ab896fb..1319dd2 100644 --- a/lib/ruby_vcloud_sdk/nic.rb +++ b/lib/ruby_vcloud_sdk/nic.rb @@ -1,4 +1,9 @@ module VCloudSdk + + ################################################################################ + # This class represents a NIC (Network Interface Card). + # The NIC are attached to VM and connected to Networks. + ################################################################################ class NIC extend Forwardable @@ -8,15 +13,29 @@ class NIC attr_reader :is_primary + ############################################################################## + # Initialize a NIC. + # @param entity_xml [String] The XML representation for the NIC. + # @param is_primary [Boolean] It defines if the NIC is the main or not. + ############################################################################## def initialize(entity_xml, is_primary) - @entity_xml = entity_xml + @entity_xml = entity_xml @is_primary = is_primary end + ############################################################################## + # Retrun the network connection index. + # @return [Integer] The newtork connection index. + ############################################################################## def network_connection_index @entity_xml.network_connection_index.to_i end + ############################################################################## + # Retuns the NIC status. + # @return [Boolean] Return "True" if the NIC is connected + # "False" otherwise + ############################################################################## def is_connected @entity_xml.is_connected == "true" end diff --git a/lib/ruby_vcloud_sdk/powerable.rb b/lib/ruby_vcloud_sdk/powerable.rb index e939f5d..07d0f15 100644 --- a/lib/ruby_vcloud_sdk/powerable.rb +++ b/lib/ruby_vcloud_sdk/powerable.rb @@ -1,9 +1,28 @@ module VCloudSdk - # Shared functions by classes VM and VApp + + ############################################################################################### + # This module defines the shared functions by classes VM and VApp + # We can retrieve the status, power on, power off, reboots, resets and suspend any VM or VApp + ############################################################################################### module Powerable + + ############################################################################################# + # Returns the status of the vApp or VM + # @return [String] The vApp or VM status: + # - FAILED_CREATION. + # - UNRESOLVED. + # - RESOLVED. + # - SUSPENDED. + # - POWERED_ON. + # - WAITING_FOR_INPUT. + # - UNKNOWN. + # - UNRECOGNIZED. + # - POWERED_OFF. + # - other. + ############################################################################################# def status status_code = entity_xml[:status].to_i - Xml::RESOURCE_ENTITY_STATUS.each_pair do |k, v| + Xml::RESOURCE_ENTITY_STATUS.each_pair do |k, v| return k.to_s if v == status_code end @@ -11,7 +30,10 @@ def status "Fail to find corresponding status for code '#{status_code}'" end - # Power on VApp or VM + ############################################################################################# + # Power on vApp or VM + # @return [vApp] or [VM] Returns the object + ############################################################################################# def power_on target = entity_xml class_name = self.class.name.split("::").last @@ -34,7 +56,10 @@ def power_on self end - # Power off VApp or VM + ############################################################################################# + # Power off vApp or VM + # @return [vApp] or [VM] Returns the object + ############################################################################################# def power_off target = entity_xml class_name = self.class.name.split("::").last @@ -62,6 +87,109 @@ def power_off self end + ############################################################################################# + # Shutdown the GuestOS of vApp or VM + # Depending the version of vmtools installed on VM it could fail. Version 9227 on Windows KO + # @return [vApp] or [VM] Returns the object + ############################################################################################# + def shutdown + target = entity_xml + class_name = self.class.name.split("::").last + + Config.logger.debug "#{class_name} status: #{target[:status]}" + if is_status?(target, :SUSPENDED) + error_msg = "#{class_name} #{target.name} suspended, discard state before powering off." + fail class_name == "VApp" ? VappSuspendedError : VmSuspendedError, + error_msg + end + if is_status?(target, :POWERED_OFF) + Config.logger.info "#{class_name} #{target.name} is already powered off." + return + end + + shutdown_link = target.shutdown_link + unless shutdown_link + fail CloudError, "#{class_name} #{target.name} is not in a state that could be powered off." + end + + task = connection.post(shutdown_link.href, nil) + monitor_task task, @session.time_limit[:power_off] + Config.logger.info "#{class_name} #{target.name} is powered off." + + undeploy(target, class_name) + self + + end + + ############################################################################################# + # Reboots vApp or VM + # @return [vApp] or [VM] Returns the object + ############################################################################################# + def reboot + target = entity_xml + class_name = self.class.name.split("::").last + Config.logger.debug "#{class_name} status: #{target[:status]}" + if !is_status?(target, :POWERED_ON) + Config.logger.info "#{class_name} #{target.name} must be powered-on." + return + end + + reboot_link = target.reboot_link + + Config.logger.info "Rebooting #{class_name} #{target.name}." + task = connection.post(reboot_link.href, nil) + task = monitor_task task, @session.time_limit[:power_on] + Config.logger.info "#{class_name} #{target.name} is rebooted." + self + + end + + ############################################################################################# + # Resets vApp or VM + # @return [vApp] or [VM] Returns the object + ############################################################################################# + def reset + target = entity_xml + class_name = self.class.name.split("::").last + Config.logger.debug "#{class_name} status: #{target[:status]}" + if !is_status?(target, :POWERED_ON) + Config.logger.info "#{class_name} #{target.name} must be powered-on." + return + end + + reset_link = target.reset_link + + Config.logger.info "Reseting #{class_name} #{target.name}." + task = connection.post(reset_link.href, nil) + task = monitor_task task, @session.time_limit[:power_on] + Config.logger.info "#{class_name} #{target.name} is reseted." + self + end + + ############################################################################################# + # Suspends vApp or VM + # @return [vApp] or [VM] Returns the object + ############################################################################################# + def suspend + target = entity_xml + class_name = self.class.name.split("::").last + Config.logger.debug "#{class_name} status: #{target[:status]}" + if !is_status?(target, :POWERED_ON) + Config.logger.info "#{class_name} #{target.name} must be powered-on." + return + end + + suspend_link = target.suspend_link + + Config.logger.info "Suspending #{class_name} #{target.name}." + task = connection.post(suspend_link.href, nil) + task = monitor_task task, @session.time_limit[:power_on] + Config.logger.info "#{class_name} #{target.name} is suspended." + + undeploy(target, class_name) + self + end + private def is_status?(target, status) @@ -69,11 +197,13 @@ def is_status?(target, status) end def undeploy(target, class_name) - params = Xml::WrapperFactory.create_instance("UndeployVAppParams") # Even for VM it's called UndeployVappParams + params = Xml::WrapperFactory.create_instance("UndeployVAppParams") + # Even for VM it's called UndeployVappParams task = connection.post(target.undeploy_link.href, params) task = monitor_task(task, @session.time_limit[:undeploy]) Config.logger.info "#{class_name} #{target.name} is undeployed." task end end + ############################################################################################### end diff --git a/lib/ruby_vcloud_sdk/resources.rb b/lib/ruby_vcloud_sdk/resources.rb index 24f9486..6e1fac0 100644 --- a/lib/ruby_vcloud_sdk/resources.rb +++ b/lib/ruby_vcloud_sdk/resources.rb @@ -1,13 +1,27 @@ module VCloudSdk + ################################################################################ + # This class represents the resource of the Virtual Data Center. + # CPU and MEMORY are quantified in MHZ and MB. + ################################################################################ class Resources - attr_reader :cpu - attr_reader :memory + attr_reader :cpu_available, :cpu_limit, :cpu_used + attr_reader :memory_available, :memory_limit, :memory_used - def initialize(cpu, memory) - @cpu = cpu - @memory = memory - end + ############################################################################## + # Initialize a Resource for the VDC. + # @param cpu [CPU] The CPU resource in Mhz of the VDC. + # @param memory [Memory] The Memory resource in MB of the VDC. + ############################################################################## + def initialize(cpu,memory) + @cpu_available = cpu.available_cores + @cpu_limit = cpu.limit_cores + @cpu_used = cpu.limit_cores.to_i - cpu.available_cores.to_i + @memory_available = memory.available_mb + @memory_limit = memory.limit_mb + @memory_used = memory.limit_mb.to_i - memory.available_mb.to_i + end end + ################################################################################ end diff --git a/lib/ruby_vcloud_sdk/template_vapp.rb b/lib/ruby_vcloud_sdk/template_vapp.rb new file mode 100644 index 0000000..01eb76a --- /dev/null +++ b/lib/ruby_vcloud_sdk/template_vapp.rb @@ -0,0 +1,45 @@ +require_relative "session" +require_relative "infrastructure" +require_relative "envelope" + +module VCloudSdk + + ############################################################################## + # This class represents a catalog item in catalog. + # It can be a vApp Template or media&other, + ############################################################################## + class TemplateVapp + include Infrastructure + + ############################################################################ + # Initializes a Catalog Item object associated with a vCloud Session and the + # the catalog item's link + # @param session [Session] The client's session + # @param link [String] The xml representation of catalog item + ############################################################################ + def initialize(session, link) + @session = session + @link = link + end + + def ovf_descriptor + ovf = VCloudSdk::Envelope.new(@session, entity_xml.ovf_link) + ovf.ent + end + + def disks + ovf = VCloudSdk::Envelope.new(@session, entity_xml.ovf_link) + ovf.disks + end + + def operating_system + ovf = VCloudSdk::Envelope.new(@session, entity_xml.ovf_link) + ovf.os + end + + def vm_link + entity_xml.vm_link + end + end + ############################################################################## +end diff --git a/lib/ruby_vcloud_sdk/vapp.rb b/lib/ruby_vcloud_sdk/vapp.rb index bb499c5..b093d12 100644 --- a/lib/ruby_vcloud_sdk/vapp.rb +++ b/lib/ruby_vcloud_sdk/vapp.rb @@ -4,19 +4,45 @@ require_relative "network_config" module VCloudSdk + + ###################################################################################### + # This class represents a vApp of the Virtual Data Center. + ###################################################################################### class VApp include Infrastructure include Powerable + #################################################################################### + # Initializes a vApp object associated with a vCloud Session and the vApp's link. + # @param session [Session] The client's session + # @param link [String] The vCloud link of the vApp + #################################################################################### def initialize(session, link) @session = session @link = link end + #################################################################################### + # Returns the identifier of the vApp (uuid) + # @return [String] The identifier of the vApp + #################################################################################### + def id + id = entity_xml.urn + id.split(":")[3] + end + + #################################################################################### + # Returns the name of the vApp + # @return [String] The name of the vApp + #################################################################################### def name entity_xml.name end + #################################################################################### + # Deletes the vApp in the VDC. + # To delete the vApp, it must be on power off state. + #################################################################################### def delete vapp = entity_xml vapp_name = name @@ -39,10 +65,17 @@ def delete "Fail to delete vApp #{vapp_name}" end + #################################################################################### + # Recompose the vApp with a vApp template + # @param catalog_name [String] The name of Catalog + # @param template_name [String] The name of vApp Template + # @return [VApp] The recomposed vApp + #################################################################################### def recompose_from_vapp_template(catalog_name, template_name) recompose_vapp_link = get_recompose_vapp_link - Config.logger.info "Recomposing from template '#{template_name}' in catalog '#{catalog_name}'." + Config.logger.info "Recomposing from template '#{template_name}' in catalog + '#{catalog_name}'." catalog = find_catalog_by_name catalog_name template = catalog.find_vapp_template_by_name template_name @@ -55,24 +88,41 @@ def recompose_from_vapp_template(catalog_name, template_name) self end - def vms + #################################################################################### + # Returns array of Vm objects associated with vApp + # @return [VApp] an array of vApp + #################################################################################### + def vms entity_xml.vms.map do |vm| VCloudSdk::VM.new(@session, vm.href) end end + #################################################################################### + # Returns array with the names of the Vms associated with vApp + # @return [String] an array of VM's names + #################################################################################### def list_vms entity_xml.vms.map do |vm| vm.name end end + #################################################################################### + # Returns if the VM identified by name exists. + # @return [Boolean] True => the VM exists. + # False => otherwise. + #################################################################################### def vm_exists?(name) entity_xml.vms.any? do |vm| vm.name == name end end + #################################################################################### + # Returns the VM identified by name. + # @return [Vm] The VM identified by name, if it exists. + #################################################################################### def find_vm_by_name(name) entity_xml.vms.each do |vm| return VCloudSdk::VM.new(@session, vm.href) if vm.name == name @@ -81,6 +131,10 @@ def find_vm_by_name(name) fail ObjectNotFoundError, "VM '#{name}' is not found" end + #################################################################################### + # Deletes the VM identified by name. + # @return [Vm] The VM deleted. + #################################################################################### def remove_vm_by_name(vm_name) target_vm = find_vm_by_name vm_name recompose_vapp_link = get_recompose_vapp_link @@ -93,6 +147,10 @@ def remove_vm_by_name(vm_name) self end + #################################################################################### + # Returns the names of networks asociated with the vApp. + # @return [String] an array of network's names + #################################################################################### def list_networks entity_xml .network_config_section @@ -100,6 +158,19 @@ def list_networks .map { |network_config| network_config.network_name } end + #################################################################################### + # Adds a network to the vApp. + # @param network_name [String] The name of network in vdc org to add to vapp. + # @param vapp_net_name [String] Optional. What to name the network of the vapp. + # Default to network_name + # @param fence_mode [String] Optional. Fencing allows identical virtual + # machines in different vApps to be powered on + # without conflict by isolating the MAC and IP + # addresses of the virtual machines. Available + # options are "BRIDGED","ISOLATED" and "NAT_ROUTED" + # Default to "BRIDGED". + # @return [VApp] The vApp + #################################################################################### def add_network_by_name( network_name, vapp_net_name = nil, @@ -123,6 +194,12 @@ def add_network_by_name( self end + #################################################################################### + # Deletes the network identified with name. + # To delete the network, it cannot be used by any VM's. + # @param name [String] The name of the network. + # @return [VApp] The vApp. + #################################################################################### def delete_network_by_name(name) unless list_networks.any? { |network_name| network_name == name } fail ObjectNotFoundError, @@ -145,6 +222,71 @@ def delete_network_by_name(name) self end + #################################################################################### + # Creates a snapshot of the vApp. There is only one snapshot. It will replace any + # existing snapshot + # @param snapshot_name [Hash] Optional.The options of the snapshot + # :name [String] The name of snapshot + # :description [String] The snapshot's description + # @return [VApp] The vApp + #################################################################################### + def create_snapshot(snapshot_hash=nil) + new_snapshot_name = snapshot_hash.nil? ? "#{name} Snapshot" : snapshot_hash[:name] + + target = entity_xml + create_snapshot_link = target.create_snapshot_link + params = Xml::WrapperFactory.create_instance("CreateSnapshotParams") + + Config.logger.info "Creating a snapshot on vApp #{name}." + task = connection.post(target.create_snapshot_link.href,params) + monitor_task(task) + Config.logger.error "vApp #{name} has created a snapshot" + self + end + + #################################################################################### + # Delete the current snapshot of the vApp. + # @return [VApp] The vApp + #################################################################################### + def remove_snapshot + target = entity_xml + remove_snapshot_link = target.remove_snapshot_link + + Config.logger.info "Removing the snapshot on vApp #{name}." + task = connection.post(target.remove_snapshot_link.href,nil) + monitor_task(task) + Config.logger.error "vApp #{name} has removed the current snapshot" + self + end + + #################################################################################### + # Revert the snapshot created in the vApp. + # @return [VApp] The vApp + #################################################################################### + def revert_snapshot + target = entity_xml + revert_snapshot_link = target.revert_snapshot_link + + Config.logger.info "Reverting to current snapshot on vApp #{name}." + task = connection.post(target.revert_snapshot_link.href,nil) + monitor_task(task) + Config.logger.error "vApp #{name} has reverted a snapshot" + end + + #################################################################################### + # Return the snapshot info in the vApp. + # @return [String] Info of the Snapshot. + # [False] If no snapshot has been created in the vApp. + #################################################################################### + def snapshot_info + info = entity_xml.snapshot_section.get_nodes("Snapshot") + if info != [] + return info + else + return false + end + end + private def recompose_from_vapp_template_param(template) @@ -181,15 +323,15 @@ def remove_vm_param(vm) def network_config_param( network, vapp_net_name, - fence_mode) + fence_mode) Xml::WrapperFactory.create_instance("NetworkConfig").tap do |params| network_entity_xml = connection.get(network.href) params.ip_scope.tap do |ip_scope| net_ip_scope = network_entity_xml.ip_scope ip_scope.is_inherited = net_ip_scope.is_inherited? ip_scope.gateway = net_ip_scope.gateway - ip_scope.netmask = net_ip_scope.netmask - ip_scope.ip_ranges.add_ranges(net_ip_scope.ip_ranges.ranges) + ip_scope.netmask = net_ip_scope.netmask + ip_scope.ip_ranges.add_ranges(net_ip_scope.ip_ranges.ranges) if !net_ip_scope.ip_ranges.nil? ##per poder afegir xarxes amb DHCP que no tenen POOL IP STATIC end params.fence_mode = fence_mode params.parent_network["name"] = network_entity_xml["name"] diff --git a/lib/ruby_vcloud_sdk/vdc.rb b/lib/ruby_vcloud_sdk/vdc.rb index 4837f12..cf56938 100644 --- a/lib/ruby_vcloud_sdk/vdc.rb +++ b/lib/ruby_vcloud_sdk/vdc.rb @@ -11,6 +11,10 @@ require_relative "edge_gateway" module VCloudSdk + + ############################################################################################### + # This class represents a Virtual Data Center in vCloud. + ############################################################################################### class VDC include Infrastructure @@ -21,23 +25,40 @@ class VDC public :find_network_by_name, :network_exists? + ############################################################################################# + # Initializes a VDC object associated with a vCloud Session and the VDC's link. + # @param session [Session] The client's session. + # @param link [String] The vCloud link of the vApp. + ############################################################################################# def initialize(session, link) @session = session @link = link end - + + ############################################################################################# + # Returns the storage profiles assoaciated with the Virtual Data Center. + # @return [VdcStorageProfile] The storafe profiles of de VDC. + ############################################################################################# def storage_profiles storage_profile_records.map do |storage_profile| VCloudSdk::VdcStorageProfile.new(storage_profile) end end + ############################################################################################# + # Returns the name's list of storage profiles assoaciated with the Virtual Data Center. + # @return [String] The array of storage profiles's names of de VDC. + ############################################################################################# def list_storage_profiles storage_profile_records.map do |storage_profile| storage_profile.name end end + ############################################################################################# + # Returns the storage profile identified by name. + # @return [VdcStorageProfile] The storafe profiles of the VDC. + ############################################################################################# def find_storage_profile_by_name(name) storage_profile_records.each do |storage_profile| if storage_profile.name == name @@ -48,24 +69,40 @@ def find_storage_profile_by_name(name) fail ObjectNotFoundError, "Storage profile '#{name}' is not found" end + ############################################################################################# + # Obtain if the storage profile identified by name exists. + # @return [Boolean] If the storage profile identified by name exists, returns "True". + ############################################################################################# def storage_profile_exists?(name) storage_profile_records.any? do |storage_profile| storage_profile.name == name end end + ############################################################################################# + # Returns the vApp's list hosted in the VDC. + # @return [VApp] The array of vApp hosted in the VDC. + ############################################################################################# def vapps entity_xml.vapps.map do |vapp_link| VCloudSdk::VApp.new(@session, vapp_link) end end + ############################################################################################# + # Returns the name's list of vApps hosted in the Virtual Data Center. + # @return [String] The array of vApps's names. + ############################################################################################# def list_vapps entity_xml.vapps.map do |vapp_link| vapp_link.name end end + ############################################################################################# + # Returns the vApp identified by name. + # @return [VApp] The vApp hosted in VDC. + ############################################################################################# def find_vapp_by_name(name) entity_xml.vapps.each do |vapp_link| if vapp_link.name == name @@ -76,30 +113,64 @@ def find_vapp_by_name(name) fail ObjectNotFoundError, "VApp '#{name}' is not found" end + ############################################################################################# + # Returns the vApp identified by uuid. + # @return [VApp] The vApp hosted in VDC. + ############################################################################################# + def find_vapp_by_id(uuid) + entity_xml.vapps.each do |vapp_link| + if vapp_link.href.split("/")[5] == "vapp-#{uuid}" + return VCloudSdk::VApp.new(@session, vapp_link) + end + end + + fail ObjectNotFoundError, "VApp '#{uuid}' is not found" + end + + ############################################################################################# + # Obtain if the vApp identified by name exists. + # @return [Boolean] If the vApp identified by name exists, returns "True". + ############################################################################################# def vapp_exists?(name) entity_xml.vapps.any? do |vapp| vapp.name == name end end - - def resources - cpu = VCloudSdk::CPU.new(entity_xml.available_cpu_cores) - memory = VCloudSdk::Memory.new(entity_xml.available_memory_mb) - VCloudSdk::Resources.new(cpu, memory) + + ############################################################################################# + # Creates Resources object representing the CPU and Memory of the VDC. + # @return [Resouces] The Resource object of the VDC. + ############################################################################################# + def resources + cpu = VCloudSdk::CPU.new(entity_xml.available_cpu_mhz,entity_xml.limit_cpu_mhz) + memory = VCloudSdk::Memory.new(entity_xml.available_memory_mb,entity_xml.limit_memory_mb) + VCloudSdk::Resources.new(cpu,memory) end + ############################################################################################# + # Returns the list of the Networks created in the VDC. + # @return [Network] The array of Networks created in the VDC. + ############################################################################################# def networks @session.org.networks.map do |network_link| VCloudSdk::Network.new(@session, network_link) end end + ############################################################################################# + # Returns the name's list of Networks created in the Virtual Data Center. + # @return [String] The array of Network's names. + ############################################################################################# def list_networks @session.org.networks.map do |network_link| network_link.name end end + ############################################################################################# + # Returns the list of Edge Gateways created in the VDC. + # @return [EdgeGateway] The array of Edge Gateways created in the VDC. + ############################################################################################# def edge_gateways connection .get(entity_xml.edge_gateways_link) @@ -109,18 +180,30 @@ def edge_gateways end end + ############################################################################################# + # Returns the list of Disks created in the VDC. + # @return [Disks] The array of Disk created in the VDC. + ############################################################################################# def disks entity_xml.disks.map do |disk_link| VCloudSdk::Disk.new(@session, disk_link) end end + ############################################################################################# + # Returns the name's list of Disks created in the Virtual Data Center. + # @return [String] The array of Disk's names. + ############################################################################################# def list_disks entity_xml.disks.map do |disk_link| disk_link.name end end + ############################################################################################# + # Returns the Disks identified by name. + # @return [Array] The Disk or Disks created in VDC. + ############################################################################################# def find_disks_by_name(name) disks = entity_xml .disks @@ -134,18 +217,28 @@ def find_disks_by_name(name) disks end + ############################################################################################# + # Obtain if the Disk identified by name exists. + # @return [Boolean] If the vApp identified by name exists, returns "True". + ############################################################################################# def disk_exists?(name) list_disks.any? do |disk_name| disk_name == name end end + ############################################################################################# + # Creates a Disk in the Virtual Data Center. + # @param name [String] The disk's name. + # @param capacity [Integer] The capacity in MB of the disk. + # @return [Disk] The object created.disk_create_param. + ############################################################################################# def create_disk( name, capacity, vm = nil, bus_type = "scsi", - bus_sub_type = "lsilogic") + bus_sub_type = "lsilogic") fail(CloudError, "Invalid size in MB #{capacity}") if capacity <= 0 @@ -164,13 +257,17 @@ def create_disk( disk = connection.post(entity_xml.add_disk_link, disk_create_params(name, capacity, bus_type, bus_sub_type, vm), - Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS]) + Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS]) wait_for_running_tasks(disk, "Disk #{name}") VCloudSdk::Disk.new(@session, disk.href) end + ############################################################################################# + # Deletes the Disk identified by "name".. + # @return [VDC] The Virtual Data Center. + ############################################################################################# def delete_disk_by_name(name) disks = find_disks_by_name(name) fail CloudError, @@ -180,6 +277,10 @@ def delete_disk_by_name(name) self end + ############################################################################################# + # Deletes ALL the Disks identified by "name".. + # @return [VDC] The Virtual Data Center. + ############################################################################################# def delete_all_disks_by_name(name) disks = find_disks_by_name(name) success = true @@ -193,10 +294,15 @@ def delete_all_disks_by_name(name) end fail CloudError, - "Failed to delete one or more of the disks with name '#{name}'. Check logs for details." unless success + "Failed to delete one or more of the disks with name '#{name}'. + Check logs for details." unless success self end + ############################################################################################# + # Returns the storage profile identified by name in XML. + # @return [XML] The storafe profiles of de VDC. + ############################################################################################# def storage_profile_xml_node(name) return nil if name.nil? @@ -230,7 +336,8 @@ def disk_create_params(name, capacity, bus_type, bus_sub_type, vm) def delete_single_disk(disk) Config.logger.info "Deleting disk '#{disk.name}', link #{disk.href}" fail CloudError, - "Disk '#{disk.name}', link #{disk.href} is attached to VM '#{disk.vm.name}'" if disk.attached? + "Disk '#{disk.name}', link #{disk.href} is attached + to VM '#{disk.vm.name}'" if disk.attached? entity_xml = connection.get(disk.href) task = connection.delete(entity_xml.remove_link.href) diff --git a/lib/ruby_vcloud_sdk/vdc_storage_profile.rb b/lib/ruby_vcloud_sdk/vdc_storage_profile.rb index 5d9eec8..bf8776c 100644 --- a/lib/ruby_vcloud_sdk/vdc_storage_profile.rb +++ b/lib/ruby_vcloud_sdk/vdc_storage_profile.rb @@ -1,9 +1,9 @@ module VCloudSdk class VdcStorageProfile - attr_reader :name + attr_reader :name, :storage_used_mb, :storage_limit_mb - def initialize(storage_profile_xml_obj) + def initialize(storage_profile_xml_obj) @storage_profile_xml_obj = storage_profile_xml_obj @name = @storage_profile_xml_obj[:name] @storage_used_mb = @storage_profile_xml_obj[:storageUsedMB].to_i diff --git a/lib/ruby_vcloud_sdk/version.rb b/lib/ruby_vcloud_sdk/version.rb index 0d399cf..3b8386c 100644 --- a/lib/ruby_vcloud_sdk/version.rb +++ b/lib/ruby_vcloud_sdk/version.rb @@ -1,3 +1,3 @@ module VCloudSdk - VERSION = '0.7.3' + VERSION = '0.7.4' end diff --git a/lib/ruby_vcloud_sdk/vm.rb b/lib/ruby_vcloud_sdk/vm.rb index ec7152a..aad3c20 100644 --- a/lib/ruby_vcloud_sdk/vm.rb +++ b/lib/ruby_vcloud_sdk/vm.rb @@ -5,6 +5,10 @@ require_relative "nic" module VCloudSdk + + ################################################################################################# + # This class represents a VM belonging a vApp of the Virtual Data Center. + ################################################################################################# class VM include Infrastructure include Powerable @@ -12,16 +16,39 @@ class VM extend Forwardable def_delegator :entity_xml, :name + ############################################################################################### + # Initializes a VM object associated with a vCloud Session and the VMs link. + # @param session [Session] The client's session + # @param link [String] The XML representation of the VM + ############################################################################################### def initialize(session, link) @session = session @link = link end + + ############################################################################################### + # Returns the identifier of the VM (uuid) + # @return [String] The identifier of the VM + ############################################################################################### + def id + id = entity_xml.urn + id.split(":")[3] + end + ############################################################################################### + # Returns the vCloud link of the VM + # @return [String] The vCloud link of the VM + ############################################################################################### def href @link end - - # returns size of memory in megabytes + def ent + entity_xml + end + ############################################################################################### + # Returns the memory of the VM + # @return [String] The memory in MB of the VM + ############################################################################################### def memory m = entity_xml .hardware_section @@ -36,7 +63,11 @@ def memory memory_mb end - # sets size of memory in megabytes + ############################################################################################### + # Modifies the memory size of the VM. + # @param size [String] The new memory size in MB. + # @throw + ############################################################################################### def memory=(size) fail(CloudError, "Invalid vm memory size #{size}MB") if size <= 0 @@ -55,7 +86,12 @@ def memory=(size) self end - # returns number of virtual cpus of VM + + ############################################################################################### + # Returns the number of virtual cpus of the VM. + # @return [Integer] The number of virtual cpus of the VM + # @throw + ############################################################################################### def vcpu cpus = entity_xml .hardware_section @@ -67,7 +103,11 @@ def vcpu cpus.to_i end - # sets number of virtual cpus of VM + ############################################################################################### + # Modifies the number of virtual cpus of the VM. + # @param count [Integer] The new number of virtual cpus. + # @throw + ############################################################################################### def vcpu=(count) fail(CloudError, "Invalid virtual CPU count #{count}") if count <= 0 @@ -86,6 +126,156 @@ def vcpu=(count) self end + def name=(name) + payload = entity_xml + payload.name = name + task = connection.post(payload.reconfigure_link.href, + payload, + Xml::MEDIA_TYPE[:VM]) + monitor_task(task) + self + end + + ############################################################################################### + # Reconfigures the VM with the parameters passed in a hash. + # All params are optional. + # @param options [Hash] The parameters of the VM. + # :name [String] The name of the VM + # :description [String] The description of the VM + # :vcpu [String] The value for number of CPU + # :memory [String] The value for memory in MB + # :nics [Array] Array of Hashes representing the nics + # to attach to VM + # :network_name [String] The network to attach nic + # :ip [String] Optional. The IP of the nic + # :mac [String] Optional. The MAC of the nic + # :disks [Array] Array of Hases representing the disks to + # attach to VM + # :id [String] Disk's identifier. + # :size [String] Size of disk in MB. + # :vapp_name [String] The name of the vApp + # @return [VM] + ############################################################################################### + def reconfigure(options) + payload = entity_xml + payload.name = options[:name] if !options[:name].nil? + payload.description = options[:description] if !options[:name].nil? + payload.change_cpu_count(options[:vcpu]) if !options[:name].nil? + payload.change_memory(options[:memory]) if !options[:name].nil? + nic_index = add_nic_index + + #NETWORK CONFIGURATION + if options[:nics] !=[] + #ADD NICS + options[:nics].each do |nic| + + mac_address = nic[:mac] + + if !mac_address or (mac_address and !find_nic_by_mac(mac_address)) + + network_name = nic[:network_name] + ip_addressing_mode = Xml::IP_ADDRESSING_MODE[:POOL] + + ip = "" + + if !nic[:ip].nil? + ip_addressing_mode = Xml::IP_ADDRESSING_MODE[:MANUAL] + ip = nic[:ip] + end + + + # Add Network to vapp + vapp.add_network_by_name(network_name) if !vapp.list_networks.include? "#{network_name}" + # Add NIC + payload.hardware_section.add_item(nic_params(payload.hardware_section, + nic_index, + network_name, + ip_addressing_mode, + ip)) + # Connect NIC + payload.network_connection_section.add_item(network_connection_params(payload.network_connection_section, + nic_index, + network_name, + ip_addressing_mode, + ip)) + #Add the mac address passed + if mac_address + payload + .network_connection_section + .network_connections.last + .mac_address = mac_address + end + nic_index = nic_index + 1 + end + end + end + + #DELETE NICS + macs = [] + options[:nics].each do |nic| + macs.push(nic[:mac]) + end + + if macs.empty? + payload.delete_nics(*nics) + else + nics.each do |nc| + options[:nics].each do |nic| + payload.delete_nics(nc) if !macs.include? "#{nc.mac_address}" + end + end + end + + #DISK CONFIGURATION + + if !options[:disks].empty? + + options[:disks].each do |disk| + + capacity = disk[:size].to_i + fail(CloudError,"Invalid size in MB #{capacity}") if capacity <= 0 + disk_id = disk[:id] + if !payload.hard_disk_exists?(disk_id) + bus_type = "scsi" + bus_type = Xml::BUS_TYPE_NAMES[bus_type.downcase] + fail(CloudError,"Invalid bus type!") unless bus_type + + bus_sub_type = "lsilogic" + bus_sub_type = Xml::BUS_SUB_TYPE_NAMES[bus_sub_type.downcase] + fail(CloudError,"Invalid bus sub type!") unless bus_sub_type + + payload.add_hard_disk(capacity.to_s, bus_type, bus_sub_type,disk_id) + end + end + + end + + #DELETE DISKS + + disks = [] + options[:disks].each do |disk| + disks.push(disk[:id]) + end + + internal_disks.each do |i_disk| + payload.delete_hard_disk_by_id(i_disk.id) if !disks.include?(i_disk.id) + end + + task = connection.post(payload.reconfigure_link.href, + payload, + Xml::MEDIA_TYPE[:VM]) + monitor_task(task) + self + end + + ############################################################################################### + # Returns the IP addresses assigned to the VM or nil. + # @return [Array or nil] The IP addresses or nil. + ############################################################################################### + def ip_address + entity_xml.ip_address + end + def list_networks entity_xml .network_connection_section @@ -106,6 +296,24 @@ def nics end end + def find_nic_by_mac(mac) + primary_index = entity_xml + .network_connection_section + .primary_network_connection_index + net = entity_xml + .network_connection_section + .network_connections.find do |n| + n.mac_address == mac.to_s + end + if net + return VCloudSdk::NIC.new(net,net.network_connection_index == primary_index) + else + return false + fail(CloudError, + "No NIC found with MAC #{mac} in VM #{name}") + end + end + def independent_disks hardware_section = entity_xml.hardware_section disks = [] @@ -129,6 +337,11 @@ def list_disks end end + ############################################################################################### + # Attaches an independent disk to VM. + # @param disk [Disk] The disk object to attach. + # @throw + ############################################################################################### def attach_disk(disk) fail CloudError, "Disk '#{disk.name}' of link #{disk.href} is attached to VM '#{disk.vm.name}'" if disk.attached? @@ -200,7 +413,9 @@ def eject_media(catalog_name, media_file_name) def add_nic( network_name, ip_addressing_mode = Xml::IP_ADDRESSING_MODE[:POOL], - ip = nil) + mac_address = nil, + ip = nil) + fail CloudError, "Invalid IP_ADDRESSING_MODE '#{ip_addressing_mode}'" unless Xml::IP_ADDRESSING_MODE .each_value @@ -214,10 +429,9 @@ def add_nic( "Network #{network_name} is not added to parent VApp #{vapp.name}" unless vapp .list_networks .any? { |n| n == network_name } - payload = entity_xml fail CloudError, - "VM #{name} is powered-on and cannot add NIC." if is_status?(payload, :POWERED_ON) + "VM #{name} is powered-on and vmware tools are not installed, cannot add NIC." if is_status?(payload, :POWERED_ON) && !self.vmtools? ##si està power-on i no té les vmware tools, error nic_index = add_nic_index @@ -232,7 +446,6 @@ def add_nic( network_name, ip_addressing_mode, ip)) - # Connect NIC payload .network_connection_section @@ -242,6 +455,14 @@ def add_nic( ip_addressing_mode, ip)) + # Si li subministrem una mac, li afegeix la que li diem + if mac_address + payload + .network_connection_section + .network_connections.last + .mac_address = mac_address + end + task = connection.post(payload.reconfigure_link.href, payload, Xml::MEDIA_TYPE[:VM]) @@ -262,6 +483,39 @@ def delete_nics(*nics) self end + def operating_system + entity_xml.operating_system + end + + def vmtools_version + entity_xml.vm_tools + end + + def vmtools? + !entity_xml.vm_tools.nil? + end + + def acquire_VMRC_ticket + + fail(CloudError, + "The VM must be powered on") if self.status != "POWERED_ON" + + Config.logger.info( + "Obtaining VMware VMware Remote Console Ticket on #{name} ...") + task = connection.post(entity_xml.vmrc_ticket_link.href,nil) + task = task.nil? ? nil : task.content + + end + + def install_vmtools + Config.logger.info( + "Mounting VMware tools on #{name} ...") + task = connection.post(entity_xml.install_vmtools_link.href,nil) + monitor_task(task) + self + end + + def product_section_properties product_section = entity_xml.product_section return [] if product_section.nil? @@ -294,7 +548,8 @@ def internal_disks def create_internal_disk( capacity, bus_type = "scsi", - bus_sub_type = "lsilogic") + bus_sub_type = "lsilogic", + disk_id = nil) fail(CloudError, "Invalid size in MB #{capacity}") if capacity <= 0 @@ -312,15 +567,15 @@ def create_internal_disk( .info "Creating internal disk #{name} of #{capacity}MB." payload = entity_xml - payload.add_hard_disk(capacity, bus_type, bus_sub_type) + payload.add_hard_disk(capacity, bus_type, bus_sub_type,disk_id) task = connection.post(payload.reconfigure_link.href, payload, - Xml::MEDIA_TYPE[:VM]) + Xml::MEDIA_TYPE[:VM]) monitor_task(task) self end - + def delete_internal_disk_by_name(name) payload = entity_xml @@ -335,6 +590,33 @@ def delete_internal_disk_by_name(name) self end + ############################################################################################################ + # Set up the options for the OS of the VM + # All params are optional. + # @param customization [Hash] The parameters of the guestOS customization. All parameters are + # optional. + # :computer_name [String] The name of the computer + # :admin_pass [String] The password for the Administrator/root user + # :custom_script [String] The customization script (Max 49,000 characters) + # :sid [Boolean] Applicable for Windows VMs and will run Sysprep + # to change Windows SID. + # :auto_password [Boolean] Generates an automatic Administrator's password. + # + # @return [VM] + ############################################################################################################ + def customization(customization) + link = entity_xml.guest_customization_link + payload = connection.get(link) + + payload = add_customization(payload,customization) + + task = connection.put(link, + payload, + Xml::MEDIA_TYPE[:GUEST_CUSTOMIZATION_SECTION]) + monitor_task(task) + self + end + private def add_nic_index @@ -407,6 +689,18 @@ def network_connection_params(section, nic_index, network_name, addressing_mode, end end + def add_customization(section, customization) + section + .tap do |params| + params.enable + params.computer_name = customization[:computer_name] unless customization[:computer_name].nil? + params.admin_pass = customization[:admin_pass] unless customization[:admin_pass].nil? + params.script = customization[:custom_script] unless customization[:custom_script].nil? + params.change_sid = customization[:sid] + params.auto_password = customization[:auto_password] unless customization[:auto_password].nil? or !customization[:admin_pass].nil? + end + end + def product_section_list_params(properties) Xml::WrapperFactory.create_instance("ProductSectionList").tap do |params| properties.each do |property| @@ -417,4 +711,5 @@ def product_section_list_params(properties) BYTES_PER_MEGABYTE = 1_048_576 # 1048576 = 1024 * 1024 = 2^20 end + ################################################################################################# end diff --git a/lib/ruby_vcloud_sdk/xml/constants.rb b/lib/ruby_vcloud_sdk/xml/constants.rb index afc894f..0fb1ef2 100644 --- a/lib/ruby_vcloud_sdk/xml/constants.rb +++ b/lib/ruby_vcloud_sdk/xml/constants.rb @@ -26,6 +26,7 @@ module Xml :CONNECTION => "Connection", :PARENT => "Parent", :ELEMENT_NAME => "ElementName", + :DESCRIPTION => "Description", :ALLOCATION_UNITS => "AllocationUnits", :VIRTUAL_QUANTITY => "VirtualQuantity" } @@ -207,6 +208,7 @@ module Xml :ADMIN_NETWORK => "application/vnd.vmware.admin.network+xml", :NETWORK => "application/vnd.vmware.vcloud.network+xml", :NETWORK_POOL => "application/vnd.vmware.admin.networkPool+xml", + :EDGE_SERVICES_CONFIG => "application/vnd.vmware.admin.edgeGatewayServiceConfiguration+xml", :CATALOG_PUBLISH => "application/vnd.vmware.admin.publishCatalogParams+xml", :OWNER => "application/vnd.vmware.vcloud.owner+xml", diff --git a/lib/ruby_vcloud_sdk/xml/wrapper.rb b/lib/ruby_vcloud_sdk/xml/wrapper.rb index 1f24e67..f438d72 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper.rb @@ -7,14 +7,14 @@ class WrapperFactory class << self def wrap_document(xml, ns = nil, namespace_defintions = nil, *args) doc = Nokogiri::XML(xml) - type_name = doc.root.name - node_class = find_wrapper_class(type_name) + type_name = doc.root.name + node_class = find_wrapper_class(type_name) node_class.new(doc, ns, namespace_defintions, *args) end def wrap_node(node, ns, namespace_defintions = nil, *args) - type_name = node.node_name - node_class = find_wrapper_class(type_name) + type_name = node.node_name + node_class = find_wrapper_class(type_name) node_class.new(node, ns, namespace_defintions, *args) end @@ -29,10 +29,11 @@ def wrap_nodes(nodes, ns, namespace_defintions) # TODO: We might run into a bug later if there are ever XML node types # of the same name but different namespace def find_wrapper_class(type_name) - # for Ruby 1.9, we would need pass false in as the 2nd parameter - if Xml.constants.find { |c| c.to_sym == type_name.to_sym } - Xml.const_get(type_name.to_sym) - else + # for Ruby 1.9, we would need pass false in as the 2nd parameter + #Xml.constants.find { |c| puts "#{c.to_sym} . #{type_name.to_sym}"} + if Xml.constants.find { |c| c.to_sym == type_name.to_sym } + Xml.const_get(type_name.to_sym) + else Wrapper end end @@ -115,13 +116,17 @@ def urn @root["id"] end - def type + def type @root["type"] end def type=(type) @root["type"] = type end + + def size + @root["size"] + end def remove_link get_nodes(XML_TYPE[:LINK], @@ -147,6 +152,18 @@ def power_off_link true).first end + def shutdown_link + get_nodes(XML_TYPE[:LINK], + { rel: "power:shutdown"}, + true).first + end + + def suspend_link + get_nodes(XML_TYPE[:LINK], + { rel: "power:suspend"}, + true).first + end + def undeploy_link get_nodes(XML_TYPE[:LINK], { rel: "undeploy" }, diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb index f5bf51a..93443df 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb @@ -4,12 +4,16 @@ require "ruby_vcloud_sdk/xml/wrapper_classes/admin_org" require "ruby_vcloud_sdk/xml/wrapper_classes/allocated_ip_addresses" require "ruby_vcloud_sdk/xml/wrapper_classes/catalog_item" +require "ruby_vcloud_sdk/xml/wrapper_classes/customization" +require "ruby_vcloud_sdk/xml/wrapper_classes/dnat_rules" require "ruby_vcloud_sdk/xml/wrapper_classes/disk" require "ruby_vcloud_sdk/xml/wrapper_classes/disk_attach_or_detach_params" require "ruby_vcloud_sdk/xml/wrapper_classes/disk_create_params" require "ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway" +require "ruby_vcloud_sdk/xml/wrapper_classes/envelope" require "ruby_vcloud_sdk/xml/wrapper_classes/entity" require "ruby_vcloud_sdk/xml/wrapper_classes/file" +require "ruby_vcloud_sdk/xml/wrapper_classes/fw_rules" require "ruby_vcloud_sdk/xml/wrapper_classes/gateway_interface" require "ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper" require "ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params" @@ -21,6 +25,7 @@ require "ruby_vcloud_sdk/xml/wrapper_classes/media" require "ruby_vcloud_sdk/xml/wrapper_classes/media_insert_or_eject_params" require "ruby_vcloud_sdk/xml/wrapper_classes/metadata_value" +require "ruby_vcloud_sdk/xml/wrapper_classes/snat_rules" require "ruby_vcloud_sdk/xml/wrapper_classes/network" require "ruby_vcloud_sdk/xml/wrapper_classes/network_config" require "ruby_vcloud_sdk/xml/wrapper_classes/network_config_section" @@ -35,6 +40,7 @@ require "ruby_vcloud_sdk/xml/wrapper_classes/query_result_records" require "ruby_vcloud_sdk/xml/wrapper_classes/recompose_vapp_params" require "ruby_vcloud_sdk/xml/wrapper_classes/session" +require "ruby_vcloud_sdk/xml/wrapper_classes/sourced_vm_instatiation_params" require "ruby_vcloud_sdk/xml/wrapper_classes/supported_versions" require "ruby_vcloud_sdk/xml/wrapper_classes/task" require "ruby_vcloud_sdk/xml/wrapper_classes/upload_vapp_template_params" diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb index 36b10cc..37e537c 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb @@ -13,6 +13,14 @@ def entity=(entity) def entity get_nodes(XML_TYPE[:ENTITY]).first end + + def description + get_nodes("Description").first.content + end + + def date + get_nodes("DateCreated").first.content + end end end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/customization.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/customization.rb new file mode 100644 index 0000000..c9ac69d --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/customization.rb @@ -0,0 +1,58 @@ +module VCloudSdk + module Xml + class GuestCustomizationSection < Wrapper + def href=(value) + @root["href"] = value + end + + def type=(value) + @root["type"] = value + end + + def enable(uuid=nil) + get_nodes("Enabled").first.content = true + get_nodes("VirtualMachineId").first.content = uuid + end + + def computer_name=(value) + get_nodes("ComputerName").first.content = value + end + + def change_sid=(value) + get_nodes("ChangeSid").first.content = value + end + + def admin_pass=(value) + get_nodes("AdminPasswordEnabled").first.content = true + get_nodes("AdminPasswordAuto").first.content = false + + if get_nodes("AdminPassword").first.nil? + nm = get_nodes("AdminPasswordAuto").last.node + nm.after("#{value}") + else + get_nodes("AdminPassword").first.content = value + end + + end + + def auto_password=(value) + get_nodes("AdminPasswordEnabled").first.content = true + get_nodes("AdminPasswordAuto").first.content = value + end + + def reset_pass=(value) + get_nodes("ResetPasswordRequired").first.content = value + end + + def script=(value) + if get_nodes("CustomizationScript").first.nil? + nm = get_nodes("ResetPasswordRequired").last.node + nm.after("#{value}") + else + get_nodes("CustomizationScript").first.content = value + + end + end + end + end +end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/dnat_rules.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/dnat_rules.rb new file mode 100644 index 0000000..bd53d78 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/dnat_rules.rb @@ -0,0 +1,56 @@ +module VCloudSdk + module Xml + class NatRule < Wrapper + + def description=(desc) + get_nodes("Description").first.content = desc + end + + def rule_type=(type) + get_nodes("RuleType").first.content = type + end + + def enabled=(opt) + get_nodes("IsEnabled").first.content = opt + end + + def id=(id) + get_nodes("Id").first.content = id + end + + def interface=(interface) + get_nodes("Interface").first["type"] = interface.get_nodes("Network").first["type"] + get_nodes("Interface").first["name"] = interface.get_nodes("Network").first["name"] + get_nodes("Interface").first["href"] = interface.get_nodes("Network").first["href"] + end + + def original_ip=(ip) + get_nodes("OriginalIp").first.content = ip + end + + def original_ip + get_nodes("OriginalIp").first.content + end + + def original_port=(port) + get_nodes("OriginalPort").first.content = port + end + + def translated_ip=(ip) + get_nodes("TranslatedIp").first.content = ip + end + + def translated_ip + get_nodes("TranslatedIp").first.content + end + + def translated_port=(port) + get_nodes("TranslatedPort").first.content = port + end + + def protocol=(protocol) + get_nodes("Protocol").first.content = protocol + end + end + end +end \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb index d91cde8..0a66dc3 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb @@ -1,6 +1,106 @@ module VCloudSdk module Xml class EdgeGateway < Wrapper + def configure_services_link + get_nodes(XML_TYPE[:LINK], + { rel: "edgeGateway:configureServices" }, + true).first + end + def configure_services + get_nodes("EdgeGatewayServiceConfiguration").first + end + + def add_fw_rules(rules) + id = obtain_id("FirewallRule").nil? ? 1 : obtain_id("FirewallRule") + rules.each do |rule| + id = id + 1 + fw_rule = Xml::WrapperFactory.create_instance("FirewallRule").tap do |params| + params.id = id.to_s + params.description = rule[:name] + params.ips(rule[:ip_src],rule[:ip_dest]) + params.ports(rule[:port_src],rule[:port_dest]) + params.action = rule[:action] + params.enabled = rule[:enabled] + end + if (!get_nodes("FirewallRule").empty?) + nm = get_nodes("FirewallRule").last.node + nm.after(fw_rule.node) + else + nm = get_nodes("FirewallService").first.node + nm.add_child(fw_rule.node) + end + end + self + end + + def remove_fw_rules(ips) + rules = get_nodes("FirewallRule") + rules.each do |rule| + ips.each do |ip| + rule.node.remove if rule.ip_dest == ip + end + end + self + end + + def add_nat_rules(rules) + id = obtain_id("NatRule").nil? ? 65537 : obtain_id("NatRule") + rules.each do |rule| + id = id + 1 + if rule[:rule_type] == "SNAT" + snat_rule = Xml::WrapperFactory.create_instance("SNatRule").tap do |params| + params.id = id.to_s + params.description = rule[:description] + params.enabled = rule[:enabled] + params.rule_type = rule[:rule_type] + params.interface = gateway_interface_by_name(rule[:interface]) + params.original_ip = rule[:original_ip] + params.translated_ip = rule[:translated_ip] + end + if (!get_nodes("NatRule").empty?) + nm = get_nodes("NatRule").last.node + nm.after(snat_rule.node) + else + nm = get_nodes("NatService").first.node + nm.add_child(snat_rule.node) + end + + elsif rule[:rule_type] == "DNAT" + dnat_rule = Xml::WrapperFactory.create_instance("DNatRule").tap do |params| + params.id = id.to_s + params.description = rule[:description] + params.enabled = rule[:enabled] + params.rule_type = rule[:rule_type] + params.interface = gateway_interface_by_name(rule[:interface]) + params.original_ip = rule[:original_ip] + params.original_port = rule[:original_port] + params.translated_ip = rule[:translated_ip] + params.translated_port = rule[:translated_port] + params.protocol = rule[:protocol] + end + if (!get_nodes("NatRule").empty?) + nm = get_nodes("NatRule").last.node + nm.after(dnat_rule.node) + else + nm = get_nodes("NatService").first.node + nm.add_child(dnat_rule.node) + end + + end + end + self + end + + def remove_nat_rules(ips) + rules = get_nodes("NatRule") + rules.each do |rule| + ips.each do |ip| + rule.node.remove if rule.original_ip == ip or rule.translated_ip == ip + end + end + self + end + def gateway_interfaces get_nodes(:Configuration, nil, true) .first @@ -8,6 +108,27 @@ def gateway_interfaces .first .get_nodes(:GatewayInterface, nil, true) end + + private + + def obtain_id(tag) + if get_nodes(tag).empty? + id = nil + else + id = get_nodes(tag).last + .get_nodes("Id").first + .content.to_i + end + return id + + end + + def gateway_interface_by_name(name) + gateway_interfaces.each do |gat_in| + return gat_in if gat_in.get_nodes("Name").first.content == name + end + end + end end end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/envelope.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/envelope.rb new file mode 100644 index 0000000..fc4d863 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/envelope.rb @@ -0,0 +1,14 @@ +module VCloudSdk + module Xml + class Envelope < Wrapper + def operating_system + get_nodes("OperatingSystemSection", nil, false, OVF).first. + get_nodes("Description",nil,false,OVF).first.content + end + + def hardware_section + get_nodes("VirtualHardwareSection",nil,false,OVF).first + end + end + end +end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/fw_rules.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/fw_rules.rb new file mode 100644 index 0000000..876b38e --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/fw_rules.rb @@ -0,0 +1,50 @@ +module VCloudSdk + module Xml + class FirewallRule < Wrapper + def href=(value) + @root["href"] = value + end + + def type=(value) + @root["type"] = value + end + + def id=(id) + get_nodes("Id").first.content = id + end + + def ip_dest + get_nodes("DestinationIp").first.content + end + + def enabled=(opt) + get_nodes("IsEnabled").first.content = opt + end + + def description=(desc) + get_nodes("Description").first.content = desc + end + + def ips(src,dest) + get_nodes("SourceIp").first.content = src + get_nodes("DestinationIp").first.content = dest + end + + def ports(src,dest) + if dest == "Any" + get_nodes("Port").first.content = "-1" + else + get_nodes("Port").first.content = dest + end + get_nodes("SourcePort").first.content = "-1" if src == "Any" + get_nodes("SourcePortRange").first.content = src + get_nodes("DestinationPortRange").first.content = dest + end + + def action=(act) + get_nodes("Policy").first.content = act + end + + end + end +end \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb index 0d08af7..9a6ee41 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb @@ -17,11 +17,19 @@ def initialize(item) def capacity_mb host_resource[HOST_RESOURCE_ATTRIBUTE[:CAPACITY]] end + + def capacity_mb= new_capacity + host_resource[HOST_RESOURCE_ATTRIBUTE[:CAPACITY]] = new_capacity + end def disk_id get_rasd_content(RASD_TYPES[:ADDRESS_ON_PARENT]) end + def disk_id= new_id + set_rasd_content(new_id,RASD_TYPES[:ADDRESS_ON_PARENT]) + end + def instance_id get_rasd_content(RASD_TYPES[:INSTANCE_ID]) end @@ -42,6 +50,10 @@ def element_name get_rasd_content(RASD_TYPES[:ELEMENT_NAME]) end + def element_name= new_name + set_rasd_content(new_name,RASD_TYPES[:ELEMENT_NAME]) + end + def host_resource get_rasd(RASD_TYPES[:HOST_RESOURCE]) end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params.rb index 33ca1ac..70b394a 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params.rb @@ -27,6 +27,15 @@ def linked_clone=(value) @root["linkedClone"] = value.to_s end + def disk_size(id,size,vm_link) + return unless id + sourced = Xml::WrapperFactory + .create_instance("SourcedVmInstantiationParams", nil, nil) + sourced.resize_disk(id,size,vm_link) + nm = get_nodes("IsSourceDelete").first.node + nm.after(sourced.node) + end + def source=(src) source_node = get_nodes("Source").first source_node["href"] = src["href"] diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb index 9b38ac0..6148659 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb @@ -10,6 +10,24 @@ def allocated_addresses_link { type: MEDIA_TYPE[:ALLOCATED_NETWORK_IPS] }, true).first end + + def description + get_nodes("Description").first.content + end + + def gateway + get_nodes(:IpScope).first. + get_nodes("Gateway").first.content + end + + def netmask + get_nodes(:IpScope).first. + get_nodes("Netmask").first.content + end + + def fence_mode + get_nodes("FenceMode").first.content + end end end end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/snat_rules.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/snat_rules.rb new file mode 100644 index 0000000..de4bcdf --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/snat_rules.rb @@ -0,0 +1,44 @@ +module VCloudSdk + module Xml + class NatRule < Wrapper + + def description=(desc) + get_nodes("Description").first.content = desc + end + + def rule_type=(type) + get_nodes("RuleType").first.content = type + end + + def enabled=(opt) + get_nodes("IsEnabled").first.content = opt + end + + def id=(id) + get_nodes("Id").first.content = id + end + + def interface=(interface) + get_nodes("Interface").first["type"] = interface.get_nodes("Network").first["type"] + get_nodes("Interface").first["name"] = interface.get_nodes("Network").first["name"] + get_nodes("Interface").first["href"] = interface.get_nodes("Network").first["href"] + end + + def original_ip=(ip) + get_nodes("OriginalIp").first.content = ip + end + + def original_ip + get_nodes("OriginalIp").first.content + end + + def translated_ip=(ip) + get_nodes("TranslatedIp").first.content = ip + end + + def translated_ip + get_nodes("TranslatedIp").first.content + end + end + end +end \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/sourced_vm_instatiation_params.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/sourced_vm_instatiation_params.rb new file mode 100644 index 0000000..8682143 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/sourced_vm_instatiation_params.rb @@ -0,0 +1,17 @@ +module VCloudSdk + module Xml + + class SourcedVmInstantiationParams < Wrapper + def name + @root["name"] + end + def resize_disk(id,size,vm_link) + disk_node = get_nodes("Source").first + disk_node["href"] = vm_link + disk_node = get_nodes("Disk").first + disk_node["instanceId"] = "200#{id}" + get_nodes("Size").first.content = size + end + end + end +end \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/template_vapp.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/template_vapp.rb new file mode 100644 index 0000000..c9de9e1 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/template_vapp.rb @@ -0,0 +1,10 @@ +module VCloudSdk + module Xml + class TemplateVapp < Wrapper + def vm_link + get_nodes("Vm").first["href"] + end + end + + end +end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb index a71e5b6..25824dc 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb @@ -1,6 +1,7 @@ module VCloudSdk module Xml class VApp < Wrapper + def description get_nodes("Description").first.content end @@ -13,6 +14,10 @@ def reboot_link get_nodes("Link", {"rel" => "power:reboot"}, true).first end + def reset_link + get_nodes("Link", {"rel" => "power:reset"}, true).first + end + def tasks get_nodes(XML_TYPE[:TASK]) end @@ -27,13 +32,35 @@ def recompose_vapp_link true).first end + def create_snapshot_link + get_nodes(XML_TYPE[:LINK], + { rel: "snapshot:create"}, + true).first + end + + def revert_snapshot_link + get_nodes(XML_TYPE[:LINK], + { rel: "snapshot:revertToCurrent"}, + true).first + end + + def remove_snapshot_link + get_nodes(XML_TYPE[:LINK], + { rel: "snapshot:removeAll"}, + true).first + end + + def snapshot_section + get_nodes("SnapshotSection").first + end + def vdc_link get_nodes(XML_TYPE[:LINK], { type: MEDIA_TYPE[:VDC] }, true).first end - def vms + def vms get_nodes("Vm") end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb index 91e0e26..f5d4ecc 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb @@ -2,6 +2,15 @@ module VCloudSdk module Xml class VAppTemplate < VApp + + def vm_link + get_nodes("Vm").first["href"] + end + + def ovf_link + get_nodes("Link", {"rel" => "ovf"}, true).first["href"] + end + def files get_nodes("File") end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb index def4a0e..d63885e 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb @@ -73,19 +73,45 @@ def storage_profile(name) .first end - def available_cpu_cores + def limit_cpu_mhz + cpu_resource = get_nodes("ComputeCapacity") + .first.get_nodes("Cpu").first + + units = cpu_resource.get_nodes("Units").first.content + cpu_limit = cpu_resource.get_nodes("Limit").first.content + if units == "GHz" + cpu_limit = cpu_limit.to_i * 1000 + end + + cpu_limit + end + + def available_cpu_mhz cpu_resource = get_nodes("ComputeCapacity") .first.get_nodes("Cpu").first - available_cpu_clock_speed = get_available_resource(cpu_resource) + available_cpu = get_available_resource(cpu_resource) # clock units can only be MHz or GHz units = cpu_resource.get_nodes("Units").first.content - if units == "MHz" - available_cpu_clock_speed = available_cpu_clock_speed / 1000 + if units == "GHz" + available_cpu = available_cpu * 1000 end - # We assume 1 GHz is converted to 1 vCpu core - available_cpu_clock_speed + available_cpu + end + + def limit_memory_mb + memory_resource = get_nodes("ComputeCapacity") + .first.get_nodes("Memory").first + + units = memory_resource.get_nodes("Units").first.content + memory_limit = memory_resource.get_nodes("Limit").first.content + + if units == "GB" + memory_limit = memory_limit.to_i * 1024 + end + + memory_limit end def available_memory_mb diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb index 1dcf64a..260c1bc 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb @@ -4,7 +4,7 @@ class Vm < Wrapper def initialize(xml, ns = nil, ns_definitions = nil) super(xml, ns, ns_definitions) @logger = Config.logger - end + end def vapp_link get_nodes(XML_TYPE[:LINK], @@ -51,6 +51,32 @@ def description=(value) value end + def operating_system + get_nodes("OperatingSystemSection",nil,false,OVF).first. + get_nodes("Description",nil,false,OVF).first.content + end + + def vm_tools + tools = get_nodes("VMWareTools") + return tools.first["version"] if !tools.empty? + return nil + end + + def vmrc_ticket_link + get_nodes(XML_TYPE[:LINK], + { rel: "screen:acquireTicket" }, + true).first + end + + def ip_address + ips = [] + get_nodes("NetworkConnection").each do |ip| + ips << ip.ip_address + end + return ips if !ips.empty? + return nil + end + def reconfigure_link get_nodes(XML_TYPE[:LINK], { rel: "reconfigureVm" }, @@ -63,6 +89,18 @@ def insert_media_link true).first end + def install_vmtools_link + get_nodes(XML_TYPE[:LINK], + { rel: "installVmwareTools" }, + true).first + end + + def guest_customization_link + get_nodes("GuestCustomizationSection").first["href"] + end + + def + def eject_media_link get_nodes(XML_TYPE[:LINK], { rel: "media:ejectMedia" }, @@ -92,19 +130,41 @@ def product_section get_nodes("ProductSection", nil, true, OVF).first end + def guest_customization_section + get_nodes("GuestCustomizationSection").first + end + + def hard_disk_exists?(disk_id) + hardware_section.hard_disks.each do |disk| + return true if disk.disk_id == disk_id + end + return false + end + # hardware modification methods - def add_hard_disk(capacity, bus_type, bus_sub_type) + def add_hard_disk(capacity, bus_type, bus_sub_type,disk_id=nil) section = hardware_section # Create a RASD item new_disk = WrapperFactory .create_instance("Item", nil, hardware_section.doc_namespaces) - section.add_item(new_disk) - # The order matters! + section.add_item(new_disk) + # The order matters! + if !disk_id.nil? + ap = RASD_TYPES[:ADDRESS_ON_PARENT] + new_disk.add_rasd(ap) + new_disk.set_rasd(ap,disk_id) + end new_disk.add_rasd(RASD_TYPES[:HOST_RESOURCE]) new_disk.add_rasd(RASD_TYPES[:INSTANCE_ID]) + if !disk_id.nil? + p = RASD_TYPES[:PARENT] + new_disk.add_rasd(p) + new_disk.set_rasd(RASD_TYPES[:PARENT],1) + end + rt = RASD_TYPES[:RESOURCE_TYPE] new_disk.add_rasd(rt) new_disk.set_rasd(rt, HARDWARE_TYPE[:HARD_DISK]) @@ -117,6 +177,18 @@ def add_hard_disk(capacity, bus_type, bus_sub_type) "busType", VCLOUD_NAMESPACE)] = bus_type end + def modify_hard_disk(name,new_capacity) + section = hardware_section + disks = section.hard_disks + disk = disks.find do |d| + d.element_name == name + end + host_resource = disk.get_rasd(RASD_TYPES[:HOST_RESOURCE]) + host_resource[disk.create_qualified_name( + "capacity", VCLOUD_NAMESPACE)] = new_capacity.to_s + end + + def delete_hard_disk?(disk_name) hardware_section.hard_disks.each do |disk| if disk.element_name == disk_name @@ -124,7 +196,16 @@ def delete_hard_disk?(disk_name) return true end end + false + end + def delete_hard_disk_by_id(disk_id) + hardware_section.hard_disks.each do |disk| + if disk.disk_id == disk_id + disk.node.remove + return true + end + end false end @@ -140,6 +221,13 @@ def change_memory(mb) item.set_rasd("VirtualQuantity", mb) end + def change_name(name) + @logger.debug("Updating name on vm #{name} to #{name} ") + item = hardware_section.cpu + item.set_rasd("VirtualQuantity", quantity) + end + + # Deletes NIC from VM. Accepts variable number of arguments for NICs. # To delete all NICs from VM use the splat operator # ex: delete_nic(vm, *vm.hardware_section.nics) diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/CreateSnapshotParams.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/CreateSnapshotParams.xml new file mode 100644 index 0000000..122b7f4 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/CreateSnapshotParams.xml @@ -0,0 +1,6 @@ + + + Snapshot + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/FirewallRule.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/FirewallRule.xml new file mode 100644 index 0000000..5db7d88 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/FirewallRule.xml @@ -0,0 +1,18 @@ + + + + + false + + allow + + true + + + + + + + + false + \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/GuestCustomizationSection.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/GuestCustomizationSection.xml index d302949..045bb1d 100644 --- a/lib/ruby_vcloud_sdk/xml/xml_templates/GuestCustomizationSection.xml +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/GuestCustomizationSection.xml @@ -1 +1,21 @@ -falsefalsefalsefalsefalsefalsefalse \ No newline at end of file + + + Specifies Guest OS Customization Settings + false + false + + false + false + + + + false + true + + false + + + \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateVAppTemplateParams.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateVAppTemplateParams.xml index 95845f6..b6ff7ba 100644 --- a/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateVAppTemplateParams.xml +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateVAppTemplateParams.xml @@ -1 +1,9 @@ -falsefalse \ No newline at end of file + + + + + + + false + false + \ No newline at end of file diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/SNatRule.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/SNatRule.xml new file mode 100644 index 0000000..df28812 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/SNatRule.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/SourcedVmInstantiationParams.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/SourcedVmInstantiationParams.xml new file mode 100644 index 0000000..fe194c3 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/SourcedVmInstantiationParams.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/ruby_vcloud_sdk.gemspec b/ruby_vcloud_sdk.gemspec index 04b79df..6d24cdd 100644 --- a/ruby_vcloud_sdk.gemspec +++ b/ruby_vcloud_sdk.gemspec @@ -1,16 +1,16 @@ # -*- encoding: utf-8 -*- -# Copyright (c) 2009-2012 VMware, Inc. Gem::Specification.new do |s| s.name = "ruby_vcloud_sdk" - s.version = "0.7.3" + s.version = "0.7.8" + s.date = Date.today.to_s s.platform = Gem::Platform::RUBY s.summary = "BOSH vCloud API client" s.description = "BOSH vCloud API client\n#{`git rev-parse HEAD`[0, 6]}" - s.author = "VMware" - s.homepage = 'https://github.com/vchs/ruby_vcloud_sdk' + s.author = "CSUC" + s.homepage = 'https://www.csuc.cat' s.license = 'Apache 2.0' - s.email = "support@cloudfoundry.com" + s.email = "ois@csuc.cat" s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") s.files = `git ls-files -- lib/*`.split("\n") + %w(README.md) @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.add_dependency "builder", ">= 3.1" s.add_dependency "httpclient", ">= 2.4.0" - s.add_dependency "rest-client", ">= 1.6.7" + s.add_dependency "rest-client", "<= 1.8.0" s.add_dependency "nokogiri", ">= 1.5.6" s.add_dependency "netaddr" end