test_block_store_service.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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(['block_store.snapshots'])
  118. def test_crud_snapshot(self):
  119. """
  120. Create a new volume, create a snapshot of the volume, and check
  121. whether list_snapshots properly detects the new snapshot.
  122. Delete everything afterwards.
  123. """
  124. name = "cb_crudsnap-{0}".format(helpers.get_uuid())
  125. test_vol = self.provider.block_store.volumes.create(
  126. name,
  127. 1,
  128. helpers.get_provider_test_data(self.provider, "placement"))
  129. with helpers.cleanup_action(lambda: test_vol.delete()):
  130. test_vol.wait_till_ready()
  131. snap_name = "cb_snap-{0}".format(name)
  132. test_snap = test_vol.create_snapshot(name=snap_name,
  133. description=snap_name)
  134. def cleanup_snap(snap):
  135. snap.delete()
  136. snap.wait_for(
  137. [SnapshotState.UNKNOWN],
  138. terminal_states=[SnapshotState.ERROR])
  139. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  140. test_snap.wait_till_ready()
  141. sit.check_standard_behaviour(
  142. self, self.provider.block_store.snapshots, test_snap)
  143. # Test volume creation from a snapshot (via VolumeService)
  144. sv_name = "cb_snapvol_{0}".format(name)
  145. snap_vol = self.provider.block_store.volumes.create(
  146. sv_name,
  147. 1,
  148. helpers.get_provider_test_data(self.provider, "placement"),
  149. snapshot=test_snap)
  150. with helpers.cleanup_action(lambda: snap_vol.delete()):
  151. snap_vol.wait_till_ready()
  152. # Test volume creation from a snapshot (via Snapshot)
  153. snap_vol2 = test_snap.create_volume(
  154. helpers.get_provider_test_data(self.provider, "placement"))
  155. with helpers.cleanup_action(lambda: snap_vol2.delete()):
  156. snap_vol2.wait_till_ready()
  157. sit.check_delete(
  158. self, self.provider.block_store.snapshots, test_snap)
  159. # Test creation of a snap via SnapshotService
  160. snap_two_name = "cb_snaptwo-{0}".format(name)
  161. time.sleep(15) # Or get SnapshotCreationPerVolumeRateExceeded
  162. test_snap_two = self.provider.block_store.snapshots.create(
  163. name=snap_two_name, volume=test_vol, description=snap_two_name)
  164. with helpers.cleanup_action(lambda: cleanup_snap(test_snap_two)):
  165. test_snap_two.wait_till_ready()
  166. sit.check_standard_behaviour(
  167. self, self.provider.block_store.snapshots, test_snap_two)
  168. @helpers.skipIfNoService(['block_store.snapshots'])
  169. def test_snapshot_properties(self):
  170. """
  171. Test snapshot properties
  172. """
  173. name = "cb_snapprop-{0}".format(uuid.uuid4())
  174. test_vol = self.provider.block_store.volumes.create(
  175. name,
  176. 1,
  177. helpers.get_provider_test_data(self.provider, "placement"))
  178. with helpers.cleanup_action(lambda: test_vol.delete()):
  179. test_vol.wait_till_ready()
  180. snap_name = "cb_snap-{0}".format(name)
  181. test_snap = test_vol.create_snapshot(name=snap_name,
  182. description=snap_name)
  183. def cleanup_snap(snap):
  184. snap.delete()
  185. snap.wait_for(
  186. [SnapshotState.UNKNOWN],
  187. terminal_states=[SnapshotState.ERROR])
  188. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  189. test_snap.wait_till_ready()
  190. self.assertTrue(isinstance(test_vol.size, six.integer_types))
  191. self.assertEqual(
  192. test_snap.size, test_vol.size,
  193. "Snapshot.size must match original volume's size: %s"
  194. " but is: %s" % (test_vol.size, test_snap.size))
  195. self.assertTrue(
  196. test_vol.description is None or
  197. isinstance(test_vol.description, six.string_types),
  198. "Snapshot.description must be None or a string. Got: %s"
  199. % test_vol.description)
  200. self.assertEqual(test_vol.id, test_snap.volume_id)
  201. self.assertIsNotNone(test_vol.create_time)
  202. test_snap.name = 'snapnewname1'
  203. test_snap.description = 'snapnewdescription1'
  204. test_snap.refresh()
  205. self.assertEqual(test_snap.name, 'snapnewname1')
  206. self.assertEqual(test_snap.description, 'snapnewdescription1')