test_block_store_service.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import time
  2. import uuid
  3. from test import helpers
  4. from test.helpers import ProviderTestBase
  5. from test.helpers import standard_interface_tests as sit
  6. from cloudbridge.cloud.interfaces import SnapshotState
  7. from cloudbridge.cloud.interfaces import VolumeState
  8. from cloudbridge.cloud.interfaces.resources import AttachmentInfo
  9. import six
  10. class CloudBlockStoreServiceTestCase(ProviderTestBase):
  11. @helpers.skipIfNoService(['block_store.volumes'])
  12. def test_crud_volume(self):
  13. """
  14. Create a new volume, check whether the expected values are set,
  15. and delete it
  16. """
  17. name = "CBUnitTestCreateVol-{0}".format(uuid.uuid4())
  18. test_vol = self.provider.block_store.volumes.create(
  19. name,
  20. 1,
  21. helpers.get_provider_test_data(self.provider, "placement"))
  22. def cleanup_vol(vol):
  23. vol.delete()
  24. vol.wait_for([VolumeState.DELETED, VolumeState.UNKNOWN],
  25. terminal_states=[VolumeState.ERROR])
  26. with helpers.cleanup_action(lambda: cleanup_vol(test_vol)):
  27. test_vol.wait_till_ready()
  28. sit.check_standard_behaviour(
  29. self, self.provider.block_store.volumes, test_vol)
  30. sit.check_delete(self, self.provider.block_store.volumes, test_vol)
  31. @helpers.skipIfNoService(['block_store.volumes'])
  32. def test_attach_detach_volume(self):
  33. """
  34. Create a new volume, and attempt to attach it to an instance
  35. """
  36. instance_name = "CBVolOps-{0}-{1}".format(
  37. self.provider.name,
  38. uuid.uuid4())
  39. # Declare these variables and late binding will allow
  40. # the cleanup method access to the most current values
  41. net = None
  42. test_instance = None
  43. with helpers.cleanup_action(lambda: helpers.cleanup_test_resources(
  44. test_instance, net)):
  45. net, subnet = helpers.create_test_network(
  46. self.provider, instance_name)
  47. test_instance = helpers.get_test_instance(
  48. self.provider, instance_name, subnet=subnet)
  49. name = "CBUnitTestAttachVol-{0}".format(uuid.uuid4())
  50. test_vol = self.provider.block_store.volumes.create(
  51. name, 1, test_instance.zone_id)
  52. with helpers.cleanup_action(lambda: test_vol.delete()):
  53. test_vol.wait_till_ready()
  54. test_vol.attach(test_instance, '/dev/sda2')
  55. test_vol.wait_for(
  56. [VolumeState.IN_USE],
  57. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  58. test_vol.detach()
  59. test_vol.wait_for(
  60. [VolumeState.AVAILABLE],
  61. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  62. @helpers.skipIfNoService(['block_store.volumes'])
  63. def test_volume_properties(self):
  64. """
  65. Test volume properties
  66. """
  67. instance_name = "CBVolProps-{0}-{1}".format(
  68. self.provider.name,
  69. uuid.uuid4())
  70. vol_desc = 'newvoldesc1'
  71. # Declare these variables and late binding will allow
  72. # the cleanup method access to the most current values
  73. test_instance = None
  74. net = None
  75. with helpers.cleanup_action(lambda: helpers.cleanup_test_resources(
  76. test_instance, net)):
  77. net, subnet = helpers.create_test_network(
  78. self.provider, instance_name)
  79. test_instance = helpers.get_test_instance(
  80. self.provider, instance_name, subnet=subnet)
  81. name = "CBUnitTestVolProps-{0}".format(uuid.uuid4())
  82. test_vol = self.provider.block_store.volumes.create(
  83. name, 1, test_instance.zone_id, description=vol_desc)
  84. with helpers.cleanup_action(lambda: test_vol.delete()):
  85. test_vol.wait_till_ready()
  86. self.assertTrue(
  87. isinstance(test_vol.size, six.integer_types) and
  88. test_vol.size >= 0,
  89. "Volume.size must be a positive number, but got %s"
  90. % test_vol.size)
  91. self.assertTrue(
  92. test_vol.description is None or
  93. isinstance(test_vol.description, six.string_types),
  94. "Volume.description must be None or a string. Got: %s"
  95. % test_vol.description)
  96. self.assertIsNone(test_vol.source)
  97. self.assertIsNone(test_vol.source)
  98. self.assertIsNotNone(test_vol.create_time)
  99. self.assertIsNotNone(test_vol.zone_id)
  100. self.assertIsNone(test_vol.attachments)
  101. test_vol.attach(test_instance, '/dev/sda2')
  102. test_vol.wait_for(
  103. [VolumeState.IN_USE],
  104. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  105. self.assertIsNotNone(test_vol.attachments)
  106. self.assertIsInstance(test_vol.attachments, AttachmentInfo)
  107. self.assertEqual(test_vol.attachments.volume, test_vol)
  108. self.assertEqual(test_vol.attachments.instance_id,
  109. test_instance.id)
  110. self.assertEqual(test_vol.attachments.device,
  111. "/dev/sda2")
  112. test_vol.detach()
  113. test_vol.name = 'newvolname1'
  114. test_vol.wait_for(
  115. [VolumeState.AVAILABLE],
  116. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  117. self.assertEqual(test_vol.name, 'newvolname1')
  118. self.assertEqual(test_vol.description, vol_desc)
  119. self.assertIsNone(test_vol.attachments)
  120. test_vol.wait_for(
  121. [VolumeState.AVAILABLE],
  122. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  123. @helpers.skipIfNoService(['block_store.snapshots'])
  124. def test_crud_snapshot(self):
  125. """
  126. Create a new volume, create a snapshot of the volume, and check
  127. whether list_snapshots properly detects the new snapshot.
  128. Delete everything afterwards.
  129. """
  130. name = "CBUnitTestCreateSnap-{0}".format(uuid.uuid4())
  131. test_vol = self.provider.block_store.volumes.create(
  132. name,
  133. 1,
  134. helpers.get_provider_test_data(self.provider, "placement"))
  135. with helpers.cleanup_action(lambda: test_vol.delete()):
  136. test_vol.wait_till_ready()
  137. snap_name = "CBSnapshot-{0}".format(name)
  138. test_snap = test_vol.create_snapshot(name=snap_name,
  139. description=snap_name)
  140. def cleanup_snap(snap):
  141. snap.delete()
  142. snap.wait_for(
  143. [SnapshotState.UNKNOWN],
  144. terminal_states=[SnapshotState.ERROR])
  145. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  146. test_snap.wait_till_ready()
  147. sit.check_standard_behaviour(
  148. self, self.provider.block_store.snapshots, test_snap)
  149. # Test volume creation from a snapshot (via VolumeService)
  150. sv_name = "CBUnitTestSnapVol-{0}".format(name)
  151. snap_vol = self.provider.block_store.volumes.create(
  152. sv_name,
  153. 1,
  154. helpers.get_provider_test_data(self.provider, "placement"),
  155. snapshot=test_snap)
  156. with helpers.cleanup_action(lambda: snap_vol.delete()):
  157. snap_vol.wait_till_ready()
  158. # Test volume creation from a snapshot (via Snapshot)
  159. snap_vol2 = test_snap.create_volume(
  160. helpers.get_provider_test_data(self.provider, "placement"))
  161. with helpers.cleanup_action(lambda: snap_vol2.delete()):
  162. snap_vol2.wait_till_ready()
  163. sit.check_delete(
  164. self, self.provider.block_store.snapshots, test_snap)
  165. # Test creation of a snap via SnapshotService
  166. snap_too_name = "CBSnapToo-{0}".format(name)
  167. time.sleep(15) # Or get SnapshotCreationPerVolumeRateExceeded
  168. test_snap_too = self.provider.block_store.snapshots.create(
  169. name=snap_too_name, volume=test_vol, description=snap_too_name)
  170. with helpers.cleanup_action(lambda: cleanup_snap(test_snap_too)):
  171. test_snap_too.wait_till_ready()
  172. self.assertTrue(
  173. test_snap_too.id in repr(test_snap_too),
  174. "repr(obj) should contain the object id so that the object"
  175. " can be reconstructed, but does not.")
  176. @helpers.skipIfNoService(['block_store.snapshots'])
  177. def test_snapshot_properties(self):
  178. """
  179. Test snapshot properties
  180. """
  181. name = "CBTestSnapProp-{0}".format(uuid.uuid4())
  182. test_vol = self.provider.block_store.volumes.create(
  183. name,
  184. 1,
  185. helpers.get_provider_test_data(self.provider, "placement"))
  186. with helpers.cleanup_action(lambda: test_vol.delete()):
  187. test_vol.wait_till_ready()
  188. snap_name = "CBSnapProp-{0}".format(name)
  189. test_snap = test_vol.create_snapshot(name=snap_name,
  190. description=snap_name)
  191. def cleanup_snap(snap):
  192. snap.delete()
  193. snap.wait_for(
  194. [SnapshotState.UNKNOWN],
  195. terminal_states=[SnapshotState.ERROR])
  196. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  197. test_snap.wait_till_ready()
  198. self.assertTrue(isinstance(test_vol.size, six.integer_types))
  199. self.assertEqual(
  200. test_snap.size, test_vol.size,
  201. "Snapshot.size must match original volume's size: %s"
  202. " but is: %s" % (test_vol.size, test_snap.size))
  203. self.assertTrue(
  204. test_vol.description is None or
  205. isinstance(test_vol.description, six.string_types),
  206. "Snapshot.description must be None or a string. Got: %s"
  207. % test_vol.description)
  208. self.assertEqual(test_vol.id, test_snap.volume_id)
  209. self.assertIsNotNone(test_vol.create_time)
  210. test_snap.name = 'snapnewname1'
  211. test_snap.description = 'snapnewdescription1'
  212. test_snap.refresh()
  213. self.assertEqual(test_snap.name, 'snapnewname1')
  214. self.assertEqual(test_snap.description, 'snapnewdescription1')