Skip to content

Commit

Permalink
Remove extraneous config profiles when cloning an Item. Fixes #64.
Browse files Browse the repository at this point in the history
  • Loading branch information
glennmatthews committed Mar 8, 2017
1 parent d7a872b commit e6aed8b
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ This project adheres to `Semantic Versioning`_.
`Unreleased`_
-------------

**Fixed**

- Fixed a case that could result in a RuntimeError being thrown when using
``cot edit-hardware`` to simultaneously create NICs and define a new
configuration profile (`#64`_).

**Added**

- ``Command`` (formerly ``COTGenericSubmodule``) now checks the available
Expand Down Expand Up @@ -708,6 +714,7 @@ Initial public release.
.. _#61: https://github.com/glennmatthews/cot/issues/61
.. _#62: https://github.com/glennmatthews/cot/issues/62
.. _#63: https://github.com/glennmatthews/cot/issues/63
.. _#64: https://github.com/glennmatthews/cot/issues/64

.. _Semantic Versioning: http://semver.org/
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
Expand Down
107 changes: 106 additions & 1 deletion COT/commands/tests/test_edit_hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ def test_set_nic_count_merge_profiles(self):
""")

def test_set_nic_count_create_new_one_profile(self):
""""Create a new NIC under a single profile."""
"""Create a new NIC under a single profile."""
self.command.package = self.input_ovf
self.command.nics = '4'
self.command.profiles = ['4CPU-4GB-3NIC']
Expand All @@ -675,6 +675,85 @@ def test_set_nic_count_create_new_one_profile(self):
+ <rasd:InstanceID>14</rasd:InstanceID>
+ <rasd:ResourceSubType>VMXNET3</rasd:ResourceSubType>
+ <rasd:ResourceType>10</rasd:ResourceType>
+ </ovf:Item>
</ovf:VirtualHardwareSection>
""")

def test_set_nic_count_create_new_and_new_profile(self):
"""Create new NICs under a new profile. Test for issue #64."""
self.command.package = self.input_ovf
self.command.nics = '4'
self.command.profiles = ['4CPU-4GB-4NIC']
self.command.run()
self.command.finished()
self.check_diff("""
</ovf:Configuration>
+ <ovf:Configuration ovf:id="4CPU-4GB-4NIC">
+ <ovf:Label>4CPU-4GB-4NIC</ovf:Label>
+ <ovf:Description>4CPU-4GB-4NIC</ovf:Description>
+ </ovf:Configuration>
</ovf:DeploymentOptionSection>
...
</ovf:Item>
- <ovf:Item ovf:configuration="4CPU-4GB-3NIC">
+ <ovf:Item ovf:configuration="4CPU-4GB-3NIC 4CPU-4GB-4NIC">
<rasd:AddressOnParent>12</rasd:AddressOnParent>
...
</ovf:Item>
- <ovf:Item ovf:configuration="4CPU-4GB-3NIC">
+ <ovf:Item ovf:configuration="4CPU-4GB-3NIC 4CPU-4GB-4NIC">
<rasd:AddressOnParent>13</rasd:AddressOnParent>
...
<rasd:InstanceID>13</rasd:InstanceID>
+ <rasd:ResourceSubType>VMXNET3</rasd:ResourceSubType>
+ <rasd:ResourceType>10</rasd:ResourceType>
+ </ovf:Item>
+ <ovf:Item ovf:configuration="4CPU-4GB-4NIC">
+ <rasd:AddressOnParent>14</rasd:AddressOnParent>
+ <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
+ <rasd:Connection>VM Network</rasd:Connection>
+ <rasd:Description>VMXNET3 ethernet adapter on "VM Network"\
</rasd:Description>
+ <rasd:ElementName>Ethernet4</rasd:ElementName>
+ <rasd:InstanceID>14</rasd:InstanceID>
<rasd:ResourceSubType>VMXNET3</rasd:ResourceSubType>
""")

def test_set_nic_count_create_new_and_split_new_profile(self):
"""Create new NICs under a new profile splitting from unified profile.
Another test for issue #64.
"""
self.command.package = self.csr_ovf
self.command.nics = '4'
self.command.profiles = ['4CPU-4GB-4NIC']
self.command.run()
self.command.finished()
self.check_diff(file1=self.csr_ovf, expected="""
</ovf:Network>
+ <ovf:Network ovf:name="GigabitEthernet4">
+ <ovf:Description>Data network 4</ovf:Description>
+ </ovf:Network>
</ovf:NetworkSection>
...
<ovf:Description>Large hardware profile (requires purchase of DRAM \
upgrade SKU) - 4 vCPUs, 8 GB RAM</ovf:Description>
+ </ovf:Configuration>
+ <ovf:Configuration ovf:id="4CPU-4GB-4NIC">
+ <ovf:Label>4CPU-4GB-4NIC</ovf:Label>
+ <ovf:Description>4CPU-4GB-4NIC</ovf:Description>
</ovf:Configuration>
...
</ovf:Item>
+ <ovf:Item ovf:configuration="4CPU-4GB-4NIC">
+ <rasd:AddressOnParent>14</rasd:AddressOnParent>
+ <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
+ <rasd:Connection>GigabitEthernet4</rasd:Connection>
+ <rasd:Description>NIC representing GigabitEthernet4</rasd:Description>
+ <rasd:ElementName>GigabitEthernet4</rasd:ElementName>
+ <rasd:InstanceID>14</rasd:InstanceID>
+ <rasd:ResourceSubType>VMXNET3 virtio</rasd:ResourceSubType>
+ <rasd:ResourceType>10</rasd:ResourceType>
+ </ovf:Item>
</ovf:VirtualHardwareSection>
""")
Expand All @@ -693,6 +772,32 @@ def test_set_nic_count_delete_nics(self):
<rasd:AddressOnParent>11</rasd:AddressOnParent>
""")

def test_set_nic_count_delete_nics_new_profile(self):
"""Set NIC count to a lower value under a newly created profile."""
self.command.package = self.csr_ovf
self.command.nics = 1
self.command.profiles = ['1CPU-4GB-1NIC']
self.command.run()
self.command.finished()
self.check_diff(file1=self.csr_ovf, expected="""
</ovf:Configuration>
+ <ovf:Configuration ovf:id="1CPU-4GB-1NIC">
+ <ovf:Label>1CPU-4GB-1NIC</ovf:Label>
+ <ovf:Description>1CPU-4GB-1NIC</ovf:Description>
+ </ovf:Configuration>
</ovf:DeploymentOptionSection>
...
</ovf:Item>
- <ovf:Item>
+ <ovf:Item ovf:configuration="1CPU-4GB 2CPU-4GB 4CPU-4GB 4CPU-8GB">
<rasd:AddressOnParent>12</rasd:AddressOnParent>
...
</ovf:Item>
- <ovf:Item>
+ <ovf:Item ovf:configuration="1CPU-4GB 2CPU-4GB 4CPU-4GB 4CPU-8GB">
<rasd:AddressOnParent>13</rasd:AddressOnParent>
""")

def test_set_nic_count_no_existing(self):
"""Create a NIC when nothing pre-exists."""
self.command.package = self.minimal_ovf
Expand Down
10 changes: 10 additions & 0 deletions COT/vm_description/ovf/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,17 @@ def clone_item(self, parent_item, profile_list):
tuple: ``(instance_id, ovfitem)``
"""
instance = self.find_unused_instance_id()
logger.debug("Cloning existing Item %s with new instance ID %s",
parent_item, instance)
ovfitem = copy.deepcopy(parent_item)

# Delete any profiles from the parent that we don't need now,
# otherwise we'll get an error when trying to set the instance ID
# on our clone due to self-inconsistency (#64).
for profile in self.ovf.config_profiles:
if ovfitem.has_profile(profile) and profile not in profile_list:
ovfitem.remove_profile(profile)

ovfitem.set_property(self.ovf.INSTANCE_ID, instance, profile_list)
ovfitem.modified = True
self.item_dict[instance] = ovfitem
Expand Down
2 changes: 1 addition & 1 deletion COT/vm_description/ovf/name_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def __getattr__(self, name):
elif name == "EPASD" or name == "SASD":
self._cache[name] = self.RASD
elif name not in self._raw:
raise AttributeError
raise AttributeError("Unknown attribute '{0}'".format(name))
else:
ns = getattr(self, self._raw[name].namespace_name)
tag = self._raw[name].tag
Expand Down

0 comments on commit e6aed8b

Please sign in to comment.