test_zfs.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for salt.states.zfs
  4. :codeauthor: Jorge Schrauwen <sjorge@blackdot.be>
  5. :maintainer: Jorge Schrauwen <sjorge@blackdot.be>
  6. :maturity: new
  7. :depends: salt.utils.zfs, salt.modules.zfs
  8. :platform: illumos,freebsd,linux
  9. """
  10. # Import Python libs
  11. from __future__ import absolute_import, print_function, unicode_literals
  12. import pytest
  13. # Import Salt Utils
  14. import salt.loader
  15. import salt.states.zfs as zfs
  16. # Import Salt Execution module to test
  17. import salt.utils.zfs
  18. from salt.utils.odict import OrderedDict
  19. from tests.support.mixins import LoaderModuleMockMixin
  20. from tests.support.mock import MagicMock, patch
  21. from tests.support.unit import TestCase
  22. # Import Salt Testing Libs
  23. from tests.support.zfs import ZFSMockData
  24. class ZfsTestCase(TestCase, LoaderModuleMockMixin):
  25. """
  26. Test cases for salt.states.zfs
  27. """
  28. def setup_loader_modules(self):
  29. self.opts = opts = salt.config.DEFAULT_MINION_OPTS.copy()
  30. self.utils_patch = ZFSMockData().get_patched_utils()
  31. for key in ("opts", "utils_patch"):
  32. self.addCleanup(delattr, self, key)
  33. utils = salt.loader.utils(opts, whitelist=["zfs"])
  34. zfs_obj = {
  35. zfs: {
  36. "__opts__": opts,
  37. "__grains__": {"kernel": "SunOS"},
  38. "__utils__": utils,
  39. }
  40. }
  41. return zfs_obj
  42. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  43. def test_filesystem_absent_nofs(self):
  44. """
  45. Test if filesystem is absent (non existing filesystem)
  46. """
  47. ret = {
  48. "name": "myzpool/filesystem",
  49. "result": True,
  50. "comment": "filesystem myzpool/filesystem is absent",
  51. "changes": {},
  52. }
  53. mock_exists = MagicMock(return_value=False)
  54. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  55. zfs.__utils__, self.utils_patch
  56. ):
  57. self.assertEqual(ret, zfs.filesystem_absent("myzpool/filesystem"))
  58. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  59. def test_filesystem_absent_removed(self):
  60. """
  61. Test if filesystem is absent
  62. """
  63. ret = {
  64. "name": "myzpool/filesystem",
  65. "result": True,
  66. "comment": "filesystem myzpool/filesystem was destroyed",
  67. "changes": {"myzpool/filesystem": "destroyed"},
  68. }
  69. mock_exists = MagicMock(return_value=True)
  70. mock_destroy = MagicMock(return_value=OrderedDict([("destroyed", True)]))
  71. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  72. zfs.__salt__, {"zfs.destroy": mock_destroy}
  73. ), patch.dict(zfs.__utils__, self.utils_patch):
  74. self.assertEqual(ret, zfs.filesystem_absent("myzpool/filesystem"))
  75. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  76. def test_filesystem_absent_fail(self):
  77. """
  78. Test if filesystem is absent (with snapshots)
  79. """
  80. ret = {
  81. "name": "myzpool/filesystem",
  82. "result": False,
  83. "comment": "\n".join(
  84. [
  85. "cannot destroy 'myzpool/filesystem': filesystem has children",
  86. "use 'recursive=True' to destroy the following datasets:",
  87. "myzpool/filesystem@snap",
  88. ]
  89. ),
  90. "changes": {},
  91. }
  92. mock_exists = MagicMock(return_value=True)
  93. mock_destroy = MagicMock(
  94. return_value=OrderedDict(
  95. [
  96. ("destroyed", False),
  97. (
  98. "error",
  99. "\n".join(
  100. [
  101. "cannot destroy 'myzpool/filesystem': filesystem has children",
  102. "use 'recursive=True' to destroy the following datasets:",
  103. "myzpool/filesystem@snap",
  104. ]
  105. ),
  106. ),
  107. ]
  108. )
  109. )
  110. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  111. zfs.__salt__, {"zfs.destroy": mock_destroy}
  112. ), patch.dict(zfs.__utils__, self.utils_patch):
  113. self.assertEqual(ret, zfs.filesystem_absent("myzpool/filesystem"))
  114. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  115. def test_volume_absent_novol(self):
  116. """
  117. Test if volume is absent (non existing volume)
  118. """
  119. ret = {
  120. "name": "myzpool/volume",
  121. "result": True,
  122. "comment": "volume myzpool/volume is absent",
  123. "changes": {},
  124. }
  125. mock_exists = MagicMock(return_value=False)
  126. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  127. zfs.__utils__, self.utils_patch
  128. ):
  129. self.assertEqual(ret, zfs.volume_absent("myzpool/volume"))
  130. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  131. def test_volume_absent_removed(self):
  132. """
  133. Test if volume is absent
  134. """
  135. ret = {
  136. "name": "myzpool/volume",
  137. "result": True,
  138. "comment": "volume myzpool/volume was destroyed",
  139. "changes": {"myzpool/volume": "destroyed"},
  140. }
  141. mock_exists = MagicMock(return_value=True)
  142. mock_destroy = MagicMock(return_value=OrderedDict([("destroyed", True)]))
  143. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  144. zfs.__salt__, {"zfs.destroy": mock_destroy}
  145. ), patch.dict(zfs.__utils__, self.utils_patch):
  146. self.assertEqual(ret, zfs.volume_absent("myzpool/volume"))
  147. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  148. def test_volume_absent_fail(self):
  149. """
  150. Test if volume is absent (with snapshots)
  151. """
  152. ret = {
  153. "name": "myzpool/volume",
  154. "result": False,
  155. "comment": "\n".join(
  156. [
  157. "cannot destroy 'myzpool/volume': volume has children",
  158. "use 'recursive=True' to destroy the following datasets:",
  159. "myzpool/volume@snap",
  160. ]
  161. ),
  162. "changes": {},
  163. }
  164. mock_exists = MagicMock(return_value=True)
  165. mock_destroy = MagicMock(
  166. return_value=OrderedDict(
  167. [
  168. ("destroyed", False),
  169. (
  170. "error",
  171. "\n".join(
  172. [
  173. "cannot destroy 'myzpool/volume': volume has children",
  174. "use 'recursive=True' to destroy the following datasets:",
  175. "myzpool/volume@snap",
  176. ]
  177. ),
  178. ),
  179. ]
  180. )
  181. )
  182. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  183. zfs.__salt__, {"zfs.destroy": mock_destroy}
  184. ), patch.dict(zfs.__utils__, self.utils_patch):
  185. self.assertEqual(ret, zfs.volume_absent("myzpool/volume"))
  186. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  187. def test_snapshot_absent_nosnap(self):
  188. """
  189. Test if snapshot is absent (non existing snapshot)
  190. """
  191. ret = {
  192. "name": "myzpool/filesystem@snap",
  193. "result": True,
  194. "comment": "snapshot myzpool/filesystem@snap is absent",
  195. "changes": {},
  196. }
  197. mock_exists = MagicMock(return_value=False)
  198. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  199. zfs.__utils__, self.utils_patch
  200. ):
  201. self.assertEqual(ret, zfs.snapshot_absent("myzpool/filesystem@snap"))
  202. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  203. def test_snapshot_absent_removed(self):
  204. """
  205. Test if snapshot is absent
  206. """
  207. ret = {
  208. "name": "myzpool/filesystem@snap",
  209. "result": True,
  210. "comment": "snapshot myzpool/filesystem@snap was destroyed",
  211. "changes": {"myzpool/filesystem@snap": "destroyed"},
  212. }
  213. mock_exists = MagicMock(return_value=True)
  214. mock_destroy = MagicMock(return_value=OrderedDict([("destroyed", True)]))
  215. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  216. zfs.__salt__, {"zfs.destroy": mock_destroy}
  217. ), patch.dict(zfs.__utils__, self.utils_patch):
  218. self.assertEqual(ret, zfs.snapshot_absent("myzpool/filesystem@snap"))
  219. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  220. def test_snapshot_absent_fail(self):
  221. """
  222. Test if snapshot is absent (with snapshots)
  223. """
  224. ret = {
  225. "name": "myzpool/filesystem@snap",
  226. "result": False,
  227. "comment": "cannot destroy snapshot myzpool/filesystem@snap: dataset is busy",
  228. "changes": {},
  229. }
  230. mock_exists = MagicMock(return_value=True)
  231. mock_destroy = MagicMock(
  232. return_value=OrderedDict(
  233. [
  234. ("destroyed", False),
  235. (
  236. "error",
  237. "cannot destroy snapshot myzpool/filesystem@snap: dataset is busy",
  238. ),
  239. ]
  240. )
  241. )
  242. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  243. zfs.__salt__, {"zfs.destroy": mock_destroy}
  244. ), patch.dict(zfs.__utils__, self.utils_patch):
  245. self.assertEqual(ret, zfs.snapshot_absent("myzpool/filesystem@snap"))
  246. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  247. def test_bookmark_absent_nobook(self):
  248. """
  249. Test if bookmark is absent (non existing bookmark)
  250. """
  251. ret = {
  252. "name": "myzpool/filesystem#book",
  253. "result": True,
  254. "comment": "bookmark myzpool/filesystem#book is absent",
  255. "changes": {},
  256. }
  257. mock_exists = MagicMock(return_value=False)
  258. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  259. zfs.__utils__, self.utils_patch
  260. ):
  261. self.assertEqual(ret, zfs.bookmark_absent("myzpool/filesystem#book"))
  262. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  263. def test_bookmark_absent_removed(self):
  264. """
  265. Test if bookmark is absent
  266. """
  267. ret = {
  268. "name": "myzpool/filesystem#book",
  269. "result": True,
  270. "comment": "bookmark myzpool/filesystem#book was destroyed",
  271. "changes": {"myzpool/filesystem#book": "destroyed"},
  272. }
  273. mock_exists = MagicMock(return_value=True)
  274. mock_destroy = MagicMock(return_value=OrderedDict([("destroyed", True)]))
  275. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  276. zfs.__salt__, {"zfs.destroy": mock_destroy}
  277. ), patch.dict(zfs.__utils__, self.utils_patch):
  278. self.assertEqual(ret, zfs.bookmark_absent("myzpool/filesystem#book"))
  279. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  280. def test_hold_absent_nohold(self):
  281. """
  282. Test if hold is absent (non existing hold)
  283. """
  284. ret = {
  285. "name": "myhold",
  286. "result": True,
  287. "comment": "hold myhold is absent",
  288. "changes": {},
  289. }
  290. mock_holds = MagicMock(return_value=OrderedDict([]))
  291. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  292. zfs.__utils__, self.utils_patch
  293. ):
  294. self.assertEqual(ret, zfs.hold_absent("myhold", "myzpool/filesystem@snap"))
  295. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  296. def test_hold_absent_removed(self):
  297. """
  298. Test if hold is absent
  299. """
  300. ret = {
  301. "name": "myhold",
  302. "result": True,
  303. "comment": "hold myhold released",
  304. "changes": OrderedDict(
  305. [("myzpool/filesystem@snap", OrderedDict([("myhold", "released")]))]
  306. ),
  307. }
  308. mock_holds = MagicMock(
  309. return_value=OrderedDict([("myhold", "Thu Feb 15 16:24 2018")])
  310. )
  311. mock_release = MagicMock(return_value=OrderedDict([("released", True)]))
  312. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  313. zfs.__salt__, {"zfs.release": mock_release}
  314. ), patch.dict(zfs.__utils__, self.utils_patch):
  315. self.assertEqual(ret, zfs.hold_absent("myhold", "myzpool/filesystem@snap"))
  316. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  317. def test_hold_absent_fail(self):
  318. """
  319. Test if hold is absent (non existing snapshot)
  320. """
  321. ret = {
  322. "name": "myhold",
  323. "result": False,
  324. "comment": "cannot open 'myzpool/filesystem@snap': dataset does not exist",
  325. "changes": {},
  326. }
  327. mock_holds = MagicMock(
  328. return_value=OrderedDict(
  329. [
  330. (
  331. "error",
  332. "cannot open 'myzpool/filesystem@snap': dataset does not exist",
  333. ),
  334. ]
  335. )
  336. )
  337. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  338. zfs.__utils__, self.utils_patch
  339. ):
  340. self.assertEqual(ret, zfs.hold_absent("myhold", "myzpool/filesystem@snap"))
  341. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  342. def test_hold_present(self):
  343. """
  344. Test if hold is present (hold already present)
  345. """
  346. ret = {
  347. "name": "myhold",
  348. "result": True,
  349. "comment": "hold myhold is present for myzpool/filesystem@snap",
  350. "changes": {},
  351. }
  352. mock_holds = MagicMock(
  353. return_value=OrderedDict([("myhold", "Thu Feb 15 16:24 2018")])
  354. )
  355. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  356. zfs.__utils__, self.utils_patch
  357. ):
  358. self.assertEqual(ret, zfs.hold_present("myhold", "myzpool/filesystem@snap"))
  359. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  360. def test_hold_present_new(self):
  361. """
  362. Test if hold is present (new)
  363. """
  364. ret = {
  365. "name": "myhold",
  366. "result": True,
  367. "comment": "hold myhold added to myzpool/filesystem@snap",
  368. "changes": {"myzpool/filesystem@snap": {"myhold": "held"}},
  369. }
  370. mock_holds = MagicMock(return_value=OrderedDict([]))
  371. mock_hold = MagicMock(return_value=OrderedDict([("held", True)]))
  372. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  373. zfs.__salt__, {"zfs.hold": mock_hold}
  374. ), patch.dict(zfs.__utils__, self.utils_patch):
  375. self.assertEqual(ret, zfs.hold_present("myhold", "myzpool/filesystem@snap"))
  376. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  377. def test_hold_present_fail(self):
  378. """
  379. Test if hold is present (using non existing snapshot)
  380. """
  381. ret = {
  382. "name": "myhold",
  383. "result": False,
  384. "comment": "cannot hold snapshot 'zsalt/filesystem@snap': dataset does not exist",
  385. "changes": {},
  386. }
  387. mock_holds = MagicMock(return_value=OrderedDict([]))
  388. mock_hold = MagicMock(
  389. return_value=OrderedDict(
  390. [
  391. ("held", False),
  392. (
  393. "error",
  394. "cannot hold snapshot 'zsalt/filesystem@snap': dataset does not exist",
  395. ),
  396. ]
  397. )
  398. )
  399. with patch.dict(zfs.__salt__, {"zfs.holds": mock_holds}), patch.dict(
  400. zfs.__salt__, {"zfs.hold": mock_hold}
  401. ), patch.dict(zfs.__utils__, self.utils_patch):
  402. self.assertEqual(ret, zfs.hold_present("myhold", "myzpool/filesystem@snap"))
  403. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  404. def test_filesystem_present(self):
  405. """
  406. Test if filesystem is present (existing filesystem)
  407. """
  408. ret = {
  409. "name": "myzpool/filesystem",
  410. "result": True,
  411. "comment": "filesystem myzpool/filesystem is uptodate",
  412. "changes": {},
  413. }
  414. mock_exists = MagicMock(return_value=True)
  415. mock_get = MagicMock(
  416. return_value=OrderedDict(
  417. [
  418. (
  419. "myzpool/filesystem",
  420. OrderedDict(
  421. [
  422. ("type", OrderedDict([("value", "filesystem")])),
  423. ("compression", OrderedDict([("value", False)])),
  424. ]
  425. ),
  426. ),
  427. ]
  428. )
  429. )
  430. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  431. zfs.__salt__, {"zfs.get": mock_get}
  432. ), patch.dict(zfs.__utils__, self.utils_patch):
  433. self.assertEqual(ret, zfs.filesystem_present("myzpool/filesystem"))
  434. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  435. def test_filesystem_present_new(self):
  436. """
  437. Test if filesystem is present (non existing filesystem)
  438. """
  439. ret = {
  440. "name": "myzpool/filesystem",
  441. "result": True,
  442. "comment": "filesystem myzpool/filesystem was created",
  443. "changes": {"myzpool/filesystem": "created"},
  444. }
  445. mock_exists = MagicMock(return_value=False)
  446. mock_create = MagicMock(return_value=OrderedDict([("created", True)]))
  447. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  448. zfs.__salt__, {"zfs.create": mock_create}
  449. ), patch.dict(zfs.__utils__, self.utils_patch):
  450. self.assertEqual(ret, zfs.filesystem_present("myzpool/filesystem"))
  451. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  452. def test_filesystem_present_update(self):
  453. """
  454. Test if filesystem is present (non existing filesystem)
  455. """
  456. ret = {
  457. "name": "myzpool/filesystem",
  458. "result": True,
  459. "comment": "filesystem myzpool/filesystem was updated",
  460. "changes": {"myzpool/filesystem": {"compression": "lz4"}},
  461. }
  462. mock_exists = MagicMock(return_value=True)
  463. mock_set = MagicMock(return_value=OrderedDict([("set", True)]))
  464. mock_get = MagicMock(
  465. return_value=OrderedDict(
  466. [
  467. (
  468. "myzpool/filesystem",
  469. OrderedDict(
  470. [
  471. ("type", OrderedDict([("value", "filesystem")])),
  472. ("compression", OrderedDict([("value", False)])),
  473. ]
  474. ),
  475. ),
  476. ]
  477. )
  478. )
  479. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  480. zfs.__salt__, {"zfs.get": mock_get}
  481. ), patch.dict(zfs.__salt__, {"zfs.set": mock_set}), patch.dict(
  482. zfs.__utils__, self.utils_patch
  483. ):
  484. self.assertEqual(
  485. ret,
  486. zfs.filesystem_present(
  487. name="myzpool/filesystem", properties={"compression": "lz4"},
  488. ),
  489. )
  490. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  491. def test_filesystem_present_fail(self):
  492. """
  493. Test if filesystem is present (non existing pool)
  494. """
  495. ret = {
  496. "name": "myzpool/filesystem",
  497. "result": False,
  498. "comment": "cannot create 'myzpool/filesystem': no such pool 'myzpool'",
  499. "changes": {},
  500. }
  501. mock_exists = MagicMock(return_value=False)
  502. mock_create = MagicMock(
  503. return_value=OrderedDict(
  504. [
  505. ("created", False),
  506. (
  507. "error",
  508. "cannot create 'myzpool/filesystem': no such pool 'myzpool'",
  509. ),
  510. ]
  511. )
  512. )
  513. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  514. zfs.__salt__, {"zfs.create": mock_create}
  515. ), patch.dict(zfs.__utils__, self.utils_patch):
  516. self.assertEqual(ret, zfs.filesystem_present("myzpool/filesystem"))
  517. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  518. def test_volume_present(self):
  519. """
  520. Test if volume is present (existing volume)
  521. """
  522. ret = {
  523. "name": "myzpool/volume",
  524. "result": True,
  525. "comment": "volume myzpool/volume is uptodate",
  526. "changes": {},
  527. }
  528. mock_exists = MagicMock(return_value=True)
  529. mock_get = MagicMock(
  530. return_value=OrderedDict(
  531. [
  532. (
  533. "myzpool/volume",
  534. OrderedDict(
  535. [
  536. ("type", OrderedDict([("value", "volume")])),
  537. ("compression", OrderedDict([("value", False)])),
  538. ]
  539. ),
  540. ),
  541. ]
  542. )
  543. )
  544. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  545. zfs.__salt__, {"zfs.get": mock_get}
  546. ), patch.dict(zfs.__utils__, self.utils_patch):
  547. self.assertEqual(
  548. ret, zfs.volume_present("myzpool/volume", volume_size="1G")
  549. )
  550. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  551. def test_volume_present_new(self):
  552. """
  553. Test if volume is present (non existing volume)
  554. """
  555. ret = {
  556. "name": "myzpool/volume",
  557. "result": True,
  558. "comment": "volume myzpool/volume was created",
  559. "changes": {"myzpool/volume": "created"},
  560. }
  561. mock_exists = MagicMock(return_value=False)
  562. mock_create = MagicMock(return_value=OrderedDict([("created", True)]))
  563. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  564. zfs.__salt__, {"zfs.create": mock_create}
  565. ), patch.dict(zfs.__utils__, self.utils_patch):
  566. self.assertEqual(
  567. ret, zfs.volume_present("myzpool/volume", volume_size="1G")
  568. )
  569. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  570. def test_volume_present_update(self):
  571. """
  572. Test if volume is present (non existing volume)
  573. """
  574. ret = {
  575. "name": "myzpool/volume",
  576. "result": True,
  577. "comment": "volume myzpool/volume was updated",
  578. "changes": {"myzpool/volume": {"compression": "lz4"}},
  579. }
  580. mock_exists = MagicMock(return_value=True)
  581. mock_set = MagicMock(return_value=OrderedDict([("set", True)]))
  582. mock_get = MagicMock(
  583. return_value=OrderedDict(
  584. [
  585. (
  586. "myzpool/volume",
  587. OrderedDict(
  588. [
  589. ("type", OrderedDict([("value", "volume")])),
  590. ("compression", OrderedDict([("value", False)])),
  591. ]
  592. ),
  593. ),
  594. ]
  595. )
  596. )
  597. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  598. zfs.__salt__, {"zfs.get": mock_get}
  599. ), patch.dict(zfs.__salt__, {"zfs.set": mock_set}), patch.dict(
  600. zfs.__utils__, self.utils_patch
  601. ):
  602. self.assertEqual(
  603. ret,
  604. zfs.volume_present(
  605. name="myzpool/volume",
  606. volume_size="1G",
  607. properties={"compression": "lz4"},
  608. ),
  609. )
  610. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  611. def test_volume_present_fail(self):
  612. """
  613. Test if volume is present (non existing pool)
  614. """
  615. ret = {
  616. "name": "myzpool/volume",
  617. "result": False,
  618. "comment": "cannot create 'myzpool/volume': no such pool 'myzpool'",
  619. "changes": {},
  620. }
  621. mock_exists = MagicMock(return_value=False)
  622. mock_create = MagicMock(
  623. return_value=OrderedDict(
  624. [
  625. ("created", False),
  626. ("error", "cannot create 'myzpool/volume': no such pool 'myzpool'"),
  627. ]
  628. )
  629. )
  630. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  631. zfs.__salt__, {"zfs.create": mock_create}
  632. ), patch.dict(zfs.__utils__, self.utils_patch):
  633. self.assertEqual(
  634. ret, zfs.volume_present("myzpool/volume", volume_size="1G")
  635. )
  636. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  637. def test_bookmark_present(self):
  638. """
  639. Test if bookmark is present (bookmark already present)
  640. """
  641. ret = {
  642. "name": "myzpool/filesystem#mybookmark",
  643. "result": True,
  644. "comment": "bookmark is present",
  645. "changes": {},
  646. }
  647. mock_exists = MagicMock(return_value=True)
  648. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  649. zfs.__utils__, self.utils_patch
  650. ):
  651. self.assertEqual(
  652. ret, zfs.bookmark_present("mybookmark", "myzpool/filesystem@snap")
  653. )
  654. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  655. def test_bookmark_present_new(self):
  656. """
  657. Test if bookmark is present (new)
  658. """
  659. ret = {
  660. "name": "myzpool/filesystem#mybookmark",
  661. "result": True,
  662. "comment": "myzpool/filesystem@snap bookmarked as myzpool/filesystem#mybookmark",
  663. "changes": {"myzpool/filesystem#mybookmark": "myzpool/filesystem@snap"},
  664. }
  665. mock_exists = MagicMock(return_value=False)
  666. mock_bookmark = MagicMock(return_value=OrderedDict([("bookmarked", True)]))
  667. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  668. zfs.__salt__, {"zfs.bookmark": mock_bookmark}
  669. ), patch.dict(zfs.__utils__, self.utils_patch):
  670. self.assertEqual(
  671. ret, zfs.bookmark_present("mybookmark", "myzpool/filesystem@snap")
  672. )
  673. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  674. def test_bookmark_present_fail(self):
  675. """
  676. Test if bookmark is present (using non existing snapshot)
  677. """
  678. ret = {
  679. "name": "myzpool/filesystem#mybookmark",
  680. "result": False,
  681. "comment": "cannot bookmark snapshot 'zsalt/filesystem@snap': dataset does not exist",
  682. "changes": {},
  683. }
  684. mock_exists = MagicMock(return_value=False)
  685. mock_bookmark = MagicMock(
  686. return_value=OrderedDict(
  687. [
  688. ("bookmarked", False),
  689. (
  690. "error",
  691. "cannot bookmark snapshot 'zsalt/filesystem@snap': dataset does not exist",
  692. ),
  693. ]
  694. )
  695. )
  696. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  697. zfs.__salt__, {"zfs.bookmark": mock_bookmark}
  698. ), patch.dict(zfs.__utils__, self.utils_patch):
  699. self.assertEqual(
  700. ret, zfs.bookmark_present("mybookmark", "myzpool/filesystem@snap")
  701. )
  702. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  703. def test_snapshot_present(self):
  704. """
  705. Test if snapshot is present (snapshot already present)
  706. """
  707. ret = {
  708. "name": "myzpool/filesystem@snap",
  709. "result": True,
  710. "comment": "snapshot is present",
  711. "changes": {},
  712. }
  713. mock_exists = MagicMock(return_value=True)
  714. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  715. zfs.__utils__, self.utils_patch
  716. ):
  717. self.assertEqual(ret, zfs.snapshot_present("myzpool/filesystem@snap"))
  718. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  719. def test_snapshot_present_new(self):
  720. """
  721. Test if snapshot is present (new)
  722. """
  723. ret = {
  724. "name": "myzpool/filesystem@snap",
  725. "result": True,
  726. "comment": "snapshot myzpool/filesystem@snap was created",
  727. "changes": {"myzpool/filesystem@snap": "snapshotted"},
  728. }
  729. mock_exists = MagicMock(return_value=False)
  730. mock_snapshot = MagicMock(return_value=OrderedDict([("snapshotted", True)]))
  731. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  732. zfs.__salt__, {"zfs.snapshot": mock_snapshot}
  733. ), patch.dict(zfs.__utils__, self.utils_patch):
  734. self.assertEqual(ret, zfs.snapshot_present("myzpool/filesystem@snap"))
  735. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  736. def test_snapshot_present_fail(self):
  737. """
  738. Test if snapshot is present (using non existing snapshot)
  739. """
  740. ret = {
  741. "name": "myzpool/filesystem@snap",
  742. "result": False,
  743. "comment": "cannot open 'myzpool/filesystem': dataset does not exist",
  744. "changes": {},
  745. }
  746. mock_exists = MagicMock(return_value=False)
  747. mock_snapshot = MagicMock(
  748. return_value=OrderedDict(
  749. [
  750. ("snapshotted", False),
  751. (
  752. "error",
  753. "cannot open 'myzpool/filesystem': dataset does not exist",
  754. ),
  755. ]
  756. )
  757. )
  758. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  759. zfs.__salt__, {"zfs.snapshot": mock_snapshot}
  760. ), patch.dict(zfs.__utils__, self.utils_patch):
  761. self.assertEqual(ret, zfs.snapshot_present("myzpool/filesystem@snap"))
  762. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  763. def test_propmoted(self):
  764. """
  765. Test promotion of clone (already promoted)
  766. """
  767. ret = {
  768. "name": "myzpool/filesystem",
  769. "result": True,
  770. "comment": "myzpool/filesystem already promoted",
  771. "changes": {},
  772. }
  773. mock_exists = MagicMock(return_value=True)
  774. mock_get = MagicMock(
  775. return_value=OrderedDict(
  776. [
  777. (
  778. "myzpool/filesystem",
  779. OrderedDict([("origin", OrderedDict([("value", "-")]))]),
  780. ),
  781. ]
  782. )
  783. )
  784. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  785. zfs.__salt__, {"zfs.get": mock_get}
  786. ), patch.dict(zfs.__utils__, self.utils_patch):
  787. self.assertEqual(ret, zfs.promoted("myzpool/filesystem"))
  788. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  789. def test_propmoted_clone(self):
  790. """
  791. Test promotion of clone
  792. """
  793. ret = {
  794. "name": "myzpool/filesystem",
  795. "result": True,
  796. "comment": "myzpool/filesystem promoted",
  797. "changes": {"myzpool/filesystem": "promoted"},
  798. }
  799. mock_exists = MagicMock(return_value=True)
  800. mock_get = MagicMock(
  801. return_value=OrderedDict(
  802. [
  803. (
  804. "myzpool/filesystem",
  805. OrderedDict(
  806. [
  807. (
  808. "origin",
  809. OrderedDict(
  810. [("value", "myzool/filesystem_source@clean")]
  811. ),
  812. ),
  813. ]
  814. ),
  815. ),
  816. ]
  817. )
  818. )
  819. mock_promote = MagicMock(return_value=OrderedDict([("promoted", True)]))
  820. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  821. zfs.__salt__, {"zfs.get": mock_get}
  822. ), patch.dict(zfs.__salt__, {"zfs.promote": mock_promote}), patch.dict(
  823. zfs.__utils__, self.utils_patch
  824. ):
  825. self.assertEqual(ret, zfs.promoted("myzpool/filesystem"))
  826. @pytest.mark.slow_test(seconds=1) # Test takes >0.1 and <=1 seconds
  827. def test_propmoted_fail(self):
  828. """
  829. Test promotion of clone (unknown dataset)
  830. """
  831. ret = {
  832. "name": "myzpool/filesystem",
  833. "result": False,
  834. "comment": "dataset myzpool/filesystem does not exist",
  835. "changes": {},
  836. }
  837. mock_exists = MagicMock(return_value=False)
  838. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  839. zfs.__utils__, self.utils_patch
  840. ):
  841. self.assertEqual(ret, zfs.promoted("myzpool/filesystem"))
  842. @pytest.mark.slow_test(seconds=5) # Test takes >1 and <=5 seconds
  843. def test_scheduled_snapshot_fail(self):
  844. """
  845. Test scheduled_snapshot of unknown dataset
  846. """
  847. ret = {
  848. "name": "myzpool/filesystem",
  849. "result": False,
  850. "comment": "dataset myzpool/filesystem does not exist",
  851. "changes": {},
  852. }
  853. mock_exists = MagicMock(return_value=False)
  854. with patch.dict(zfs.__salt__, {"zfs.exists": mock_exists}), patch.dict(
  855. zfs.__utils__, self.utils_patch
  856. ):
  857. self.assertEqual(
  858. ret,
  859. zfs.scheduled_snapshot(
  860. "myzpool/filesystem", "shadow", schedule={"hour": 6}
  861. ),
  862. )