__init__.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import functools
  2. import os
  3. import sys
  4. import traceback
  5. import unittest
  6. import uuid
  7. from contextlib import contextmanager
  8. from cloudbridge.cloud.factory import CloudProviderFactory
  9. from cloudbridge.cloud.interfaces import InstanceState
  10. from cloudbridge.cloud.interfaces import TestMockHelperMixin
  11. from six import reraise
  12. def parse_bool(val):
  13. if val:
  14. return str(val).upper() in ['TRUE', 'YES']
  15. else:
  16. return False
  17. @contextmanager
  18. def cleanup_action(cleanup_func):
  19. """
  20. Context manager to carry out a given
  21. cleanup action after carrying out a set
  22. of tasks, or when an exception occurs.
  23. If any errors occur during the cleanup
  24. action, those are ignored, and the original
  25. traceback is preserved.
  26. :params func: This function is called if
  27. an exception occurs or at the end of the
  28. context block. If any exceptions raised
  29. by func are ignored.
  30. Usage:
  31. with cleanup_action(lambda e: print("Oops!")):
  32. do_something()
  33. """
  34. try:
  35. yield
  36. except Exception:
  37. ex_class, ex_val, ex_traceback = sys.exc_info()
  38. try:
  39. cleanup_func()
  40. except Exception as e:
  41. print("Error during exception cleanup: {0}".format(e))
  42. traceback.print_exc()
  43. reraise(ex_class, ex_val, ex_traceback)
  44. try:
  45. cleanup_func()
  46. except Exception as e:
  47. print("Error during cleanup: {0}".format(e))
  48. traceback.print_exc()
  49. def skipIfNoService(services):
  50. """
  51. A decorator for skipping tests if the provider
  52. does not implement a given service.
  53. """
  54. def wrap(func):
  55. """
  56. The actual wrapper
  57. """
  58. @functools.wraps(func)
  59. def wrapper(self, *args, **kwargs):
  60. provider = getattr(self, 'provider')
  61. if provider:
  62. for service in services:
  63. if not provider.has_service(service):
  64. self.skipTest("Skipping test because '%s' service is"
  65. " not implemented" % (service,))
  66. func(self, *args, **kwargs)
  67. return wrapper
  68. return wrap
  69. TEST_DATA_CONFIG = {
  70. "AWSCloudProvider": {
  71. "image": os.environ.get('CB_IMAGE_AWS', 'ami-5ac2cd4d'),
  72. "vm_type": os.environ.get('CB_VM_TYPE_AWS', 't2.nano'),
  73. "placement": os.environ.get('CB_PLACEMENT_AWS', 'us-east-1a'),
  74. },
  75. "OpenStackCloudProvider": {
  76. "image": os.environ.get('CB_IMAGE_OS',
  77. '842b949c-ea76-48df-998d-8a41f2626243'),
  78. "vm_type": os.environ.get('CB_VM_TYPE_OS', 'm1.tiny'),
  79. "placement": os.environ.get('CB_PLACEMENT_OS', 'zone-r1'),
  80. },
  81. "AzureCloudProvider": {
  82. "placement":
  83. os.environ.get('CB_PLACEMENT_AZURE', 'eastus'),
  84. "image":
  85. os.environ.get('CB_IMAGE_AZURE', 'CbTest-Img'),
  86. "instance_type":
  87. os.environ.get('CB_INSTANCE_TYPE_AZURE', 'Standard_DS1_v2'),
  88. }
  89. }
  90. def get_provider_test_data(provider, key):
  91. if "AWSCloudProvider" in provider.name:
  92. return TEST_DATA_CONFIG.get("AWSCloudProvider").get(key)
  93. elif "OpenStackCloudProvider" in provider.name:
  94. return TEST_DATA_CONFIG.get("OpenStackCloudProvider").get(key)
  95. return None
  96. def create_test_network(provider, name):
  97. """
  98. Create a network with one subnet, returning the network and subnet objects.
  99. """
  100. net = provider.networking.networks.create(name=name,
  101. cidr_block='10.0.0.0/16')
  102. cidr_block = (net.cidr_block).split('/')[0] or '10.0.0.1'
  103. sn = net.create_subnet(cidr_block='{0}/28'.format(cidr_block), name=name,
  104. zone=get_provider_test_data(provider, 'placement'))
  105. return net, sn
  106. def delete_test_network(network):
  107. """
  108. Delete the supplied network, first deleting any contained subnets.
  109. """
  110. with cleanup_action(lambda: network.delete()):
  111. for sn in network.subnets:
  112. sn.delete()
  113. def create_test_instance(
  114. provider, instance_name, subnet, launch_config=None,
  115. key_pair=None, vm_firewalls=None, user_data=None):
  116. kp = None
  117. if not key_pair:
  118. kp = provider.security.key_pairs.create(name=instance_name)
  119. instance = provider.compute.instances.create(
  120. instance_name,
  121. get_provider_test_data(provider, 'image'),
  122. get_provider_test_data(provider, 'vm_type'),
  123. subnet=subnet,
  124. zone=get_provider_test_data(provider, 'placement'),
  125. key_pair=key_pair or kp,
  126. vm_firewalls=vm_firewalls,
  127. launch_config=launch_config,
  128. user_data=user_data)
  129. if kp:
  130. kp.delete()
  131. return instance
  132. def get_test_instance(provider, name, key_pair=None, vm_firewalls=None,
  133. subnet=None, user_data=None):
  134. launch_config = None
  135. instance = create_test_instance(
  136. provider,
  137. name,
  138. subnet=subnet,
  139. key_pair=key_pair,
  140. vm_firewalls=vm_firewalls,
  141. launch_config=launch_config,
  142. user_data=user_data)
  143. instance.wait_till_ready()
  144. return instance
  145. def get_test_fixtures_folder():
  146. return os.path.join(os.path.dirname(__file__), '../fixtures/')
  147. def delete_test_instance(instance):
  148. if instance:
  149. instance.delete()
  150. instance.wait_for([InstanceState.DELETED, InstanceState.UNKNOWN],
  151. terminal_states=[InstanceState.ERROR])
  152. def cleanup_test_resources(instance=None, network=None, vm_firewall=None,
  153. key_pair=None):
  154. """Clean up any combination of supplied resources."""
  155. with cleanup_action(lambda: delete_test_network(network)
  156. if network else None):
  157. with cleanup_action(lambda: key_pair.delete() if key_pair else None):
  158. with cleanup_action(lambda: vm_firewall.delete()
  159. if vm_firewall else None):
  160. delete_test_instance(instance)
  161. def get_uuid():
  162. return str(uuid.uuid4())
  163. class ProviderTestBase(unittest.TestCase):
  164. _provider = None
  165. def setUp(self):
  166. if isinstance(self.provider, TestMockHelperMixin):
  167. self.provider.setUpMock()
  168. def tearDown(self):
  169. if isinstance(self.provider, TestMockHelperMixin):
  170. self.provider.tearDownMock()
  171. self._provider = None
  172. def get_provider_wait_interval(self, provider_class):
  173. if issubclass(provider_class, TestMockHelperMixin):
  174. return 0
  175. else:
  176. return 1
  177. def create_provider_instance(self):
  178. provider_name = os.environ.get("CB_TEST_PROVIDER", "azure")
  179. use_mock_drivers = parse_bool(
  180. os.environ.get("CB_USE_MOCK_PROVIDERS", "True"))
  181. factory = CloudProviderFactory()
  182. provider_class = factory.get_provider_class(provider_name,
  183. get_mock=use_mock_drivers)
  184. config = {
  185. 'default_wait_interval':
  186. self.get_provider_wait_interval(provider_class),
  187. 'default_result_limit': 1}
  188. return provider_class(config)
  189. @property
  190. def provider(self):
  191. if not self._provider:
  192. self._provider = self.create_provider_instance()
  193. return self._provider