part btrfs.01 ... btrfs <mountpoint> [--data=<level>] \ [--metadata=<level>] \ [--subvol] \ [--label=<label>] \ [--noformat] \ [--useexisting] \ <device>+ --- pykickstart/commands/__init__.py | 2 +- pykickstart/commands/btrfs.py | 161 ++++++++++++++++++++++++++++++++++++++ pykickstart/handlers/control.py | 2 + tests/commands/btrfs.py | 87 ++++++++++++++++++++ 4 files changed, 251 insertions(+), 1 deletions(-) create mode 100644 pykickstart/commands/btrfs.py create mode 100644 tests/commands/btrfs.py diff --git a/pykickstart/commands/__init__.py b/pykickstart/commands/__init__.py index da48ff5..3c76794 100644 --- a/pykickstart/commands/__init__.py +++ b/pykickstart/commands/__init__.py @@ -17,7 +17,7 @@ # subject to the GNU General Public License and may only be used or replicated # with the express permission of Red Hat, Inc. # -import authconfig, autopart, autostep, bootloader, clearpart, device +import authconfig, autopart, autostep, bootloader, btrfs, clearpart, device import deviceprobe, displaymode, dmraid, driverdisk, fcoe, firewall, firstboot import group, ignoredisk, interactive, iscsi, iscsiname, key, keyboard, lang import langsupport, lilocheck, logging, logvol, mediacheck, method, monitor diff --git a/pykickstart/commands/btrfs.py b/pykickstart/commands/btrfs.py new file mode 100644 index 0000000..5f0c388 --- /dev/null +++ b/pykickstart/commands/btrfs.py @@ -0,0 +1,161 @@ +# +# Chris Lumens <clumens@xxxxxxxxxx> +# David Lehman <dlehman@xxxxxxxxxx> +# +# Copyright 2005, 2006, 2007, 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +from pykickstart.base import * +from pykickstart.errors import * +from pykickstart.options import * + +import gettext +import warnings +_ = lambda x: gettext.ldgettext("pykickstart", x) + +class F17_BTRFSData(BaseData): + removedKeywords = BaseData.removedKeywords + removedAttrs = BaseData.removedAttrs + + def __init__(self, *args, **kwargs): + BaseData.__init__(self, *args, **kwargs) + self.format = kwargs.get("format", True) + self.preexist = kwargs.get("preexist", False) + self.label = kwargs.get("label", "") + self.mountpoint = kwargs.get("mountpoint", "") + self.devices = kwargs.get("devices", []) + self.dataLevel = kwargs.get("data", None) + self.metaDataLevel = kwargs.get("metadata", None) + + # subvolume-specific + self.subvol = kwargs.get("subvol", False) + self.name = kwargs.get("name", None) # required + + def __eq__(self, y): + return self.mountpoint == y.mountpoint + + def _getArgsAsStr(self): + retval = "" + if not self.format: + retval += " --noformat" + if self.preexist: + retval += " --useexisting" + if self.label: + retval += " --label=%s" % self.label + if self.dataLevel: + retval += " --data=%s" % self.dataLevel + if self.metaDataLevel: + retval += " --metadata=%s" % self.metaDataLevel + if self.subvol: + retval += " --subvol --name=%s" % self.name + + return retval + + def __str__(self): + retval = BaseData.__str__(self) + retval += "btrfs %s" % self.mountpoint + retval += self._getArgsAsStr() + return retval + " " + " ".join(self.devices) + "\n" + +class F17_BTRFS(KickstartCommand): + removedKeywords = KickstartCommand.removedKeywords + removedAttrs = KickstartCommand.removedAttrs + + def __init__(self, writePriority=132, *args, **kwargs): + KickstartCommand.__init__(self, writePriority, *args, **kwargs) + self.op = self._getParser() + + # A dict of all the RAID levels we support. This means that if we + # support more levels in the future, subclasses don't have to + # duplicate too much. + self.levelMap = { "RAID0": "RAID0", "0": "RAID0", + "RAID1": "RAID1", "1": "RAID1", + "RAID10": "RAID10", "10": "RAID10", + "single": "single" } + + self.btrfsList = kwargs.get("btrfsList", []) + + def __str__(self): + retval = "" + for btr in self.btrfsList: + retval += btr.__str__() + + return retval + + def _getParser(self): + # Have to be a little more complicated to set two values. + def btrfs_cb (option, opt_str, value, parser): + parser.values.format = False + parser.values.preexist = True + + def level_cb (option, opt_str, value, parser): + if self.levelMap.has_key(value): + parser.values.ensure_value(option.dest, self.levelMap[value]) + + op = KSOptionParser() + op.add_option("--noformat", action="callback", callback=btrfs_cb, + dest="format", default=True, nargs=0) + op.add_option("--useexisting", action="callback", callback=btrfs_cb, + dest="preexist", default=False, nargs=0) + + # label, data, metadata + op.add_option("--label", dest="label", default="") + op.add_option("--data", dest="dataLevel", action="callback", + callback=level_cb, type="string", nargs=1) + op.add_option("--metadata", dest="metaDataLevel", action="callback", + callback=level_cb, type="string", nargs=1) + + # + # subvolumes + # + op.add_option("--subvol", dest="subvol", action="store_true", + default=False) + + # parent must be a device spec (LABEL, UUID, &c) + op.add_option("--parent", dest="parent", default="") + op.add_option("--name", dest="name", default="") + #op.add_option("--default", dest="store_true", default=False) + + return op + + def parse(self, args): + (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) + data = self.handler.BTRFSData() + self._setToObj(self.op, opts, data) + data.lineno = self.lineno + + if len(extra) == 0: + raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("btrfs must be given a mountpoint")) + + if len(extra) == 1 and not data.subvol: + raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("btrfs must be given a list of partitions")) + elif len(extra) == 1: + raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("btrfs subvol requires specification of parent volume")) + + if data.subvol and not data.name: + raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("btrfs subvolume requires a name")) + + data.mountpoint = extra[0] + data.devices = extra[1:] + + # Check for duplicates in the data list. + if data in self.dataList(): + warnings.warn(_("A btrfs volume with the mountpoint %s has already been defined.") % data.label) + + return data + + def dataList(self): + return self.btrfsList diff --git a/pykickstart/handlers/control.py b/pykickstart/handlers/control.py index bc9cc27..4a6ee8b 100644 --- a/pykickstart/handlers/control.py +++ b/pykickstart/handlers/control.py @@ -830,6 +830,7 @@ commandMap = { "autopart": autopart.F16_AutoPart, "autostep": autostep.FC3_AutoStep, "bootloader": bootloader.F17_Bootloader, + "btrfs": btrfs.F17_BTRFS, "cdrom": method.F14_Method, "clearpart": clearpart.FC3_ClearPart, "cmdline": displaymode.FC3_DisplayMode, @@ -1315,6 +1316,7 @@ dataMap = { "ZFCPData": zfcp.F14_ZFCPData, }, F17: { + "BTRFSData": btrfs.F17_BTRFSData, "DriverDiskData": driverdisk.F14_DriverDiskData, "DeviceData": device.F8_DeviceData, "DmRaidData": dmraid.FC6_DmRaidData, diff --git a/tests/commands/btrfs.py b/tests/commands/btrfs.py new file mode 100644 index 0000000..26dfc28 --- /dev/null +++ b/tests/commands/btrfs.py @@ -0,0 +1,87 @@ +# +# David Lehman <dlehman@xxxxxxxxxx> +# +# Copyright 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# + +import unittest +from tests.baseclass import * + +from pykickstart.errors import * +from pykickstart.commands.dmraid import * + +class F17_TestCase(CommandTest): + command = "btrfs" + + def __init__(self, *kargs, **kwargs): + CommandTest.__init__(self, *kargs, **kwargs) + self.validLevels = ["raid0", "raid1", "raid10", "single"] + + def runTest(self): + # valid levels + pre = "btrfs /" + post = "btrfs.01" + for data in self.validLevels: + self.assert_parse("%s --data=%s %s" % (pre, data, post)) + for meta in self.validLevels: + self.assert_parse("%s --data=%s --metadata=%s %s" % (pre, data, + meta, post)) + self.assert_parse("%s --metadata=%s %s" % (pre, meta, post)) + + # no mountpoint or options ... just partitions + self.assert_parse("btrfs none part.01 part.01") + + # useexisting + self.assert_parse("btrfs /foo --data=1 --useexisting LABEL=foo") + self.assert_parse("btrfs /foo --data=RAID1 --useexisting LABEL=foo") + + # noformat + self.assert_parse("btrfs /foo --data=1 --noformat --useexisting LABEL=foo") + self.assert_parse("btrfs /foo --data=RAID1 --noformat --useexisting LABEL=foo") + + # fail + # no mountpoint or options + self.assert_parse_error("btrfs", KickstartValueError) + + # no options + self.assert_parse_error("btrfs /", KickstartValueError) + + # No members + self.assert_parse_error("btrfs / --data=0 --label=root", KickstartValueError) + + # subvol with no name + self.assert_parse_error("btrfs / --subvol LABEL=test", KickstartValueError) + + # subvol with no parent + self.assert_parse_error("btrfs / --subvol --name=root", KickstartValueError) + + self.assert_parse("btrfs / --subvol --name=root LABEL=test") + self.assert_parse("btrfs / --subvol --name=root test") + + # preexisting + self.assert_parse("btrfs / --useexisting btrfs.01 btrfs.02") + self.assert_parse("btrfs / --useexisting LABEL=test") + + # preexisting subvol with parent specified by label + self.assert_parse("btrfs /home --subvol --name=home --useexisting LABEL=test") + + # pass + self.assert_parse("btrfs / --label=ROOT --data=1 part.01 part.02") + self.assert_parse("btrfs / --data=RAID1 --label=ROOT part.01 part.02") + +if __name__ == "__main__": + unittest.main() -- 1.7.3.4 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list