test_provider_compute_service.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import uuid
  2. import ipaddress
  3. from cloudbridge.providers.interfaces import InstanceState
  4. from cloudbridge.providers.interfaces.resources \
  5. import InvalidConfigurationException
  6. from cloudbridge.providers.interfaces.services import LaunchConfig
  7. from test.helpers import ProviderTestBase
  8. import test.helpers as helpers
  9. class ProviderComputeServiceTestCase(ProviderTestBase):
  10. def __init__(self, methodName, provider):
  11. super(ProviderComputeServiceTestCase, self).__init__(
  12. methodName=methodName, provider=provider)
  13. def test_crud_instance(self):
  14. name = "CBInstCrud-{0}-{1}".format(
  15. self.provider.name,
  16. uuid.uuid4())
  17. inst = helpers.create_test_instance(self.provider, name)
  18. with helpers.exception_action(lambda: inst.terminate()):
  19. inst.wait_till_ready(interval=self.get_test_wait_interval())
  20. all_instances = self.provider.compute.instances.list()
  21. found_instances = [i for i in all_instances if i.name == name]
  22. self.assertTrue(
  23. len(found_instances) == 1,
  24. "List instances does not return the expected instance %s" %
  25. name)
  26. get_inst = self.provider.compute.instances.get(
  27. inst.instance_id)
  28. self.assertTrue(
  29. found_instances[0].instance_id ==
  30. get_inst.instance_id == inst.instance_id,
  31. "Ids returned by list: {0} and get: {1} are not as "
  32. " expected: {2}" .format(found_instances[0].instance_id,
  33. get_inst.instance_id,
  34. inst.instance_id))
  35. self.assertTrue(
  36. found_instances[0].name ==
  37. get_inst.name == inst.name,
  38. "Names returned by list: {0} and get: {1} are not as "
  39. " expected: {2}" .format(found_instances[0].name,
  40. get_inst.name,
  41. inst.name))
  42. inst.terminate()
  43. inst.wait_for(
  44. [InstanceState.TERMINATED, InstanceState.UNKNOWN],
  45. terminal_states=[InstanceState.ERROR],
  46. interval=self.get_test_wait_interval())
  47. deleted_inst = self.provider.compute.instances.get(
  48. inst.instance_id)
  49. self.assertTrue(
  50. deleted_inst is None or deleted_inst.state in (
  51. InstanceState.TERMINATED,
  52. InstanceState.UNKNOWN),
  53. "Instance %s should have been deleted but still exists." %
  54. name)
  55. def _is_valid_ip(self, address):
  56. try:
  57. ipaddress.ip_address(address)
  58. except ValueError:
  59. return False
  60. return True
  61. def test_instance_properties(self):
  62. instance_name = "CBInstProps-{0}-{1}".format(
  63. self.provider.name,
  64. uuid.uuid4())
  65. test_instance = helpers.get_test_instance(self.provider,
  66. instance_name)
  67. with helpers.exception_action(lambda: test_instance.terminate()):
  68. self.assertEqual(
  69. test_instance.name, instance_name,
  70. "Instance name {0} is not equal to the expected name"
  71. " {1}".format(test_instance.name, instance_name))
  72. image_id = helpers.get_provider_test_data(self.provider, "image")
  73. self.assertEqual(test_instance.image_id, image_id,
  74. "Image id {0} is not equal to the expected id"
  75. " {1}".format(test_instance.image_id, image_id))
  76. self.assertIsInstance(test_instance.public_ips, list)
  77. self.assertIsInstance(test_instance.private_ips, list)
  78. # Must have either a public or a private ip
  79. ip_private = test_instance.private_ips[0] \
  80. if test_instance.private_ips else None
  81. ip_address = test_instance.public_ips[0] \
  82. if test_instance.public_ips else ip_private
  83. self.assertIsNotNone(
  84. ip_address,
  85. "Instance must have either a public IP or a private IP")
  86. self.assertTrue(
  87. self._is_valid_ip(ip_address),
  88. "Instance must have a valid IP address")
  89. test_instance.terminate()
  90. def test_block_device_mappings(self):
  91. name = "CBInstBlkMap-{0}-{1}".format(
  92. self.provider.name,
  93. uuid.uuid4())
  94. outer_inst = helpers.create_test_instance(self.provider, name)
  95. with helpers.exception_action(lambda: outer_inst.terminate()):
  96. img = outer_inst.create_image(name)
  97. with helpers.exception_action(lambda: img.delete()):
  98. lc = self.provider.compute.instances.create_launch_config()
  99. # specifying no size with a destination of volume should raise
  100. # an exception
  101. with self.assertRaises(InvalidConfigurationException):
  102. lc.add_block_device(LaunchConfig.DestinationType.VOLUME)
  103. # specifying an invalid source type should raise an error
  104. with self.assertRaises(InvalidConfigurationException):
  105. lc.add_block_device(LaunchConfig.DestinationType.LOCAL,
  106. source='1234')
  107. # specifying an invalid size should raise an error
  108. with self.assertRaises(InvalidConfigurationException):
  109. lc.add_block_device(LaunchConfig.DestinationType.LOCAL,
  110. source=img, size=-1)
  111. # block_devices should be empty so far
  112. self.assertFalse(
  113. lc.block_devices, "No block devices should have been added"
  114. " to mappings list since the configuration was invalid")
  115. # Add a new volume
  116. lc.add_block_device(LaunchConfig.DestinationType.VOLUME,
  117. size=1)
  118. # Override root volume size
  119. if img:
  120. lc.add_block_device(LaunchConfig.DestinationType.LOCAL,
  121. source=img, size=11)
  122. # Since the previous addition with destination=LOCAL with
  123. # source=img implies a root volume, attempting to add another
  124. # root volume should raise an exception.
  125. with self.assertRaises(InvalidConfigurationException):
  126. lc.add_block_device(LaunchConfig.DestinationType.LOCAL,
  127. size=1, is_root=True)
  128. # Add all available ephemeral devices
  129. instance_type_name = helpers.get_provider_test_data(
  130. self.provider,
  131. "instance_type")
  132. inst_type = self.provider.compute.instance_types.find_by_name(
  133. instance_type_name)
  134. for _ in range(inst_type.num_ephemeral_disks):
  135. lc.add_block_device(LaunchConfig.DestinationType.LOCAL)
  136. # block_devices should be populated
  137. self.assertTrue(
  138. len(lc.block_devices) >= 1,
  139. "Expected number of block devices %s not found" %
  140. len(lc.block_devices))
  141. inst = helpers.create_test_instance(
  142. self.provider,
  143. name,
  144. launch_config=lc)
  145. with helpers.exception_action(lambda: inst.terminate()):
  146. inst.wait_till_ready(
  147. interval=self.get_test_wait_interval())
  148. inst.terminate()
  149. inst.wait_for(
  150. [InstanceState.TERMINATED, InstanceState.UNKNOWN],
  151. terminal_states=[InstanceState.ERROR],
  152. interval=self.get_test_wait_interval())
  153. # TODO: Check instance attachments and make sure they
  154. # correspond to requested mappings