base.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. """
  2. Implementation of common methods across cloud providers.
  3. """
  4. import logging
  5. import time
  6. from cloudbridge.providers.interfaces import CloudProvider
  7. from cloudbridge.providers.interfaces import Instance
  8. from cloudbridge.providers.interfaces import InstanceState
  9. from cloudbridge.providers.interfaces import InstanceWaitException
  10. from cloudbridge.providers.interfaces import KeyPair
  11. from cloudbridge.providers.interfaces import MachineImage
  12. from cloudbridge.providers.interfaces import MachineImageState
  13. from cloudbridge.providers.interfaces import MachineImageWaitException
  14. from cloudbridge.providers.interfaces import SecurityGroup
  15. log = logging.getLogger(__name__)
  16. class BaseCloudProvider(CloudProvider):
  17. def __init__(self, config):
  18. self.config = config
  19. @property
  20. def name(self):
  21. return str(self.__class__.__name__)
  22. def has_service(self, service_type):
  23. """
  24. Checks whether this provider supports a given service.
  25. :type service_type: str or :class:``.CloudProviderServiceType``
  26. :param service_type: Type of service to check support for.
  27. :rtype: bool
  28. :return: ``True`` if the service type is supported.
  29. """
  30. try:
  31. if getattr(self, service_type):
  32. return True
  33. except AttributeError:
  34. pass # Undefined service type
  35. return False
  36. def _get_config_value(self, key, default_value):
  37. """
  38. A convenience method to extract a configuration value.
  39. :type key: str
  40. :param key: a field to look for in the ``self.config`` field
  41. :type default_value: anything
  42. : param default_value: the default value to return if a value for the
  43. ``key`` is not available
  44. :return: a configuration value for the supplied ``key``
  45. """
  46. if isinstance(self.config, dict):
  47. return self.config.get(key, default_value)
  48. else:
  49. return getattr(self.config, key) if hasattr(
  50. self.config, key) and getattr(self.config, key) else default_value
  51. class BaseInstance(Instance):
  52. @property
  53. def ready_states(self):
  54. return [InstanceState.RUNNING]
  55. @property
  56. def terminal_states(self):
  57. return [InstanceState.TERMINATED, InstanceState.ERROR]
  58. def wait_till_ready(self, timeout=600, interval=5):
  59. assert timeout > 0
  60. assert timeout > interval
  61. assert interval > 0
  62. for time_left in range(timeout, 0, -interval):
  63. state = self.instance_state
  64. if state in self.ready_states:
  65. return True
  66. elif state in self.terminal_states:
  67. raise InstanceWaitException(
  68. "Instance is in state: {0} which is a terminal state and cannot be waited on.".format(state))
  69. else:
  70. log.debug(
  71. "Instance is in state '{0}'. Waiting another {1} seconds to reach state a ready state...".format(
  72. state,
  73. time_left))
  74. time.sleep(interval)
  75. self.refresh()
  76. raise InstanceWaitException(
  77. "Waited too long for instance to become ready. Instance Id: %s is in state: %s".format(
  78. self.instance_id,
  79. self.name,
  80. self.instance_state))
  81. class BaseMachineImage(MachineImage):
  82. @property
  83. def ready_states(self):
  84. return [MachineImageState.AVAILABLE]
  85. @property
  86. def terminal_states(self):
  87. return [MachineImageState.ERROR]
  88. def wait_till_ready(self, timeout=600, interval=5):
  89. assert timeout > 0
  90. assert timeout > interval
  91. assert interval > 0
  92. for time_left in range(timeout, 0, -interval):
  93. state = self.image_state
  94. if state in self.ready_states:
  95. return True
  96. elif state in self.terminal_states:
  97. raise MachineImageWaitException(
  98. "Image is in state: {0} which is a terminal state and cannot be waited on.".format(state))
  99. else:
  100. log.debug(
  101. "Image is in state '{0}'. Waiting another {1} seconds to reach state a ready state...".format(
  102. state,
  103. time_left))
  104. time.sleep(interval)
  105. self.refresh()
  106. raise MachineImageWaitException(
  107. "Waited too long for image to become ready. Image Id: %s is still in state: %s".format(
  108. self.image_id,
  109. self.name,
  110. self.image_state))
  111. class BaseKeyPair(KeyPair):
  112. def __init__(self, name, material=None):
  113. self.name = name
  114. self.material = material
  115. def __repr__(self):
  116. return "<CBKeyPair: {0}>".format(self.name)
  117. class BaseSecurityGroup(SecurityGroup):
  118. def __init__(self, name):
  119. self.name = name
  120. def __repr__(self):
  121. return "<CBSecurityGroup: {0}>".format(self.name)