Class: Fog::VcloudDirector::Generators::Compute::ReconfigureVm

Inherits:
Object
  • Object
show all
Extended by:
ComposeCommon
Defined in:
lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb

Constant Summary collapse

NETWORK_SECTION_ORDER =
['ovf:Info'] + %w(PrimaryNetworkConnectionIndex NetworkConnection Link)
NETWORK_CONNECTION_ORDER =
%w(NetworkConnectionIndex IpAddress ExternalIpAddress IsConnected MACAddress IpAddressAllocationMode NetworkAdapterType).freeze

Class Method Summary collapse

Methods included from ComposeCommon

initialize

Class Method Details

.add_network_connection_section(xml, primary: nil, **nic) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 135

def add_network_connection_section(xml, primary: nil, **nic)
  nic.delete(:idx)
  network_section = xml.at('//xmlns:NetworkConnectionSection')
  network_section.add_namespace_definition('vcloud', 'http://www.vmware.com/vcloud/v1.5')
  Nokogiri::XML::Builder.with(network_section) do |section|
    network_section_nic(section, **nic)
  end

  # Move the new item to satisfy vCloud's sorting requirements.
  item = network_section.at('./xmlns:NetworkConnection[last()]').remove
  (previous = find_previous(network_section, 'NetworkConnection', NETWORK_SECTION_ORDER)) ? previous.after(item) : network_section.prepend_child(item)

  set_primary_nic(xml, nic[:new_idx]) if primary
end

.add_virtual_hardware_section_item(xml) ⇒ Object



89
90
91
92
93
94
95
96
97
98
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 89

def add_virtual_hardware_section_item(xml)
  virtual_hardware = xml.at('//ovf:VirtualHardwareSection')
  virtual_hardware.add_namespace_definition('vcloud', 'http://www.vmware.com/vcloud/v1.5')
  Nokogiri::XML::Builder.with(virtual_hardware) do |section|
    yield section
  end
  # Move the new item to satisfy vCloud's sorting requirements.
  item = virtual_hardware.at('./ovf:Item[last()]').remove
  virtual_hardware.at('./ovf:Item[last()]').after(item)
end

.add_virtual_hardware_section_item_hdd(xml, **disk) ⇒ Object



82
83
84
85
86
87
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 82

def add_virtual_hardware_section_item_hdd(xml, **disk)
  disk[:id] = rand(10_000..100_000)
  add_virtual_hardware_section_item(xml) do |section|
    virtual_hardware_section_item_hdd(section, **disk)
  end
end

.find_previous(xml, leaf_name, order) ⇒ Object

Finds previous sybling for a leaf_name in accordance with ordered list of child elements. Arguments:

  • xml: parent xml whose children are we checking

  • leaf_name: child element name that we want to find preceeding sybling for (without namespace)

  • order: list of child names in proper order

Returns:

  • previous sybling element if found or nil



178
179
180
181
182
183
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 178

def find_previous(xml, leaf_name, order)
  order.reduce(nil) do |res, curr_name|
    break res if curr_name == leaf_name
    xml.at(curr_name.include?(':') ? "./#{curr_name}" : "./xmlns:#{curr_name}") || res
  end
end

.generate_xml(current, options) ⇒ String

Generates VM reconfiguration XML.

Parameters:

  • current (Nokogiri::Xml)

    DOM representing current VM configuration.

  • options (Hash)

    desired configuration. Please see examples-vm-reconfigure.md for details.

Returns:

  • (String)

    xml string, a modification of ‘current` input, with desired configurations applied.



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 20

def generate_xml(current, options)
  current.root['name'] = options[:name] if options[:name]
  current.at('Description').content = options[:description] if options[:description]
  # Remove entire section when no moification is required to improve performance, see
  # https://pubs.vmware.com/vcd-80/index.jsp#com.vmware.vcloud.api.sp.doc_90/GUID-4759B018-86C2-4C91-8176-3EC73CD7122B.html
  options[:hardware] ? update_virtual_hardware_section(current, options[:hardware]) : current.at('//ovf:VirtualHardwareSection').remove
  options[:networks] ? update_network_connection_section(current, options[:networks]) : current.at('//xmlns:NetworkConnectionSection').remove
  current.at('//ovf:OperatingSystemSection').remove # TODO(miha-plesko): support this type of customization
  current.at('//xmlns:GuestCustomizationSection').remove # TODO(miha-plesko): support this type of customization

  current.to_xml
end

.leaf_at(xml, leaf_name, order, ns: 'xmlns') ⇒ Object

Find leaf element if present or create new one. Respect XML ordering when adding new. Arguments:

  • xml: parent xml whose child element are we updating/adding

  • leaf_name: child element name (without namespace)

  • order: list of child names in proper order

  • ns: leaf element’s namespace

Returns:

  • leaf element



162
163
164
165
166
167
168
169
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 162

def leaf_at(xml, leaf_name, order, ns: 'xmlns')
  el = xml.at("./#{ns}:#{leaf_name}")
  el || begin
    el = Nokogiri::XML::Node.new(ns == 'xmlns' ? leaf_name : "#{ns}:#{leaf_name}", xml)
    (previous = find_previous(xml, leaf_name, order)) ? previous.after(el) : xml.prepend_child(el)
    el
  end
end

.remove_network_connection_section_by_index(xml, idx:) ⇒ Object



130
131
132
133
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 130

def remove_network_connection_section_by_index(xml, idx:)
  conn = xml.at("//xmlns:NetworkConnectionSection/xmlns:NetworkConnection[./xmlns:NetworkConnectionIndex = '#{idx}']")
  conn.remove if conn
end

.remove_virtual_hardware_section_item(xml, type:, id:) ⇒ Object



111
112
113
114
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 111

def remove_virtual_hardware_section_item(xml, type:, id:)
  item = xml.at("//ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType = '#{type}' and rasd:InstanceID = '#{id}']")
  item.remove if item
end

.remove_virtual_hardware_section_item_hdd(xml, id:) ⇒ Object



78
79
80
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 78

def remove_virtual_hardware_section_item_hdd(xml, id:)
  remove_virtual_hardware_section_item(xml, :type => 17, :id => id)
end

.set_primary_nic(xml, idx) ⇒ Object



150
151
152
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 150

def set_primary_nic(xml, idx)
  leaf_at(xml.at('//xmlns:NetworkConnectionSection'), 'PrimaryNetworkConnectionIndex', NETWORK_SECTION_ORDER).content = idx
end

.update_network_connection_section(xml, networks) ⇒ Object

Apply desired NIC connection modifications to the original xml.



43
44
45
46
47
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 43

def update_network_connection_section(xml, networks)
  array_wrap(networks).reject { |n| n[:new_idx] == -1 || n[:idx].nil? }.each { |nic| update_network_connection_section_by_index(xml, **nic) }
  array_wrap(networks).select { |n| n[:new_idx] == -1 }.each { |nic| remove_network_connection_section_by_index(xml, :idx => nic[:idx]) }
  array_wrap(networks).select { |n| n[:idx].nil? }.each { |nic| add_network_connection_section(xml, **nic) }
end

.update_network_connection_section_by_index(xml, idx:, name: nil, mac: nil, ip: nil, connected: nil, mode: nil, type: nil, needs: nil, new_idx: nil, primary: nil) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 116

def update_network_connection_section_by_index(xml, idx:, name: nil, mac: nil, ip: nil, connected: nil, mode: nil, type: nil, needs: nil, new_idx: nil, primary: nil)
  conn = xml.at("//xmlns:NetworkConnectionSection/xmlns:NetworkConnection[./xmlns:NetworkConnectionIndex = '#{idx}']")
  conn['network'] = name if name
  conn['needsCustomization'] = needs unless needs.nil?
  leaf_at(conn, 'IpAddress', NETWORK_CONNECTION_ORDER).content = ip unless ip.nil?
  leaf_at(conn, 'IpAddressAllocationMode', NETWORK_CONNECTION_ORDER).content = mode if mode
  leaf_at(conn, 'IsConnected', NETWORK_CONNECTION_ORDER).content = connected unless connected.nil?
  leaf_at(conn, 'MACAddress', NETWORK_CONNECTION_ORDER).content = mac if mac
  leaf_at(conn, 'NetworkAdapterType', NETWORK_CONNECTION_ORDER).content = type if type
  leaf_at(conn, 'NetworkConnectionIndex', NETWORK_CONNECTION_ORDER).content = new_idx if new_idx

  set_primary_nic(xml, new_idx || idx) if primary
end

.update_virtual_hardware_section(xml, hardware) ⇒ Object

Apply desired hardware modifications to the original xml.



34
35
36
37
38
39
40
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 34

def update_virtual_hardware_section(xml, hardware)
  update_virtual_hardware_section_item_mem(xml, **hardware[:memory]) if hardware[:memory]
  update_virtual_hardware_section_item_cpu(xml, **hardware[:cpu]) if hardware[:cpu]
  array_wrap(hardware[:disk]).reject { |d| d[:id].nil? || d[:capacity_mb] == -1 }.each { |disk| update_virtual_hardware_section_item_hdd(xml, **disk) }
  array_wrap(hardware[:disk]).select { |d| d[:id].nil? }.each { |disk| add_virtual_hardware_section_item_hdd(xml, **disk) }
  array_wrap(hardware[:disk]).select { |d| d[:capacity_mb] == -1 }.each { |disk| remove_virtual_hardware_section_item_hdd(xml, id: disk[:id]) }
end

.update_virtual_hardware_section_item(xml, type:, id: nil) ⇒ Object



100
101
102
103
104
105
106
107
108
109
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 100

def update_virtual_hardware_section_item(xml, type:, id: nil)
  condition = "rasd:ResourceType = '#{type}'"
  condition += " and rasd:InstanceID = '#{id}'" if id
  if (item = xml.at("//ovf:VirtualHardwareSection/ovf:Item[#{condition}]"))
    yield item
    true
  else
    false
  end
end

.update_virtual_hardware_section_item_cpu(xml, num_cores: nil, cores_per_socket: nil, reservation: nil, limit: nil, weight: nil) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 49

def update_virtual_hardware_section_item_cpu(xml, num_cores: nil, cores_per_socket: nil, reservation: nil, limit: nil, weight: nil)
  update_virtual_hardware_section_item(xml, :type => 3) do |item|
    item.at('./rasd:VirtualQuantity').content = num_cores if num_cores
    item.at('./rasd:Reservation').content = reservation if reservation
    item.at('./rasd:Limit').content = limit if limit
    item.at('./rasd:Weight').content = weight if weight
    item.at('./vmw:CoresPerSocket').content = cores_per_socket if cores_per_socket
  end
end

.update_virtual_hardware_section_item_hdd(xml, id:, capacity_mb: nil, address: nil, type: nil, subtype: nil) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 68

def update_virtual_hardware_section_item_hdd(xml, id:, capacity_mb: nil, address: nil, type: nil, subtype: nil)
  hdd_exists = update_virtual_hardware_section_item(xml, :type => 17, :id => id) do |item|
    item.at('./rasd:AddressOnParent').content = address if address
    item.at('./rasd:HostResource')['ns13:capacity'] = capacity_mb if capacity_mb
    item.at('./rasd:HostResource')['ns13:busType'] = type if type
    item.at('./rasd:HostResource')['ns13:busSubType'] = subtype if subtype
  end
  raise Fog::VcloudDirector::Compute::PreProcessingError.new("Error resizing disk: disk with id '#{id}' does not exist.") unless hdd_exists
end

.update_virtual_hardware_section_item_mem(xml, quantity_mb: nil, reservation: nil, limit: nil, weight: nil) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/fog/vcloud_director/generators/compute/reconfigure_vm.rb', line 59

def update_virtual_hardware_section_item_mem(xml, quantity_mb: nil, reservation: nil, limit: nil, weight: nil)
  update_virtual_hardware_section_item(xml, :type => 4) do |item|
    item.at('./rasd:VirtualQuantity').content = quantity_mb if quantity_mb
    item.at('./rasd:Reservation').content = reservation if reservation
    item.at('./rasd:Limit').content = limit if limit
    item.at('./rasd:Weight').content = weight if weight
  end
end