Allow recommended flag for non-prexisting logical volumes (#1149718)
[pykickstart.git] / pykickstart / commands / logvol.py
blob8c4a7c09567e94a10dc41b069a2635874658d193
2 # Chris Lumens <clumens@redhat.com>
4 # Copyright 2005, 2006, 2007, 2008, 2012 Red Hat, Inc.
6 # This copyrighted material is made available to anyone wishing to use, modify,
7 # copy, or redistribute it subject to the terms and conditions of the GNU
8 # General Public License v.2. This program is distributed in the hope that it
9 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
10 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # See the GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
16 # trademarks that are incorporated in the source code or documentation are not
17 # subject to the GNU General Public License and may only be used or replicated
18 # with the express permission of Red Hat, Inc.
20 from pykickstart.base import BaseData, KickstartCommand
21 from pykickstart.errors import KickstartParseError, KickstartValueError, formatErrorMsg
22 from pykickstart.options import KSOptionParser
24 import gettext
25 import warnings
26 _ = lambda x: gettext.ldgettext("pykickstart", x)
28 class FC3_LogVolData(BaseData):
29 removedKeywords = BaseData.removedKeywords
30 removedAttrs = BaseData.removedAttrs
32 def __init__(self, *args, **kwargs):
33 BaseData.__init__(self, *args, **kwargs)
34 self.fstype = kwargs.get("fstype", "")
35 self.grow = kwargs.get("grow", False)
36 self.maxSizeMB = kwargs.get("maxSizeMB", 0)
37 self.name = kwargs.get("name", "")
38 self.format = kwargs.get("format", True)
39 self.percent = kwargs.get("percent", 0)
40 self.recommended = kwargs.get("recommended", False)
41 self.size = kwargs.get("size", None)
42 self.preexist = kwargs.get("preexist", False)
43 self.vgname = kwargs.get("vgname", "")
44 self.mountpoint = kwargs.get("mountpoint", "")
46 def __eq__(self, y):
47 if not y:
48 return False
50 return self.vgname == y.vgname and self.name == y.name
52 def __ne__(self, y):
53 return not self == y
55 def _getArgsAsStr(self):
56 retval = ""
58 if self.fstype != "":
59 retval += " --fstype=\"%s\"" % self.fstype
60 if self.grow:
61 retval += " --grow"
62 if self.maxSizeMB > 0:
63 retval += " --maxsize=%d" % self.maxSizeMB
64 if not self.format:
65 retval += " --noformat"
66 if self.percent > 0:
67 retval += " --percent=%d" % self.percent
68 if self.recommended:
69 retval += " --recommended"
70 if self.size > 0:
71 retval += " --size=%d" % self.size
72 if self.preexist:
73 retval += " --useexisting"
75 return retval
77 def __str__(self):
78 retval = BaseData.__str__(self)
79 retval += "logvol %s %s --name=%s --vgname=%s\n" % (self.mountpoint, self._getArgsAsStr(), self.name, self.vgname)
80 return retval
82 class FC4_LogVolData(FC3_LogVolData):
83 removedKeywords = FC3_LogVolData.removedKeywords
84 removedAttrs = FC3_LogVolData.removedAttrs
86 def __init__(self, *args, **kwargs):
87 FC3_LogVolData.__init__(self, *args, **kwargs)
88 self.bytesPerInode = kwargs.get("bytesPerInode", 4096)
89 self.fsopts = kwargs.get("fsopts", "")
91 def _getArgsAsStr(self):
92 retval = FC3_LogVolData._getArgsAsStr(self)
94 if hasattr(self, "bytesPerInode") and self.bytesPerInode != 0:
95 retval += " --bytes-per-inode=%d" % self.bytesPerInode
96 if self.fsopts != "":
97 retval += " --fsoptions=\"%s\"" % self.fsopts
99 return retval
101 class RHEL5_LogVolData(FC4_LogVolData):
102 removedKeywords = FC4_LogVolData.removedKeywords
103 removedAttrs = FC4_LogVolData.removedAttrs
105 def __init__(self, *args, **kwargs):
106 FC4_LogVolData.__init__(self, *args, **kwargs)
107 self.encrypted = kwargs.get("encrypted", False)
108 self.passphrase = kwargs.get("passphrase", "")
110 def _getArgsAsStr(self):
111 retval = FC4_LogVolData._getArgsAsStr(self)
113 if self.encrypted:
114 retval += " --encrypted"
116 if self.passphrase != "":
117 retval += " --passphrase=\"%s\"" % self.passphrase
119 return retval
121 class F9_LogVolData(FC4_LogVolData):
122 removedKeywords = FC4_LogVolData.removedKeywords + ["bytesPerInode"]
123 removedAttrs = FC4_LogVolData.removedAttrs + ["bytesPerInode"]
125 def __init__(self, *args, **kwargs):
126 FC4_LogVolData.__init__(self, *args, **kwargs)
127 self.deleteRemovedAttrs()
129 self.fsopts = kwargs.get("fsopts", "")
130 self.fsprofile = kwargs.get("fsprofile", "")
131 self.encrypted = kwargs.get("encrypted", False)
132 self.passphrase = kwargs.get("passphrase", "")
134 def _getArgsAsStr(self):
135 retval = FC4_LogVolData._getArgsAsStr(self)
137 if self.fsprofile != "":
138 retval += " --fsprofile=\"%s\"" % self.fsprofile
139 if self.encrypted:
140 retval += " --encrypted"
142 if self.passphrase != "":
143 retval += " --passphrase=\"%s\"" % self.passphrase
145 return retval
147 class F12_LogVolData(F9_LogVolData):
148 removedKeywords = F9_LogVolData.removedKeywords
149 removedAttrs = F9_LogVolData.removedAttrs
151 def __init__(self, *args, **kwargs):
152 F9_LogVolData.__init__(self, *args, **kwargs)
153 self.deleteRemovedAttrs()
155 self.escrowcert = kwargs.get("escrowcert", "")
156 self.backuppassphrase = kwargs.get("backuppassphrase", False)
158 def _getArgsAsStr(self):
159 retval = F9_LogVolData._getArgsAsStr(self)
161 if self.encrypted and self.escrowcert != "":
162 retval += " --escrowcert=\"%s\"" % self.escrowcert
164 if self.backuppassphrase:
165 retval += " --backuppassphrase"
167 return retval
169 class RHEL6_LogVolData(F12_LogVolData):
170 removedKeywords = F12_LogVolData.removedKeywords
171 removedAttrs = F12_LogVolData.removedAttrs
173 def __init__(self, *args, **kwargs):
174 F12_LogVolData.__init__(self, *args, **kwargs)
176 self.cipher = kwargs.get("cipher", "")
177 self.hibernation = kwargs.get("hibernation", False)
179 def _getArgsAsStr(self):
180 retval = F12_LogVolData._getArgsAsStr(self)
182 if self.encrypted and self.cipher:
183 retval += " --cipher=\"%s\"" % self.cipher
184 if self.hibernation:
185 retval += " --hibernation"
187 return retval
189 F14_LogVolData = F12_LogVolData
191 class F15_LogVolData(F14_LogVolData):
192 removedKeywords = F14_LogVolData.removedKeywords
193 removedAttrs = F14_LogVolData.removedAttrs
195 def __init__(self, *args, **kwargs):
196 F14_LogVolData.__init__(self, *args, **kwargs)
197 self.label = kwargs.get("label", "")
199 def _getArgsAsStr(self):
200 retval = F14_LogVolData._getArgsAsStr(self)
202 if self.label != "":
203 retval += " --label=\"%s\"" % self.label
205 return retval
207 class F17_LogVolData(F15_LogVolData):
208 def __init__(self, *args, **kwargs):
209 F15_LogVolData.__init__(self, *args, **kwargs)
210 self.resize = kwargs.get("resize", False)
212 def _getArgsAsStr(self):
213 retval = F15_LogVolData._getArgsAsStr(self)
214 if self.resize:
215 retval += " --resize"
217 return retval
219 class F18_LogVolData(F17_LogVolData):
220 def __init__(self, *args, **kwargs):
221 F17_LogVolData.__init__(self, *args, **kwargs)
222 self.hibernation = kwargs.get("hibernation", False)
223 self.cipher = kwargs.get("cipher", "")
225 def _getArgsAsStr(self):
226 retval = F17_LogVolData._getArgsAsStr(self)
228 if self.hibernation:
229 retval += " --hibernation"
231 if self.encrypted and self.cipher:
232 retval += " --cipher=\"%s\"" % self.cipher
234 return retval
236 class F20_LogVolData(F18_LogVolData):
237 def __init__(self, *args, **kwargs):
238 F18_LogVolData.__init__(self, *args, **kwargs)
239 self.thin_pool = kwargs.get("thin_pool", False)
240 self.thin_volume = kwargs.get("thin_volume", False)
241 self.pool_name = kwargs.get("pool_name", "")
243 # these are only for thin pools
244 self.chunk_size = kwargs.get("chunk_size", None) # kilobytes
245 self.metadata_size = kwargs.get("metadata_size", None) # megabytes
247 def _getArgsAsStr(self):
248 retval = F18_LogVolData._getArgsAsStr(self)
250 if self.thin_pool:
251 retval += " --thinpool"
253 if self.metadata_size:
254 retval += " --metadatasize=%d" % self.metadata_size
256 if self.chunk_size:
257 retval += " --chunksize=%d" % self.chunk_size
259 if self.thin_volume:
260 retval += " --thin --poolname=%s" % self.pool_name
262 return retval
264 class F21_LogVolData(F20_LogVolData):
265 def __init__(self, *args, **kwargs):
266 F20_LogVolData.__init__(self, *args, **kwargs)
267 self.profile = kwargs.get("profile", "")
269 def _getArgsAsStr(self):
270 retval = F20_LogVolData._getArgsAsStr(self)
272 if self.profile:
273 retval += "--profile=%s" % self.profile
275 return retval
277 class FC3_LogVol(KickstartCommand):
278 removedKeywords = KickstartCommand.removedKeywords
279 removedAttrs = KickstartCommand.removedAttrs
281 def __init__(self, writePriority=133, *args, **kwargs):
282 KickstartCommand.__init__(self, writePriority, *args, **kwargs)
283 self.op = self._getParser()
285 self.lvList = kwargs.get("lvList", [])
287 def __str__(self):
288 retval = ""
290 for part in self.lvList:
291 retval += part.__str__()
293 return retval
295 def _getParser(self):
296 def lv_cb (option, opt_str, value, parser):
297 parser.values.format = False
298 parser.values.preexist = True
300 op = KSOptionParser()
301 op.add_option("--fstype", dest="fstype")
302 op.add_option("--grow", dest="grow", action="store_true",
303 default=False)
304 op.add_option("--maxsize", dest="maxSizeMB", action="store", type="int",
305 nargs=1)
306 op.add_option("--name", dest="name", required=1)
307 op.add_option("--noformat", action="callback", callback=lv_cb,
308 dest="format", default=True, nargs=0)
309 op.add_option("--percent", dest="percent", action="store", type="int",
310 nargs=1)
311 op.add_option("--recommended", dest="recommended", action="store_true",
312 default=False)
313 op.add_option("--size", dest="size", action="store", type="int",
314 nargs=1)
315 op.add_option("--useexisting", dest="preexist", action="store_true",
316 default=False)
317 op.add_option("--vgname", dest="vgname", required=1)
318 return op
320 def parse(self, args):
321 (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno)
323 if len(extra) == 0:
324 raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("Mount point required for %s") % "logvol"))
326 lvd = self.handler.LogVolData()
327 self._setToObj(self.op, opts, lvd)
328 lvd.lineno = self.lineno
329 lvd.mountpoint=extra[0]
331 # Check for duplicates in the data list.
332 if lvd in self.dataList():
333 warnings.warn(_("A logical volume with the name %s has already been defined in volume group %s.") % (lvd.name, lvd.vgname))
335 return lvd
337 def dataList(self):
338 return self.lvList
340 class FC4_LogVol(FC3_LogVol):
341 removedKeywords = FC3_LogVol.removedKeywords
342 removedAttrs = FC3_LogVol.removedAttrs
344 def _getParser(self):
345 op = FC3_LogVol._getParser(self)
346 op.add_option("--bytes-per-inode", dest="bytesPerInode", action="store",
347 type="int", nargs=1)
348 op.add_option("--fsoptions", dest="fsopts")
349 return op
351 class RHEL5_LogVol(FC4_LogVol):
352 removedKeywords = FC4_LogVol.removedKeywords
353 removedAttrs = FC4_LogVol.removedAttrs
355 def _getParser(self):
356 op = FC4_LogVol._getParser(self)
357 op.add_option("--encrypted", action="store_true", default=False)
358 op.add_option("--passphrase")
359 return op
361 class F9_LogVol(FC4_LogVol):
362 removedKeywords = FC4_LogVol.removedKeywords
363 removedAttrs = FC4_LogVol.removedAttrs
365 def _getParser(self):
366 op = FC4_LogVol._getParser(self)
367 op.add_option("--bytes-per-inode", deprecated=1)
368 op.add_option("--fsprofile", dest="fsprofile", action="store",
369 type="string", nargs=1)
370 op.add_option("--encrypted", action="store_true", default=False)
371 op.add_option("--passphrase")
372 return op
374 class F12_LogVol(F9_LogVol):
375 removedKeywords = F9_LogVol.removedKeywords
376 removedAttrs = F9_LogVol.removedAttrs
378 def _getParser(self):
379 op = F9_LogVol._getParser(self)
380 op.add_option("--escrowcert")
381 op.add_option("--backuppassphrase", action="store_true", default=False)
382 return op
384 class RHEL6_LogVol(F12_LogVol):
385 removedKeywords = F12_LogVol.removedKeywords
386 removedAttrs = F12_LogVol.removedAttrs
388 def _getParser(self):
389 op = F12_LogVol._getParser(self)
390 op.add_option("--cipher")
391 op.add_option("--hibernation", dest="hibernation", action="store_true",
392 default=False)
394 return op
396 def parse(self, args):
397 # call the overriden method
398 retval = F12_LogVol.parse(self, args)
399 # the logvol command can't be used together with the autopart command
400 # due to the hard to debug behavior their combination introduces
401 if self.handler.autopart.seen:
402 errorMsg = _("The logvol and autopart commands can't be used at the same time")
403 raise KickstartParseError(formatErrorMsg(self.lineno, msg=errorMsg))
404 return retval
406 class F14_LogVol(F12_LogVol):
407 removedKeywords = F12_LogVol.removedKeywords
408 removedAttrs = F12_LogVol.removedAttrs
410 def _getParser(self):
411 op = F12_LogVol._getParser(self)
412 op.remove_option("--bytes-per-inode")
413 return op
415 class F15_LogVol(F14_LogVol):
416 removedKeywords = F14_LogVol.removedKeywords
417 removedAttrs = F14_LogVol.removedAttrs
419 def _getParser(self):
420 op = F14_LogVol._getParser(self)
421 op.add_option("--label")
422 return op
424 class F17_LogVol(F15_LogVol):
425 def _getParser(self):
426 op = F15_LogVol._getParser(self)
427 op.add_option("--resize", action="store_true", default=False)
428 return op
430 def parse(self, args):
431 retval = F15_LogVol.parse(self, args)
433 if retval.resize and not retval.preexist:
434 raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize can only be used in conjunction with --useexisting")))
436 if retval.resize and not retval.size:
437 raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize requires --size to indicate new size")))
439 return retval
441 class F18_LogVol(F17_LogVol):
442 def _getParser(self):
443 op = F17_LogVol._getParser(self)
444 op.add_option("--hibernation", action="store_true", default=False)
445 op.add_option("--cipher")
446 return op
448 class F20_LogVol(F18_LogVol):
449 def _getParser(self):
450 op = F18_LogVol._getParser(self)
451 op.add_option("--thinpool", action="store_true", dest="thin_pool",
452 default=False)
453 op.add_option("--thin", action="store_true", dest="thin_volume",
454 default=False)
455 op.add_option("--poolname", dest="pool_name")
456 op.add_option("--chunksize", type="int", dest="chunk_size")
457 op.add_option("--metadatasize", type="int", dest="metadata_size")
458 return op
460 def parse(self, args):
461 retval = F18_LogVol.parse(self, args)
463 if retval.thin_volume and retval.thin_pool:
464 err = formatErrorMsg(self.lineno,
465 msg=_("--thin and --thinpool cannot both be "
466 "specified for the same logvol"))
467 raise KickstartParseError(err)
469 if retval.thin_volume and not retval.pool_name:
470 err = formatErrorMsg(self.lineno,
471 msg=_("--thin requires --poolname to specify "
472 "pool name"))
473 raise KickstartParseError(err)
475 if (retval.chunk_size or retval.metadata_size) and \
476 not retval.thin_pool:
477 err = formatErrorMsg(self.lineno,
478 msg=_("--chunksize and --metadatasize are "
479 "for thin pools only"))
480 raise KickstartParseError(err)
482 # the logvol command can't be used together with the autopart command
483 # due to the hard to debug behavior their combination introduces
484 if self.handler.autopart.seen:
485 errorMsg = _("The logvol and autopart commands can't be used at the same time")
486 raise KickstartParseError(formatErrorMsg(self.lineno, msg=errorMsg))
488 if not retval.preexist and not retval.percent and not retval.size and not retval.recommended:
489 errorMsg = _("No size given for logical volume. Use one of --useexisting, --noformat, --size, or --percent.")
490 raise KickstartParseError(formatErrorMsg(self.lineno, msg=errorMsg))
492 if retval.percent is not None and (retval.percent < 0 or retval.percent > 100):
493 errorMsg = _("Percentage must be between 0 and 100.")
494 raise KickstartValueError(formatErrorMsg(self.lineno, msg=errorMsg))
496 return retval
498 class F21_LogVol(F20_LogVol):
499 def _getParser(self):
500 op = F20_LogVol._getParser(self)
501 op.add_option("--profile")
503 return op
505 def parse(self, args):
506 retval = F20_LogVol.parse(self, args)
508 if retval.size and retval.percent:
509 err = formatErrorMsg(self.lineno,
510 msg=_("--size and --percent cannot both be "
511 "specified for the same logvol"))
512 raise KickstartParseError(err)
514 return retval
516 class RHEL7_LogVol(F20_LogVol):
517 def parse(self, args):
518 retval = F20_LogVol.parse(self, args)
520 if retval.size and retval.percent:
521 err = formatErrorMsg(self.lineno,
522 msg=_("--size and --percent cannot both be "
523 "specified for the same logvol"))
524 raise KickstartParseError(err)
526 return retval