Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

Commit

Permalink
Update vsphere_manager to parse the ovf so the property specs
Browse files Browse the repository at this point in the history
are always in the correct order

Signed-off-by: Joseph Palermo <[email protected]>
  • Loading branch information
kvedurmu authored and jpalermo committed Nov 16, 2018
1 parent 1ecbf17 commit 73fa1f8
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 48 deletions.
76 changes: 30 additions & 46 deletions lib/vm_shepherd/vsphere_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,23 @@ def extract_ovf_from(ova_path)
end

def create_network_mappings(ovf_file_path, vsphere_config)
ovf = Nokogiri::XML(File.read(ovf_file_path))
ovf.remove_namespaces!
ovf = parse_ovf(ovf_file_path)
networks = ovf.xpath('//NetworkSection/Network').map { |x| x['name'] }
Hash[networks.map { |ovf_network| [ovf_network, network(vsphere_config)] }]
end

def parse_ovf(ovf_file_path)
ovf = Nokogiri::XML(File.read(ovf_file_path))
ovf.remove_namespaces!
ovf
end

def boot_vm(ovf_file_path, vm_config, vsphere_config)
ensure_folder_exists(vsphere_config[:folder])
template = deploy_ovf_template(ovf_file_path, vsphere_config)
vm = create_vm_from_template(template, vm_config, vsphere_config)

reconfigure_vm(vm, vm_config)
reconfigure_vm(vm, vm_config, ovf_file_path)
power_on_vm(vm)
end

Expand Down Expand Up @@ -233,8 +238,8 @@ def create_vm_from_template(template, vm_config, vsphere_config)
}
end

def reconfigure_vm(vm, vm_config)
virtual_machine_config_spec = create_virtual_machine_config_spec(vm_config)
def reconfigure_vm(vm, vm_config, ovf_file_path)
virtual_machine_config_spec = create_virtual_machine_config_spec(vm_config, ovf_file_path)
logger.info("BEGIN reconfigure_vm_task virtual_machine_config_spec=#{virtual_machine_config_spec.inspect}")
vm.ReconfigVM_Task(
spec: virtual_machine_config_spec
Expand All @@ -243,12 +248,12 @@ def reconfigure_vm(vm, vm_config)
}
end

def create_virtual_machine_config_spec(vm_config)
def create_virtual_machine_config_spec(vm_config, ovf_file_path)
logger.info('BEGIN VmConfigSpec creation')
vm_config_spec =
RbVmomi::VIM::VmConfigSpec.new.tap do |vcs|
vcs.ovfEnvironmentTransport = ['com.vmware.guestInfo']
vcs.property = create_vapp_property_specs(vm_config)
vcs.property = create_vapp_property_specs(vm_config, ovf_file_path)
end
logger.info("END VmConfigSpec creation: #{vm_config_spec.inspect}")

Expand All @@ -259,57 +264,36 @@ def create_virtual_machine_config_spec(vm_config)
end
end

def create_vapp_property_specs(vm_config)
ip_configuration = {
'ip0' => vm_config[:ip],
'netmask0' => vm_config[:netmask],
'gateway' => vm_config[:gateway],
'DNS' => vm_config[:dns],
def create_vapp_property_specs(vm_config, ovf_file_path)
property_value_map = {
'ip0' => vm_config[:ip],
'netmask0' => vm_config[:netmask],
'gateway' => vm_config[:gateway],
'DNS' => vm_config[:dns],
'ntp_servers' => vm_config[:ntp_servers],
'admin_password' => vm_config[:vm_password],
'public_ssh_key' => vm_config[:public_ssh_key],
'custom_hostname' => vm_config[:custom_hostname],
}

vapp_property_specs = []

logger.info("BEGIN VAppPropertySpec creation configuration=#{ip_configuration.inspect}")
# IP Configuration key order must match OVF template property order
ip_configuration.each_with_index do |(key, value), i|
logger.info("BEGIN VAppPropertySpec creation configuration=#{property_value_map.inspect}")

# VAppPropertySpec order must match OVF template property order
ovf = parse_ovf(ovf_file_path)
ovf.xpath('//ProductSection/Property').each_with_index do |property, index|
label = property.attribute('key').value
vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
spec.operation = 'edit'
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
p.key = i
p.label = key
p.value = value
p.key = index
p.label = label
p.value = property_value_map[label]
end
end
end

vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
spec.operation = 'edit'
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
p.key = 5 # this needs to be 5th to match the ovf template property order.
p.label = 'admin_password'
p.value = vm_config[:vm_password]
end
end

vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
spec.operation = 'edit'
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
p.key = 6 # ditto. see above. it makes me sad, too.
p.label = 'public_ssh_key'
p.value = vm_config[:public_ssh_key]
end
end

vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
spec.operation = 'edit'
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
p.key = 7 # ditto. see above. it makes me sad, too.
p.label = 'custom_hostname'
p.value = vm_config[:custom_hostname]
end
end unless vm_config[:custom_hostname].nil?

logger.info("END VAppPropertySpec creation vapp_property_specs=#{vapp_property_specs.inspect}")
vapp_property_specs
end
Expand Down
136 changes: 136 additions & 0 deletions spec/fixtures/ova_manager/default.ovf
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?xml version="1.0"?>
<Envelope ovf:version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xml:lang="en-US" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
xmlns:vmw="http://www.vmware.com/schema/ovf">

<References>
<File ovf:href="pivotal-ops-manager-disk1.vmdk" ovf:size="4243996160" ovf:id="file1"/>
</References>

<DiskSection>
<Info>List of the virtual disks used in the package</Info>
<Disk ovf:capacity="171798603879"
ovf:diskId="vmdisk1"
ovf:fileRef="file1"
ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"/>
</DiskSection>

<NetworkSection>
<Info>Logical networks used in the package</Info>
<Network ovf:name="Network 1">
<Description>Logical network used by this appliance.</Description>
</Network>
</NetworkSection>

<vmw:IpAssignmentSection ovf:required="false" vmw:protocols="IPv4" vmw:schemes="">
<Info>Supported IP assignment schemes</Info>
</vmw:IpAssignmentSection>

<VirtualSystem ovf:id="FAKE_FILENAME">
<Info>A virtual machine</Info>

<ProductSection>
<Info/>
<Product>Ops Manager</Product>
<Vendor>Pivotal</Vendor>
<Version>2.3-build.203</Version>
<Property ovf:key="ip0" ovf:userConfigurable="true" ovf:type="string">
<Label>IP Address</Label>
<Description>The IP address for the Ops Manager. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="netmask0" ovf:userConfigurable="true" ovf:type="string">
<Label>Netmask</Label>
<Description>The netmask for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="gateway" ovf:userConfigurable="true" ovf:type="string">
<Label>Default Gateway</Label>
<Description>The default gateway address for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="DNS" ovf:userConfigurable="true" ovf:type="string">
<Label>DNS</Label>
<Description>The domain name servers for the Ops Manager (comma separated). Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="ntp_servers" ovf:userConfigurable="true" ovf:type="string">
<Label>NTP Servers</Label>
<Description>Comma-delimited list of NTP servers</Description>
</Property>
<Property ovf:key="admin_password" ovf:userConfigurable="true" ovf:type="password">
<Label>Admin Password</Label>
<Description>This password is used to SSH into the Ops Manager. The username is 'ubuntu'. One or both of Admin Password and SSH Key is required.</Description>
</Property>
<Property ovf:key="public_ssh_key" ovf:userConfigurable="true" ovf:type="string">
<Label>Public SSH Key</Label>
<Description>The Public SSH Key is used to allow SSHing into the Ops Manager with your private ssh key. The username is 'ubuntu'. One or both of Admin Password and SSH Key is required.</Description>
</Property>
<Property ovf:key="custom_hostname" ovf:userConfigurable="true" ovf:type="string">
<Label>Custom Hostname</Label>
<Description>This will be set as the hostname on the VM. Default: 'pivotal-ops-manager'.</Description>
</Property>
</ProductSection>

<AnnotationSection>
<Info/>
<Annotation>Ops Manager for Pivotal Cloud Foundry
installs and manages PCF products and services.</Annotation>
</AnnotationSection>

<VirtualHardwareSection ovf:required="false" ovf:transport="com.vmware.guestInfo">
<Info>Virtual hardware requirements for a virtual machine</Info>
<System>
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
<vssd:InstanceID>0</vssd:InstanceID>
<vssd:VirtualSystemIdentifier>FAKE_FILENAME</vssd:VirtualSystemIdentifier>
<vssd:VirtualSystemType>vmx-09</vssd:VirtualSystemType>
</System>
<Item>
<rasd:Caption>1 virtual CPU</rasd:Caption>
<rasd:Description>Number of virtual CPUs</rasd:Description>
<rasd:ElementName>1 virtual CPU</rasd:ElementName>
<rasd:InstanceID>1</rasd:InstanceID>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
<rasd:Caption>8192 MB of memory</rasd:Caption>
<rasd:Description>Memory Size</rasd:Description>
<rasd:ElementName>8192 MB of memory</rasd:ElementName>
<rasd:InstanceID>2</rasd:InstanceID>
<rasd:ResourceType>4</rasd:ResourceType>
<rasd:VirtualQuantity>8192</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Caption>scsiController0</rasd:Caption>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>scsiController0</rasd:ElementName>
<rasd:InstanceID>3</rasd:InstanceID>
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item>
<Item>
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
<rasd:Caption>Ethernet adapter on 'Network 1'</rasd:Caption>
<rasd:Connection>Network 1</rasd:Connection>
<rasd:ElementName>Ethernet adapter on 'Network 1'</rasd:ElementName>
<rasd:InstanceID>4</rasd:InstanceID>
<rasd:ResourceSubType>E1000</rasd:ResourceSubType>
<rasd:ResourceType>10</rasd:ResourceType>
</Item>
<Item>
<rasd:AddressOnParent>0</rasd:AddressOnParent>
<rasd:Caption>disk1</rasd:Caption>
<rasd:Description>Disk Image</rasd:Description>
<rasd:ElementName>disk1</rasd:ElementName>
<rasd:HostResource>/disk/vmdisk1</rasd:HostResource>
<rasd:InstanceID>5</rasd:InstanceID>
<rasd:Parent>3</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item>
</VirtualHardwareSection>
</VirtualSystem>
</Envelope>
132 changes: 132 additions & 0 deletions spec/fixtures/ova_manager/without_public_ssh_key.ovf
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?xml version="1.0"?>
<Envelope ovf:version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xml:lang="en-US" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
xmlns:vmw="http://www.vmware.com/schema/ovf">

<References>
<File ovf:href="pivotal-ops-manager-disk1.vmdk" ovf:size="4223308288" ovf:id="file1"/>
</References>

<DiskSection>
<Info>List of the virtual disks used in the package</Info>
<Disk ovf:capacity="171798603879"
ovf:diskId="vmdisk1"
ovf:fileRef="file1"
ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"/>
</DiskSection>

<NetworkSection>
<Info>Logical networks used in the package</Info>
<Network ovf:name="Network 1">
<Description>Logical network used by this appliance.</Description>
</Network>
</NetworkSection>

<vmw:IpAssignmentSection ovf:required="false" vmw:protocols="IPv4" vmw:schemes="">
<Info>Supported IP assignment schemes</Info>
</vmw:IpAssignmentSection>

<VirtualSystem ovf:id="FAKE_FILENAME">
<Info>A virtual machine</Info>

<ProductSection>
<Info/>
<Product>Ops Manager</Product>
<Vendor>Pivotal</Vendor>
<Version>2.2-build.365</Version>
<Property ovf:key="ip0" ovf:userConfigurable="true" ovf:type="string">
<Label>IP Address</Label>
<Description>The IP address for the Ops Manager. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="netmask0" ovf:userConfigurable="true" ovf:type="string">
<Label>Netmask</Label>
<Description>The netmask for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="gateway" ovf:userConfigurable="true" ovf:type="string">
<Label>Default Gateway</Label>
<Description>The default gateway address for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="DNS" ovf:userConfigurable="true" ovf:type="string">
<Label>DNS</Label>
<Description>The domain name servers for the Ops Manager (comma separated). Leave blank if DHCP is desired.</Description>
</Property>
<Property ovf:key="ntp_servers" ovf:userConfigurable="true" ovf:type="string">
<Label>NTP Servers</Label>
<Description>Comma-delimited list of NTP servers</Description>
</Property>
<Property ovf:key="admin_password" ovf:required="true" ovf:userConfigurable="true" ovf:type="password">
<Label>Admin Password</Label>
<Description>This password is used to SSH into the Ops Manager. The username is 'ubuntu'.</Description>
</Property>
<Property ovf:key="custom_hostname" ovf:userConfigurable="true" ovf:type="string">
<Label>Custom Hostname</Label>
<Description>This will be set as the hostname on the VM. Default: 'pivotal-ops-manager'.</Description>
</Property>
</ProductSection>

<AnnotationSection>
<Info/>
<Annotation>Ops Manager for Pivotal Cloud Foundry
installs and manages PCF products and services.</Annotation>
</AnnotationSection>

<VirtualHardwareSection ovf:required="false" ovf:transport="com.vmware.guestInfo">
<Info>Virtual hardware requirements for a virtual machine</Info>
<System>
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
<vssd:InstanceID>0</vssd:InstanceID>
<vssd:VirtualSystemIdentifier>FAKE_FILENAME</vssd:VirtualSystemIdentifier>
<vssd:VirtualSystemType>vmx-09</vssd:VirtualSystemType>
</System>
<Item>
<rasd:Caption>1 virtual CPU</rasd:Caption>
<rasd:Description>Number of virtual CPUs</rasd:Description>
<rasd:ElementName>1 virtual CPU</rasd:ElementName>
<rasd:InstanceID>1</rasd:InstanceID>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
<rasd:Caption>8192 MB of memory</rasd:Caption>
<rasd:Description>Memory Size</rasd:Description>
<rasd:ElementName>8192 MB of memory</rasd:ElementName>
<rasd:InstanceID>2</rasd:InstanceID>
<rasd:ResourceType>4</rasd:ResourceType>
<rasd:VirtualQuantity>8192</rasd:VirtualQuantity>
</Item>
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Caption>scsiController0</rasd:Caption>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>scsiController0</rasd:ElementName>
<rasd:InstanceID>3</rasd:InstanceID>
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item>
<Item>
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
<rasd:Caption>Ethernet adapter on 'Network 1'</rasd:Caption>
<rasd:Connection>Network 1</rasd:Connection>
<rasd:ElementName>Ethernet adapter on 'Network 1'</rasd:ElementName>
<rasd:InstanceID>4</rasd:InstanceID>
<rasd:ResourceSubType>E1000</rasd:ResourceSubType>
<rasd:ResourceType>10</rasd:ResourceType>
</Item>
<Item>
<rasd:AddressOnParent>0</rasd:AddressOnParent>
<rasd:Caption>disk1</rasd:Caption>
<rasd:Description>Disk Image</rasd:Description>
<rasd:ElementName>disk1</rasd:ElementName>
<rasd:HostResource>/disk/vmdisk1</rasd:HostResource>
<rasd:InstanceID>5</rasd:InstanceID>
<rasd:Parent>3</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item>
</VirtualHardwareSection>
</VirtualSystem>
</Envelope>
Loading

0 comments on commit 73fa1f8

Please sign in to comment.