resources.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. """
  2. Specifications for data objects exposed through a provider or service
  3. """
  4. class CloudProviderServiceType(object):
  5. """
  6. Defines possible service types that are offered by providers.
  7. Providers can implement the ``has_service`` method and clients can check
  8. for the availability of a service with::
  9. if (provider.has_service(CloudProviderServiceTypes.OBJECTSTORE))
  10. ...
  11. """
  12. COMPUTE = 'compute'
  13. IMAGE = 'image'
  14. SECURITY = 'security'
  15. VOLUME = 'volume'
  16. BLOCKSTORE = 'block_store'
  17. OBJECTSTORE = 'object_store'
  18. class WaitStateException(Exception):
  19. """
  20. Marker interface for object wait exceptions.
  21. Thrown when a timeout or errors occurs waiting for an object does not reach
  22. the expected state within a specified time limit.
  23. """
  24. pass
  25. class ObjectLifeCycleMixin(object):
  26. """
  27. A mixin for an object with a defined life-cycle, such as an Instance,
  28. Volume, Image or Snapshot. An object that supports ObjectLifeCycleMixin
  29. will always have a state, defining which point in its lifecycle it is
  30. currently at.
  31. It also defines a wait_till_ready operation, which indicates that the
  32. object is in a state in its lifecycle where it is ready to be used by an
  33. end-user.
  34. A refresh operation allows the object to synchronise its state with the
  35. service provider.
  36. """
  37. @property
  38. def state(self):
  39. """
  40. Get the current state of this object.
  41. :rtype: ``str``
  42. :return: The current state as a string
  43. """
  44. raise NotImplementedError(
  45. 'LifeCycleObject.state not implemented by this service')
  46. def refresh(self):
  47. """
  48. Refreshs this object's state and synchronize it with the underlying
  49. service provider.
  50. """
  51. raise NotImplementedError(
  52. 'LifeCycleObject.refresh not implemented by this service')
  53. def wait_till_ready(self, timeout, interval):
  54. """
  55. Wait till the current object is in a ready state, which is any
  56. state where the end-user can successfully interact with the object.
  57. Will throw a WaitStateException if the object is not ready within
  58. the specified timeout.
  59. :type timeout: int
  60. :param timeout: The maximum length of time (in seconds) to wait for the
  61. object to become ready.
  62. :type interval: int
  63. :param interval: How frequently to poll the object's ready state (in
  64. seconds)
  65. :rtype: ``True``
  66. :return: Returns True if successful. A WaitStateException exception may
  67. be thrown by the underlying service if the object cannot get into a
  68. ready state (e.g. If the object is in an error state)
  69. """
  70. raise NotImplementedError(
  71. 'LifeCycleObject.wait_till_ready not implemented by this service')
  72. class InstanceState(object):
  73. """
  74. Standard states for a node
  75. :cvar UNKNOWN: Instance state unknown.
  76. :cvar PENDING: Instance is pending
  77. :cvar CONFIGURING: Instance is being reconfigured in some way.
  78. :cvar RUNNING: Instance is running.
  79. :cvar REBOOTING: Instance is rebooting.
  80. :cvar TERMINATED: Instance is terminated. No further operations possible.
  81. :cvar STOPPED: Instance is stopped. Instance can be resumed.
  82. :cvar ERROR: Instance is in an error state. No further operations possible.
  83. """
  84. UNKNOWN = "unknown"
  85. PENDING = "pending"
  86. CONFIGURING = "configuring"
  87. RUNNING = "running"
  88. REBOOTING = "rebooting"
  89. TERMINATED = "terminated"
  90. STOPPED = "stopped"
  91. ERROR = "error"
  92. class Instance(ObjectLifeCycleMixin):
  93. @property
  94. def instance_id(self):
  95. """
  96. Get the instance identifier.
  97. :rtype: str
  98. :return: ID for this instance as returned by the cloud middleware.
  99. """
  100. raise NotImplementedError(
  101. 'Instance.instance_id not implemented by this provider')
  102. @property
  103. def name(self):
  104. """
  105. Get the instance name.
  106. :rtype: str
  107. :return: Name for this instance as returned by the cloud middleware.
  108. """
  109. raise NotImplementedError(
  110. 'Instance.name not implemented by this provider')
  111. @property
  112. def public_ips(self):
  113. """
  114. Get all the public IP addresses for this instance.
  115. :rtype: list
  116. :return: A list of public IP addresses associated with this instance.
  117. """
  118. raise NotImplementedError(
  119. 'Instance.public_ips not implemented by this provider')
  120. @property
  121. def private_ips(self):
  122. """
  123. Get all the private IP addresses for this instance.
  124. :rtype: list
  125. :return: A list of private IP addresses associated with this instance.
  126. """
  127. raise NotImplementedError(
  128. 'Instance.private_ips not implemented by this provider')
  129. @property
  130. def instance_type(self):
  131. """
  132. Get the instance type.
  133. :rtype: str
  134. :return: API type of this instance (e.g., ``m1.large``)
  135. """
  136. raise NotImplementedError(
  137. 'Instance.instance_type not implemented by this provider')
  138. def reboot(self):
  139. """
  140. Reboot this instance (using the cloud middleware API).
  141. :rtype: bool
  142. :return: ``True`` if the reboot was succesful; ``False`` otherwise.
  143. """
  144. raise NotImplementedError(
  145. 'Instance.reboot not implemented by this provider')
  146. def terminate(self):
  147. """
  148. Permanently terminate this instance.
  149. :rtype: bool
  150. :return: ``True`` if the termination of the instance was succesfully
  151. initiated; ``False`` otherwise.
  152. """
  153. raise NotImplementedError(
  154. 'Instance.terminate not implemented by this provider')
  155. @property
  156. def image_id(self):
  157. """
  158. Get the image ID for this insance.
  159. :rtype: str
  160. :return: Image ID (i.e., AMI) this instance is using.
  161. """
  162. raise NotImplementedError(
  163. 'Instance.image_id not implemented by this provider')
  164. @property
  165. def placement_zone(self):
  166. """
  167. Get the placement zone where this instance is running.
  168. :rtype: str
  169. :return: Region/zone/placement where this instance is running.
  170. """
  171. raise NotImplementedError(
  172. 'Instance.placement not implemented by this provider')
  173. @property
  174. def mac_address(self):
  175. """
  176. Get the MAC address for this instance.
  177. :rtype: str
  178. :return: MAC address for ths instance.
  179. """
  180. raise NotImplementedError(
  181. 'Instance.mac_address not implemented by this provider')
  182. @property
  183. def security_group_ids(self):
  184. """
  185. Get the security group IDs associated with this instance.
  186. :rtype: list
  187. :return: A list of security group IDs associated with this instance.
  188. """
  189. raise NotImplementedError(
  190. 'Instance.security_group_ids not implemented by this provider')
  191. @property
  192. def key_pair_name(self):
  193. """
  194. Get the name of the key pair associated with this instance.
  195. :rtype: str
  196. :return: Name of the ssh key pair associated with this instance.
  197. """
  198. raise NotImplementedError(
  199. 'Instance.key_pair_name not implemented by this provider')
  200. def create_image(self, name):
  201. """
  202. Create a new image based on this instance.
  203. :return: an Image object
  204. :rtype: ``object`` of :class:`.Image`
  205. """
  206. raise NotImplementedError(
  207. 'Instance.create_image not implemented by this provider')
  208. class MachineImageState(object):
  209. """
  210. Standard states for a machine image
  211. :cvar UNKNOWN: Image state unknown.
  212. :cvar PENDING: Image is pending
  213. :cvar AVAILABLE: Image is available
  214. :cvar ERROR: Image is in an error state. Not recoverable.
  215. """
  216. UNKNOWN = "unknown"
  217. PENDING = "pending"
  218. AVAILABLE = "available"
  219. ERROR = "error"
  220. class MachineImage(ObjectLifeCycleMixin):
  221. @property
  222. def image_id(self):
  223. """
  224. Get the image identifier.
  225. :rtype: ``str``
  226. :return: ID for this instance as returned by the cloud middleware.
  227. """
  228. raise NotImplementedError(
  229. 'MachineImage.image_id not implemented by this provider')
  230. @property
  231. def name(self):
  232. """
  233. Get the image name.
  234. :rtype: ``str``
  235. :return: Name for this image as returned by the cloud middleware.
  236. """
  237. raise NotImplementedError(
  238. 'MachineImage.name not implemented by this provider')
  239. @property
  240. def description(self):
  241. """
  242. Get the image description.
  243. :rtype: ``str``
  244. :return: Description for this image as returned by the cloud middleware
  245. """
  246. raise NotImplementedError(
  247. 'MachineImage.description not implemented by this provider')
  248. def delete(self):
  249. """
  250. Delete this image
  251. :rtype: ``bool``
  252. :return: True if the operation succeeded
  253. """
  254. raise NotImplementedError(
  255. 'MachineImage.delete not implemented by this provider')
  256. class VolumeState(object):
  257. """
  258. Standard states for a volume
  259. :cvar UNKNOWN: Volume state unknown.
  260. :cvar CREATING: Volume is being created.
  261. :cvar CONFIGURING: Volume is being configured in some way.
  262. :cvar AVAILABLE: Volume is available and can be attached to an instance.
  263. :cvar IN_USE: Volume is attached and in-use.
  264. :cvar DELETED: Volume has been deleted. No further operations possible.
  265. :cvar ERROR: Volume is in an error state. No further operations possible.
  266. """
  267. UNKNOWN = "unknown"
  268. CREATING = "creating"
  269. CONFIGURING = "configuring"
  270. AVAILABLE = "available"
  271. IN_USE = "in-use"
  272. DELETED = "deleted"
  273. ERROR = "error"
  274. class Volume(ObjectLifeCycleMixin):
  275. @property
  276. def volume_id(self):
  277. """
  278. Get the volume identifier.
  279. :rtype: ``str``
  280. :return: ID for this instance as returned by the cloud middleware.
  281. """
  282. raise NotImplementedError(
  283. 'Volume.volume_id not implemented by this provider')
  284. @property
  285. def name(self):
  286. """
  287. Get the volume name.
  288. :rtype: ``str``
  289. :return: Name for this volume as returned by the cloud middleware.
  290. """
  291. raise NotImplementedError(
  292. 'Volume.name not implemented by this provider')
  293. def attach(self, instance_id, device):
  294. """
  295. Attach this volume to an instance.
  296. :type instance_id: str
  297. :param instance_id: The ID of the instance to which it will
  298. be attached.
  299. :type device: str
  300. :param device: The device on the instance through which the
  301. volume will be exposed (e.g. /dev/sdh)
  302. :rtype: bool
  303. :return: True if successful
  304. """
  305. raise NotImplementedError(
  306. 'Volume.attach not implemented by this provider')
  307. def detach(self, force=False):
  308. """
  309. Detach this volume from an instance.
  310. :type force: bool
  311. :param force: Forces detachment if the previous detachment
  312. attempt did not occur cleanly. This option is supported on select
  313. clouds only. This option can lead to data loss or a corrupted file
  314. system. Use this option only as a last resort to detach a volume
  315. from a failed instance. The instance will not have an opportunity
  316. to flush file system caches nor file system meta data. If you
  317. use this option, you must perform file system check and
  318. repair procedures.
  319. :rtype: bool
  320. :return: True if successful
  321. """
  322. raise NotImplementedError(
  323. 'Volume.detach not implemented by this provider')
  324. def create_snapshot(self, description=None):
  325. """
  326. Create a snapshot of this Volume.
  327. :type description: str
  328. :param description: A description of the snapshot.
  329. Limited to 256 characters.
  330. :rtype: :class:`.Snapshot`
  331. :return: The created Snapshot object
  332. """
  333. raise NotImplementedError(
  334. 'Volume.snapshot not implemented by this provider')
  335. def delete(self):
  336. """
  337. Delete this volume.
  338. :rtype: bool
  339. :return: True if successful
  340. """
  341. raise NotImplementedError(
  342. 'Volume.delete not implemented by this provider')
  343. class SnapshotState(object):
  344. """
  345. Standard states for a snapshot
  346. :cvar UNKNOWN: Snapshot state unknown.
  347. :cvar PENDING: Snapshot is pending.
  348. :cvar CONFIGURING: Snapshot is being configured in some way.
  349. :cvar AVAILABLE: Snapshot has been completed and is ready for use.
  350. :cvar ERROR: Snapshot is in an error state. No further operations possible.
  351. """
  352. UNKNOWN = "unknown"
  353. PENDING = "pending"
  354. CONFIGURING = "configuring"
  355. AVAILABLE = "available"
  356. ERROR = "error"
  357. class Snapshot(ObjectLifeCycleMixin):
  358. def create_volume(self, placement, size=None, volume_type=None, iops=None):
  359. """
  360. Create a new Volume from this Snapshot.
  361. :type zone: str
  362. :param zone: The availability zone in which the Volume will be created.
  363. :type size: int
  364. :param size: The size of the new volume, in GiB (optional). Defaults to
  365. the size of the snapshot.
  366. :type volume_type: str
  367. :param volume_type: The type of the volume (optional). Availability and
  368. valid values depend on the provider.
  369. :type iops: int
  370. :param iops: The provisioned IOPs you want to associate with
  371. this volume (optional). Availability depends on the
  372. provider.
  373. :rtype: :class:`.Volume`
  374. :return: An instance of the created Volume
  375. """
  376. raise NotImplementedError(
  377. 'create_volume not implemented by this provider')
  378. def share(self, user_ids=None):
  379. """
  380. Share this Snapshot.
  381. :type user_ids: list of strings
  382. :param user_ids: A list of cloud provider compatible user IDs. If no
  383. IDs are specified, the snapshot is made public.
  384. :rtype: bool
  385. :return: True if successful
  386. """
  387. raise NotImplementedError('share not implemented by this provider')
  388. def unshare(self, user_ids=None):
  389. """
  390. Unshare this Snapshot.
  391. :type user_ids: list of strings
  392. :param user_ids: A list of cloud provider compatible user IDs. If no
  393. IDs are specified, the snapshot is made private.
  394. :rtype: bool
  395. :return: True if successful
  396. """
  397. raise NotImplementedError('unshare not implemented by this provider')
  398. def delete(self):
  399. """
  400. Delete this snapshot.
  401. :rtype: bool
  402. :return: True if successful
  403. """
  404. raise NotImplementedError('delete not implemented by this provider')
  405. class KeyPair(object):
  406. @property
  407. def name(self):
  408. """
  409. Return the name of this key pair.
  410. :rtype: str
  411. :return: A name of this ssh key pair
  412. """
  413. raise NotImplementedError(
  414. 'name not implemented by this provider')
  415. @property
  416. def material(self):
  417. """
  418. Unencrypted private key.
  419. :rtype: str
  420. :return: Unencrypted private key.
  421. """
  422. raise NotImplementedError(
  423. 'material not implemented by this provider')
  424. def delete(self):
  425. """
  426. Delete this key pair.
  427. :rtype: bool
  428. :return: ``True`` is successful.
  429. """
  430. raise NotImplementedError(
  431. 'delete not implemented by this provider')
  432. class Region(object):
  433. """
  434. Represents a cloud region, typically a separate geographic area and will
  435. contain at least one placement zone.
  436. """
  437. @property
  438. def name(self):
  439. """
  440. Name of the region.
  441. :rtype: str
  442. :return: Name of the region.
  443. """
  444. raise NotImplementedError(
  445. 'name not implemented by this provider')
  446. def list_zones(self):
  447. """
  448. List all available placement zones within this region.
  449. :rtype: list
  450. :return: List of all the available placement zones.
  451. """
  452. raise NotImplementedError(
  453. 'list_zones not implemented by this provider')
  454. class PlacementZone(object):
  455. """
  456. Represents a placement zone. A placement zone is contained within a Region.
  457. """
  458. @property
  459. def name(self):
  460. """
  461. Name of the placement zone.
  462. :rtype: str
  463. :return: Name of the placement zone.
  464. """
  465. raise NotImplementedError(
  466. 'PlacementZone.name not implemented by this provider')
  467. @property
  468. def region(self):
  469. """
  470. A region this placement zone is associated with.
  471. :rtype: str
  472. :return: The name of the region the zone is associated with.
  473. """
  474. raise NotImplementedError(
  475. 'region_name not implemented by this provider')
  476. class InstanceType(object):
  477. """
  478. An instance type object.
  479. """
  480. @property
  481. def id(self):
  482. raise NotImplementedError(
  483. 'InstanceType.id not implemented by this provider')
  484. @property
  485. def name(self):
  486. raise NotImplementedError(
  487. 'InstanceType.name not implemented by this provider')
  488. class SecurityGroup(object):
  489. @property
  490. def name(self):
  491. """
  492. Return the name of this security group.
  493. :rtype: str
  494. :return: A name of this security group.
  495. """
  496. raise NotImplementedError(
  497. 'name not implemented by this provider')
  498. @property
  499. def description(self):
  500. """
  501. Return the description of this security group.
  502. :rtype: str
  503. :return: A description of this security group.
  504. """
  505. raise NotImplementedError(
  506. 'description not implemented by this provider')
  507. @property
  508. def id(self):
  509. """
  510. Get the ID of this security group.
  511. :rtype: str
  512. :return: Security group ID
  513. """
  514. raise NotImplementedError(
  515. 'id not implemented by this provider')
  516. def delete(self):
  517. """
  518. Delete this security group.
  519. :rtype: bool
  520. :return: ``True`` is successful.
  521. """
  522. raise NotImplementedError(
  523. 'delete not implemented by this provider')
  524. def add_rule(self, ip_protocol=None, from_port=None, to_port=None,
  525. cidr_ip=None, group_id=None):
  526. """
  527. Create a security group rule
  528. :type ip_protocol: str
  529. :param ip_protocol: Either ``tcp`` | ``udp`` | ``icmp``
  530. :type from_port: int
  531. :param from_port: The beginning port number you are enabling
  532. :type to_port: int
  533. :param to_port: The ending port number you are enabling
  534. :type cidr_ip: str or list of strings
  535. :param cidr_ip: The CIDR block you are providing access to.
  536. :type group_id: ``object`` of :class:`.SecurityGroup`
  537. :param group_id: The Security Group you are granting access to.
  538. :rtype: bool
  539. :return: True if successful.
  540. """
  541. raise NotImplementedError(
  542. 'add_rule not implemented by this provider')