services.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. """
  2. Services implemented by the AWS provider.
  3. """
  4. from boto.exception import EC2ResponseError
  5. from cloudbridge.providers.interfaces import BlockStoreService
  6. from cloudbridge.providers.interfaces import ComputeService
  7. from cloudbridge.providers.interfaces import ImageService
  8. from cloudbridge.providers.interfaces import InstanceType
  9. from cloudbridge.providers.interfaces import KeyPair
  10. from cloudbridge.providers.interfaces import KeyPairService
  11. from cloudbridge.providers.interfaces import MachineImage
  12. from cloudbridge.providers.interfaces import ObjectStoreService
  13. from cloudbridge.providers.interfaces import PlacementZone
  14. from cloudbridge.providers.interfaces import SecurityGroup
  15. from cloudbridge.providers.interfaces import SecurityGroupService
  16. from cloudbridge.providers.interfaces import SecurityService
  17. from cloudbridge.providers.interfaces import SnapshotService
  18. from cloudbridge.providers.interfaces import VolumeService
  19. from .resources import AWSContainer
  20. from .resources import AWSInstance
  21. from .resources import AWSKeyPair
  22. from .resources import AWSMachineImage
  23. from .resources import AWSSecurityGroup
  24. from .resources import AWSSnapshot
  25. from .resources import AWSVolume
  26. class AWSSecurityService(SecurityService):
  27. def __init__(self, provider):
  28. self.provider = provider
  29. # Initialize provider services
  30. self._key_pairs = AWSKeyPairService(provider)
  31. self._security_groups = AWSSecurityGroupService(provider)
  32. @property
  33. def key_pairs(self):
  34. """
  35. Provides access to key pairs for this provider.
  36. :rtype: ``object`` of :class:`.KeyPairService`
  37. :return: a KeyPairService object
  38. """
  39. return self._key_pairs
  40. @property
  41. def security_groups(self):
  42. """
  43. Provides access to security groups for this provider.
  44. :rtype: ``object`` of :class:`.SecurityGroupService`
  45. :return: a SecurityGroupService object
  46. """
  47. return self._security_groups
  48. class AWSKeyPairService(KeyPairService):
  49. def __init__(self, provider):
  50. self.provider = provider
  51. def list(self):
  52. """
  53. List all key pairs associated with this account.
  54. :rtype: ``list`` of :class:`.KeyPair`
  55. :return: list of KeyPair objects
  56. """
  57. key_pairs = self.provider.ec2_conn.get_all_key_pairs()
  58. return [AWSKeyPair(self.provider, kp) for kp in key_pairs]
  59. def create(self, key_name):
  60. """
  61. Create a new key pair.
  62. :type key_name: str
  63. :param key_name: The name of the key pair to be created.
  64. :rtype: ``object`` of :class:`.KeyPair`
  65. :return: A keypair instance or None if one was not be created.
  66. """
  67. kp = self.provider.ec2_conn.create_key_pair(key_name)
  68. if kp:
  69. return AWSKeyPair(self.provider, kp)
  70. return None
  71. def delete(self, key_name):
  72. """
  73. Delete an existing key pair.
  74. :type key_name: str
  75. :param key_name: The name of the key pair to be deleted.
  76. :rtype: ``bool``
  77. :return: ``True`` if the key does not exist, ``False`` otherwise. Note
  78. that this implies that the key may not have been deleted by
  79. this method but instead has not existed in the first place.
  80. """
  81. for kp in self.provider.ec2_conn.get_all_key_pairs():
  82. if kp.name == key_name:
  83. kp.delete()
  84. return True
  85. return True
  86. class AWSSecurityGroupService(SecurityGroupService):
  87. def __init__(self, provider):
  88. self.provider = provider
  89. def list(self):
  90. """
  91. List all security groups associated with this account.
  92. :rtype: ``list`` of :class:`.SecurityGroup`
  93. :return: list of SecurityGroup objects
  94. """
  95. security_groups = self.provider.ec2_conn.get_all_security_groups()
  96. return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
  97. def create(self, name, description):
  98. """
  99. Create a new SecurityGroup.
  100. :type name: str
  101. :param name: The name of the new security group.
  102. :type description: str
  103. :param description: The description of the new security group.
  104. :rtype: ``object`` of :class:`.SecurityGroup`
  105. :return: A SecurityGroup instance or ``None`` if one was not created.
  106. """
  107. sg = self.provider.ec2_conn.create_security_group(name, description)
  108. if sg:
  109. return AWSSecurityGroup(self.provider, sg)
  110. return None
  111. def get(self, group_names=None, group_ids=None):
  112. """
  113. Get all security groups associated with your account.
  114. :type group_names: list
  115. :param group_names: A list of the names of security groups to retrieve.
  116. If not provided, all security groups will be
  117. returned.
  118. :type group_ids: list
  119. :param group_ids: A list of IDs of security groups to retrieve.
  120. If not provided, all security groups will be
  121. returned.
  122. :rtype: list of :class:`SecurityGroup`
  123. :return: A list of SecurityGroup objects or an empty list if none
  124. found.
  125. """
  126. try:
  127. security_groups = self.provider.ec2_conn.get_all_security_groups(
  128. groupnames=group_names, group_ids=group_ids)
  129. except EC2ResponseError:
  130. security_groups = []
  131. return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
  132. def delete(self, group_id):
  133. """
  134. Delete an existing SecurityGroup.
  135. :type group_id: str
  136. :param group_id: The security group ID to be deleted.
  137. :rtype: ``bool``
  138. :return: ``True`` if the security group does not exist, ``False``
  139. otherwise. Note that this implies that the group may not have
  140. been deleted by this method but instead has not existed in
  141. the first place.
  142. """
  143. try:
  144. for sg in self.provider.ec2_conn.get_all_security_groups(
  145. group_ids=[group_id]):
  146. try:
  147. sg.delete()
  148. except EC2ResponseError:
  149. return False
  150. except EC2ResponseError:
  151. pass
  152. return True
  153. class AWSBlockStoreService(BlockStoreService):
  154. def __init__(self, provider):
  155. self.provider = provider
  156. # Initialize provider services
  157. self._volumes = AWSVolumeService(self.provider)
  158. self._snapshots = AWSSnapshotService(self.provider)
  159. @property
  160. def volumes(self):
  161. return self._volumes
  162. @property
  163. def snapshots(self):
  164. return self._snapshots
  165. class AWSVolumeService(VolumeService):
  166. def __init__(self, provider):
  167. self.provider = provider
  168. def get_volume(self, volume_id):
  169. """
  170. Returns a volume given its id.
  171. """
  172. vols = self.provider.ec2_conn.get_all_volumes(volume_ids=[volume_id])
  173. return AWSVolume(self.provider, vols[0]) if vols else None
  174. def find_volume(self, name):
  175. """
  176. Searches for a volume by a given list of attributes.
  177. """
  178. raise NotImplementedError(
  179. 'find_volume not implemented by this provider')
  180. def list_volumes(self):
  181. """
  182. List all volumes.
  183. """
  184. return [AWSVolume(self.provider, vol)
  185. for vol in self.provider.ec2_conn.get_all_volumes()]
  186. def create_volume(self, name, size, zone, snapshot=None):
  187. """
  188. Creates a new volume.
  189. """
  190. zone_name = zone.name if isinstance(zone, PlacementZone) else zone
  191. snapshot_id = snapshot.snapshot_id if isinstance(
  192. zone, AWSSnapshot) and snapshot else snapshot
  193. ec2_vol = self.provider.ec2_conn.create_volume(
  194. size,
  195. zone_name,
  196. snapshot=snapshot_id)
  197. cb_vol = AWSVolume(self.provider, ec2_vol)
  198. cb_vol.name = name
  199. return cb_vol
  200. class AWSObjectStoreService(ObjectStoreService):
  201. def __init__(self, provider):
  202. self.provider = provider
  203. def get_container(self, container_id):
  204. """
  205. Returns a container given its id. Returns None if the container
  206. does not exist.
  207. """
  208. bucket = self.provider.s3_conn.lookup(container_id)
  209. if bucket:
  210. return AWSContainer(self.provider, bucket)
  211. else:
  212. return None
  213. def find_container(self, name):
  214. """
  215. Searches for a container by a given list of attributes
  216. """
  217. raise NotImplementedError(
  218. 'find_container not implemented by this provider')
  219. def list_containers(self):
  220. """
  221. List all containers.
  222. """
  223. buckets = self.provider.s3_conn.get_all_buckets()
  224. return [AWSContainer(self.provider, bucket) for bucket in buckets]
  225. def create_container(self, name, location=None):
  226. """
  227. Create a new container.
  228. """
  229. bucket = self.provider.s3_conn.create_bucket(
  230. name,
  231. location=location if location else '')
  232. return AWSContainer(self.provider, bucket)
  233. class AWSSnapshotService(SnapshotService):
  234. def __init__(self, provider):
  235. self.provider = provider
  236. def get_snapshot(self, snapshot_id):
  237. """
  238. Returns a snapshot given its id.
  239. """
  240. snaps = self.provider.ec2_conn.get_all_snapshots(
  241. snapshot_ids=[snapshot_id])
  242. return AWSSnapshot(self.provider, snaps[0]) if snaps else None
  243. def find_snapshot(self, name):
  244. """
  245. Searches for a volume by a given list of attributes.
  246. """
  247. raise NotImplementedError(
  248. 'find_volume not implemented by this provider')
  249. def list_snapshots(self):
  250. """
  251. List all snapshot.
  252. """
  253. # TODO: get_all_images returns too many images - some kind of filtering
  254. # abilities are needed. Forced to "self" for now
  255. return [AWSSnapshot(self.provider, snap)
  256. for snap in
  257. self.provider.ec2_conn.get_all_snapshots(owner="self")]
  258. def create_snapshot(self, name, volume, description=None):
  259. """
  260. Creates a new snapshot of a given volume.
  261. """
  262. volume_id = volume.volume_id if isinstance(
  263. volume,
  264. AWSVolume) else volume
  265. ec2_snap = self.provider.ec2_conn.create_snapshot(
  266. volume_id,
  267. description=description)
  268. cb_snap = AWSSnapshot(self.provider, ec2_snap)
  269. cb_snap.name = name
  270. return cb_snap
  271. class AWSImageService(ImageService):
  272. def __init__(self, provider):
  273. self.provider = provider
  274. def get_image(self, image_id):
  275. """
  276. Returns an Image given its id
  277. """
  278. try:
  279. image = self.provider.ec2_conn.get_image(image_id)
  280. if image:
  281. return AWSMachineImage(self.provider, image)
  282. except EC2ResponseError:
  283. pass
  284. return None
  285. def find_image(self, name):
  286. """
  287. Searches for an image by a given list of attributes
  288. """
  289. raise NotImplementedError(
  290. 'find_image not implemented by this provider')
  291. def list_images(self):
  292. """
  293. List all images.
  294. """
  295. # TODO: get_all_images returns too many images - some kind of filtering
  296. # abilities are needed. Forced to "self" for now
  297. images = self.provider.ec2_conn.get_all_images(owners="self")
  298. return [AWSMachineImage(self.provider, image) for image in images]
  299. class AWSComputeService(ComputeService):
  300. def __init__(self, provider):
  301. self.provider = provider
  302. def create_instance(self, name, image, instance_type, zone=None,
  303. keypair=None, security_groups=None, user_data=None,
  304. block_device_mapping=None, network_interfaces=None,
  305. **kwargs):
  306. """
  307. Creates a new virtual machine instance.
  308. """
  309. image_id = image.image_id if isinstance(image, MachineImage) else image
  310. instance_size = instance_type.name if \
  311. isinstance(instance_type, InstanceType) else instance_type
  312. zone_name = zone.name if isinstance(zone, PlacementZone) else zone
  313. keypair_name = keypair.name if isinstance(
  314. keypair,
  315. KeyPair) else keypair
  316. if security_groups:
  317. if isinstance(security_groups, list) and \
  318. isinstance(security_groups[0], SecurityGroup):
  319. security_groups_list = [sg.name for sg in security_groups]
  320. else:
  321. security_groups_list = security_groups
  322. else:
  323. security_groups_list = None
  324. reservation = self.provider.ec2_conn.run_instances(
  325. image_id=image_id, instance_type=instance_size,
  326. min_count=1, max_count=1, placement=zone_name,
  327. key_name=keypair_name, security_groups=security_groups_list,
  328. user_data=user_data
  329. )
  330. if reservation:
  331. instance = AWSInstance(self.provider, reservation.instances[0])
  332. instance.name = name
  333. return instance
  334. def get_instance(self, instance_id):
  335. """
  336. Returns an instance given its id. Returns None
  337. if the object does not exist.
  338. """
  339. reservation = self.provider.ec2_conn.get_all_reservations(
  340. instance_ids=[instance_id])
  341. if reservation:
  342. return AWSInstance(self.provider, reservation.instances[0])
  343. def find_instance(self, name):
  344. """
  345. Searches for an instance by a given list of attributes.
  346. :rtype: ``object`` of :class:`.Instance`
  347. :return: an Instance object
  348. """
  349. raise NotImplementedError(
  350. 'find_instance not implemented by this provider')
  351. def list_instances(self):
  352. """
  353. List all instances.
  354. """
  355. reservations = self.provider.ec2_conn.get_all_reservations()
  356. return [AWSInstance(self.provider, inst)
  357. for res in reservations
  358. for inst in res.instances]