services.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. """
  2. Base implementation for services available through a provider
  3. """
  4. import logging
  5. from cloudbridge.cloud.interfaces.exceptions import InvalidParamException
  6. from cloudbridge.cloud.interfaces.resources import Network
  7. from cloudbridge.cloud.interfaces.services import BucketObjectService
  8. from cloudbridge.cloud.interfaces.services import BucketService
  9. from cloudbridge.cloud.interfaces.services import CloudService
  10. from cloudbridge.cloud.interfaces.services import ComputeService
  11. from cloudbridge.cloud.interfaces.services import FloatingIPService
  12. from cloudbridge.cloud.interfaces.services import GatewayService
  13. from cloudbridge.cloud.interfaces.services import ImageService
  14. from cloudbridge.cloud.interfaces.services import InstanceService
  15. from cloudbridge.cloud.interfaces.services import KeyPairService
  16. from cloudbridge.cloud.interfaces.services import NetworkService
  17. from cloudbridge.cloud.interfaces.services import NetworkingService
  18. from cloudbridge.cloud.interfaces.services import RegionService
  19. from cloudbridge.cloud.interfaces.services import RouterService
  20. from cloudbridge.cloud.interfaces.services import SecurityService
  21. from cloudbridge.cloud.interfaces.services import SnapshotService
  22. from cloudbridge.cloud.interfaces.services import StorageService
  23. from cloudbridge.cloud.interfaces.services import SubnetService
  24. from cloudbridge.cloud.interfaces.services import VMFirewallRuleService
  25. from cloudbridge.cloud.interfaces.services import VMFirewallService
  26. from cloudbridge.cloud.interfaces.services import VMTypeService
  27. from cloudbridge.cloud.interfaces.services import VolumeService
  28. from . import helpers as cb_helpers
  29. from .middleware import dispatch
  30. from .resources import BaseNetwork
  31. from .resources import BasePageableObjectMixin
  32. from .resources import BaseRouter
  33. from .resources import BaseSubnet
  34. from .resources import ClientPagedResultList
  35. log = logging.getLogger(__name__)
  36. class BaseCloudService(CloudService):
  37. STANDARD_EVENT_PRIORITY = 2500
  38. def __init__(self, provider):
  39. self._service_event_pattern = "provider"
  40. self._provider = provider
  41. # discover and register all middleware
  42. provider.middleware.add(self)
  43. @property
  44. def provider(self):
  45. return self._provider
  46. @property
  47. def events(self):
  48. return self._provider.events
  49. class BaseSecurityService(SecurityService, BaseCloudService):
  50. def __init__(self, provider):
  51. super(BaseSecurityService, self).__init__(provider)
  52. class BaseKeyPairService(
  53. BasePageableObjectMixin, KeyPairService, BaseCloudService):
  54. def __init__(self, provider):
  55. super(BaseKeyPairService, self).__init__(provider)
  56. self._service_event_pattern += ".security.key_pairs"
  57. class BaseVMFirewallService(
  58. BasePageableObjectMixin, VMFirewallService, BaseCloudService):
  59. def __init__(self, provider):
  60. super(BaseVMFirewallService, self).__init__(provider)
  61. self._service_event_pattern += ".security.vm_firewalls"
  62. @dispatch(event="provider.security.vm_firewalls.find",
  63. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  64. def find(self, **kwargs):
  65. obj_list = self
  66. filters = ['label']
  67. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  68. # All kwargs should have been popped at this time.
  69. if len(kwargs) > 0:
  70. raise InvalidParamException(
  71. "Unrecognised parameters for search: %s. Supported "
  72. "attributes: %s" % (kwargs, ", ".join(filters)))
  73. return ClientPagedResultList(self.provider,
  74. matches if matches else [])
  75. class BaseVMFirewallRuleService(BasePageableObjectMixin,
  76. VMFirewallRuleService,
  77. BaseCloudService):
  78. def __init__(self, provider):
  79. super(BaseVMFirewallRuleService, self).__init__(provider)
  80. self._provider = provider
  81. @property
  82. def provider(self):
  83. return self._provider
  84. @dispatch(event="provider.security.vm_firewall_rules.get",
  85. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  86. def get(self, firewall, rule_id):
  87. matches = [rule for rule in firewall.rules if rule.id == rule_id]
  88. if matches:
  89. return matches[0]
  90. else:
  91. return None
  92. @dispatch(event="provider.security.vm_firewall_rules.find",
  93. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  94. def find(self, firewall, **kwargs):
  95. obj_list = firewall.rules
  96. filters = ['name', 'direction', 'protocol', 'from_port', 'to_port',
  97. 'cidr', 'src_dest_fw', 'src_dest_fw_id']
  98. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  99. return ClientPagedResultList(self._provider, list(matches))
  100. class BaseStorageService(StorageService, BaseCloudService):
  101. def __init__(self, provider):
  102. super(BaseStorageService, self).__init__(provider)
  103. class BaseVolumeService(
  104. BasePageableObjectMixin, VolumeService, BaseCloudService):
  105. def __init__(self, provider):
  106. super(BaseVolumeService, self).__init__(provider)
  107. self._service_event_pattern += ".storage.volumes"
  108. class BaseSnapshotService(
  109. BasePageableObjectMixin, SnapshotService, BaseCloudService):
  110. def __init__(self, provider):
  111. super(BaseSnapshotService, self).__init__(provider)
  112. self._service_event_pattern += ".storage.snapshots"
  113. class BaseBucketService(
  114. BasePageableObjectMixin, BucketService, BaseCloudService):
  115. def __init__(self, provider):
  116. super(BaseBucketService, self).__init__(provider)
  117. self._service_event_pattern += ".storage.buckets"
  118. # Generic find will be used for providers where we have not implemented
  119. # provider-specific querying for find method
  120. @dispatch(event="provider.storage.buckets.find",
  121. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  122. def find(self, **kwargs):
  123. obj_list = self
  124. filters = ['name']
  125. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  126. # All kwargs should have been popped at this time.
  127. if len(kwargs) > 0:
  128. raise InvalidParamException(
  129. "Unrecognised parameters for search: %s. Supported "
  130. "attributes: %s" % (kwargs, ", ".join(filters)))
  131. return ClientPagedResultList(self.provider,
  132. matches if matches else [])
  133. class BaseBucketObjectService(BucketObjectService, BaseCloudService):
  134. def __init__(self, provider):
  135. super(BaseBucketObjectService, self).__init__(provider)
  136. self._service_event_pattern += ".storage._bucket_objects"
  137. self._bucket = None
  138. class BaseComputeService(ComputeService, BaseCloudService):
  139. def __init__(self, provider):
  140. super(BaseComputeService, self).__init__(provider)
  141. class BaseImageService(
  142. BasePageableObjectMixin, ImageService, BaseCloudService):
  143. def __init__(self, provider):
  144. super(BaseImageService, self).__init__(provider)
  145. self._service_event_pattern += ".compute.images"
  146. class BaseInstanceService(
  147. BasePageableObjectMixin, InstanceService, BaseCloudService):
  148. def __init__(self, provider):
  149. super(BaseInstanceService, self).__init__(provider)
  150. self._service_event_pattern += ".compute.instances"
  151. class BaseVMTypeService(
  152. BasePageableObjectMixin, VMTypeService, BaseCloudService):
  153. def __init__(self, provider):
  154. super(BaseVMTypeService, self).__init__(provider)
  155. self._service_event_pattern += ".compute.vm_types"
  156. @dispatch(event="provider.compute.vm_types.get",
  157. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  158. def get(self, vm_type_id):
  159. vm_type = (t for t in self if t.id == vm_type_id)
  160. return next(vm_type, None)
  161. @dispatch(event="provider.compute.vm_types.find",
  162. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  163. def find(self, **kwargs):
  164. obj_list = self
  165. filters = ['name']
  166. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  167. return ClientPagedResultList(self._provider, list(matches))
  168. class BaseRegionService(
  169. BasePageableObjectMixin, RegionService, BaseCloudService):
  170. def __init__(self, provider):
  171. super(BaseRegionService, self).__init__(provider)
  172. self._service_event_pattern += ".compute.regions"
  173. @dispatch(event="provider.compute.regions.find",
  174. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  175. def find(self, **kwargs):
  176. obj_list = self
  177. filters = ['name']
  178. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  179. return ClientPagedResultList(self._provider, list(matches))
  180. class BaseNetworkingService(NetworkingService, BaseCloudService):
  181. def __init__(self, provider):
  182. super(BaseNetworkingService, self).__init__(provider)
  183. class BaseNetworkService(
  184. BasePageableObjectMixin, NetworkService, BaseCloudService):
  185. def __init__(self, provider):
  186. super(BaseNetworkService, self).__init__(provider)
  187. self._service_event_pattern += ".networking.networks"
  188. @property
  189. def subnets(self):
  190. return [subnet for subnet in self.provider.subnets
  191. if subnet.network_id == self.id]
  192. def get_or_create_default(self):
  193. networks = self.provider.networking.networks.find(
  194. label=BaseNetwork.CB_DEFAULT_NETWORK_LABEL)
  195. if networks:
  196. return networks[0]
  197. else:
  198. log.info("Creating a CloudBridge-default network labeled %s",
  199. BaseNetwork.CB_DEFAULT_NETWORK_LABEL)
  200. return self.provider.networking.networks.create(
  201. BaseNetwork.CB_DEFAULT_NETWORK_LABEL, '10.0.0.0/16')
  202. @dispatch(event="provider.networking.networks.find",
  203. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  204. def find(self, **kwargs):
  205. obj_list = self
  206. filters = ['label']
  207. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  208. # All kwargs should have been popped at this time.
  209. if len(kwargs) > 0:
  210. raise TypeError("Unrecognised parameters for search: %s."
  211. " Supported attributes: %s" % (kwargs,
  212. ", ".join(filters)))
  213. return ClientPagedResultList(self.provider,
  214. matches if matches else [])
  215. class BaseSubnetService(
  216. BasePageableObjectMixin, SubnetService, BaseCloudService):
  217. def __init__(self, provider):
  218. super(BaseSubnetService, self).__init__(provider)
  219. self._service_event_pattern += ".networking.subnets"
  220. @dispatch(event="provider.networking.subnets.find",
  221. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  222. def find(self, network=None, **kwargs):
  223. if not network:
  224. obj_list = self
  225. else:
  226. obj_list = network.subnets
  227. filters = ['label']
  228. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  229. return ClientPagedResultList(self._provider, list(matches))
  230. def get_or_create_default(self, zone):
  231. # Look for a CB-default subnet
  232. matches = self.find(label=BaseSubnet.CB_DEFAULT_SUBNET_LABEL)
  233. if matches:
  234. return matches[0]
  235. # No provider-default Subnet exists, try to create it (net + subnets)
  236. network = self.provider.networking.networks.get_or_create_default()
  237. subnet = self.create(BaseSubnet.CB_DEFAULT_SUBNET_LABEL, network,
  238. BaseSubnet.CB_DEFAULT_SUBNET_IPV4RANGE, zone)
  239. return subnet
  240. class BaseRouterService(
  241. BasePageableObjectMixin, RouterService, BaseCloudService):
  242. def __init__(self, provider):
  243. super(BaseRouterService, self).__init__(provider)
  244. self._service_event_pattern += ".networking.routers"
  245. def get_or_create_default(self, network):
  246. net_id = network.id if isinstance(network, Network) else network
  247. routers = self.provider.networking.routers.find(
  248. label=BaseRouter.CB_DEFAULT_ROUTER_LABEL)
  249. for router in routers:
  250. if router.network_id == net_id:
  251. return router
  252. else:
  253. return self.provider.networking.routers.create(
  254. network=net_id, label=BaseRouter.CB_DEFAULT_ROUTER_LABEL)
  255. class BaseGatewayService(GatewayService, BaseCloudService):
  256. def __init__(self, provider):
  257. super(BaseGatewayService, self).__init__(provider)
  258. self._provider = provider
  259. @property
  260. def provider(self):
  261. return self._provider
  262. class BaseFloatingIPService(FloatingIPService, BaseCloudService):
  263. def __init__(self, provider):
  264. super(BaseFloatingIPService, self).__init__(provider)
  265. self._provider = provider
  266. @property
  267. def provider(self):
  268. return self._provider
  269. @dispatch(event="provider.networking.floating_ips.find",
  270. priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  271. def find(self, gateway, **kwargs):
  272. obj_list = gateway.floating_ips
  273. filters = ['name', 'public_ip']
  274. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  275. return ClientPagedResultList(self._provider, list(matches))