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