/test/createsnapshot_tester.py

https://github.com/hpe-storage/python-hpedockerplugin · Python · 323 lines · 248 code · 61 blank · 14 comment · 0 complexity · 070c8314ac7f95ccc70bae6f1e456206 MD5 · raw file

  1. # import mock
  2. import copy
  3. import test.createvolume_tester as createvolume
  4. import test.fake_3par_data as data
  5. from hpedockerplugin import exception as hpe_exc
  6. # Derives all the functionality from CreteVolumeUnitTest itself
  7. class CreateSnapshotUnitTest(createvolume.CreateVolumeUnitTest):
  8. pass
  9. # This exercises online-copy path
  10. class TestCreateSnapshotDefault(CreateSnapshotUnitTest):
  11. def __init__(self, **kwargs):
  12. super(type(self), self).__init__(**kwargs)
  13. self._parent_vol = copy.deepcopy(data.volume)
  14. def get_request_params(self):
  15. return {"Name": data.SNAPSHOT_NAME1,
  16. "Opts": {"virtualCopyOf": data.VOLUME_NAME}}
  17. def setup_mock_objects(self):
  18. mock_etcd = self.mock_objects['mock_etcd']
  19. volume = copy.deepcopy(data.volume)
  20. mock_etcd.get_vol_byname.side_effect = [
  21. None,
  22. volume,
  23. None,
  24. volume,
  25. None
  26. ]
  27. mock_3parclient = self.mock_objects['mock_3parclient']
  28. mock_3parclient.isOnlinePhysicalCopy.return_value = False
  29. def check_response(self, resp):
  30. self._test_case.assertEqual(resp, {u"Err": ''})
  31. # Ensure that createSnapshot was called on 3PAR Client
  32. mock_3parclient = self.mock_objects['mock_3parclient']
  33. mock_3parclient.createSnapshot.assert_called()
  34. class TestCreateSnapshotWithExpiryRetentionTimes(CreateSnapshotUnitTest):
  35. def get_request_params(self):
  36. return {"Name": data.SNAPSHOT_NAME1,
  37. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  38. "expirationHours": '10',
  39. "retentionHours": '5'}}
  40. def setup_mock_objects(self):
  41. mock_etcd = self.mock_objects['mock_etcd']
  42. volume = copy.deepcopy(data.volume)
  43. mock_etcd.get_vol_byname.side_effect = [
  44. None,
  45. volume,
  46. None,
  47. volume
  48. ]
  49. mock_3parclient = self.mock_objects['mock_3parclient']
  50. mock_3parclient.isOnlinePhysicalCopy.return_value = False
  51. def check_response(self, resp):
  52. self._test_case.assertEqual(resp, {u"Err": ''})
  53. # Ensure that createSnapshot was called on 3PAR Client
  54. mock_3parclient = self.mock_objects['mock_3parclient']
  55. mock_3parclient.createSnapshot.assert_called()
  56. # Tries to create a snapshot with a duplicate name
  57. class TestCreateSnapshotDuplicateName(CreateSnapshotUnitTest):
  58. def get_request_params(self):
  59. return {"Name": data.SNAPSHOT_NAME1,
  60. "Opts": {"virtualCopyOf": data.VOLUME_NAME}}
  61. def setup_mock_objects(self):
  62. mock_etcd = self.mock_objects['mock_etcd']
  63. mock_etcd.get_vol_byname.side_effect = [
  64. None,
  65. data.snap1,
  66. data.snap1
  67. ]
  68. def check_response(self, resp):
  69. self._test_case.assertEqual(resp, {u"Err": 'snapshot snapshot-1'
  70. ' already exists'})
  71. # Tries to create snapshot with retention time > expiry time. This should fail.
  72. class TestCreateSnapshotWithInvalidTimes(CreateSnapshotUnitTest):
  73. def get_request_params(self):
  74. return {"Name": "snap-001",
  75. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  76. "expirationHours": '10',
  77. "retentionHours": '20'}}
  78. def check_response(self, resp):
  79. # TODO: Implement this check in the actual flow
  80. self._test_case.assertEqual(resp,
  81. {u"Err": 'retention time cannot be '
  82. 'greater than expiration time'})
  83. # Tries to create snapshot for a non-existent volume
  84. class TestCreateSnapshotForNonExistentVolume(CreateSnapshotUnitTest):
  85. def get_request_params(self):
  86. return {"Name": "snap-001",
  87. "Opts": {"virtualCopyOf": 'i_do_not_exist_volume'}}
  88. def setup_mock_objects(self):
  89. mock_etcd = self.mock_objects['mock_etcd']
  90. mock_etcd.get_vol_byname.side_effect = [
  91. None,
  92. None
  93. ]
  94. def check_response(self, resp):
  95. expected = 'Volume/Snapshot %s does not exist' % \
  96. 'i_do_not_exist_volume'
  97. self._test_case.assertEqual(resp, {u"Err": expected})
  98. class TestCreateSnapshotEtcdSaveFails(CreateSnapshotUnitTest):
  99. def get_request_params(self):
  100. return {"Name": data.SNAPSHOT_NAME1,
  101. "Opts": {"virtualCopyOf": data.VOLUME_NAME}}
  102. def setup_mock_objects(self):
  103. mock_etcd = self.mock_objects['mock_etcd']
  104. mock_etcd.get_vol_byname.side_effect = [
  105. None,
  106. data.volume,
  107. None,
  108. copy.deepcopy(data.volume)
  109. ]
  110. mock_etcd.save_vol.side_effect = \
  111. [hpe_exc.HPEPluginSaveFailed(obj='snap-001')]
  112. mock_3parclient = self.mock_objects['mock_3parclient']
  113. mock_3parclient.isOnlinePhysicalCopy.return_value = False
  114. def check_response(self, resp):
  115. expected = "ETCD data save failed: snap-001"
  116. self._test_case.assertEqual(resp, {u"Err": expected})
  117. # Ensure that createSnapshot was called on 3PAR Client
  118. mock_3parclient = self.mock_objects['mock_3parclient']
  119. mock_3parclient.createSnapshot.assert_called()
  120. # Rollback
  121. mock_3parclient.deleteVolume.assert_called()
  122. class TestCreateSnpSchedule(CreateSnapshotUnitTest):
  123. def get_request_params(self):
  124. return {"Name": data.SNAPSHOT_NAME4,
  125. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  126. "scheduleName": '3parsched1',
  127. "scheduleFrequency": "10 * * * *",
  128. "snapshotPrefix": "pqrst",
  129. "expHrs": '4',
  130. "retHrs": '2'}}
  131. def setup_mock_objects(self):
  132. mock_etcd = self.mock_objects['mock_etcd']
  133. mock_etcd.get_vol_byname.side_effect = [
  134. None,
  135. data.volume,
  136. None,
  137. copy.deepcopy(data.volume)
  138. ]
  139. mock_3parclient = self.mock_objects['mock_3parclient']
  140. mock_3parclient.isOnlinePhysicalCopy.return_value = False
  141. def check_response(self, resp):
  142. self._test_case.assertEqual(resp, {u"Err": ''})
  143. # Ensure that createSnapshot was called on 3PAR Client
  144. mock_3parclient = self.mock_objects['mock_3parclient']
  145. mock_3parclient._run.assert_called()
  146. mock_3parclient.createSnapshot.assert_called()
  147. class TestCreateSnpSchedNegFreq(CreateSnapshotUnitTest):
  148. def get_request_params(self):
  149. return {"Name": data.SNAPSHOT_NAME4,
  150. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  151. "scheduleName": '3parsched1',
  152. "snapshotPrefix": "pqrst",
  153. "expHrs": '4',
  154. "retHrs": '2'}}
  155. def check_response(self, resp):
  156. opts = ['scheduleName', 'snapshotPrefix', 'scheduleFrequency']
  157. opts.sort()
  158. expected = "Invalid input received: One or more mandatory options " \
  159. "%s are missing for operation create snapshot schedule" \
  160. % opts
  161. self._test_case.assertEqual(resp, {u"Err": expected})
  162. class TestCreateSnpSchedNegPrefx(CreateSnapshotUnitTest):
  163. def get_request_params(self):
  164. return {"Name": data.SNAPSHOT_NAME4,
  165. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  166. "scheduleName": '3parsched1',
  167. "scheduleFrequency": "10 * * * *",
  168. "expHrs": '4',
  169. "retHrs": '2'}}
  170. def check_response(self, resp):
  171. opts = ['scheduleName', 'snapshotPrefix', 'scheduleFrequency']
  172. opts.sort()
  173. expected = "Invalid input received: One or more mandatory options " \
  174. "%s are missing for operation create snapshot schedule" \
  175. % opts
  176. self._test_case.assertEqual(resp, {u"Err": expected})
  177. class TestCreateSnpSchedInvPrefxLen(CreateSnapshotUnitTest):
  178. def get_request_params(self):
  179. return {"Name": data.SNAPSHOT_NAME4,
  180. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  181. "scheduleName": '3parsched1',
  182. "scheduleFrequency": "10 * * * *",
  183. "snapshotPrefix": "pqrstwdstyuijowkdlasihguf",
  184. "expHrs": '4',
  185. "retHrs": '2'}}
  186. def check_response(self, resp):
  187. expected = 'Please provide a scheduleName with max 31 characters '\
  188. 'and snapshotPrefix with max length of 15 characters'
  189. self._test_case.assertEqual(resp, {u"Err": expected})
  190. class TestCreateSnpSchedNoSchedName(CreateSnapshotUnitTest):
  191. def get_request_params(self):
  192. return {"Name": data.SNAPSHOT_NAME4,
  193. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  194. "scheduleFrequency": "10 * * * *",
  195. "snapshotPrefix": "pqrst",
  196. "expHrs": '4',
  197. "retHrs": '2'}}
  198. def check_response(self, resp):
  199. opts = ['scheduleName', 'snapshotPrefix', 'scheduleFrequency']
  200. opts.sort()
  201. expected = "Invalid input received: One or more mandatory options " \
  202. "%s are missing for operation create snapshot schedule" \
  203. % opts
  204. self._test_case.assertEqual(resp, {u"Err": expected})
  205. class TestCreateSnpSchedwithRetToBase(CreateSnapshotUnitTest):
  206. def get_request_params(self):
  207. return {"Name": data.SNAPSHOT_NAME4,
  208. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  209. "scheduleName": '3parsched1',
  210. "scheduleFrequency": "10 * * * *",
  211. "snapshotPrefix": "pqrst",
  212. "retentionHours": '5',
  213. "expHrs": '4',
  214. "retHrs": '2'}}
  215. def check_response(self, resp):
  216. invalid_opts = ['retentionHours']
  217. expected = "Invalid input received: Invalid option(s) %s " \
  218. "specified for operation create snapshot schedule. " \
  219. "Please check help for usage." % invalid_opts
  220. self._test_case.assertEqual(resp, {u"Err": expected})
  221. class TestCreateSnpSchedRetExpNeg(CreateSnapshotUnitTest):
  222. def get_request_params(self):
  223. return {"Name": data.SNAPSHOT_NAME4,
  224. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  225. "scheduleName": '3parsched1',
  226. "scheduleFrequency": "10 * * * *",
  227. "snapshotPrefix": "pqrst",
  228. "expHrs": '2',
  229. "retHrs": '4'}}
  230. def check_response(self, resp):
  231. expected = 'create schedule failed, error is: expiration hours '\
  232. 'must be greater than retention hours'
  233. self._test_case.assertEqual(resp, {u"Err": expected})
  234. class TestCreateSnpSchedInvSchedFreq(CreateSnapshotUnitTest):
  235. def get_request_params(self):
  236. return {"Name": data.SNAPSHOT_NAME4,
  237. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  238. "scheduleName": '3parsched1',
  239. "scheduleFrequency": "10 * * * * *",
  240. "snapshotPrefix": "pqrst",
  241. "expHrs": '4',
  242. "retHrs": '2'}}
  243. def check_response(self, resp):
  244. expected = 'Invalid schedule string is passed: HPE Docker Volume '\
  245. 'plugin Create volume failed: create schedule failed, '\
  246. 'error is: Improper string passed. '
  247. self._test_case.assertEqual(resp, {u"Err": expected})
  248. class TestCreateSnapshotInvalidOptions(CreateSnapshotUnitTest):
  249. def get_request_params(self):
  250. return {"Name": data.SNAPSHOT_NAME4,
  251. "Opts": {"virtualCopyOf": data.VOLUME_NAME,
  252. "mountConflictDelay": 22,
  253. "backend": "dummy"}}
  254. def check_response(self, resp):
  255. invalid_opts = ['backend']
  256. invalid_opts.sort()
  257. expected = "Invalid input received: Invalid option(s) " \
  258. "%s specified for operation create snapshot. " \
  259. "Please check help for usage." % invalid_opts
  260. self._test_case.assertEqual(resp, {u"Err": expected})
  261. # class TestCreateSnapshotUnauthorized(CreateSnapshotUnitTest):
  262. # pass