[blivet] add support for lvm thin provisioning
by David Lehman
This is a new thing that allows you to create a special type of
lv (thin pool) that acts as a container for another special type of
lv (thin lv). The thin provisioning part means the space for the thin
lvs is not actually allocated from the pool until it is used/written.
This means the pool does not necessarily have to have a size equal or
greater to the sum of the sizes of the thin lvs it contains.
There are some more detailed comments in both the commit messages and
the code itself.
I am only proposing this for master -- not for f19.
10 years, 10 months
[PATCH][pykickstart] Add support for lvm thin provisioning.
by David Lehman
This adds a new autopart type and options to the logvol command.
---
pykickstart/commands/autopart.py | 18 ++++++++------
pykickstart/commands/logvol.py | 54 ++++++++++++++++++++++++++++++++++++++++
pykickstart/constants.py | 1 +
pykickstart/handlers/control.py | 10 ++++----
tests/commands/autopart.py | 2 ++
tests/commands/logvol.py | 34 +++++++++++++++++++++++++
6 files changed, 107 insertions(+), 12 deletions(-)
diff --git a/pykickstart/commands/autopart.py b/pykickstart/commands/autopart.py
index c31e014..308ff25 100644
--- a/pykickstart/commands/autopart.py
+++ b/pykickstart/commands/autopart.py
@@ -184,7 +184,8 @@ class F17_AutoPart(F16_AutoPart):
self.typeMap = { "lvm": AUTOPART_TYPE_LVM,
"btrfs": AUTOPART_TYPE_BTRFS,
"plain": AUTOPART_TYPE_PLAIN,
- "partition": AUTOPART_TYPE_PLAIN }
+ "partition": AUTOPART_TYPE_PLAIN,
+ "thinp": AUTOPART_TYPE_LVM_THINP }
def __str__(self):
retval = F16_AutoPart.__str__(self)
@@ -195,12 +196,10 @@ class F17_AutoPart(F16_AutoPart):
# remove any trailing newline
retval = retval.strip()
retval += " --type="
- if self.type == AUTOPART_TYPE_LVM:
- retval += "lvm"
- elif self.type == AUTOPART_TYPE_BTRFS:
- retval += "btrfs"
- else:
- retval += "plain"
+ for s, n in self.typeMap.items():
+ if self.type == n:
+ retval += s
+ break
retval += "\n"
return retval
@@ -259,3 +258,8 @@ class F18_AutoPart(F17_AutoPart):
op = F17_AutoPart._getParser(self)
op.add_option("--cipher")
return op
+
+class F19_AutoPart(F18_AutoPart):
+ def __init__(self, writePriority=100, *args, **kwargs):
+ F18_AutoPart.__init__(self, writePriority=writePriority, *args, **kwargs)
+ self.typeMap["thinp"] = AUTOPART_TYPE_LVM_THINP
diff --git a/pykickstart/commands/logvol.py b/pykickstart/commands/logvol.py
index 9a7b54c..28b8b50 100644
--- a/pykickstart/commands/logvol.py
+++ b/pykickstart/commands/logvol.py
@@ -233,6 +233,34 @@ class F18_LogVolData(F17_LogVolData):
return retval
+class F19_LogVolData(F18_LogVolData):
+ def __init__(self, *args, **kwargs):
+ F18_LogVolData.__init__(self, *args, **kwargs)
+ self.thin_pool = kwargs.get("thin_pool", False)
+ self.thin_volume = kwargs.get("thin_volume", False)
+ self.pool_name = kwargs.get("pool_name", "")
+
+ # these are only for thin pools
+ self.chunk_size = kwargs.get("chunk_size", None) # kilobytes
+ self.metadata_size = kwargs.get("metadata_size", None) # megabytes
+
+ def _getArgsAsStr(self):
+ retval = F18_LogVolData._getArgsAsStr(self)
+
+ if self.thin_pool:
+ retval += " --thinpool"
+
+ if self.metadata_size:
+ retval += " --metadatasize=%d" % self.metadata_size
+
+ if self.chunk_size:
+ retval += " --chunksize=%d" % self.chunk_size
+
+ if self.thin_volume:
+ retval += " --thin --poolname=%s" % self.pool_name
+
+ return retval
+
class FC3_LogVol(KickstartCommand):
removedKeywords = KickstartCommand.removedKeywords
removedAttrs = KickstartCommand.removedAttrs
@@ -394,3 +422,29 @@ class F18_LogVol(F17_LogVol):
op.add_option("--cipher")
return op
+class F19_LogVol(F18_LogVol):
+ def _getParser(self):
+ op = F18_LogVol._getParser(self)
+ op.add_option("--thinpool", action="store_true", dest="thin_pool",
+ default=False)
+ op.add_option("--thin", action="store_true", dest="thin_volume",
+ default=False)
+ op.add_option("--poolname", dest="pool_name")
+ op.add_option("--chunksize", type="int", dest="chunk_size")
+ op.add_option("--metadatasize", type="int", dest="metadata_size")
+ return op
+
+ def parse(self, args):
+ retval = F18_LogVol.parse(self, args)
+
+ if retval.thin_volume and retval.thin_pool:
+ raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--thin and --thinpool cannot both be specified for the same logvol")))
+
+ if retval.thin_volume and not retval.pool_name:
+ raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--thin requires --poolname to specify pool name")))
+
+ if (retval.chunk_size or retval.metadata_size) and \
+ not retval.thin_pool:
+ raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--chunksize and --metadatasize are for thin pools only")))
+
+ return retval
diff --git a/pykickstart/constants.py b/pykickstart/constants.py
index d476c49..7a19a00 100644
--- a/pykickstart/constants.py
+++ b/pykickstart/constants.py
@@ -25,6 +25,7 @@ CLEARPART_TYPE_LIST = 3
AUTOPART_TYPE_PLAIN = 0
AUTOPART_TYPE_BTRFS = 1
AUTOPART_TYPE_LVM = 2
+AUTOPART_TYPE_LVM_THINP = 3
DISPLAY_MODE_CMDLINE = 0
DISPLAY_MODE_GRAPHICAL = 1
diff --git a/pykickstart/handlers/control.py b/pykickstart/handlers/control.py
index 82a2139..f01a052 100644
--- a/pykickstart/handlers/control.py
+++ b/pykickstart/handlers/control.py
@@ -948,7 +948,7 @@ commandMap = {
F19: {
"auth": authconfig.FC3_Authconfig,
"authconfig": authconfig.FC3_Authconfig,
- "autopart": autopart.F18_AutoPart,
+ "autopart": autopart.F19_AutoPart,
"autostep": autostep.FC3_AutoStep,
"bootloader": bootloader.F19_Bootloader,
"btrfs": btrfs.F17_BTRFS,
@@ -974,7 +974,7 @@ commandMap = {
"lang": lang.F19_Lang,
"liveimg": method.F19_Method,
"logging": logging.FC6_Logging,
- "logvol": logvol.F18_LogVol,
+ "logvol": logvol.F19_LogVol,
"mediacheck": mediacheck.FC4_MediaCheck,
"multipath": multipath.FC6_MultiPath,
"network": network.F19_Network,
@@ -1257,7 +1257,7 @@ commandMap = {
"lang": lang.F19_Lang,
"liveimg": method.F19_Method,
"logging": logging.FC6_Logging,
- "logvol": logvol.F18_LogVol,
+ "logvol": logvol.F19_LogVol,
"mediacheck": mediacheck.FC4_MediaCheck,
"multipath": multipath.FC6_MultiPath,
"network": network.F19_Network,
@@ -1547,7 +1547,7 @@ dataMap = {
"FcoeData": fcoe.F13_FcoeData,
"GroupData": group.F12_GroupData,
"IscsiData": iscsi.F17_IscsiData,
- "LogVolData": logvol.F18_LogVolData,
+ "LogVolData": logvol.F19_LogVolData,
"MultiPathData": multipath.FC6_MultiPathData,
"NetworkData": network.F19_NetworkData,
"PartData": partition.F18_PartData,
@@ -1616,7 +1616,7 @@ dataMap = {
"FcoeData": fcoe.F13_FcoeData,
"GroupData": group.F12_GroupData,
"IscsiData": iscsi.F17_IscsiData,
- "LogVolData": logvol.F18_LogVolData,
+ "LogVolData": logvol.F19_LogVolData,
"MultiPathData": multipath.FC6_MultiPathData,
"NetworkData": network.F19_NetworkData,
"PartData": partition.F18_PartData,
diff --git a/tests/commands/autopart.py b/tests/commands/autopart.py
index 39dbb8f..c298b7c 100644
--- a/tests/commands/autopart.py
+++ b/tests/commands/autopart.py
@@ -119,6 +119,8 @@ class F17_TestCase(F16_TestCase):
"autopart --type=lvm\n")
self.assert_parse("autopart --type=btrfs",
"autopart --type=btrfs\n")
+ self.assert_parse("autopart --type=thinp",
+ "autopart --type=thinp\n")
self.assert_parse("autopart --nolvm",
"autopart --type=plain\n")
diff --git a/tests/commands/logvol.py b/tests/commands/logvol.py
index cd868fd..5eb0361 100644
--- a/tests/commands/logvol.py
+++ b/tests/commands/logvol.py
@@ -243,5 +243,39 @@ class F18_TestCase(F17_TestCase):
self.assert_parse_error("logvol / --cipher --name=NAME --vgname=VGNAME")
+class F19_TestCase(F18_TestCase):
+ def runTest(self):
+ F18_TestCase.runTest(self)
+
+ self.assert_parse("logvol none --name=pool1 --vgname=vg --thinpool",
+ "logvol none --thinpool --name=pool1 --vgname=vg\n")
+ self.assert_parse("logvol none --name=pool1 --vgname=vg --thinpool "
+ "--chunksize=512",
+ "logvol none --thinpool --chunksize=512 "
+ "--name=pool1 --vgname=vg\n")
+ self.assert_parse("logvol none --name=pool1 --vgname=vg --thinpool "
+ "--metadatasize=4 --chunksize=1024",
+ "logvol none --thinpool --metadatasize=4 "
+ "--chunksize=1024 --name=pool1 --vgname=vg\n")
+ self.assert_parse("logvol /home --name=home --vgname=vg "
+ "--thin --poolname=pool1",
+ "logvol /home --thin --poolname=pool1 "
+ "--name=home --vgname=vg\n")
+
+ # missing pool name
+ self.assert_parse_error("logvol /home --name=home --vgname=vg --thin")
+
+ # chunksize is an int
+ self.assert_parse_error("logvol none --name=pool1 --vgname=vg "
+ "--thinpool --chunksize=foo")
+
+ # both --thin and --thinpool
+ self.assert_parse_error("logvol /home --name=home --thin --thinpool --vgname=vg --size=10000")
+
+ # chunksize and/or metadata size and not thinpool
+ self.assert_parse_error("logvol none --name=pool1 --vgname=vg "
+ "--chunksize=512")
+
+
if __name__ == "__main__":
unittest.main()
--
1.8.1.4
10 years, 10 months
[PATCH rhel6-branch] Add kickstart network --ipv6gateway option (#905227)
by Radek Vykydal
Resolves: rhbz#905227
---
anaconda.spec.in | 2 +-
kickstart.py | 3 +++
loader/net.c | 17 +++++++++++++++++
network.py | 2 +-
4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/anaconda.spec.in b/anaconda.spec.in
index b3a68c0..a3bd496 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -27,7 +27,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%define intltoolver 0.31.2-3
%define libnlver 1.0
%define libselinuxver 1.6
-%define pykickstartver 1.74.12
+%define pykickstartver 1.74.13
%define rpmpythonver 4.2-0.61
%define slangver 2.0.6-2
%define yumver 2.9.2
diff --git a/kickstart.py b/kickstart.py
index c227822..b3aa9c8 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -711,6 +711,9 @@ class NetworkData(commands.network.RHEL6_NetworkData):
if self.gateway != "":
anaconda.id.network.setGateway(self.gateway, dev.iface)
+ if self.ipv6gateway != "":
+ dev.set(('IPV6_DEFAULTGW', self.ipv6gateway))
+
if self.nodefroute:
dev.set (("DEFROUTE", "no"))
diff --git a/loader/net.c b/loader/net.c
index 7c6bf01..f188d56 100644
--- a/loader/net.c
+++ b/loader/net.c
@@ -1716,6 +1716,7 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
struct in_addr addr;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
+ gchar *ipv6gateway = NULL;
#endif
int rc;
GOptionEntry ksOptions[] = {
@@ -1727,6 +1728,8 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
{ "ip", 'i', 0, G_OPTION_ARG_STRING, &loaderData->ipv4, NULL, NULL },
#ifdef ENABLE_IPV6
{ "ipv6", 0, 0, G_OPTION_ARG_STRING, &loaderData->ipv6, NULL, NULL },
+ { "ipv6gateway", 0, 0, G_OPTION_ARG_STRING, &ipv6gateway,
+ NULL, NULL },
#endif
{ "mtu", 0, 0, G_OPTION_ARG_INT, &mtu, NULL, NULL },
{ "nameserver", 'n', 0, G_OPTION_ARG_STRING, &loaderData->dns,
@@ -1849,6 +1852,20 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
}
}
+#ifdef ENABLE_IPV6
+ if (ipv6gateway) {
+ if ((rc = inet_pton(AF_INET6, ipv6gateway, &addr6)) == 1) {
+ loaderData->gateway6 = strdup(ipv6gateway);
+ } else if (rc == 0) {
+ logMessage(WARNING,
+ "invalid address in kickstart --ipv6gateway");
+ } else {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ }
+#endif
+
if (!noksdev) {
if (device) {
/* If --device=MAC was given, translate into a device name now. */
diff --git a/network.py b/network.py
index 8bc2d21..523ef6b 100644
--- a/network.py
+++ b/network.py
@@ -542,7 +542,7 @@ class Network:
if dev.get('IPV6ADDR'):
line += " --ipv6 %s" % dev.get('IPV6ADDR')
if dev.get('IPV6_DEFAULTGW'):
- line += " --gateway %s" % dev.get('IPV6_DEFAULTGW')
+ line += " --ipv6gateway %s" % dev.get('IPV6_DEFAULTGW')
if dev.get('DHCPV6') == "yes":
line += " --ipv6 dhcp"
--
1.7.11.7
10 years, 10 months
[f19-branch???/master][PATCH] Do not preselect the environment if using kickstart packages (#978852)
by Vratislav Podzimek
Doing so overrides the kickstart package selection and stops the automated
installation.
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
pyanaconda/ui/tui/spokes/software.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/ui/tui/spokes/software.py b/pyanaconda/ui/tui/spokes/software.py
index 84d0737..065f232 100644
--- a/pyanaconda/ui/tui/spokes/software.py
+++ b/pyanaconda/ui/tui/spokes/software.py
@@ -49,6 +49,9 @@ class SoftwareSpoke(NormalTUISpoke):
# for detecting later whether any changes have been made
self._origEnv = None
+ # are we taking values (package list) from a kickstart file?
+ self._kickstarted = flags.automatedInstall and self.data.packages.seen
+
def initialize(self):
NormalTUISpoke.initialize(self)
threadMgr.add(AnacondaThread(name=THREAD_SOFTWARE_WATCHER, target=self._initialize))
@@ -56,7 +59,7 @@ class SoftwareSpoke(NormalTUISpoke):
def _initialize(self):
""" Private initialize. """
threadMgr.wait(THREAD_PAYLOAD)
- if flags.automatedInstall and self.data.packages.seen:
+ if self._kickstarted:
threadMgr.wait(THREAD_PAYLOAD_MD)
else:
try:
@@ -82,14 +85,15 @@ class SoftwareSpoke(NormalTUISpoke):
# quite ugly, but env isn't getting set to gnome (or anything) by
# default, and it really should be so we can maintain consistency
# with graphical behavior
- if self._selection >= 0 and not self.environment:
+ if self._selection >= 0 and not self.environment \
+ and not self._kickstarted:
self.apply()
if not self.environment:
# Ks installs with %packages will have an env selected, unless
# they did an install without a desktop environment. This should
# catch that one case.
- if flags.automatedInstall and self.data.packages.seen:
+ if self._kickstarted:
return _("Custom software selected")
return _("Nothing selected")
@@ -158,7 +162,11 @@ class SoftwareSpoke(NormalTUISpoke):
def apply(self):
""" Apply our selections """
self._apply()
+
+ # no longer using values from kickstart
+ self._kickstarted = False
self.data.packages.seen = True
+
threadMgr.add(AnacondaThread(name=THREAD_CHECK_SOFTWARE,
target=self.checkSoftwareSelection))
--
1.7.11.7
10 years, 10 months
[rhel6-branch] Show ks lvm DeviceErrors in the UI (#880625)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
kickstart.py | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/kickstart.py b/kickstart.py
index c227822..6231d38 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -560,13 +560,17 @@ class LogVolData(commands.logvol.RHEL6_LogVolData):
except KeyError:
pass
- request = storage.newLV(format=format,
- name=self.name,
- vg=vg,
- size=self.size,
- grow=self.grow,
- maxsize=self.maxSizeMB,
- percent=self.percent)
+ try:
+ request = storage.newLV(format=format,
+ name=self.name,
+ vg=vg,
+ size=self.size,
+ grow=self.grow,
+ maxsize=self.maxSizeMB,
+ percent=self.percent)
+ except DeviceError as e:
+ # Promote DeviceError to KickstartError so the UI will display it
+ raise KickstartError(str(e))
if self.fsprofile and hasattr(request.format, "fsprofile"):
request.format.fsprofile = self.fsprofile
--
1.8.1.4
10 years, 10 months
[PATCH] Narrow down the list of suggested mountpoints to those supported by arch.
by Chris Lumens
It doesn't make a lot of sense to suggest prepboot and biosboot on platforms
that do not support them.
---
pyanaconda/ui/gui/spokes/custom.py | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index ef5b32c..e0b4ff6 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -41,6 +41,7 @@ from blivet import devicefactory
from blivet.formats import device_formats
from blivet.formats import getFormat
from blivet.formats.fs import FS
+from blivet.platform import platform
from blivet.size import Size
from blivet import Root
from blivet.devicefactory import DEVICE_TYPE_LVM
@@ -173,8 +174,18 @@ def ui_storage_logger():
def populate_mountpoint_store(store, used_mountpoints):
# sure, add whatever you want to this list. this is just a start.
- paths = ["/", "/boot", "/boot/efi", "/home", "/usr", "/var",
- "swap", "biosboot", "prepboot"]
+ paths = ["/", "/boot", "/home", "/usr", "/var"] + \
+ platform.bootStage1ConstraintDict["mountpoints"]
+
+ # Sort the list now so all the real mountpoints go to the front, then
+ # add all the pseudo mountpoints we have.
+ paths.sort()
+ paths += ["swap"]
+
+ for fmt in ["appleboot", "biosboot", "prepboot"]:
+ if getFormat(fmt).supported:
+ paths += [fmt]
+
for path in paths:
if path not in used_mountpoints:
store.append([path])
--
1.8.1.2
10 years, 10 months
[PATCH][lorax] Include device-mapper-persistent-data for thinp support.
by David Lehman
---
share/runtime-install.tmpl | 1 +
1 file changed, 1 insertion(+)
diff --git a/share/runtime-install.tmpl b/share/runtime-install.tmpl
index fe52d79..7f93f71 100644
--- a/share/runtime-install.tmpl
+++ b/share/runtime-install.tmpl
@@ -82,6 +82,7 @@ installpkg python-imaging
installpkg btrfs-progs jfsutils xfsprogs reiserfs-utils gfs2-utils ntfs-3g ntfsprogs
installpkg python-volume_key volume_key
installpkg system-storage-manager
+installpkg device-mapper-persistent-data
## SELinux support
installpkg selinux-policy-targeted audit libsemanage-python
--
1.8.1.4
10 years, 10 months
[PATCH] Skip network.execute for dirInstall
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
pyanaconda/install.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
index 43be542..19cc8a6 100644
--- a/pyanaconda/install.py
+++ b/pyanaconda/install.py
@@ -73,7 +73,7 @@ def doConfiguration(storage, payload, ksdata, instClass):
ksdata.firewall.execute(storage, ksdata, instClass)
ksdata.xconfig.execute(storage, ksdata, instClass)
- if not flags.flags.imageInstall:
+ if not flags.flags.imageInstall and not flags.flags.dirInstall:
with progress_report(_("Writing network configuration")):
ksdata.network.execute(storage, ksdata, instClass)
--
1.8.1.4
10 years, 10 months
[PATCH 1/2] Change the name label of a MountpointSelector from grey to black.
by Chris Lumens
Grey-on-blue is really, really hard to read.
---
widgets/src/MountpointSelector.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/widgets/src/MountpointSelector.c b/widgets/src/MountpointSelector.c
index 517d77e..726b42e 100644
--- a/widgets/src/MountpointSelector.c
+++ b/widgets/src/MountpointSelector.c
@@ -161,7 +161,7 @@ static void format_size_label(AnacondaMountpointSelector *widget, const char *va
static void format_name_label(AnacondaMountpointSelector *widget, const char *value) {
char *markup;
- markup = g_markup_printf_escaped("<span fgcolor='grey' size='small'>%s</span>", value);
+ markup = g_markup_printf_escaped("<span fgcolor='black' size='small'>%s</span>", value);
gtk_label_set_markup(GTK_LABEL(widget->priv->name_label), markup);
g_free(markup);
}
--
1.8.1.2
10 years, 10 months