test_block_store_service.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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 = "cb_createvol-{0}".format(helpers.get_uuid())
  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. name = "cb_attachvol-{0}".format(helpers.get_uuid())
  37. # Declare these variables and late binding will allow
  38. # the cleanup method access to the most current values
  39. net = None
  40. test_instance = None
  41. with helpers.cleanup_action(lambda: helpers.cleanup_test_resources(
  42. test_instance, net)):
  43. net, subnet = helpers.create_test_network(
  44. self.provider, name)
  45. test_instance = helpers.get_test_instance(
  46. self.provider, name, subnet=subnet)
  47. test_vol = self.provider.block_store.volumes.create(
  48. name, 1, test_instance.zone_id)
  49. with helpers.cleanup_action(lambda: test_vol.delete()):
  50. test_vol.wait_till_ready()
  51. test_vol.attach(test_instance, '/dev/sda2')
  52. test_vol.wait_for(
  53. [VolumeState.IN_USE],
  54. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  55. test_vol.detach()
  56. test_vol.wait_for(
  57. [VolumeState.AVAILABLE],
  58. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  59. @helpers.skipIfNoService(['block_store.volumes'])
  60. def test_volume_properties(self):
  61. """
  62. Test volume properties
  63. """
  64. name = "cb_volprops-{0}".format(helpers.get_uuid())
  65. vol_desc = 'newvoldesc1'
  66. # Declare these variables and late binding will allow
  67. # the cleanup method access to the most current values
  68. test_instance = None
  69. net = None
  70. with helpers.cleanup_action(lambda: helpers.cleanup_test_resources(
  71. test_instance, net)):
  72. net, subnet = helpers.create_test_network(
  73. self.provider, name)
  74. test_instance = helpers.get_test_instance(
  75. self.provider, name, subnet=subnet)
  76. test_vol = self.provider.block_store.volumes.create(
  77. name, 1, test_instance.zone_id, description=vol_desc)
  78. with helpers.cleanup_action(lambda: test_vol.delete()):
  79. test_vol.wait_till_ready()
  80. self.assertTrue(
  81. isinstance(test_vol.size, six.integer_types) and
  82. test_vol.size >= 0,
  83. "Volume.size must be a positive number, but got %s"
  84. % test_vol.size)
  85. self.assertTrue(
  86. test_vol.description is None or
  87. isinstance(test_vol.description, six.string_types),
  88. "Volume.description must be None or a string. Got: %s"
  89. % test_vol.description)
  90. self.assertIsNone(test_vol.source)
  91. self.assertIsNone(test_vol.source)
  92. self.assertIsNotNone(test_vol.create_time)
  93. self.assertIsNotNone(test_vol.zone_id)
  94. self.assertIsNone(test_vol.attachments)
  95. test_vol.attach(test_instance, '/dev/sda2')
  96. test_vol.wait_for(
  97. [VolumeState.IN_USE],
  98. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  99. self.assertIsNotNone(test_vol.attachments)
  100. self.assertIsInstance(test_vol.attachments, AttachmentInfo)
  101. self.assertEqual(test_vol.attachments.volume, test_vol)
  102. self.assertEqual(test_vol.attachments.instance_id,
  103. test_instance.id)
  104. self.assertEqual(test_vol.attachments.device,
  105. "/dev/sda2")
  106. test_vol.detach()
  107. test_vol.name = 'newvolname1'
  108. test_vol.wait_for(
  109. [VolumeState.AVAILABLE],
  110. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  111. self.assertEqual(test_vol.name, 'newvolname1')
  112. self.assertEqual(test_vol.description, vol_desc)
  113. self.assertIsNone(test_vol.attachments)
  114. test_vol.wait_for(
  115. [VolumeState.AVAILABLE],
  116. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  117. @helpers.skipIfNoService(['until.jetstream.is.fixed'])
  118. # @helpers.skipIfNoService(['block_store.snapshots'])
  119. def test_crud_snapshot(self):
  120. """
  121. Create a new volume, create a snapshot of the volume, and check
  122. whether list_snapshots properly detects the new snapshot.
  123. Delete everything afterwards.
  124. """
  125. name = "cb_crudsnap-{0}".format(helpers.get_uuid())
  126. test_vol = self.provider.block_store.volumes.create(
  127. name,
  128. 1,
  129. helpers.get_provider_test_data(self.provider, "placement"))
  130. with helpers.cleanup_action(lambda: test_vol.delete()):
  131. test_vol.wait_till_ready()
  132. snap_name = "cb_snap-{0}".format(name)
  133. test_snap = test_vol.create_snapshot(name=snap_name,
  134. description=snap_name)
  135. def cleanup_snap(snap):
  136. snap.delete()
  137. snap.wait_for(
  138. [SnapshotState.UNKNOWN],
  139. terminal_states=[SnapshotState.ERROR])
  140. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  141. test_snap.wait_till_ready()
  142. sit.check_standard_behaviour(
  143. self, self.provider.block_store.snapshots, test_snap)
  144. # Test volume creation from a snapshot (via VolumeService)
  145. sv_name = "cb_snapvol_{0}".format(name)
  146. snap_vol = self.provider.block_store.volumes.create(
  147. sv_name,
  148. 1,
  149. helpers.get_provider_test_data(self.provider, "placement"),
  150. snapshot=test_snap)
  151. with helpers.cleanup_action(lambda: snap_vol.delete()):
  152. snap_vol.wait_till_ready()
  153. # Test volume creation from a snapshot (via Snapshot)
  154. snap_vol2 = test_snap.create_volume(
  155. helpers.get_provider_test_data(self.provider, "placement"))
  156. with helpers.cleanup_action(lambda: snap_vol2.delete()):
  157. snap_vol2.wait_till_ready()
  158. sit.check_delete(
  159. self, self.provider.block_store.snapshots, test_snap)
  160. # Test creation of a snap via SnapshotService
  161. snap_two_name = "cb_snaptwo-{0}".format(name)
  162. time.sleep(15) # Or get SnapshotCreationPerVolumeRateExceeded
  163. test_snap_two = self.provider.block_store.snapshots.create(
  164. name=snap_two_name, volume=test_vol, description=snap_two_name)
  165. with helpers.cleanup_action(lambda: cleanup_snap(test_snap_two)):
  166. test_snap_two.wait_till_ready()
  167. sit.check_standard_behaviour(
  168. self, self.provider.block_store.snapshots, test_snap_two)
  169. @helpers.skipIfNoService(['until.jetstream.is.fixed'])
  170. # @helpers.skipIfNoService(['block_store.snapshots'])
  171. def test_snapshot_properties(self):
  172. """
  173. Test snapshot properties
  174. """
  175. name = "cb_snapprop-{0}".format(uuid.uuid4())
  176. test_vol = self.provider.block_store.volumes.create(
  177. name,
  178. 1,
  179. helpers.get_provider_test_data(self.provider, "placement"))
  180. with helpers.cleanup_action(lambda: test_vol.delete()):
  181. test_vol.wait_till_ready()
  182. snap_name = "cb_snap-{0}".format(name)
  183. test_snap = test_vol.create_snapshot(name=snap_name,
  184. description=snap_name)
  185. def cleanup_snap(snap):
  186. snap.delete()
  187. snap.wait_for(
  188. [SnapshotState.UNKNOWN],
  189. terminal_states=[SnapshotState.ERROR])
  190. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  191. test_snap.wait_till_ready()
  192. self.assertTrue(isinstance(test_vol.size, six.integer_types))
  193. self.assertEqual(
  194. test_snap.size, test_vol.size,
  195. "Snapshot.size must match original volume's size: %s"
  196. " but is: %s" % (test_vol.size, test_snap.size))
  197. self.assertTrue(
  198. test_vol.description is None or
  199. isinstance(test_vol.description, six.string_types),
  200. "Snapshot.description must be None or a string. Got: %s"
  201. % test_vol.description)
  202. self.assertEqual(test_vol.id, test_snap.volume_id)
  203. self.assertIsNotNone(test_vol.create_time)
  204. test_snap.name = 'snapnewname1'
  205. test_snap.description = 'snapnewdescription1'
  206. test_snap.refresh()
  207. self.assertEqual(test_snap.name, 'snapnewname1')
  208. self.assertEqual(test_snap.description, 'snapnewdescription1')