test_compute_service.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import uuid
  2. import ipaddress
  3. from cloudbridge.cloud.interfaces \
  4. import InvalidConfigurationException
  5. from cloudbridge.cloud.interfaces import InstanceState
  6. from cloudbridge.cloud.interfaces.resources import InstanceType
  7. from cloudbridge.cloud.interfaces.resources import WaitStateException
  8. from test.helpers import ProviderTestBase
  9. import test.helpers as helpers
  10. class CloudComputeServiceTestCase(ProviderTestBase):
  11. def __init__(self, methodName, provider):
  12. super(CloudComputeServiceTestCase, self).__init__(
  13. methodName=methodName, provider=provider)
  14. def test_crud_instance(self):
  15. name = "CBInstCrud-{0}-{1}".format(
  16. self.provider.name,
  17. uuid.uuid4())
  18. inst = helpers.create_test_instance(self.provider, name)
  19. def cleanup_inst(instance):
  20. instance.terminate()
  21. instance.wait_for(
  22. [InstanceState.TERMINATED, InstanceState.UNKNOWN],
  23. terminal_states=[InstanceState.ERROR],
  24. interval=self.get_test_wait_interval())
  25. with helpers.cleanup_action(lambda: cleanup_inst(inst)):
  26. inst.wait_till_ready(interval=self.get_test_wait_interval())
  27. all_instances = self.provider.compute.instances.list()
  28. found_instances = [i for i in all_instances if i.name == name]
  29. self.assertTrue(
  30. len(found_instances) == 1,
  31. "List instances does not return the expected instance %s" %
  32. name)
  33. # check iteration
  34. found_instances = [i for i in self.provider.compute.instances
  35. if i.name == name]
  36. self.assertTrue(
  37. len(found_instances) == 1,
  38. "Iter instances does not return the expected instance %s" %
  39. name)
  40. get_inst = self.provider.compute.instances.get(
  41. inst.id)
  42. self.assertTrue(
  43. found_instances[0].id ==
  44. get_inst.id == inst.id,
  45. "Ids returned by list: {0} and get: {1} are not as "
  46. " expected: {2}" .format(found_instances[0].id,
  47. get_inst.id,
  48. inst.id))
  49. self.assertTrue(
  50. found_instances[0].name ==
  51. get_inst.name == inst.name,
  52. "Names returned by list: {0} and get: {1} are not as "
  53. " expected: {2}" .format(found_instances[0].name,
  54. get_inst.name,
  55. inst.name))
  56. deleted_inst = self.provider.compute.instances.get(
  57. inst.id)
  58. self.assertTrue(
  59. deleted_inst is None or deleted_inst.state in (
  60. InstanceState.TERMINATED,
  61. InstanceState.UNKNOWN),
  62. "Instance %s should have been deleted but still exists." %
  63. name)
  64. def _is_valid_ip(self, address):
  65. try:
  66. ipaddress.ip_address(address)
  67. except ValueError:
  68. return False
  69. return True
  70. def test_instance_properties(self):
  71. instance_name = "CBInstProps-{0}-{1}".format(
  72. self.provider.name,
  73. uuid.uuid4())
  74. test_instance = helpers.get_test_instance(self.provider,
  75. instance_name)
  76. with helpers.cleanup_action(lambda: test_instance.terminate()):
  77. self.assertTrue(
  78. test_instance.id in repr(test_instance),
  79. "repr(obj) should contain the object id so that the object"
  80. " can be reconstructed, but does not. eval(repr(obj)) == obj")
  81. self.assertEqual(
  82. test_instance.name, instance_name,
  83. "Instance name {0} is not equal to the expected name"
  84. " {1}".format(test_instance.name, instance_name))
  85. image_id = helpers.get_provider_test_data(self.provider, "image")
  86. self.assertEqual(test_instance.image_id, image_id,
  87. "Image id {0} is not equal to the expected id"
  88. " {1}".format(test_instance.image_id, image_id))
  89. self.assertIsInstance(test_instance.public_ips, list)
  90. self.assertIsInstance(test_instance.private_ips, list)
  91. # Must have either a public or a private ip
  92. ip_private = test_instance.private_ips[0] \
  93. if test_instance.private_ips else None
  94. ip_address = test_instance.public_ips[0] \
  95. if test_instance.public_ips else ip_private
  96. self.assertIsNotNone(
  97. ip_address,
  98. "Instance must have either a public IP or a private IP")
  99. self.assertTrue(
  100. self._is_valid_ip(ip_address),
  101. "Instance must have a valid IP address")
  102. self.assertIsInstance(test_instance.instance_type, InstanceType)
  103. def test_block_device_mappings(self):
  104. name = "CBInstBlkMap-{0}-{1}".format(
  105. self.provider.name,
  106. uuid.uuid4())
  107. lc = self.provider.compute.instances.create_launch_config()
  108. # specifying an invalid size should raise
  109. # an exception
  110. with self.assertRaises(InvalidConfigurationException):
  111. lc.add_volume_device(size=-1)
  112. # Attempting to add a blank volume without specifying a size
  113. # should raise an exception
  114. with self.assertRaises(InvalidConfigurationException):
  115. lc.add_volume_device(source=None)
  116. # block_devices should be empty so far
  117. self.assertListEqual(
  118. lc.block_devices, [], "No block devices should have been"
  119. " added to mappings list since the configuration was"
  120. " invalid")
  121. # Add a new volume
  122. lc.add_volume_device(size=1, delete_on_terminate=True)
  123. # Override root volume size
  124. image_id = helpers.get_provider_test_data(self.provider, "image")
  125. img = self.provider.compute.images.get(image_id)
  126. lc.add_volume_device(
  127. is_root=True,
  128. source=img,
  129. # TODO: This should be greater than the ami size or tests will fail
  130. # on actual infrastructure. Needs an image.size method
  131. size=2,
  132. delete_on_terminate=True)
  133. # Attempting to add more than one root volume should raise an
  134. # exception.
  135. with self.assertRaises(InvalidConfigurationException):
  136. lc.add_volume_device(size=1, is_root=True)
  137. # Add all available ephemeral devices
  138. instance_type_name = helpers.get_provider_test_data(
  139. self.provider,
  140. "instance_type")
  141. inst_type = next(self.provider.compute.instance_types.find(
  142. name=instance_type_name))
  143. for _ in range(inst_type.num_ephemeral_disks):
  144. lc.add_ephemeral_device()
  145. # block_devices should be populated
  146. self.assertTrue(
  147. len(lc.block_devices) == 2 + inst_type.num_ephemeral_disks,
  148. "Expected %d total block devices bit found %d" %
  149. (2 + inst_type.num_ephemeral_disks, len(lc.block_devices)))
  150. inst = helpers.create_test_instance(
  151. self.provider,
  152. name,
  153. zone=helpers.get_provider_test_data(self.provider, 'placement'),
  154. launch_config=lc)
  155. with helpers.cleanup_action(lambda: inst.terminate()):
  156. try:
  157. inst.wait_till_ready(
  158. interval=self.get_test_wait_interval())
  159. except WaitStateException as e:
  160. self.fail("The block device mapped launch did not complete"
  161. " successfully: %s" % e)
  162. inst.terminate()
  163. inst.wait_for(
  164. [InstanceState.TERMINATED, InstanceState.UNKNOWN],
  165. terminal_states=[InstanceState.ERROR],
  166. interval=self.get_test_wait_interval())
  167. # TODO: Check instance attachments and make sure they
  168. # correspond to requested mappings