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.factory import ProviderList
  7. from cloudbridge.cloud.interfaces import SnapshotState
  8. from cloudbridge.cloud.interfaces import VolumeState
  9. from cloudbridge.cloud.interfaces.provider import TestMockHelperMixin
  10. from cloudbridge.cloud.interfaces.resources import AttachmentInfo
  11. from cloudbridge.cloud.interfaces.resources import Snapshot
  12. from cloudbridge.cloud.interfaces.resources import Volume
  13. import six
  14. class CloudBlockStoreServiceTestCase(ProviderTestBase):
  15. _multiprocess_can_split_ = True
  16. @helpers.skipIfNoService(['storage.volumes'])
  17. def test_crud_volume(self):
  18. """
  19. Create a new volume, check whether the expected values are set,
  20. and delete it
  21. """
  22. def create_vol(name):
  23. return self.provider.storage.volumes.create(
  24. name,
  25. 1,
  26. helpers.get_provider_test_data(self.provider, "placement"))
  27. def cleanup_vol(vol):
  28. print("--- vol: %s" % vol)
  29. if vol:
  30. vol.delete()
  31. vol.wait_for([VolumeState.DELETED, VolumeState.UNKNOWN],
  32. terminal_states=[VolumeState.ERROR])
  33. raise Exception
  34. sit.check_crud(self, self.provider.storage.volumes, Volume,
  35. "cb_createvol", create_vol, cleanup_vol)
  36. @helpers.skipIfNoService(['storage.volumes'])
  37. def test_attach_detach_volume(self):
  38. """
  39. Create a new volume, and attempt to attach it to an instance
  40. """
  41. name = "cb_attachvol-{0}".format(helpers.get_uuid())
  42. # Declare these variables and late binding will allow
  43. # the cleanup method access to the most current values
  44. net = None
  45. test_instance = None
  46. with helpers.cleanup_action(lambda: helpers.cleanup_test_resources(
  47. test_instance, net)):
  48. net, subnet = helpers.create_test_network(
  49. self.provider, name)
  50. test_instance = helpers.get_test_instance(
  51. self.provider, name, subnet=subnet)
  52. test_vol = self.provider.storage.volumes.create(
  53. name, 1, test_instance.zone_id)
  54. with helpers.cleanup_action(lambda: test_vol.delete()):
  55. test_vol.wait_till_ready()
  56. test_vol.attach(test_instance, '/dev/sda2')
  57. test_vol.wait_for(
  58. [VolumeState.IN_USE],
  59. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  60. test_vol.detach()
  61. test_vol.wait_for(
  62. [VolumeState.AVAILABLE],
  63. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  64. @helpers.skipIfNoService(['storage.volumes'])
  65. def test_volume_properties(self):
  66. """
  67. Test volume properties
  68. """
  69. name = "cb_volprops-{0}".format(helpers.get_uuid())
  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, name)
  79. test_instance = helpers.get_test_instance(
  80. self.provider, name, subnet=subnet)
  81. test_vol = self.provider.storage.volumes.create(
  82. name, 1, test_instance.zone_id, description=vol_desc)
  83. with helpers.cleanup_action(lambda: test_vol.delete()):
  84. test_vol.wait_till_ready()
  85. self.assertTrue(
  86. isinstance(test_vol.size, six.integer_types) and
  87. test_vol.size >= 0,
  88. "Volume.size must be a positive number, but got %s"
  89. % test_vol.size)
  90. self.assertTrue(
  91. test_vol.description is None or
  92. isinstance(test_vol.description, six.string_types),
  93. "Volume.description must be None or a string. Got: %s"
  94. % test_vol.description)
  95. self.assertIsNone(test_vol.source)
  96. self.assertIsNone(test_vol.source)
  97. self.assertIsNotNone(test_vol.create_time)
  98. self.assertIsNotNone(test_vol.zone_id)
  99. self.assertIsNone(test_vol.attachments)
  100. test_vol.attach(test_instance, '/dev/sda2')
  101. test_vol.wait_for(
  102. [VolumeState.IN_USE],
  103. terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
  104. self.assertIsNotNone(test_vol.attachments)
  105. self.assertIsInstance(test_vol.attachments, AttachmentInfo)
  106. self.assertEqual(test_vol.attachments.volume, test_vol)
  107. self.assertEqual(test_vol.attachments.instance_id,
  108. test_instance.id)
  109. if not self.provider.PROVIDER_ID == 'azure':
  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(['storage.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 = "cb_crudsnap-{0}".format(helpers.get_uuid())
  131. test_vol = self.provider.storage.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. def create_snap(name):
  138. return test_vol.create_snapshot(name=name,
  139. description=name)
  140. def cleanup_snap(snap):
  141. if snap:
  142. snap.delete()
  143. snap.wait_for([SnapshotState.UNKNOWN],
  144. terminal_states=[SnapshotState.ERROR])
  145. sit.check_crud(self, self.provider.storage.snapshots, Snapshot,
  146. "cb_snap", create_snap, cleanup_snap)
  147. # Test creation of a snap via SnapshotService
  148. def create_snap2(name):
  149. return self.provider.storage.snapshots.create(
  150. name=name, volume=test_vol, description=name)
  151. if (self.provider.PROVIDER_ID == ProviderList.AWS and
  152. not isinstance(self.provider, TestMockHelperMixin)):
  153. time.sleep(15) # Or get SnapshotCreationPerVolumeRateExceeded
  154. sit.check_crud(self, self.provider.storage.snapshots, Snapshot,
  155. "cb_snaptwo", create_snap2, cleanup_snap)
  156. @helpers.skipIfNoService(['storage.snapshots'])
  157. def test_snapshot_properties(self):
  158. """
  159. Test snapshot properties
  160. """
  161. name = "cb_snapprop-{0}".format(uuid.uuid4())
  162. test_vol = self.provider.storage.volumes.create(
  163. name,
  164. 1,
  165. helpers.get_provider_test_data(self.provider, "placement"))
  166. with helpers.cleanup_action(lambda: test_vol.delete()):
  167. test_vol.wait_till_ready()
  168. snap_name = "cb_snap-{0}".format(name)
  169. test_snap = test_vol.create_snapshot(name=snap_name,
  170. description=snap_name)
  171. def cleanup_snap(snap):
  172. if snap:
  173. snap.delete()
  174. snap.wait_for([SnapshotState.UNKNOWN],
  175. terminal_states=[SnapshotState.ERROR])
  176. with helpers.cleanup_action(lambda: cleanup_snap(test_snap)):
  177. test_snap.wait_till_ready()
  178. self.assertTrue(isinstance(test_vol.size, six.integer_types))
  179. self.assertEqual(
  180. test_snap.size, test_vol.size,
  181. "Snapshot.size must match original volume's size: %s"
  182. " but is: %s" % (test_vol.size, test_snap.size))
  183. self.assertTrue(
  184. test_vol.description is None or
  185. isinstance(test_vol.description, six.string_types),
  186. "Snapshot.description must be None or a string. Got: %s"
  187. % test_vol.description)
  188. self.assertEqual(test_vol.id, test_snap.volume_id)
  189. self.assertIsNotNone(test_vol.create_time)
  190. test_snap.name = 'snapnewname1'
  191. test_snap.description = 'snapnewdescription1'
  192. test_snap.refresh()
  193. self.assertEqual(test_snap.name, 'snapnewname1')
  194. self.assertEqual(test_snap.description, 'snapnewdescription1')
  195. # Test volume creation from a snapshot (via VolumeService)
  196. sv_name = "cb_snapvol_{0}".format(test_snap.name)
  197. snap_vol = self.provider.storage.volumes.create(
  198. sv_name,
  199. 1,
  200. helpers.get_provider_test_data(self.provider, "placement"),
  201. snapshot=test_snap)
  202. with helpers.cleanup_action(lambda: snap_vol.delete()):
  203. snap_vol.wait_till_ready()
  204. # Test volume creation from a snapshot (via Snapshot)
  205. snap_vol2 = test_snap.create_volume(
  206. helpers.get_provider_test_data(self.provider, "placement"))
  207. with helpers.cleanup_action(lambda: snap_vol2.delete()):
  208. snap_vol2.wait_till_ready()