test_zfs.py 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Tests for the zfs utils library
  4. :codeauthor: Jorge Schrauwen <sjorge@blackdot.be>
  5. :maintainer: Jorge Schrauwen <sjorge@blackdot.be>
  6. :maturity: new
  7. :platform: illumos,freebsd,linux
  8. .. versionadded:: 2018.3.1
  9. '''
  10. # Import Python libs
  11. from __future__ import absolute_import, unicode_literals, print_function
  12. # Import Salt Testing libs
  13. from tests.support.unit import skipIf, TestCase
  14. from tests.support.mock import (
  15. MagicMock,
  16. patch,
  17. NO_MOCK,
  18. NO_MOCK_REASON,
  19. )
  20. # Import Salt Execution module to test
  21. import salt.utils.zfs as zfs
  22. # Import Salt Utils
  23. import salt.loader
  24. from salt.utils.odict import OrderedDict
  25. # property_map mocks
  26. pmap_exec_zpool = {
  27. 'retcode': 2,
  28. 'stdout': '',
  29. 'stderr': "\n".join([
  30. 'missing property argument',
  31. 'usage:',
  32. ' get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...',
  33. '',
  34. 'the following properties are supported:',
  35. '',
  36. ' PROPERTY EDIT VALUES',
  37. '',
  38. ' allocated NO <size>',
  39. ' capacity NO <size>',
  40. ' dedupratio NO <1.00x or higher if deduped>',
  41. ' expandsize NO <size>',
  42. ' fragmentation NO <percent>',
  43. ' free NO <size>',
  44. ' freeing NO <size>',
  45. ' guid NO <guid>',
  46. ' health NO <state>',
  47. ' leaked NO <size>',
  48. ' size NO <size>',
  49. ' altroot YES <path>',
  50. ' autoexpand YES on | off',
  51. ' autoreplace YES on | off',
  52. ' bootfs YES <filesystem>',
  53. ' bootsize YES <size>',
  54. ' cachefile YES <file> | none',
  55. ' comment YES <comment-string>',
  56. ' dedupditto YES <threshold (min 100)>',
  57. ' delegation YES on | off',
  58. ' failmode YES wait | continue | panic',
  59. ' listsnapshots YES on | off',
  60. ' readonly YES on | off',
  61. ' version YES <version>',
  62. ' feature@... YES disabled | enabled | active',
  63. '',
  64. 'The feature@ properties must be appended with a feature name.',
  65. 'See zpool-features(5). ',
  66. ]),
  67. }
  68. pmap_zpool = {
  69. 'comment': {
  70. 'edit': True,
  71. 'type': 'str',
  72. 'values': '<comment-string>'
  73. },
  74. 'freeing': {
  75. 'edit': False,
  76. 'type': 'size',
  77. 'values': '<size>'
  78. },
  79. 'listsnapshots': {
  80. 'edit': True,
  81. 'type': 'bool',
  82. 'values': 'on | off'
  83. },
  84. 'leaked': {
  85. 'edit': False,
  86. 'type': 'size',
  87. 'values': '<size>'
  88. },
  89. 'version': {
  90. 'edit': True,
  91. 'type': 'numeric',
  92. 'values': '<version>'
  93. },
  94. 'write': {
  95. 'edit': False,
  96. 'type': 'size',
  97. 'values': '<size>'
  98. },
  99. 'replace': {
  100. 'edit': True,
  101. 'type': 'bool',
  102. 'values': 'on | off'
  103. },
  104. 'delegation': {
  105. 'edit': True,
  106. 'type': 'bool',
  107. 'values': 'on | off'
  108. },
  109. 'dedupditto': {
  110. 'edit': True,
  111. 'type': 'str',
  112. 'values': '<threshold (min 100)>'
  113. },
  114. 'autoexpand': {
  115. 'edit': True,
  116. 'type': 'bool',
  117. 'values': 'on | off'
  118. },
  119. 'alloc': {
  120. 'edit': False,
  121. 'type': 'size',
  122. 'values': '<size>'
  123. },
  124. 'allocated': {
  125. 'edit': False,
  126. 'type': 'size',
  127. 'values': '<size>'
  128. },
  129. 'guid': {
  130. 'edit': False,
  131. 'type': 'numeric',
  132. 'values': '<guid>'
  133. },
  134. 'size': {
  135. 'edit': False,
  136. 'type': 'size',
  137. 'values': '<size>'
  138. },
  139. 'cap': {
  140. 'edit': False,
  141. 'type': 'numeric',
  142. 'values': '<count>'
  143. },
  144. 'capacity': {
  145. 'edit': False,
  146. 'type': 'size',
  147. 'values': '<size>'
  148. },
  149. "capacity-alloc": {
  150. "edit": False,
  151. "type": "size",
  152. "values": "<size>"
  153. },
  154. "capacity-free": {
  155. "edit": False,
  156. "type": "size",
  157. "values": "<size>"
  158. },
  159. 'cachefile': {
  160. 'edit': True,
  161. 'type': 'str',
  162. 'values': '<file> | none'
  163. },
  164. "cksum": {
  165. "edit": False,
  166. "type": "numeric",
  167. "values": "<count>"
  168. },
  169. 'bootfs': {
  170. 'edit': True,
  171. 'type': 'str',
  172. 'values': '<filesystem>'
  173. },
  174. 'autoreplace': {
  175. 'edit': True,
  176. 'type': 'bool',
  177. 'values': 'on | off'
  178. },
  179. "bandwith-read": {
  180. "edit": False,
  181. "type": "size",
  182. "values": "<size>"
  183. },
  184. "bandwith-write": {
  185. "edit": False,
  186. "type": "size",
  187. "values": "<size>"
  188. },
  189. "operations-read": {
  190. "edit": False,
  191. "type": "size",
  192. "values": "<size>"
  193. },
  194. "operations-write": {
  195. "edit": False,
  196. "type": "size",
  197. "values": "<size>"
  198. },
  199. "read": {
  200. "edit": False,
  201. "type": "size",
  202. "values": "<size>"
  203. },
  204. 'readonly': {
  205. 'edit': True,
  206. 'type': 'bool',
  207. 'values': 'on | off'
  208. },
  209. 'dedupratio': {
  210. 'edit': False,
  211. 'type': 'str',
  212. 'values': '<1.00x or higher if deduped>'
  213. },
  214. 'health': {
  215. 'edit': False,
  216. 'type': 'str',
  217. 'values': '<state>'
  218. },
  219. 'feature@': {
  220. 'edit': True,
  221. 'type': 'str',
  222. 'values': 'disabled | enabled | active'
  223. },
  224. 'expandsize': {
  225. 'edit': False,
  226. 'type': 'size',
  227. 'values': '<size>'
  228. },
  229. 'listsnaps': {
  230. 'edit': True,
  231. 'type': 'bool',
  232. 'values': 'on | off'
  233. },
  234. 'bootsize': {
  235. 'edit': True,
  236. 'type': 'size',
  237. 'values': '<size>'
  238. },
  239. 'free': {
  240. 'edit': False,
  241. 'type': 'size',
  242. 'values': '<size>'
  243. },
  244. 'failmode': {
  245. 'edit': True,
  246. 'type': 'str',
  247. 'values': 'wait | continue | panic'
  248. },
  249. 'altroot': {
  250. 'edit': True,
  251. 'type': 'str',
  252. 'values': '<path>'
  253. },
  254. 'expand': {
  255. 'edit': True,
  256. 'type': 'bool',
  257. 'values': 'on | off'
  258. },
  259. 'frag': {
  260. 'edit': False,
  261. 'type': 'str',
  262. 'values': '<percent>'
  263. },
  264. 'fragmentation': {
  265. 'edit': False,
  266. 'type': 'str',
  267. 'values': '<percent>'
  268. }
  269. }
  270. pmap_exec_zfs = {
  271. 'retcode': 2,
  272. 'stdout': '',
  273. 'stderr': "\n".join([
  274. 'missing property argument',
  275. 'usage:',
  276. ' get [-crHp] [-d max] [-o "all" | field[,...]]',
  277. ' [-t type[,...]] [-s source[,...]]',
  278. ' <"all" | property[,...]> [filesystem|volume|snapshot|bookmark] ...',
  279. '',
  280. 'The following properties are supported:',
  281. '',
  282. ' PROPERTY EDIT INHERIT VALUES',
  283. '',
  284. ' available NO NO <size>',
  285. ' clones NO NO <dataset>[,...]',
  286. ' compressratio NO NO <1.00x or higher if compressed>',
  287. ' creation NO NO <date>',
  288. ' defer_destroy NO NO yes | no',
  289. ' filesystem_count NO NO <count>',
  290. ' logicalreferenced NO NO <size>',
  291. ' logicalused NO NO <size>',
  292. ' mounted NO NO yes | no',
  293. ' origin NO NO <snapshot>',
  294. ' receive_resume_token NO NO <string token>',
  295. ' refcompressratio NO NO <1.00x or higher if compressed>',
  296. ' referenced NO NO <size>',
  297. ' snapshot_count NO NO <count>',
  298. ' type NO NO filesystem | volume | snapshot | bookmark',
  299. ' used NO NO <size>',
  300. ' usedbychildren NO NO <size>',
  301. ' usedbydataset NO NO <size>',
  302. ' usedbyrefreservation NO NO <size>',
  303. ' usedbysnapshots NO NO <size>',
  304. ' userrefs NO NO <count>',
  305. ' written NO NO <size>',
  306. ' aclinherit YES YES discard | noallow | restricted | passthrough | passthrough-x',
  307. ' aclmode YES YES discard | groupmask | passthrough | restricted',
  308. ' atime YES YES on | off',
  309. ' canmount YES NO on | off | noauto',
  310. ' casesensitivity NO YES sensitive | insensitive | mixed',
  311. ' checksum YES YES on | off | fletcher2 | fletcher4 | sha256 | sha512 | skein | edonr',
  312. ' compression YES YES on | off | lzjb | gzip | gzip-[1-9] | zle | lz4',
  313. ' copies YES YES 1 | 2 | 3',
  314. ' dedup YES YES on | off | verify | sha256[,verify], sha512[,verify], skein[,verify], edonr,verify',
  315. ' devices YES YES on | off',
  316. ' exec YES YES on | off',
  317. ' filesystem_limit YES NO <count> | none',
  318. ' logbias YES YES latency | throughput',
  319. ' mlslabel YES YES <sensitivity label>',
  320. ' mountpoint YES YES <path> | legacy | none',
  321. ' nbmand YES YES on | off',
  322. ' normalization NO YES none | formC | formD | formKC | formKD',
  323. ' primarycache YES YES all | none | metadata',
  324. ' quota YES NO <size> | none',
  325. ' readonly YES YES on | off',
  326. ' recordsize YES YES 512 to 1M, power of 2',
  327. ' redundant_metadata YES YES all | most',
  328. ' refquota YES NO <size> | none',
  329. ' refreservation YES NO <size> | none',
  330. ' reservation YES NO <size> | none',
  331. ' secondarycache YES YES all | none | metadata',
  332. ' setuid YES YES on | off',
  333. ' sharenfs YES YES on | off | share(1M) options',
  334. ' sharesmb YES YES on | off | sharemgr(1M) options',
  335. ' snapdir YES YES hidden | visible',
  336. ' snapshot_limit YES NO <count> | none',
  337. ' sync YES YES standard | always | disabled',
  338. ' utf8only NO YES on | off',
  339. ' version YES NO 1 | 2 | 3 | 4 | 5 | current',
  340. ' volblocksize NO YES 512 to 128k, power of 2',
  341. ' volsize YES NO <size>',
  342. ' vscan YES YES on | off',
  343. ' xattr YES YES on | off',
  344. ' zoned YES YES on | off',
  345. ' userused@... NO NO <size>',
  346. ' groupused@... NO NO <size>',
  347. ' userquota@... YES NO <size> | none',
  348. ' groupquota@... YES NO <size> | none',
  349. ' written@<snap> NO NO <size>',
  350. '',
  351. 'Sizes are specified in bytes with standard units such as K, M, G, etc.',
  352. '',
  353. 'User-defined properties can be specified by using a name containing a colon (:).',
  354. '',
  355. 'The {user|group}{used|quota}@ properties must be appended with',
  356. 'a user or group specifier of one of these forms:',
  357. ' POSIX name (eg: "matt")',
  358. ' POSIX id (eg: "126829")',
  359. ' SMB name@domain (eg: "matt@sun")',
  360. ' SMB SID (eg: "S-1-234-567-89")',
  361. ]),
  362. }
  363. pmap_zfs = {
  364. "origin": {
  365. "edit": False,
  366. "inherit": False,
  367. "values": "<snapshot>",
  368. "type": "str"
  369. },
  370. "setuid": {
  371. "edit": True,
  372. "inherit": True,
  373. "values": "on | off",
  374. "type": "bool"
  375. },
  376. "referenced": {
  377. "edit": False,
  378. "inherit": False,
  379. "values": "<size>",
  380. "type": "size"
  381. },
  382. "vscan": {
  383. "edit": True,
  384. "inherit": True,
  385. "values": "on | off",
  386. "type": "bool"
  387. },
  388. "logicalused": {
  389. "edit": False,
  390. "inherit": False,
  391. "values": "<size>",
  392. "type": "size"
  393. },
  394. "userrefs": {
  395. "edit": False,
  396. "inherit": False,
  397. "values": "<count>",
  398. "type": "numeric"
  399. },
  400. "primarycache": {
  401. "edit": True,
  402. "inherit": True,
  403. "values": "all | none | metadata",
  404. "type": "str"
  405. },
  406. "logbias": {
  407. "edit": True,
  408. "inherit": True,
  409. "values": "latency | throughput",
  410. "type": "str"
  411. },
  412. "creation": {
  413. "edit": False,
  414. "inherit": False,
  415. "values": "<date>",
  416. "type": "str"
  417. },
  418. "sync": {
  419. "edit": True,
  420. "inherit": True,
  421. "values": "standard | always | disabled",
  422. "type": "str"
  423. },
  424. "dedup": {
  425. "edit": True,
  426. "inherit": True,
  427. "values": "on | off | verify | sha256[,verify], sha512[,verify], skein[,verify], edonr,verify",
  428. "type": "bool"
  429. },
  430. "sharenfs": {
  431. "edit": True,
  432. "inherit": True,
  433. "values": "on | off | share(1m) options",
  434. "type": "bool"
  435. },
  436. "receive_resume_token": {
  437. "edit": False,
  438. "inherit": False,
  439. "values": "<string token>",
  440. "type": "str"
  441. },
  442. "usedbyrefreservation": {
  443. "edit": False,
  444. "inherit": False,
  445. "values": "<size>",
  446. "type": "size"
  447. },
  448. "sharesmb": {
  449. "edit": True,
  450. "inherit": True,
  451. "values": "on | off | sharemgr(1m) options",
  452. "type": "bool"
  453. },
  454. "rdonly": {
  455. "edit": True,
  456. "inherit": True,
  457. "values": "on | off",
  458. "type": "bool"
  459. },
  460. "reservation": {
  461. "edit": True,
  462. "inherit": False,
  463. "values": "<size> | none",
  464. "type": "size"
  465. },
  466. "reserv": {
  467. "edit": True,
  468. "inherit": False,
  469. "values": "<size> | none",
  470. "type": "size"
  471. },
  472. "mountpoint": {
  473. "edit": True,
  474. "inherit": True,
  475. "values": "<path> | legacy | none",
  476. "type": "str"
  477. },
  478. "casesensitivity": {
  479. "edit": False,
  480. "inherit": True,
  481. "values": "sensitive | insensitive | mixed",
  482. "type": "str"
  483. },
  484. "utf8only": {
  485. "edit": False,
  486. "inherit": True,
  487. "values": "on | off",
  488. "type": "bool"
  489. },
  490. "usedbysnapshots": {
  491. "edit": False,
  492. "inherit": False,
  493. "values": "<size>",
  494. "type": "size"
  495. },
  496. "readonly": {
  497. "edit": True,
  498. "inherit": True,
  499. "values": "on | off",
  500. "type": "bool"
  501. },
  502. "written@": {
  503. "edit": False,
  504. "inherit": False,
  505. "values": "<size>",
  506. "type": "size"
  507. },
  508. "avail": {
  509. "edit": False,
  510. "inherit": False,
  511. "values": "<size>",
  512. "type": "size"
  513. },
  514. "recsize": {
  515. "edit": True,
  516. "inherit": True,
  517. "values": "512 to 1m, power of 2",
  518. "type": "str"
  519. },
  520. "atime": {
  521. "edit": True,
  522. "inherit": True,
  523. "values": "on | off",
  524. "type": "bool"
  525. },
  526. "compression": {
  527. "edit": True,
  528. "inherit": True,
  529. "values": "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4",
  530. "type": "bool"
  531. },
  532. "snapdir": {
  533. "edit": True,
  534. "inherit": True,
  535. "values": "hidden | visible",
  536. "type": "str"
  537. },
  538. "aclmode": {
  539. "edit": True,
  540. "inherit": True,
  541. "values": "discard | groupmask | passthrough | restricted",
  542. "type": "str"
  543. },
  544. "zoned": {
  545. "edit": True,
  546. "inherit": True,
  547. "values": "on | off",
  548. "type": "bool"
  549. },
  550. "copies": {
  551. "edit": True,
  552. "inherit": True,
  553. "values": "1 | 2 | 3",
  554. "type": "numeric"
  555. },
  556. "snapshot_limit": {
  557. "edit": True,
  558. "inherit": False,
  559. "values": "<count> | none",
  560. "type": "numeric"
  561. },
  562. "aclinherit": {
  563. "edit": True,
  564. "inherit": True,
  565. "values": "discard | noallow | restricted | passthrough | passthrough-x",
  566. "type": "str"
  567. },
  568. "compressratio": {
  569. "edit": False,
  570. "inherit": False,
  571. "values": "<1.00x or higher if compressed>",
  572. "type": "str"
  573. },
  574. "xattr": {
  575. "edit": True,
  576. "inherit": True,
  577. "values": "on | off",
  578. "type": "bool"
  579. },
  580. "written": {
  581. "edit": False,
  582. "inherit": False,
  583. "values": "<size>",
  584. "type": "size"
  585. },
  586. "version": {
  587. "edit": True,
  588. "inherit": False,
  589. "values": "1 | 2 | 3 | 4 | 5 | current",
  590. "type": "numeric"
  591. },
  592. "recordsize": {
  593. "edit": True,
  594. "inherit": True,
  595. "values": "512 to 1m, power of 2",
  596. "type": "str"
  597. },
  598. "refquota": {
  599. "edit": True,
  600. "inherit": False,
  601. "values": "<size> | none",
  602. "type": "size"
  603. },
  604. "filesystem_limit": {
  605. "edit": True,
  606. "inherit": False,
  607. "values": "<count> | none",
  608. "type": "numeric"
  609. },
  610. "lrefer.": {
  611. "edit": False,
  612. "inherit": False,
  613. "values": "<size>",
  614. "type": "size"
  615. },
  616. "type": {
  617. "edit": False,
  618. "inherit": False,
  619. "values": "filesystem | volume | snapshot | bookmark",
  620. "type": "str"
  621. },
  622. "secondarycache": {
  623. "edit": True,
  624. "inherit": True,
  625. "values": "all | none | metadata",
  626. "type": "str"
  627. },
  628. "refer": {
  629. "edit": False,
  630. "inherit": False,
  631. "values": "<size>",
  632. "type": "size"
  633. },
  634. "available": {
  635. "edit": False,
  636. "inherit": False,
  637. "values": "<size>",
  638. "type": "size"
  639. },
  640. "used": {
  641. "edit": False,
  642. "inherit": False,
  643. "values": "<size>",
  644. "type": "size"
  645. },
  646. "exec": {
  647. "edit": True,
  648. "inherit": True,
  649. "values": "on | off",
  650. "type": "bool"
  651. },
  652. "compress": {
  653. "edit": True,
  654. "inherit": True,
  655. "values": "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4",
  656. "type": "bool"
  657. },
  658. "volblock": {
  659. "edit": False,
  660. "inherit": True,
  661. "values": "512 to 128k, power of 2",
  662. "type": "str"
  663. },
  664. "refcompressratio": {
  665. "edit": False,
  666. "inherit": False,
  667. "values": "<1.00x or higher if compressed>",
  668. "type": "str"
  669. },
  670. "quota": {
  671. "edit": True,
  672. "inherit": False,
  673. "values": "<size> | none",
  674. "type": "size"
  675. },
  676. "groupquota@": {
  677. "edit": True,
  678. "inherit": False,
  679. "values": "<size> | none",
  680. "type": "size"
  681. },
  682. "userquota@": {
  683. "edit": True,
  684. "inherit": False,
  685. "values": "<size> | none",
  686. "type": "size"
  687. },
  688. "snapshot_count": {
  689. "edit": False,
  690. "inherit": False,
  691. "values": "<count>",
  692. "type": "numeric"
  693. },
  694. "volsize": {
  695. "edit": True,
  696. "inherit": False,
  697. "values": "<size>",
  698. "type": "size"
  699. },
  700. "clones": {
  701. "edit": False,
  702. "inherit": False,
  703. "values": "<dataset>[,...]",
  704. "type": "str"
  705. },
  706. "canmount": {
  707. "edit": True,
  708. "inherit": False,
  709. "values": "on | off | noauto",
  710. "type": "bool"
  711. },
  712. "mounted": {
  713. "edit": False,
  714. "inherit": False,
  715. "values": "yes | no",
  716. "type": "bool_alt"
  717. },
  718. "groupused@": {
  719. "edit": False,
  720. "inherit": False,
  721. "values": "<size>",
  722. "type": "size"
  723. },
  724. "normalization": {
  725. "edit": False,
  726. "inherit": True,
  727. "values": "none | formc | formd | formkc | formkd",
  728. "type": "str"
  729. },
  730. "usedbychildren": {
  731. "edit": False,
  732. "inherit": False,
  733. "values": "<size>",
  734. "type": "size"
  735. },
  736. "usedbydataset": {
  737. "edit": False,
  738. "inherit": False,
  739. "values": "<size>",
  740. "type": "size"
  741. },
  742. "mlslabel": {
  743. "edit": True,
  744. "inherit": True,
  745. "values": "<sensitivity label>",
  746. "type": "str"
  747. },
  748. "refreserv": {
  749. "edit": True,
  750. "inherit": False,
  751. "values": "<size> | none",
  752. "type": "size"
  753. },
  754. "defer_destroy": {
  755. "edit": False,
  756. "inherit": False,
  757. "values": "yes | no",
  758. "type": "bool_alt"
  759. },
  760. "volblocksize": {
  761. "edit": False,
  762. "inherit": True,
  763. "values": "512 to 128k, power of 2",
  764. "type": "str"
  765. },
  766. "lused.": {
  767. "edit": False,
  768. "inherit": False,
  769. "values": "<size>",
  770. "type": "size"
  771. },
  772. "redundant_metadata": {
  773. "edit": True,
  774. "inherit": True,
  775. "values": "all | most",
  776. "type": "str"
  777. },
  778. "filesystem_count": {
  779. "edit": False,
  780. "inherit": False,
  781. "values": "<count>",
  782. "type": "numeric"
  783. },
  784. "devices": {
  785. "edit": True,
  786. "inherit": True,
  787. "values": "on | off",
  788. "type": "bool"
  789. },
  790. "refreservation": {
  791. "edit": True,
  792. "inherit": False,
  793. "values": "<size> | none",
  794. "type": "size"
  795. },
  796. "userused@": {
  797. "edit": False,
  798. "inherit": False,
  799. "values": "<size>",
  800. "type": "size"
  801. },
  802. "logicalreferenced": {
  803. "edit": False,
  804. "inherit": False,
  805. "values": "<size>",
  806. "type": "size"
  807. },
  808. "checksum": {
  809. "edit": True,
  810. "inherit": True,
  811. "values": "on | off | fletcher2 | fletcher4 | sha256 | sha512 | skein | edonr",
  812. "type": "bool"
  813. },
  814. "nbmand": {
  815. "edit": True,
  816. "inherit": True,
  817. "values": "on | off",
  818. "type": "bool"
  819. }
  820. }
  821. def _from_auto(name, value, source='auto'):
  822. '''
  823. some more complex patching for zfs.from_auto
  824. '''
  825. with patch.object(salt.utils.zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)), \
  826. patch.object(salt.utils.zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  827. return salt.utils.zfs.from_auto(name, value, source)
  828. def _from_auto_dict(values, source='auto'):
  829. '''
  830. some more complex patching for zfs.from_auto_dict
  831. '''
  832. with patch.object(salt.utils.zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)), \
  833. patch.object(salt.utils.zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  834. return salt.utils.zfs.from_auto_dict(values, source)
  835. def _to_auto(name, value, source='auto', convert_to_human=True):
  836. '''
  837. some more complex patching for zfs.to_auto
  838. '''
  839. with patch.object(salt.utils.zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)), \
  840. patch.object(salt.utils.zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  841. return salt.utils.zfs.to_auto(name, value, source, convert_to_human)
  842. def _to_auto_dict(values, source='auto', convert_to_human=True):
  843. '''
  844. some more complex patching for zfs.to_auto_dict
  845. '''
  846. with patch.object(salt.utils.zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)), \
  847. patch.object(salt.utils.zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  848. return salt.utils.zfs.to_auto_dict(values, source, convert_to_human)
  849. utils_patch = {
  850. 'zfs.is_supported': MagicMock(return_value=True),
  851. 'zfs.has_feature_flags': MagicMock(return_value=True),
  852. 'zfs.property_data_zpool': MagicMock(return_value=pmap_zpool),
  853. 'zfs.property_data_zfs': MagicMock(return_value=pmap_zfs),
  854. # NOTE: we make zpool_command and zfs_command a NOOP
  855. # these are extensively tested in tests.unit.utils.test_zfs
  856. 'zfs.zpool_command': MagicMock(return_value='/bin/false'),
  857. 'zfs.zfs_command': MagicMock(return_value='/bin/false'),
  858. # NOTE: from_auto_dict is a special snowflake
  859. # internally it calls multiple calls from
  860. # salt.utils.zfs but we cannot patch those using
  861. # the common methode, __utils__ is not available
  862. # so they are direct calls, we do some voodoo here.
  863. 'zfs.from_auto_dict': _from_auto_dict,
  864. 'zfs.from_auto': _from_auto,
  865. 'zfs.to_auto_dict': _to_auto_dict,
  866. 'zfs.to_auto': _to_auto,
  867. }
  868. # Skip this test case if we don't have access to mock!
  869. @skipIf(NO_MOCK, NO_MOCK_REASON)
  870. class ZfsUtilsTestCase(TestCase):
  871. '''
  872. This class contains a set of functions that test salt.utils.zfs utils
  873. '''
  874. ## NOTE: test parameter parsing
  875. def test_is_supported(self):
  876. '''
  877. Test zfs.is_supported method
  878. '''
  879. for value in [False, True]:
  880. with patch('salt.utils.path.which',
  881. MagicMock(return_value=value)):
  882. with patch('salt.utils.platform.is_linux',
  883. MagicMock(return_value=value)):
  884. self.assertEqual(value, zfs.is_supported())
  885. def test_property_data_zpool(self):
  886. '''
  887. Test parsing of zpool get output
  888. '''
  889. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  890. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  891. with patch.object(zfs, '_exec', MagicMock(return_value=pmap_exec_zpool)):
  892. self.assertEqual(zfs.property_data_zpool(), pmap_zpool)
  893. def test_property_data_zfs(self):
  894. '''
  895. Test parsing of zfs get output
  896. '''
  897. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  898. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  899. with patch.object(zfs, '_exec', MagicMock(return_value=pmap_exec_zfs)):
  900. self.assertEqual(zfs.property_data_zfs(), pmap_zfs)
  901. ## NOTE: testing from_bool results
  902. def test_from_bool_on(self):
  903. '''
  904. Test from_bool with 'on'
  905. '''
  906. self.assertTrue(zfs.from_bool('on'))
  907. self.assertTrue(zfs.from_bool(zfs.from_bool('on')))
  908. def test_from_bool_off(self):
  909. '''
  910. Test from_bool with 'off'
  911. '''
  912. self.assertFalse(zfs.from_bool('off'))
  913. self.assertFalse(zfs.from_bool(zfs.from_bool('off')))
  914. def test_from_bool_none(self):
  915. '''
  916. Test from_bool with 'none'
  917. '''
  918. self.assertEqual(zfs.from_bool('none'), None)
  919. self.assertEqual(zfs.from_bool(zfs.from_bool('none')), None)
  920. def test_from_bool_passthrough(self):
  921. '''
  922. Test from_bool with 'passthrough'
  923. '''
  924. self.assertEqual(zfs.from_bool('passthrough'), 'passthrough')
  925. self.assertEqual(zfs.from_bool(zfs.from_bool('passthrough')), 'passthrough')
  926. def test_from_bool_alt_yes(self):
  927. '''
  928. Test from_bool_alt with 'yes'
  929. '''
  930. self.assertTrue(zfs.from_bool_alt('yes'))
  931. self.assertTrue(zfs.from_bool_alt(zfs.from_bool_alt('yes')))
  932. def test_from_bool_alt_no(self):
  933. '''
  934. Test from_bool_alt with 'no'
  935. '''
  936. self.assertFalse(zfs.from_bool_alt('no'))
  937. self.assertFalse(zfs.from_bool_alt(zfs.from_bool_alt('no')))
  938. def test_from_bool_alt_none(self):
  939. '''
  940. Test from_bool_alt with 'none'
  941. '''
  942. self.assertEqual(zfs.from_bool_alt('none'), None)
  943. self.assertEqual(zfs.from_bool_alt(zfs.from_bool_alt('none')), None)
  944. def test_from_bool_alt_passthrough(self):
  945. '''
  946. Test from_bool_alt with 'passthrough'
  947. '''
  948. self.assertEqual(zfs.from_bool_alt('passthrough'), 'passthrough')
  949. self.assertEqual(zfs.from_bool_alt(zfs.from_bool_alt('passthrough')), 'passthrough')
  950. ## NOTE: testing to_bool results
  951. def test_to_bool_true(self):
  952. '''
  953. Test to_bool with True
  954. '''
  955. self.assertEqual(zfs.to_bool(True), 'on')
  956. self.assertEqual(zfs.to_bool(zfs.to_bool(True)), 'on')
  957. def test_to_bool_false(self):
  958. '''
  959. Test to_bool with False
  960. '''
  961. self.assertEqual(zfs.to_bool(False), 'off')
  962. self.assertEqual(zfs.to_bool(zfs.to_bool(False)), 'off')
  963. def test_to_bool_none(self):
  964. '''
  965. Test to_bool with None
  966. '''
  967. self.assertEqual(zfs.to_bool(None), 'none')
  968. self.assertEqual(zfs.to_bool(zfs.to_bool(None)), 'none')
  969. def test_to_bool_passthrough(self):
  970. '''
  971. Test to_bool with 'passthrough'
  972. '''
  973. self.assertEqual(zfs.to_bool('passthrough'), 'passthrough')
  974. self.assertEqual(zfs.to_bool(zfs.to_bool('passthrough')), 'passthrough')
  975. def test_to_bool_alt_true(self):
  976. '''
  977. Test to_bool_alt with True
  978. '''
  979. self.assertEqual(zfs.to_bool_alt(True), 'yes')
  980. self.assertEqual(zfs.to_bool_alt(zfs.to_bool_alt(True)), 'yes')
  981. def test_to_bool_alt_false(self):
  982. '''
  983. Test to_bool_alt with False
  984. '''
  985. self.assertEqual(zfs.to_bool_alt(False), 'no')
  986. self.assertEqual(zfs.to_bool_alt(zfs.to_bool_alt(False)), 'no')
  987. def test_to_bool_alt_none(self):
  988. '''
  989. Test to_bool_alt with None
  990. '''
  991. self.assertEqual(zfs.to_bool_alt(None), 'none')
  992. self.assertEqual(zfs.to_bool_alt(zfs.to_bool_alt(None)), 'none')
  993. def test_to_bool_alt_passthrough(self):
  994. '''
  995. Test to_bool_alt with 'passthrough'
  996. '''
  997. self.assertEqual(zfs.to_bool_alt('passthrough'), 'passthrough')
  998. self.assertEqual(zfs.to_bool_alt(zfs.to_bool_alt('passthrough')), 'passthrough')
  999. ## NOTE: testing from_numeric results
  1000. def test_from_numeric_str(self):
  1001. '''
  1002. Test from_numeric with '42'
  1003. '''
  1004. self.assertEqual(zfs.from_numeric('42'), 42)
  1005. self.assertEqual(zfs.from_numeric(zfs.from_numeric('42')), 42)
  1006. def test_from_numeric_int(self):
  1007. '''
  1008. Test from_numeric with 42
  1009. '''
  1010. self.assertEqual(zfs.from_numeric(42), 42)
  1011. self.assertEqual(zfs.from_numeric(zfs.from_numeric(42)), 42)
  1012. def test_from_numeric_none(self):
  1013. '''
  1014. Test from_numeric with 'none'
  1015. '''
  1016. self.assertEqual(zfs.from_numeric('none'), None)
  1017. self.assertEqual(zfs.from_numeric(zfs.from_numeric('none')), None)
  1018. def test_from_numeric_passthrough(self):
  1019. '''
  1020. Test from_numeric with 'passthrough'
  1021. '''
  1022. self.assertEqual(zfs.from_numeric('passthrough'), 'passthrough')
  1023. self.assertEqual(zfs.from_numeric(zfs.from_numeric('passthrough')), 'passthrough')
  1024. ## NOTE: testing to_numeric results
  1025. def test_to_numeric_str(self):
  1026. '''
  1027. Test to_numeric with '42'
  1028. '''
  1029. self.assertEqual(zfs.to_numeric('42'), 42)
  1030. self.assertEqual(zfs.to_numeric(zfs.to_numeric('42')), 42)
  1031. def test_to_numeric_int(self):
  1032. '''
  1033. Test to_numeric with 42
  1034. '''
  1035. self.assertEqual(zfs.to_numeric(42), 42)
  1036. self.assertEqual(zfs.to_numeric(zfs.to_numeric(42)), 42)
  1037. def test_to_numeric_none(self):
  1038. '''
  1039. Test to_numeric with 'none'
  1040. '''
  1041. self.assertEqual(zfs.to_numeric(None), 'none')
  1042. self.assertEqual(zfs.to_numeric(zfs.to_numeric(None)), 'none')
  1043. def test_to_numeric_passthrough(self):
  1044. '''
  1045. Test to_numeric with 'passthrough'
  1046. '''
  1047. self.assertEqual(zfs.to_numeric('passthrough'), 'passthrough')
  1048. self.assertEqual(zfs.to_numeric(zfs.to_numeric('passthrough')), 'passthrough')
  1049. ## NOTE: testing from_size results
  1050. def test_from_size_absolute(self):
  1051. '''
  1052. Test from_size with '5G'
  1053. '''
  1054. self.assertEqual(zfs.from_size('5G'), 5368709120)
  1055. self.assertEqual(zfs.from_size(zfs.from_size('5G')), 5368709120)
  1056. def test_from_size_decimal(self):
  1057. '''
  1058. Test from_size with '4.20M'
  1059. '''
  1060. self.assertEqual(zfs.from_size('4.20M'), 4404019)
  1061. self.assertEqual(zfs.from_size(zfs.from_size('4.20M')), 4404019)
  1062. def test_from_size_none(self):
  1063. '''
  1064. Test from_size with 'none'
  1065. '''
  1066. self.assertEqual(zfs.from_size('none'), None)
  1067. self.assertEqual(zfs.from_size(zfs.from_size('none')), None)
  1068. def test_from_size_passthrough(self):
  1069. '''
  1070. Test from_size with 'passthrough'
  1071. '''
  1072. self.assertEqual(zfs.from_size('passthrough'), 'passthrough')
  1073. self.assertEqual(zfs.from_size(zfs.from_size('passthrough')), 'passthrough')
  1074. ## NOTE: testing to_size results
  1075. def test_to_size_str_absolute(self):
  1076. '''
  1077. Test to_size with '5368709120'
  1078. '''
  1079. self.assertEqual(zfs.to_size('5368709120'), '5G')
  1080. self.assertEqual(zfs.to_size(zfs.to_size('5368709120')), '5G')
  1081. def test_to_size_str_decimal(self):
  1082. '''
  1083. Test to_size with '4404019'
  1084. '''
  1085. self.assertEqual(zfs.to_size('4404019'), '4.20M')
  1086. self.assertEqual(zfs.to_size(zfs.to_size('4404019')), '4.20M')
  1087. def test_to_size_int_absolute(self):
  1088. '''
  1089. Test to_size with 5368709120
  1090. '''
  1091. self.assertEqual(zfs.to_size(5368709120), '5G')
  1092. self.assertEqual(zfs.to_size(zfs.to_size(5368709120)), '5G')
  1093. def test_to_size_int_decimal(self):
  1094. '''
  1095. Test to_size with 4404019
  1096. '''
  1097. self.assertEqual(zfs.to_size(4404019), '4.20M')
  1098. self.assertEqual(zfs.to_size(zfs.to_size(4404019)), '4.20M')
  1099. def test_to_size_none(self):
  1100. '''
  1101. Test to_size with 'none'
  1102. '''
  1103. self.assertEqual(zfs.to_size(None), 'none')
  1104. self.assertEqual(zfs.to_size(zfs.to_size(None)), 'none')
  1105. def test_to_size_passthrough(self):
  1106. '''
  1107. Test to_size with 'passthrough'
  1108. '''
  1109. self.assertEqual(zfs.to_size('passthrough'), 'passthrough')
  1110. self.assertEqual(zfs.to_size(zfs.to_size('passthrough')), 'passthrough')
  1111. ## NOTE: testing from_str results
  1112. def test_from_str_space(self):
  1113. '''
  1114. Test from_str with "\"my pool/my dataset\"
  1115. '''
  1116. self.assertEqual(zfs.from_str('"my pool/my dataset"'), 'my pool/my dataset')
  1117. self.assertEqual(zfs.from_str(zfs.from_str('"my pool/my dataset"')), 'my pool/my dataset')
  1118. def test_from_str_squote_space(self):
  1119. '''
  1120. Test from_str with "my pool/jorge's dataset"
  1121. '''
  1122. self.assertEqual(zfs.from_str("my pool/jorge's dataset"), "my pool/jorge's dataset")
  1123. self.assertEqual(zfs.from_str(zfs.from_str("my pool/jorge's dataset")), "my pool/jorge's dataset")
  1124. def test_from_str_dquote_space(self):
  1125. '''
  1126. Test from_str with "my pool/the \"good\" stuff"
  1127. '''
  1128. self.assertEqual(zfs.from_str("my pool/the \"good\" stuff"), 'my pool/the "good" stuff')
  1129. self.assertEqual(zfs.from_str(zfs.from_str("my pool/the \"good\" stuff")), 'my pool/the "good" stuff')
  1130. def test_from_str_none(self):
  1131. '''
  1132. Test from_str with 'none'
  1133. '''
  1134. self.assertEqual(zfs.from_str('none'), None)
  1135. self.assertEqual(zfs.from_str(zfs.from_str('none')), None)
  1136. def test_from_str_passthrough(self):
  1137. '''
  1138. Test from_str with 'passthrough'
  1139. '''
  1140. self.assertEqual(zfs.from_str('passthrough'), 'passthrough')
  1141. self.assertEqual(zfs.from_str(zfs.from_str('passthrough')), 'passthrough')
  1142. ## NOTE: testing to_str results
  1143. def test_to_str_space(self):
  1144. '''
  1145. Test to_str with 'my pool/my dataset'
  1146. '''
  1147. ## NOTE: for fun we use both the '"str"' and "\"str\"" way of getting the literal string: "str"
  1148. self.assertEqual(zfs.to_str('my pool/my dataset'), '"my pool/my dataset"')
  1149. self.assertEqual(zfs.to_str(zfs.to_str('my pool/my dataset')), "\"my pool/my dataset\"")
  1150. def test_to_str_squote_space(self):
  1151. '''
  1152. Test to_str with "my pool/jorge's dataset"
  1153. '''
  1154. self.assertEqual(zfs.to_str("my pool/jorge's dataset"), "\"my pool/jorge's dataset\"")
  1155. self.assertEqual(zfs.to_str(zfs.to_str("my pool/jorge's dataset")), "\"my pool/jorge's dataset\"")
  1156. def test_to_str_none(self):
  1157. '''
  1158. Test to_str with 'none'
  1159. '''
  1160. self.assertEqual(zfs.to_str(None), 'none')
  1161. self.assertEqual(zfs.to_str(zfs.to_str(None)), 'none')
  1162. def test_to_str_passthrough(self):
  1163. '''
  1164. Test to_str with 'passthrough'
  1165. '''
  1166. self.assertEqual(zfs.to_str('passthrough'), 'passthrough')
  1167. self.assertEqual(zfs.to_str(zfs.to_str('passthrough')), 'passthrough')
  1168. ## NOTE: testing is_snapshot
  1169. def test_is_snapshot_snapshot(self):
  1170. '''
  1171. Test is_snapshot with a valid snapshot name
  1172. '''
  1173. self.assertTrue(zfs.is_snapshot('zpool_name/dataset@backup'))
  1174. def test_is_snapshot_bookmark(self):
  1175. '''
  1176. Test is_snapshot with a valid bookmark name
  1177. '''
  1178. self.assertFalse(zfs.is_snapshot('zpool_name/dataset#backup'))
  1179. def test_is_snapshot_filesystem(self):
  1180. '''
  1181. Test is_snapshot with a valid filesystem name
  1182. '''
  1183. self.assertFalse(zfs.is_snapshot('zpool_name/dataset'))
  1184. ## NOTE: testing is_bookmark
  1185. def test_is_bookmark_snapshot(self):
  1186. '''
  1187. Test is_bookmark with a valid snapshot name
  1188. '''
  1189. self.assertFalse(zfs.is_bookmark('zpool_name/dataset@backup'))
  1190. def test_is_bookmark_bookmark(self):
  1191. '''
  1192. Test is_bookmark with a valid bookmark name
  1193. '''
  1194. self.assertTrue(zfs.is_bookmark('zpool_name/dataset#backup'))
  1195. def test_is_bookmark_filesystem(self):
  1196. '''
  1197. Test is_bookmark with a valid filesystem name
  1198. '''
  1199. self.assertFalse(zfs.is_bookmark('zpool_name/dataset'))
  1200. ## NOTE: testing is_dataset
  1201. def test_is_dataset_snapshot(self):
  1202. '''
  1203. Test is_dataset with a valid snapshot name
  1204. '''
  1205. self.assertFalse(zfs.is_dataset('zpool_name/dataset@backup'))
  1206. def test_is_dataset_bookmark(self):
  1207. '''
  1208. Test is_dataset with a valid bookmark name
  1209. '''
  1210. self.assertFalse(zfs.is_dataset('zpool_name/dataset#backup'))
  1211. def test_is_dataset_filesystem(self):
  1212. '''
  1213. Test is_dataset with a valid filesystem/volume name
  1214. '''
  1215. self.assertTrue(zfs.is_dataset('zpool_name/dataset'))
  1216. ## NOTE: testing zfs_command
  1217. def test_zfs_command_simple(self):
  1218. '''
  1219. Test if zfs_command builds the correct string
  1220. '''
  1221. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1222. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1223. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1224. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1225. self.assertEqual(
  1226. zfs.zfs_command('list'),
  1227. "/sbin/zfs list"
  1228. )
  1229. def test_zfs_command_none_target(self):
  1230. '''
  1231. Test if zfs_command builds the correct string with a target of None
  1232. '''
  1233. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1234. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1235. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1236. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1237. self.assertEqual(
  1238. zfs.zfs_command('list', target=[None, 'mypool', None]),
  1239. "/sbin/zfs list mypool"
  1240. )
  1241. def test_zfs_command_flag(self):
  1242. '''
  1243. Test if zfs_command builds the correct string
  1244. '''
  1245. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1246. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1247. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1248. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1249. my_flags = [
  1250. '-r', # recursive
  1251. ]
  1252. self.assertEqual(
  1253. zfs.zfs_command('list', flags=my_flags),
  1254. "/sbin/zfs list -r"
  1255. )
  1256. def test_zfs_command_opt(self):
  1257. '''
  1258. Test if zfs_command builds the correct string
  1259. '''
  1260. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1261. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1262. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1263. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1264. my_opts = {
  1265. '-t': 'snap', # only list snapshots
  1266. }
  1267. self.assertEqual(
  1268. zfs.zfs_command('list', opts=my_opts),
  1269. "/sbin/zfs list -t snap"
  1270. )
  1271. def test_zfs_command_flag_opt(self):
  1272. '''
  1273. Test if zfs_command builds the correct string
  1274. '''
  1275. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1276. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1277. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1278. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1279. my_flags = [
  1280. '-r', # recursive
  1281. ]
  1282. my_opts = {
  1283. '-t': 'snap', # only list snapshots
  1284. }
  1285. self.assertEqual(
  1286. zfs.zfs_command('list', flags=my_flags, opts=my_opts),
  1287. "/sbin/zfs list -r -t snap"
  1288. )
  1289. def test_zfs_command_target(self):
  1290. '''
  1291. Test if zfs_command builds the correct string
  1292. '''
  1293. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1294. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1295. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1296. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1297. my_flags = [
  1298. '-r', # recursive
  1299. ]
  1300. my_opts = {
  1301. '-t': 'snap', # only list snapshots
  1302. }
  1303. self.assertEqual(
  1304. zfs.zfs_command('list', flags=my_flags, opts=my_opts, target='mypool'),
  1305. "/sbin/zfs list -r -t snap mypool"
  1306. )
  1307. def test_zfs_command_target_with_space(self):
  1308. '''
  1309. Test if zfs_command builds the correct string
  1310. '''
  1311. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1312. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1313. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1314. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1315. my_flags = [
  1316. '-r', # recursive
  1317. ]
  1318. my_opts = {
  1319. '-t': 'snap', # only list snapshots
  1320. }
  1321. self.assertEqual(
  1322. zfs.zfs_command('list', flags=my_flags, opts=my_opts, target='my pool'),
  1323. '/sbin/zfs list -r -t snap "my pool"'
  1324. )
  1325. def test_zfs_command_property(self):
  1326. '''
  1327. Test if zfs_command builds the correct string
  1328. '''
  1329. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1330. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1331. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1332. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1333. self.assertEqual(
  1334. zfs.zfs_command('get', property_name='quota', target='mypool'),
  1335. "/sbin/zfs get quota mypool"
  1336. )
  1337. def test_zfs_command_property_value(self):
  1338. '''
  1339. Test if zfs_command builds the correct string
  1340. '''
  1341. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1342. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1343. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1344. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1345. my_flags = [
  1346. '-r', # recursive
  1347. ]
  1348. self.assertEqual(
  1349. zfs.zfs_command('set', flags=my_flags, property_name='quota', property_value='5G', target='mypool'),
  1350. "/sbin/zfs set -r quota=5368709120 mypool"
  1351. )
  1352. def test_zfs_command_multi_property_value(self):
  1353. '''
  1354. Test if zfs_command builds the correct string
  1355. '''
  1356. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1357. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1358. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1359. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1360. property_name = ['quota', 'readonly']
  1361. property_value = ['5G', 'no']
  1362. self.assertEqual(
  1363. zfs.zfs_command('set', property_name=property_name, property_value=property_value, target='mypool'),
  1364. "/sbin/zfs set quota=5368709120 readonly=off mypool"
  1365. )
  1366. def test_zfs_command_fs_props(self):
  1367. '''
  1368. Test if zfs_command builds the correct string
  1369. '''
  1370. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1371. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1372. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1373. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1374. my_flags = [
  1375. '-p', # create parent
  1376. ]
  1377. my_props = {
  1378. 'quota': '1G',
  1379. 'compression': 'lz4',
  1380. }
  1381. self.assertEqual(
  1382. zfs.zfs_command('create', flags=my_flags, filesystem_properties=my_props, target='mypool/dataset'),
  1383. "/sbin/zfs create -p -o compression=lz4 -o quota=1073741824 mypool/dataset"
  1384. )
  1385. def test_zfs_command_fs_props_with_space(self):
  1386. '''
  1387. Test if zfs_command builds the correct string
  1388. '''
  1389. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1390. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1391. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1392. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1393. my_props = {
  1394. 'quota': '4.2M',
  1395. 'compression': 'lz4',
  1396. }
  1397. self.assertEqual(
  1398. zfs.zfs_command('create', filesystem_properties=my_props, target="my pool/jorge's dataset"),
  1399. '/sbin/zfs create -o compression=lz4 -o quota=4404019 "my pool/jorge\'s dataset"'
  1400. )
  1401. ## NOTE: testing zpool_command
  1402. def test_zpool_command_simple(self):
  1403. '''
  1404. Test if zfs_command builds the correct string
  1405. '''
  1406. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1407. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1408. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1409. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1410. self.assertEqual(
  1411. zfs.zpool_command('list'),
  1412. "/sbin/zpool list"
  1413. )
  1414. def test_zpool_command_opt(self):
  1415. '''
  1416. Test if zpool_command builds the correct string
  1417. '''
  1418. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1419. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1420. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1421. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1422. my_opts = {
  1423. '-o': 'name,size', # show only name and size
  1424. }
  1425. self.assertEqual(
  1426. zfs.zpool_command('list', opts=my_opts),
  1427. "/sbin/zpool list -o name,size"
  1428. )
  1429. def test_zpool_command_opt_list(self):
  1430. '''
  1431. Test if zpool_command builds the correct string
  1432. '''
  1433. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1434. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1435. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1436. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1437. my_opts = {
  1438. '-d': ['/tmp', '/zvol'],
  1439. }
  1440. self.assertEqual(
  1441. zfs.zpool_command('import', opts=my_opts, target='mypool'),
  1442. "/sbin/zpool import -d /tmp -d /zvol mypool"
  1443. )
  1444. def test_zpool_command_flag_opt(self):
  1445. '''
  1446. Test if zpool_command builds the correct string
  1447. '''
  1448. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1449. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1450. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1451. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1452. my_opts = {
  1453. '-o': 'name,size', # show only name and size
  1454. }
  1455. self.assertEqual(
  1456. zfs.zpool_command('list', opts=my_opts),
  1457. "/sbin/zpool list -o name,size"
  1458. )
  1459. def test_zpool_command_target(self):
  1460. '''
  1461. Test if zpool_command builds the correct string
  1462. '''
  1463. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1464. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1465. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1466. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1467. my_opts = {
  1468. '-o': 'name,size', # show only name and size
  1469. }
  1470. self.assertEqual(
  1471. zfs.zpool_command('list', opts=my_opts, target='mypool'),
  1472. "/sbin/zpool list -o name,size mypool"
  1473. )
  1474. def test_zpool_command_target_with_space(self):
  1475. '''
  1476. Test if zpool_command builds the correct string
  1477. '''
  1478. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1479. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1480. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1481. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1482. fs_props = {
  1483. 'quota': '100G',
  1484. }
  1485. pool_props = {
  1486. 'comment': "jorge's comment has a space",
  1487. }
  1488. self.assertEqual(
  1489. zfs.zpool_command('create', pool_properties=pool_props, filesystem_properties=fs_props, target='my pool'),
  1490. "/sbin/zpool create -O quota=107374182400 -o comment=\"jorge's comment has a space\" \"my pool\""
  1491. )
  1492. def test_zpool_command_property(self):
  1493. '''
  1494. Test if zpool_command builds the correct string
  1495. '''
  1496. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1497. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1498. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1499. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1500. self.assertEqual(
  1501. zfs.zpool_command('get', property_name='comment', target='mypool'),
  1502. "/sbin/zpool get comment mypool"
  1503. )
  1504. def test_zpool_command_property_value(self):
  1505. '''
  1506. Test if zpool_command builds the correct string
  1507. '''
  1508. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1509. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1510. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1511. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1512. my_flags = [
  1513. '-v', # verbose
  1514. ]
  1515. self.assertEqual(
  1516. zfs.zpool_command('iostat', flags=my_flags, target=['mypool', 60, 1]),
  1517. "/sbin/zpool iostat -v mypool 60 1"
  1518. )
  1519. def test_parse_command_result_success(self):
  1520. '''
  1521. Test if parse_command_result returns the expected result
  1522. '''
  1523. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1524. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1525. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1526. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1527. res = {}
  1528. res['retcode'] = 0
  1529. res['stderr'] = ''
  1530. res['stdout'] = ''
  1531. self.assertEqual(
  1532. zfs.parse_command_result(res, 'tested'),
  1533. OrderedDict([('tested', True)]),
  1534. )
  1535. def test_parse_command_result_success_nolabel(self):
  1536. '''
  1537. Test if parse_command_result returns the expected result
  1538. '''
  1539. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1540. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1541. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1542. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1543. res = {}
  1544. res['retcode'] = 0
  1545. res['stderr'] = ''
  1546. res['stdout'] = ''
  1547. self.assertEqual(
  1548. zfs.parse_command_result(res),
  1549. OrderedDict(),
  1550. )
  1551. def test_parse_command_result_fail(self):
  1552. '''
  1553. Test if parse_command_result returns the expected result on failure
  1554. '''
  1555. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1556. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1557. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1558. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1559. res = {}
  1560. res['retcode'] = 1
  1561. res['stderr'] = ''
  1562. res['stdout'] = ''
  1563. self.assertEqual(
  1564. zfs.parse_command_result(res, 'tested'),
  1565. OrderedDict([('tested', False)]),
  1566. )
  1567. def test_parse_command_result_nolabel(self):
  1568. '''
  1569. Test if parse_command_result returns the expected result on failure
  1570. '''
  1571. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1572. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1573. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1574. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1575. res = {}
  1576. res['retcode'] = 1
  1577. res['stderr'] = ''
  1578. res['stdout'] = ''
  1579. self.assertEqual(
  1580. zfs.parse_command_result(res),
  1581. OrderedDict(),
  1582. )
  1583. def test_parse_command_result_fail_message(self):
  1584. '''
  1585. Test if parse_command_result returns the expected result on failure with stderr
  1586. '''
  1587. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1588. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1589. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1590. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1591. res = {}
  1592. res['retcode'] = 1
  1593. res['stderr'] = "\n".join([
  1594. 'ice is not hot',
  1595. 'usage:',
  1596. 'this should not be printed',
  1597. ])
  1598. res['stdout'] = ''
  1599. self.assertEqual(
  1600. zfs.parse_command_result(res, 'tested'),
  1601. OrderedDict([('tested', False), ('error', 'ice is not hot')]),
  1602. )
  1603. def test_parse_command_result_fail_message_nolabel(self):
  1604. '''
  1605. Test if parse_command_result returns the expected result on failure with stderr
  1606. '''
  1607. with patch.object(zfs, '_zfs_cmd', MagicMock(return_value='/sbin/zfs')):
  1608. with patch.object(zfs, '_zpool_cmd', MagicMock(return_value='/sbin/zpool')):
  1609. with patch.object(zfs, 'property_data_zfs', MagicMock(return_value=pmap_zfs)):
  1610. with patch.object(zfs, 'property_data_zpool', MagicMock(return_value=pmap_zpool)):
  1611. res = {}
  1612. res['retcode'] = 1
  1613. res['stderr'] = "\n".join([
  1614. 'ice is not hot',
  1615. 'usage:',
  1616. 'this should not be printed',
  1617. ])
  1618. res['stdout'] = ''
  1619. self.assertEqual(
  1620. zfs.parse_command_result(res),
  1621. OrderedDict([('error', 'ice is not hot')]),
  1622. )
  1623. # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4