Merge ~raharper/curtin:fix/lvm-over-raid into curtin:master

Proposed by Ryan Harper
Status: Merged
Approved by: Scott Moser
Approved revision: ed603a4e7eba552cb4345961c8dca5a71de8e343
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~raharper/curtin:fix/lvm-over-raid
Merge into: curtin:master
Diff against target: 353 lines (+223/-24)
8 files modified
curtin/block/clear_holders.py (+3/-0)
curtin/block/lvm.py (+23/-5)
examples/tests/dirty_disks_config.yaml (+30/-3)
examples/tests/lvmoverraid.yaml (+98/-0)
tests/unittests/test_block_lvm.py (+13/-13)
tests/unittests/test_clear_holders.py (+5/-2)
tests/vmtests/test_lvm_raid.py (+50/-0)
tests/vmtests/test_lvm_root.py (+1/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Scott Moser (community) Approve
Review via email: mp+351384@code.launchpad.net

Commit message

clear-holders: rescan for lvm devices after assembling raid arrays

Lvm devices to be found after assembling raid arrays. Add a call after
lvm_scan to activate any discovered vgs and lvs.

LP: #1783413

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

Fixing up trusty; it's lvm2 is fickle without lvmetad.

Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Ryan Harper (raharper) wrote :

OK, I think I've got trusty sorted out.

https://jenkins.ubuntu.com/server/job/curtin-vmtest-devel-debug/80/console

It's now passing, so I think we can review this.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

I had some comments inline in my review above.
Please address or explain.

review: Needs Information
Revision history for this message
Ryan Harper (raharper) wrote :

> is there a reason not to have lvm_scan do the udevadm_settle ?
> it seems like all callers are probably interested in having that happen.
>
> maybe we even have race conditions elsewhere as I don't see anywhere else
> that does use settle after calling this.

In blockmeta, creating a volgroup does not create any device nodes, but creating the
logical volumes will. We don't currently do a devsync() (which does a settle using
the --exit-if-exists=/path/to/device/expected to have a fast exit path if the
device node has been created) at the end of lvm logical volume creation, but
the subsequent call of the user of the lvm device uses get_path_to_storage() which
will do a devsync().

I don't think we've any race conditions due calls to scan in block-meta, the devsync
ensures we don't.

And generally adding the settle to the scan can't use the more specific --exist-if-exists
parameter since in clear-holders, we don't know what to expect.

So I generally think that leaving the need for settle up to the caller outside of the
scan itself.

> can we make this '--activate=ay' instead of 2 parms?
> Its much more clear that way. I thought you'd typod'
> your commit message with a rogue 'ay' in it.

Yes

> comments needed in dirty-disk yaml for shutting down lvm/raid

Yes, will add comments.

Revision history for this message
Scott Moser (smoser) wrote :

> > is there a reason not to have lvm_scan do the udevadm_settle ?
> > it seems like all callers are probably interested in having that happen.
> >
> > maybe we even have race conditions elsewhere as I don't see anywhere else
> > that does use settle after calling this.
>
> In blockmeta, creating a volgroup does not create any device nodes, but

But if that is the first time that 'lvm_scan' is run, I'm not sure
how that would not possibly create device nodes.

> creating the logical volumes will. We don't currently do a devsync()
> (which does a settle using the --exit-if-exists=/path/to/device/expected

I generally think that '--exit-if-exists=' is a bug.
consider this:
 a.) /dev/sda has 1 partition on it, so '/dev/sda1' exists (from previous
install).
 b.) we repartition /dev/sda, blockdev --rereadpt, and and then call
   'udevadm settle --exit-if-exists=/dev/sda1'
 c.) udevadm checks to see if /dev/sda1 exists. It does (it always did)
 d.) udev events continue, and re-read the partition table, delete all
     the old partitions and re-create them.
 e.) while 'd' is happening our code thinks it is fine to use /dev/sda1

I think we have this general fallacy in logic at places.

/dev/sda1 above could just as well be /dev/vg0 or any other device.

> to have a fast exit path if the device node has been created) at the end
> of lvm logical volume creation, but > the subsequent call of the user
> of the lvm device uses get_path_to_storage() which will do a devsync().

udevadm settle is *not* a slow operation if there are no events in the
queue. It is a very important one if there *is* events in the queue.

  $ time udevadm settle
  real 0m0.013s
  user 0m0.004s
  sys 0m0.001s

So... I'd much rather have any functions that may cause udevadm events
to call settle by default and be safe than try to shave off an extra
1/100th of a second in a OS install.

Revision history for this message
Ryan Harper (raharper) wrote :
Download full text (4.0 KiB)

On Wed, Aug 1, 2018 at 8:13 AM Scott Moser <email address hidden> wrote:
>
> > > is there a reason not to have lvm_scan do the udevadm_settle ?
> > > it seems like all callers are probably interested in having that happen.
> > >
> > > maybe we even have race conditions elsewhere as I don't see anywhere else
> > > that does use settle after calling this.
> >
> > In blockmeta, creating a volgroup does not create any device nodes, but
>
> But if that is the first time that 'lvm_scan' is run, I'm not sure
> how that would not possibly create device nodes.

A volume group is not directly accessible as a block device. You have
to create an LV on a VG to get an accessible block device.

>
> > creating the logical volumes will. We don't currently do a devsync()
> > (which does a settle using the --exit-if-exists=/path/to/device/expected
>
> I generally think that '--exit-if-exists=' is a bug.
> consider this:
> a.) /dev/sda has 1 partition on it, so '/dev/sda1' exists (from previous
> install).
> b.) we repartition /dev/sda, blockdev --rereadpt, and and then call
> 'udevadm settle --exit-if-exists=/dev/sda1'

We wipe the disk's partition table, and then force a reread of the
partition table
and ensure that the disk no longer has *any* partitions, whatever
their name was or the location.

The disk is clean before we create any new partitions.

> c.) udevadm checks to see if /dev/sda1 exists. It does (it always did)
> d.) udev events continue, and re-read the partition table, delete all
> the old partitions and re-create them.
> e.) while 'd' is happening our code thinks it is fine to use /dev/sda1
>
> I think we have this general fallacy in logic at places.

I disagree. The order of events that happen in curtin are as follows:

1) clear-holders calls wipe_superblock on /dev/sda (which has a /dev/sda1)
2) if the device being wiped has partitions (it does), then we wipe
the partition table
      and then reread the partition table, settle and query the disk
for any partitions, repeat
      until there are no partitions reported from the kernel, we fail
if we cannot wipe the partitions.
3) after all disks are clear (no partitions are left on any disk
specified which has wipe superblock
4) we create a partition table (empty) on /dev/sda
5) we create a first partition on /dev/sda, say /dev/sda1
6) we query the path to /dev/sda1 via the get_path_to_storage() which
calls devsync() which
    does a udevadm settle --exit-if-exists

There isn't a logic bug here because we know that *we* were the ones
to create the partition and we know what the expected /dev path is.

>
> /dev/sda1 above could just as well be /dev/vg0 or any other device.

It won't be a volume group, but yes, any other block device that we
create. The logic above holds for those as well. Where do you think
it fails after accounting for how we wipe devices and ensure they're
clear (including partitions)?

>
> > to have a fast exit path if the device node has been created) at the end
> > of lvm logical volume creation, but > the subsequent call of the user
> > of the lvm device uses get_path_to_storage() which will do a devsync().
>
> udevadm settle is *not* a slow op...

Read more...

Revision history for this message
Scott Moser (smoser) wrote :
Download full text (4.6 KiB)

> > > creating the logical volumes will. We don't currently do a devsync()
> > > (which does a settle using the --exit-if-exists=/path/to/device/expected
> >
> > I generally think that '--exit-if-exists=' is a bug.
> > consider this:
> > a.) /dev/sda has 1 partition on it, so '/dev/sda1' exists (from previous
> > install).
> > b.) we repartition /dev/sda, blockdev --rereadpt, and and then call
> > 'udevadm settle --exit-if-exists=/dev/sda1'
>
> We wipe the disk's partition table, and then force a reread of the
> partition table
> and ensure that the disk no longer has *any* partitions, whatever
> their name was or the location.
>
> The disk is clean before we create any new partitions.
>
> > c.) udevadm checks to see if /dev/sda1 exists. It does (it always did)
> > d.) udev events continue, and re-read the partition table, delete all
> > the old partitions and re-create them.
> > e.) while 'd' is happening our code thinks it is fine to use /dev/sda1
> >
> > I think we have this general fallacy in logic at places.
>
> I disagree. The order of events that happen in curtin are as follows:
>
> 1) clear-holders calls wipe_superblock on /dev/sda (which has a /dev/sda1)
> 2) if the device being wiped has partitions (it does), then we wipe
> the partition table
> and then reread the partition table, settle and query the disk
> for any partitions, repeat
> until there are no partitions reported from the kernel, we fail
> if we cannot wipe the partitions.
> 3) after all disks are clear (no partitions are left on any disk
> specified which has wipe superblock
> 4) we create a partition table (empty) on /dev/sda
> 5) we create a first partition on /dev/sda, say /dev/sda1
> 6) we query the path to /dev/sda1 via the get_path_to_storage() which
> calls devsync() which
> does a udevadm settle --exit-if-exists
>
> There isn't a logic bug here because we know that *we* were the ones
> to create the partition and we know what the expected /dev path is.
>
> >
> > /dev/sda1 above could just as well be /dev/vg0 or any other device.
>
> It won't be a volume group, but yes, any other block device that we
> create. The logic above holds for those as well. Where do you think
> it fails after accounting for how we wipe devices and ensure they're
> clear (including partitions)?
>
>
> >
> > > to have a fast exit path if the device node has been created) at the end
> > > of lvm logical volume creation, but > the subsequent call of the user
> > > of the lvm device uses get_path_to_storage() which will do a devsync().
> >
> > udevadm settle is *not* a slow operation if there are no events in the
> > queue. It is a very important one if there *is* events in the queue.
> >
> > $ time udevadm settle
> > real 0m0.013s
> > user 0m0.004s
> > sys 0m0.001s
>
> At best, at worst, the default timeout for udevadm settle is 120
> seconds; and without an --exit-if-exists, we wait on *all* events in
> the queue at the time of the settle call.

>
> >
> > So... I'd much rather have any functions that may cause udevadm events
> > to call settle by default and be safe than try to shave off an extra
> > 1/100th of a second in a OS...

Read more...

Revision history for this message
Ryan Harper (raharper) wrote :
Download full text (7.0 KiB)

On Wed, Aug 8, 2018 at 9:58 AM Scott Moser <email address hidden> wrote:
>
> > > > creating the logical volumes will. We don't currently do a devsync()
> > > > (which does a settle using the --exit-if-exists=/path/to/device/expected
> > >
> > > I generally think that '--exit-if-exists=' is a bug.
> > > consider this:
> > > a.) /dev/sda has 1 partition on it, so '/dev/sda1' exists (from previous
> > > install).
> > > b.) we repartition /dev/sda, blockdev --rereadpt, and and then call
> > > 'udevadm settle --exit-if-exists=/dev/sda1'
> >
> > We wipe the disk's partition table, and then force a reread of the
> > partition table
> > and ensure that the disk no longer has *any* partitions, whatever
> > their name was or the location.
> >
> > The disk is clean before we create any new partitions.
> >
> > > c.) udevadm checks to see if /dev/sda1 exists. It does (it always did)
> > > d.) udev events continue, and re-read the partition table, delete all
> > > the old partitions and re-create them.
> > > e.) while 'd' is happening our code thinks it is fine to use /dev/sda1
> > >
> > > I think we have this general fallacy in logic at places.
> >
> > I disagree. The order of events that happen in curtin are as follows:
> >
> > 1) clear-holders calls wipe_superblock on /dev/sda (which has a /dev/sda1)
> > 2) if the device being wiped has partitions (it does), then we wipe
> > the partition table
> > and then reread the partition table, settle and query the disk
> > for any partitions, repeat
> > until there are no partitions reported from the kernel, we fail
> > if we cannot wipe the partitions.
> > 3) after all disks are clear (no partitions are left on any disk
> > specified which has wipe superblock
> > 4) we create a partition table (empty) on /dev/sda
> > 5) we create a first partition on /dev/sda, say /dev/sda1
> > 6) we query the path to /dev/sda1 via the get_path_to_storage() which
> > calls devsync() which
> > does a udevadm settle --exit-if-exists
> >
> > There isn't a logic bug here because we know that *we* were the ones
> > to create the partition and we know what the expected /dev path is.
> >
> > >
> > > /dev/sda1 above could just as well be /dev/vg0 or any other device.
> >
> > It won't be a volume group, but yes, any other block device that we
> > create. The logic above holds for those as well. Where do you think
> > it fails after accounting for how we wipe devices and ensure they're
> > clear (including partitions)?
> >
> >
> > >
> > > > to have a fast exit path if the device node has been created) at the end
> > > > of lvm logical volume creation, but > the subsequent call of the user
> > > > of the lvm device uses get_path_to_storage() which will do a devsync().
> > >
> > > udevadm settle is *not* a slow operation if there are no events in the
> > > queue. It is a very important one if there *is* events in the queue.
> > >
> > > $ time udevadm settle
> > > real 0m0.013s
> > > user 0m0.004s
> > > sys 0m0.001s
> >
> > At best, at worst, the default timeout for udevadm settle is 120
> > seconds; and without an --exit-if-exists, we wait on *all* events in
> > the queue at the time ...

Read more...

Revision history for this message
Scott Moser (smoser) wrote :
Download full text (5.8 KiB)

> > non-sense.
> > have you ever seen 'udevadm settle' take 120 seconds? Can you give
> > an example of when it *could* do that? The only thing I can reasonably
>
> https://ask.fedoraproject.org/en/question/81006/slow-boot-time-udev-settle/
> https://askubuntu.com/questions/888010/about-systemd-udev-settle-service-and-
> slow-booting
> https://bugzilla.redhat.com/show_bug.cgi?id=735866
> https://bbs.archlinux.org/viewtopic.php?id=189369
> https://forums.opensuse.org/showthread.php/506828-Udev-3-minute-delay-on-boot
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=754987
> https://lists.debian.org/debian-user/2015/04/msg01592.html

Every single example link above is in regard to slow boot times.
Boot is a time when there is a flurry of udev events. curtin does
not run in that time frame which is a *huge* outlier in the general
life of a system.

In order to get actual numbers on how long we spend time waiting for
udev events that I think are important, I put up:
 https://code.launchpad.net/~smoser/curtin/+git/curtin/+merge/352791

A full vmtest run produced 13098 calls to udevadm settle over 257
installs. Of those calls, 1555 took over .1 seconds. The longest
coming in during TrustyHWEXTestRaid5Bcache at 1.809 seconds.
 http://paste.ubuntu.com/p/t2k6tDw6x7/

Here is a log of total time spent in settle along with total time
spent in 'curtin install'.
 http://paste.ubuntu.com/p/rNsqfpmxkr/
Admittedly the total time we spend "waiting" can be 10% of the
time of our install, but I'd still argue that those waits are
almost certainly valid.

> Settle can block up to 120 seconds any time one or more events
> that are in the queue when settle is called that do not get processed.
> The event in queue may be unrelated to storage; it can be any event
> in the system (net, block, usb); settle doesn't care.

And you think that at the time frame that an installer is running
there is likely a flurry of net or usb events coming in?
Go ahead, find a busy system that is not booting and run 'udevadm monitor'
See if you see a single event over the course of 10 minutes or so.

I gave that a try, I ran 'lxc launch' on a lxd with zfs. I was honestly
floored at how many events came through. (1163 UDEV , 1163 KERNEL).
I ran a loop of 'time udevadm settle' during that, and it never took more
than 1/100th of a second.

> > come up with are disk based operations on large md or something.
> > Those are exactly the reasons we want to settle. Anything else that
> > was seemingly unrelated but is taking significant time honestly
> > probably something important to an installer. I'd much rather
> > see a log entry that showed a timeout failed on a settle than
> > try to diagnose some related failure.
>
> Recall this discussion:
> https://bugs.launchpad.net/cloud-init/+bug/1766287
> https://code.launchpad.net/~raharper/cloud-init/+git/cloud-
> init/+merge/344198

Both of our responses on that bug is that we'd much rather
have *stable* behavior than fast behavior. That is what I'm arguing for here.
So I'm confused on your pointing to it.

> My argument is that we should only call settle when we *need* it.
> Extra calls to settle just because at best waste a...

Read more...

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

jenkins vmtest run approves:

https://jenkins.ubuntu.com/server/job/curtin-vmtest-devel-debug/91/console

----------------------------------------------------------------------
Ran 3198 tests in 13805.907s

OK (SKIP=288)
Mon, 13 Aug 2018 18:33:50 +0000: vmtest end [0] in 13809s

Revision history for this message
Scott Moser (smoser) wrote :

bah. a comment i had made a week ago inline that didn't get saved.

this does look really good though at this point.

Revision history for this message
Ryan Harper (raharper) wrote :

On Fri, Aug 17, 2018 at 7:51 AM Scott Moser <email address hidden> wrote:
>
> bah. a comment i had made a week ago inline that didn't get saved.
>
> this does look really good though at this point.
>
>
> Diff comments:
>
> > diff --git a/examples/tests/lvmoverraid.yaml b/examples/tests/lvmoverraid.yaml
>
> By adding the lvm stop and mdadm stop you are pushing us through a very close path that we'd previously not been through. But aren't you also ensuring we do not hit the previously tested (and more common) code path?
> At least for lvm wouldn't the ephemeral environment normal have
> The pscan running?

Thanks for raising this.

In the previous "common" case, the LVMs were never removed (kernel
still knew of them, device nodes existed) since we've never performed
the stop; and they were never "rediscovered" by a scan since the lvm
tools examine /etc/lvm/* for config before looking at the disk. I
confirmed this when attempting to reproduce the failure only worked
once I added the above code to the dirty-disk mode.

I believe that what we are doing now matches more closely to what
curtin would see on first-boot of a system which has LVM on block
devices but the OS (our ephemeral image) will have no record of it and
it can *only* be found via our lvm_scan() + vg_activate().

>
> > new file mode 100644
> > index 0000000..a1d41e9
>
>
> --
> https://code.launchpad.net/~raharper/curtin/+git/curtin/+merge/351384
> You are the owner of ~raharper/curtin:fix/lvm-over-raid.

Revision history for this message
Scott Moser (smoser) wrote :

Sounds reasonable.

On Fri, Aug 17, 2018 at 10:24 AM Ryan Harper <email address hidden>
wrote:

> On Fri, Aug 17, 2018 at 7:51 AM Scott Moser <email address hidden>
> wrote:
> >
> > bah. a comment i had made a week ago inline that didn't get saved.
> >
> > this does look really good though at this point.
> >
> >
> > Diff comments:
> >
> > > diff --git a/examples/tests/lvmoverraid.yaml
> b/examples/tests/lvmoverraid.yaml
> >
> > By adding the lvm stop and mdadm stop you are pushing us through a very
> close path that we'd previously not been through. But aren't you also
> ensuring we do not hit the previously tested (and more common) code path?
> > At least for lvm wouldn't the ephemeral environment normal have
> > The pscan running?
>
> Thanks for raising this.
>
> In the previous "common" case, the LVMs were never removed (kernel
> still knew of them, device nodes existed) since we've never performed
> the stop; and they were never "rediscovered" by a scan since the lvm
> tools examine /etc/lvm/* for config before looking at the disk. I
> confirmed this when attempting to reproduce the failure only worked
> once I added the above code to the dirty-disk mode.
>
> I believe that what we are doing now matches more closely to what
> curtin would see on first-boot of a system which has LVM on block
> devices but the OS (our ephemeral image) will have no record of it and
> it can *only* be found via our lvm_scan() + vg_activate().
>
>
>
> >
> > > new file mode 100644
> > > index 0000000..a1d41e9
> >
> >
> > --
> > https://code.launchpad.net/~raharper/curtin/+git/curtin/+merge/351384
> > You are the owner of ~raharper/curtin:fix/lvm-over-raid.
>
> --
> https://code.launchpad.net/~raharper/curtin/+git/curtin/+merge/351384
> You are reviewing the proposed merge of ~raharper/curtin:fix/lvm-over-raid
> into curtin:master.
>

Revision history for this message
Scott Moser (smoser) wrote :

sounds good.

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://jenkins.ubuntu.com/server/job/curtin-autoland-test/15/
Executed test runs:
    None: https://jenkins.ubuntu.com/server/job/admin-lp-git-autoland/52/console

review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/curtin/block/clear_holders.py b/curtin/block/clear_holders.py
index 9d73b28..a2042d5 100644
--- a/curtin/block/clear_holders.py
+++ b/curtin/block/clear_holders.py
@@ -624,6 +624,9 @@ def start_clear_holders_deps():
624 # all disks and partitions should be sufficient to remove the mdadm624 # all disks and partitions should be sufficient to remove the mdadm
625 # metadata625 # metadata
626 mdadm.mdadm_assemble(scan=True, ignore_errors=True)626 mdadm.mdadm_assemble(scan=True, ignore_errors=True)
627 # scan and activate for logical volumes
628 lvm.lvm_scan()
629 lvm.activate_volgroups()
627 # the bcache module needs to be present to properly detect bcache devs630 # the bcache module needs to be present to properly detect bcache devs
628 # on some systems (precise without hwe kernel) it may not be possible to631 # on some systems (precise without hwe kernel) it may not be possible to
629 # lad the bcache module bcause it is not present in the kernel. if this632 # lad the bcache module bcause it is not present in the kernel. if this
diff --git a/curtin/block/lvm.py b/curtin/block/lvm.py
index 8643245..eca64f6 100644
--- a/curtin/block/lvm.py
+++ b/curtin/block/lvm.py
@@ -57,14 +57,32 @@ def lvmetad_running():
57 '/run/lvmetad.pid'))57 '/run/lvmetad.pid'))
5858
5959
60def lvm_scan():60def activate_volgroups():
61 """
62 Activate available volgroups and logical volumes within.
63
64 # found
65 % vgchange -ay
66 1 logical volume(s) in volume group "vg1sdd" now active
67
68 # none found (no output)
69 % vgchange -ay
70 """
71
72 # vgchange handles syncing with udev by default
73 # see man 8 vgchange and flag --noudevsync
74 out, _ = util.subp(['vgchange', '--activate=y'], capture=True)
75 if out:
76 LOG.info(out)
77
78
79def lvm_scan(activate=True):
61 """80 """
62 run full scan for volgroups, logical volumes and physical volumes81 run full scan for volgroups, logical volumes and physical volumes
63 """82 """
64 # the lvm tools lvscan, vgscan and pvscan on ubuntu precise do not83 # prior to xenial, lvmetad is not packaged, so even if a tool supports
65 # support the flag --cache. the flag is present for the tools in ubuntu84 # flag --cache it has no effect. In Xenial and newer the --cache flag is
66 # trusty and later. since lvmetad is used in current releases of85 # used (if lvmetad is running) to ensure that the data cached by
67 # ubuntu, the --cache flag is needed to ensure that the data cached by
68 # lvmetad is updated.86 # lvmetad is updated.
6987
70 # before appending the cache flag though, check if lvmetad is running. this88 # before appending the cache flag though, check if lvmetad is running. this
diff --git a/examples/tests/dirty_disks_config.yaml b/examples/tests/dirty_disks_config.yaml
index 75d44c3..fb9a0d6 100644
--- a/examples/tests/dirty_disks_config.yaml
+++ b/examples/tests/dirty_disks_config.yaml
@@ -27,6 +27,31 @@ bucket:
27 # disable any rpools to trigger disks with zfs_member label but inactive27 # disable any rpools to trigger disks with zfs_member label but inactive
28 # pools28 # pools
29 zpool export rpool ||:29 zpool export rpool ||:
30 - &lvm_stop |
31 #!/bin/sh
32 # This function disables any existing lvm logical volumes that
33 # have been created during the early storage config stage
34 # and simulates the effect of booting into a system with existing
35 # (but inactive) lvm configuration.
36 for vg in `pvdisplay -C --separator = -o vg_name --noheadings`; do
37 vgchange -an $vg ||:
38 done
39 # disable the automatic pvscan, we want to test that curtin
40 # can find/enable logical volumes without this service
41 command -v systemctl && systemctl mask lvm2-pvscan\@.service
42 # remove any existing metadata written from early disk config
43 rm -rf /etc/lvm/archive /etc/lvm/backup
44 - &mdadm_stop |
45 #!/bin/sh
46 # This function disables any existing raid devices which may
47 # have been created during the early storage config stage
48 # and simulates the effect of booting into a system with existing
49 # but inactive mdadm configuration.
50 for md in /dev/md*; do
51 mdadm --stop $md ||:
52 done
53 # remove any existing metadata written from early disk config
54 rm -f /etc/mdadm/mdadm.conf
3055
31early_commands:56early_commands:
32 # running block-meta custom from the install environment57 # running block-meta custom from the install environment
@@ -34,9 +59,11 @@ early_commands:
34 # the disks exactly as in this config before the rest of the install59 # the disks exactly as in this config before the rest of the install
35 # will just blow it all away. We have clean out other environment60 # will just blow it all away. We have clean out other environment
36 # that could unintentionally mess things up.61 # that could unintentionally mess things up.
37 blockmeta: [env, -u, OUTPUT_FSTAB,62 01-blockmeta: [env, -u, OUTPUT_FSTAB,
38 TARGET_MOUNT_POINT=/tmp/my.bdir/target,63 TARGET_MOUNT_POINT=/tmp/my.bdir/target,
39 WORKING_DIR=/tmp/my.bdir/work.d, 64 WORKING_DIR=/tmp/my.bdir/work.d,
40 curtin, --showtrace, -v, block-meta, --umount, custom]65 curtin, --showtrace, -v, block-meta, --umount, custom]
41 enable_swaps: [sh, -c, *swapon]66 02-enable_swaps: [sh, -c, *swapon]
42 disable_rpool: [sh, -c, *zpool_export]67 03-disable_rpool: [sh, -c, *zpool_export]
68 04-lvm_stop: [sh, -c, *lvm_stop]
69 05-mdadm_stop: [sh, -c, *mdadm_stop]
diff --git a/examples/tests/lvmoverraid.yaml b/examples/tests/lvmoverraid.yaml
43new file mode 10064470new file mode 100644
index 0000000..a1d41e9
--- /dev/null
+++ b/examples/tests/lvmoverraid.yaml
@@ -0,0 +1,98 @@
1storage:
2 config:
3 - grub_device: true
4 id: disk-0
5 model: QEMU_HARDDISK
6 name: 'main_disk'
7 serial: disk-a
8 preserve: false
9 ptable: gpt
10 type: disk
11 wipe: superblock
12 - grub_device: false
13 id: disk-2
14 name: 'disk-2'
15 serial: disk-b
16 preserve: false
17 type: disk
18 wipe: superblock
19 - grub_device: false
20 id: disk-1
21 name: 'disk-1'
22 serial: disk-c
23 preserve: false
24 type: disk
25 wipe: superblock
26 - grub_device: false
27 id: disk-3
28 name: 'disk-3'
29 serial: disk-d
30 preserve: false
31 type: disk
32 wipe: superblock
33 - grub_device: false
34 id: disk-4
35 name: 'disk-4'
36 serial: disk-e
37 preserve: false
38 type: disk
39 wipe: superblock
40 - device: disk-0
41 flag: bios_grub
42 id: part-0
43 preserve: false
44 size: 1048576
45 type: partition
46 - device: disk-0
47 flag: ''
48 id: part-1
49 preserve: false
50 size: 4G
51 type: partition
52 - devices:
53 - disk-2
54 - disk-1
55 id: raid-0
56 name: md0
57 raidlevel: 1
58 spare_devices: []
59 type: raid
60 - devices:
61 - disk-3
62 - disk-4
63 id: raid-1
64 name: md1
65 raidlevel: 1
66 spare_devices: []
67 type: raid
68 - devices:
69 - raid-0
70 - raid-1
71 id: vg-0
72 name: vg0
73 type: lvm_volgroup
74 - id: lv-0
75 name: lv-0
76 size: 3G
77 type: lvm_partition
78 volgroup: vg-0
79 - fstype: ext4
80 id: fs-0
81 preserve: false
82 type: format
83 volume: part-1
84 - fstype: ext4
85 id: fs-1
86 preserve: false
87 type: format
88 volume: lv-0
89 - device: fs-0
90 id: mount-0
91 path: /
92 type: mount
93 - device: fs-1
94 id: mount-1
95 path: /home
96 type: mount
97 version: 1
98
diff --git a/tests/unittests/test_block_lvm.py b/tests/unittests/test_block_lvm.py
index 341f2fa..22fb064 100644
--- a/tests/unittests/test_block_lvm.py
+++ b/tests/unittests/test_block_lvm.py
@@ -75,24 +75,24 @@ class TestBlockLvm(CiTestCase):
75 @mock.patch('curtin.block.lvm.util')75 @mock.patch('curtin.block.lvm.util')
76 def test_lvm_scan(self, mock_util, mock_lvmetad):76 def test_lvm_scan(self, mock_util, mock_lvmetad):
77 """check that lvm_scan formats commands correctly for each release"""77 """check that lvm_scan formats commands correctly for each release"""
78 cmds = [['pvscan'], ['vgscan', '--mknodes']]
78 for (count, (codename, lvmetad_status, use_cache)) in enumerate(79 for (count, (codename, lvmetad_status, use_cache)) in enumerate(
79 [('precise', False, False), ('precise', True, False),80 [('precise', False, False),
80 ('trusty', False, False), ('trusty', True, True),81 ('trusty', False, False),
81 ('vivid', False, False), ('vivid', True, True),
82 ('wily', False, False), ('wily', True, True),
83 ('xenial', False, False), ('xenial', True, True),82 ('xenial', False, False), ('xenial', True, True),
84 ('yakkety', True, True), ('UNAVAILABLE', True, True),
85 (None, True, True), (None, False, False)]):83 (None, True, True), (None, False, False)]):
86 mock_util.lsb_release.return_value = {'codename': codename}84 mock_util.lsb_release.return_value = {'codename': codename}
87 mock_lvmetad.return_value = lvmetad_status85 mock_lvmetad.return_value = lvmetad_status
88 lvm.lvm_scan()86 lvm.lvm_scan()
89 self.assertEqual(87 expected = [cmd for cmd in cmds]
90 len(mock_util.subp.call_args_list), 2 * (count + 1))88 for cmd in expected:
91 for (expected, actual) in zip(89 if lvmetad_status:
92 [['pvscan'], ['vgscan', '--mknodes']],90 cmd.append('--cache')
93 mock_util.subp.call_args_list[2 * count:2 * count + 2]):91
94 if use_cache:92 calls = [mock.call(cmd, capture=True) for cmd in expected]
95 expected.append('--cache')93 self.assertEqual(len(expected), len(mock_util.subp.call_args_list))
96 self.assertEqual(mock.call(expected, capture=True), actual)94 mock_util.subp.has_calls(calls)
95 mock_util.subp.reset_mock()
96
9797
98# vi: ts=4 expandtab syntax=python98# vi: ts=4 expandtab syntax=python
diff --git a/tests/unittests/test_clear_holders.py b/tests/unittests/test_clear_holders.py
index 6c29171..21f76be 100644
--- a/tests/unittests/test_clear_holders.py
+++ b/tests/unittests/test_clear_holders.py
@@ -779,10 +779,12 @@ class TestClearHolders(CiTestCase):
779 mock_gen_holders_tree.return_value = self.example_holders_trees[1][1]779 mock_gen_holders_tree.return_value = self.example_holders_trees[1][1]
780 clear_holders.assert_clear(device)780 clear_holders.assert_clear(device)
781781
782 @mock.patch('curtin.block.clear_holders.lvm')
782 @mock.patch('curtin.block.clear_holders.zfs')783 @mock.patch('curtin.block.clear_holders.zfs')
783 @mock.patch('curtin.block.clear_holders.mdadm')784 @mock.patch('curtin.block.clear_holders.mdadm')
784 @mock.patch('curtin.block.clear_holders.util')785 @mock.patch('curtin.block.clear_holders.util')
785 def test_start_clear_holders_deps(self, mock_util, mock_mdadm, mock_zfs):786 def test_start_clear_holders_deps(self, mock_util, mock_mdadm, mock_zfs,
787 mock_lvm):
786 mock_zfs.zfs_supported.return_value = True788 mock_zfs.zfs_supported.return_value = True
787 clear_holders.start_clear_holders_deps()789 clear_holders.start_clear_holders_deps()
788 mock_mdadm.mdadm_assemble.assert_called_with(790 mock_mdadm.mdadm_assemble.assert_called_with(
@@ -790,11 +792,12 @@ class TestClearHolders(CiTestCase):
790 mock_util.load_kernel_module.assert_has_calls([792 mock_util.load_kernel_module.assert_has_calls([
791 mock.call('bcache'), mock.call('zfs')])793 mock.call('bcache'), mock.call('zfs')])
792794
795 @mock.patch('curtin.block.clear_holders.lvm')
793 @mock.patch('curtin.block.clear_holders.zfs')796 @mock.patch('curtin.block.clear_holders.zfs')
794 @mock.patch('curtin.block.clear_holders.mdadm')797 @mock.patch('curtin.block.clear_holders.mdadm')
795 @mock.patch('curtin.block.clear_holders.util')798 @mock.patch('curtin.block.clear_holders.util')
796 def test_start_clear_holders_deps_nozfs(self, mock_util, mock_mdadm,799 def test_start_clear_holders_deps_nozfs(self, mock_util, mock_mdadm,
797 mock_zfs):800 mock_zfs, mock_lvm):
798 """test that we skip zfs modprobe on unsupported platforms"""801 """test that we skip zfs modprobe on unsupported platforms"""
799 mock_zfs.zfs_supported.return_value = False802 mock_zfs.zfs_supported.return_value = False
800 clear_holders.start_clear_holders_deps()803 clear_holders.start_clear_holders_deps()
diff --git a/tests/vmtests/test_lvm_raid.py b/tests/vmtests/test_lvm_raid.py
801new file mode 100644804new file mode 100644
index 0000000..0c50941
--- /dev/null
+++ b/tests/vmtests/test_lvm_raid.py
@@ -0,0 +1,50 @@
1# This file is part of curtin. See LICENSE file for copyright and license info.
2
3from .releases import base_vm_classes as relbase
4from .test_mdadm_bcache import TestMdadmAbs
5from .test_lvm import TestLvmAbs
6
7import textwrap
8
9
10class TestLvmOverRaidAbs(TestMdadmAbs, TestLvmAbs):
11 conf_file = "examples/tests/lvmoverraid.yaml"
12 active_mdadm = "2"
13 nr_cpus = 2
14 dirty_disks = True
15 extra_disks = ['10G'] * 4
16
17 collect_scripts = TestLvmAbs.collect_scripts
18 collect_scripts += TestMdadmAbs.collect_scripts + [textwrap.dedent("""
19 cd OUTPUT_COLLECT_D
20 ls -al /dev/md* > dev_md
21 cp -a /etc/mdadm etc_mdadm
22 cp -a /etc/lvm etc_lvm
23 """)]
24
25 fstab_expected = {
26 '/dev/vg1/lv1': '/srv/data',
27 '/dev/vg1/lv2': '/srv/backup',
28 }
29 disk_to_check = [('main_disk', 1),
30 ('md0', 0),
31 ('md1', 0)]
32
33 def test_lvs(self):
34 self.check_file_strippedline("lvs", "lv-0=vg0")
35
36 def test_pvs(self):
37 self.check_file_strippedline("pvs", "vg0=/dev/md0")
38 self.check_file_strippedline("pvs", "vg0=/dev/md1")
39
40
41class CosmicTestLvmOverRaid(relbase.cosmic, TestLvmOverRaidAbs):
42 __test__ = True
43
44
45class BionicTestLvmOverRaid(relbase.bionic, TestLvmOverRaidAbs):
46 __test__ = True
47
48
49class XenialGATestLvmOverRaid(relbase.xenial_ga, TestLvmOverRaidAbs):
50 __test__ = True
diff --git a/tests/vmtests/test_lvm_root.py b/tests/vmtests/test_lvm_root.py
index 8ca69d4..bc8b047 100644
--- a/tests/vmtests/test_lvm_root.py
+++ b/tests/vmtests/test_lvm_root.py
@@ -113,7 +113,7 @@ class XenialTestUefiLvmRootXfs(relbase.xenial, TestUefiLvmRootAbs):
113 }113 }
114114
115115
116@VMBaseClass.skip_by_date("1652822", fixby="2019-06-01")116@VMBaseClass.skip_by_date("1652822", fixby="2019-06-01", install=False)
117class XenialTestUefiLvmRootXfsBootXfs(relbase.xenial, TestUefiLvmRootAbs):117class XenialTestUefiLvmRootXfsBootXfs(relbase.xenial, TestUefiLvmRootAbs):
118 """This tests xfs root and xfs boot with uefi.118 """This tests xfs root and xfs boot with uefi.
119119

Subscribers

People subscribed via source and target branches