Commit Graph

236 Commits

Author SHA1 Message Date
Rusty Bird
023cb49293
storage/reflink: show size in refused volume shrink message
Like e6bb282 did for lvm.
2018-03-11 15:34:56 +00:00
Rusty Bird
c31d317c63
storage/reflink: fsync() after resizing existing file
Ensure that the updated metadata is written to disk.
2018-03-11 15:34:55 +00:00
Marek Marczykowski-Górecki
1774be1c69
storage/kernel: skip modules.img block device if kernel dir doesn't have it
Some kernels (like pvgrub2) may not provide modules.img and it isn't an
error. Don't break VM startup in that case, skip that device instead.

Fixes QubesOS/qubes-issues#3563
2018-02-27 04:35:05 +01:00
Marek Marczykowski-Górecki
7731a56daa
Merge remote-tracking branch 'qubesos/pr/192'
* qubesos/pr/192:
  storage/lvm: add more details to refused volume shrink message
  tests: storage/lvm resize
  storage/lvm: fix resizing not persistent volumes
2018-02-22 19:46:11 +01:00
Rusty Bird
37e1aedfa3
reflink: style fix 2018-02-16 21:47:39 +00:00
Rusty Bird
c871424fb0
storage: typo fix 2018-02-16 21:47:37 +00:00
Rusty Bird
f6542effc5
lvm_thin: _remove_revisions() on revisions_to_keep==0
If revisions_to_keep is 0, it may nevertheless have been > 0 before, so
it makes sense to call _remove_revisions() and hold back none (not all)
of the revisions in this case.
2018-02-16 21:47:36 +00:00
Rusty Bird
ade49d44b7
lvm_thin: don't purge one revision too few
We just added one that must be taken into account.
2018-02-16 21:47:35 +00:00
Rusty Bird
86998b0815
lvm_thin: really remove revision 2018-02-16 21:47:33 +00:00
Rusty Bird
9f468f93f5
lvm_thin: fill in volume's revisions_to_keep from pool
Otherwise, the base class defaults revisions_to_keep to 0.
2018-02-16 21:47:32 +00:00
Rusty Bird
1695a732b8
file-reflink, a storage driver optimized for CoW filesystems
This adds the file-reflink storage driver. It is never selected
automatically for pool creation, especially not the creation of
'varlibqubes' (though it can be used if set up manually).

The code is quite small:

               reflink.py  lvm.py      file.py + block-snapshot
    sloccount  334 lines   447 (134%)  570 (171%)

Background: btrfs and XFS (but not yet ZFS) support instant copies of
individual files through the 'FICLONE' ioctl behind 'cp --reflink'.
Which file-reflink uses to snapshot VM image files without an extra
device-mapper layer. All the snapshots are essentially freestanding;
there's no functional origin vs. snapshot distinction.

In contrast to 'file'-on-btrfs, file-reflink inherently avoids
CoW-on-CoW. Which is a bigger issue now on R4.0, where even AppVMs'
private volumes are CoW. (And turning off the lower, filesystem-level
CoW for 'file'-on-btrfs images would turn off data checksums too, i.e.
protection against bit rot.)

Also in contrast to 'file', all storage features are supported,
including

    - any number of revisions_to_keep
    - volume.revert()
    - volume.is_outdated
    - online fstrim/discard

Example tree of a file-reflink pool - *-dirty.img are connected to Xen:

    - /var/lib/testpool/appvms/foo/volatile-dirty.img
    - /var/lib/testpool/appvms/foo/root-dirty.img
    - /var/lib/testpool/appvms/foo/root.img
    - /var/lib/testpool/appvms/foo/private-dirty.img
    - /var/lib/testpool/appvms/foo/private.img
    - /var/lib/testpool/appvms/foo/private.img@2018-01-02T03:04:05Z
    - /var/lib/testpool/appvms/foo/private.img@2018-01-02T04:05:06Z
    - /var/lib/testpool/appvms/foo/private.img@2018-01-02T05:06:07Z
    - /var/lib/testpool/appvms/bar/...
    - /var/lib/testpool/appvms/...
    - /var/lib/testpool/template-vms/fedora-26/...
    - /var/lib/testpool/template-vms/...

It looks similar to a 'file' pool tree, and in fact file-reflink is
drop-in compatible:

    $ qvm-shutdown --all --wait
    $ systemctl stop qubesd
    $ sed 's/ driver="file"/ driver="file-reflink"/g' -i.bak /var/lib/qubes/qubes.xml
    $ systemctl start qubesd
    $ sudo rm -f /path/to/pool/*/*/*-cow.img*

If the user tries to create a fresh file-reflink pool on a filesystem
that doesn't support reflinks, qvm-pool will abort and mention the
'setup_check=no' option. Which can be passed to force a fallback on
regular sparse copies, with of course lots of time/space overhead. The
same fallback code is also used when initially cloning a VM from a
foreign pool, or from another file-reflink pool on a different
mountpoint.

'journalctl -fu qubesd' will show all file-reflink copy/rename/remove
operations on VM creation/startup/shutdown/etc.
2018-02-12 21:20:05 +00:00
Marek Marczykowski-Górecki
e6bb2828f1
storage/lvm: add more details to refused volume shrink message
Include old and new size.
2018-02-07 02:07:25 +01:00
Marek Marczykowski-Górecki
7903dc53f9
storage/lvm: fix resizing not persistent volumes
Even when volume is not persistent (like TemplateBasedVM:root), it
should be resizeable. Just the new size, similarly to the volume
content, will be reverted after qube shutdown.

Additionally, when VM is running, volume resize should affect _only_ its
temporary snapshot. This way resize can be properly reverted together
with actual volume changes (which include resize2fs call).

Fixes QubesOS/qubes-issues#3519
2018-02-07 02:07:25 +01:00
Marek Marczykowski-Górecki
32c6083e1c
Make pylint happy
Fix thing detected by updated pylint in Travis-CI
2017-12-21 18:19:10 +01:00
Marek Marczykowski-Górecki
96bd734852
storage/lvm: clean -snap LV on volume removal 2017-12-14 23:26:52 +01:00
Marek Marczykowski-Górecki
81f455e15d
storage/file: move revisions_to_keep restrictions to property setter
Do not check for accepted value only in constructor, do that in property
setter. This will allow enforcing the limit regardless of how the value
was set.

This is preparation for dynamic revisions_to_keep change.

QubesOS/qubes-issues#3256
2017-11-07 02:57:59 +01:00
Marek Marczykowski-Górecki
439d9b87ff
storage/lvm: fix importing different-sized volume from another pool
Fixes QubesOS/qubes-issues#3257
2017-11-07 02:57:59 +01:00
Marek Marczykowski-Górecki
f3455b5d99
storage/file: fix preserving spareness on volume clone
Force creating sparse file, even if source volume is not such file (for
example block device).

Reported by @na--
QubesOS/qubes-issues#3255
2017-11-07 02:57:58 +01:00
Marek Marczykowski-Górecki
e76372b934
storage: add size and usage properties to pool object
Add Pool.size and Pool.usage to the API. Implement them for LVM and File
pools. Add appropriate tests.

QubesOS/qubes-issues#3240
2017-11-07 02:57:58 +01:00
Marek Marczykowski-Górecki
49e35e66aa
storage: improve error reporting
- make it clear that failed qubes.ResizeDisk service call means the need
to resize filesystem manually (but not necessarily the volume itself)
- propagate exceptions raised by async storage pool implementations

Related QubesOS/qubes-issues#3173
2017-10-21 03:35:01 +02:00
Marek Marczykowski-Górecki
836d9f902a
Merge branch 'bug3164'
* bug3164:
  tests: add regression test for #3164
  storage/lvm: make sure volume cache is refreshed after changes
  storage/lvm: fix Volume.verify()
  storage/lvm: remove old volume only after successfully cloning new one
2017-10-16 04:28:26 +02:00
Marek Marczykowski-Górecki
08583af1ff
storage/lvm: make sure volume cache is refreshed after changes
Even if start/stop fails, still refresh the cache. The failed operation
might still modified something.
2017-10-16 00:44:52 +02:00
Marek Marczykowski-Górecki
145ccfb34e
storage/lvm: fix Volume.verify()
This function is supposed to raise an exception if something is wrong,
not just return False. Document this.
2017-10-16 00:43:10 +02:00
Marek Marczykowski-Górecki
021047f950
storage/lvm: remove old volume only after successfully cloning new one
In some cases, it may happen that new volume (`self._vid_snap`) does not
exists. This is normally an error, but even in such a case, do not
remove the only remaining instance of volume (`self.vid`). Instead,
rename it temporarily and remove only after new volume is successfully
cloned.

Fixes QubesOS/qubes-issues#3164
2017-10-13 01:11:55 +02:00
Marek Marczykowski-Górecki
2164a8d7b8
Change license to LGPL v2.1+
See this thread for reasoning and acceptance from contributors:
https://groups.google.com/d/topic/qubes-devel/G7KzrfU0lWY/discussion
"Changing qubes-core-admin license to LGPL v2.1+"
2017-10-12 00:11:50 +02:00
Marek Marczykowski-Górecki
b8d45c214d
storage/lvm: don't crash when resizing to the same size
This applies to qvm-template-postprocess, which at the beginning try to
resize root volume to appropriate size. It makes more sense to silently
succeed here, instead of forcing every client-side utility to check if
the volume have already desired size.
2017-10-08 18:37:25 +02:00
Marek Marczykowski-Górecki
6091bbbe88
storage/lvm: fix size units on resize
lvextend uses MiB, not MB.
2017-10-03 18:46:39 +02:00
Marek Marczykowski-Górecki
34125d915b
storage: fix method name in LinuxModules volume
It's `import_volume`, not `clone`.
2017-09-29 11:53:01 +02:00
Nicolai Søborg
9d797cc864
lvm->init_cache: fix incorrect max splits 2017-09-13 18:50:02 +02:00
Nicolai Søborg
c30131633b Fix service qubesd not working with some locales
On certain locales (e.g. danish) `usage_percent` will output a comma-separated number, which will make `attr` point the last two decimal points, s.t. `return vol_info['attr'][4] == 'a'` (in the `verify` func) will fail and `qubesd` wont run.
2017-09-12 01:57:49 +02:00
Marek Marczykowski-Górecki
6e5fe58128
storage/lvm: fix Volume() instance init when physical volume is unavailable
First, cache objects created with init_volume - this is the only place
where we have full volume configuration (including snap_on_start and
save_on_stop properties).
But also implement get_volume method, to get a volume instance for given
volume id. Such volume instance may be incomplete (other attributes are
available only in owning domain configuration), but it will be enough
for basic operations - like cheching and changing its size, cloning
etc.
Listing volumes still use list of physically present volumes.

This makes it possible to start qubesd service, without physical
presence of some storage devices. Starting VMs using such storage would
still fail, of course.

Fixes QubesOS/qubes-issues#2960
2017-08-12 22:44:03 +02:00
Marek Marczykowski-Górecki
9ad85a3dff
storage: fix getting list of pool driver parameters
function.func_code existed in python2. Use inspect module (instead of
__code__ attribute).
2017-08-12 22:42:30 +02:00
Marek Marczykowski-Górecki
3338854b1c
storage: fix storage.import_data_end when given Volume instance
Leftover from '0f12870 storage: use direct object references, not only
identifiers'
2017-08-12 22:39:41 +02:00
Marek Marczykowski-Górecki
a833692c63
storage/lvm: extend volume snapshot of running VM too
Extend both backing volume as well as current snapshot, so the increased
size is visible immediately to the user.

Fixes QubesOS/qubes-issues#2982
2017-08-06 20:54:10 +02:00
Marek Marczykowski-Górecki
b9c217704c
storage/file: fix disk usage reporting
Do not report root image usage in template-based VMs. This space is used
only once - by template.
2017-07-30 18:36:23 +02:00
Marek Marczykowski-Górecki
76640df091
Merge branch 'tests-storage'
* tests-storage:
  tests: register libvirt events
  tests: even more agressive cleanup in tearDown
  app: do not wrap libvirt_conn.close() in auto-reconnect wrapper
  api: keep track of established connections
  tests: drop VM cleanup from tearDownClass, fix asyncio usage in tearDown
  storage: fix Storage.clone and Storage.clone_volume
  tests: more tests fixes
  firewall: raise ValueError on invalid hostname in dsthost=
  qmemman: don't load qubes.xml
  tests: fix AdminVM test
  tests: create temporary files in /tmp
  tests: remove renaming test - it isn't supported anymore
  tests: various fixes for storage tests
  tests: fix removing LVM volumes
  tests: fix asyncio usage in some tests
  tests: minor fixes to api/admin tests
  storage/file: create -cow.img only when needed
  storage: move volume_config['source'] filling to one place
  app: do not create 'default' storage pool
  app: add missing setters for default_pool* global properties
2017-07-29 05:01:42 +02:00
Marek Marczykowski-Górecki
639fa26079
Merge branch 'qdb-watch'
* qdb-watch:
  tests: add qdb_watch test
  ext/block: make use of QubesDB watch
  vm: add API for watching changes in QubesDB
  vm: optimize imports
  api/admin: don't send internal events in admin.Events
  Add explanation why admin.vm.volume.Import is a custom script
  Follow change of qubesdb path return type
  Rename vm.qdb to vm.untrusted_qdb
2017-07-29 05:01:13 +02:00
Marek Marczykowski-Górecki
46bfa14d08
storage/lvm: make sure that volumes have /dev entries when export() is called
In some cases (even manual manipulation) those files may not be present
- especially because thin snapshots do not have nodes in /dev by default.
2017-07-29 04:47:44 +02:00
Marek Marczykowski-Górecki
910f793c61
storage: fix Storage.clone and Storage.clone_volume
1. Volume.import_volume expect volume to be created first.
2. asyncio.wait do not accept generator, it must be concrete iterable.
2017-07-26 03:26:59 +02:00
Marek Marczykowski-Górecki
4208897146
storage/file: create -cow.img only when needed
Do not create it at volume creation time. It it needed only when VM is
running, so create it just before startup only.

QubesOS/qubes-issues#2256
2017-07-26 03:26:11 +02:00
Marek Marczykowski-Górecki
c5667791e8
storage: move volume_config['source'] filling to one place
Don't set 'source' volume in various places (each VM class constructor
etc), do it as part of volume initialization. And when it needs to be
re-calculated, call storage.init_volume again.

This code was duplicated, and as usual in such a case, those copies
were different - one have set 'size', the other one not.

QubesOS/qubes-issues#2256
2017-07-26 03:26:11 +02:00
Marek Marczykowski-Górecki
3a21e1f1b3
app: do not create 'default' storage pool
Since we have app.default_pool* properties, create appropriately named
pool and let those properties choose the right pool. This also means we
don't need to specify pool name in default volume config anymore

QubesOS/qubes-issues#2256
2017-07-25 06:20:42 +02:00
Marek Marczykowski-Górecki
1759bca00f
Rename vm.qdb to vm.untrusted_qdb
QubesDB can be freely modified by a VM, so one should take care when
reading any data retrieved from it.

Fixes QubesOS/qubes-issues#2934
2017-07-24 13:01:55 +02:00
Marek Marczykowski-Górecki
088c838ac3
storage: typo fix in comment 2017-07-20 12:19:02 +02:00
Marek Marczykowski-Górecki
c6e09b5a99
storage: fix resize and revert handling
- fix coroutine calling from Admin API
 - fix off-by-one error in resize
 - adjust tests
2017-07-18 01:42:37 +02:00
Marek Marczykowski-Górecki
ab7ed776f9
Merge branch 'dispvm-fix'
* dispvm-fix:
  storage: add comment about source volume lookup
  vm/dispvm: convert DispVM related function to coroutines
  vm/dispvm: fix DispVM storage definition
2017-07-14 01:13:20 +02:00
Marek Marczykowski-Górecki
1e45d297b3
storage: add comment about source volume lookup 2017-07-12 21:37:12 +02:00
Marek Marczykowski-Górecki
f2f89c7b0c
storage: do not use deepcopy on volume configs
There may be Pool or Volume object references, which is intentional to
keep them as is - not copy whole Pool/Volume objects.
2017-07-12 21:33:14 +02:00
Marek Marczykowski-Górecki
148d1cda78
vm/dispvm: fix DispVM storage definition
Specify empty 'source' field, so it gets filled with appropriate
template's images. Then also fix recursive 'source' handling - DispVM
root volume should point at TemplateVM's root volume as a source, not a
AppVM's one - which is also only a snapshot.

Fixes QubesOS/qubes-issues#2896
2017-07-08 02:58:21 +02:00
Marek Marczykowski-Górecki
12adf8bede
storage/lvm: major cleanup, update
- remove obsolete volume types, use snap_on_start/save_on_stop directly
- handle multiple revisions
- implement is_outdated()

QubesOS/qubes-issues#2256
2017-07-04 14:25:09 +02:00