Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable use of a prefix in the zfs tree used by iocage #34

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ iocage_tests_task:
- pkg
install_iocage_script:
- python3 setup.py install
test_script: pytest --zpool=pool tests/functional_tests --junit-xml=reports/pytest-report.xml -rA --image
matrix:
- name: No prefix
test_script: pytest -rA --zpool=pool tests/functional_tests --junit-xml=reports/pytest-report.xml --image
- name: Custom prefix
test_script: pytest -rA --zpool=pool --prefix=test-prefix tests/functional_tests --junit-xml=reports/pytest-report.xml --image
always:
pytest_results_artifacts:
path: reports/*.xml
Expand Down
14 changes: 14 additions & 0 deletions doc/source/advanced-use.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ Snapshots are point-in-time copies of data, a safety point to which a
jail can be reverted at any time. Initially, snapshots take up almost no
space, as only changing data is recorded.

You may use **ALL** as a target jail name for these commands if you want to target all jails at once.

List snapshots for a jail:

:command:`iocage snaplist [UUID|NAME]`
Expand All @@ -168,6 +170,18 @@ Create a new snapshot:

This creates a snapshot based on the current time.

:command:`iocage snapshot [UUID|NAME] -n [SNAPSHOT NAME]`

This creates a snapshot with the given name.

Delete a snapshot:

:command:`iocage snapremove [UUID|NAME] -n [SNAPSHOT NAME]`

Delete all snapshots from a jail (requires `-f / --force`):

:command:`iocage snapremove [UUID|NAME] -n ALL -f`

.. index:: Resource Limits
.. _Resource Limits:

Expand Down
14 changes: 12 additions & 2 deletions iocage_cli/activate.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@


@click.command(name="activate", help="Set a zpool active for iocage usage.")
@click.option(
"--prefix", "-p", default='',
help="Provide a prefix for dataset path."
)
@click.argument("zpool")
def cli(zpool):
def cli(zpool, prefix):
"""Calls ZFS set to change the property org.freebsd.ioc:active to yes."""
ioc.IOCage(activate=True).activate(zpool)
ioc.IOCage(activate=True).activate(zpool, prefix)

ioc_common.logit({
"level" : "INFO",
"message": f"ZFS pool '{zpool}' successfully activated."
})

if prefix:
ioc_common.logit({
"level" : "INFO",
"message": f"Dataset prefix '{prefix}' set."
})
6 changes: 3 additions & 3 deletions iocage_cli/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ def cli(force, delete):
for uuid, path in jails.items():
pool = ioc_json.IOCJson().json_get_value("pool")
iocroot = ioc_json.IOCJson(pool).json_get_value("iocroot")
jail = f"{pool}/iocage/jails/{uuid}"
jail_old = f"{pool}/iocage/jails_old/{uuid}"
jail = f"{iocroot}/jails/{uuid}"
jail_old = f"{iocroot}/jails_old/{uuid}"
conf = ioc_json.IOCJson(path).json_get_value('all')

try:
Expand Down Expand Up @@ -164,7 +164,7 @@ def cli(force, delete):
try:
su.check_call([
"zfs", "destroy", "-r", "-f",
f"{pool}/iocage/jails_old"
f"{iocroot}/jails_old"
])
except su.CalledProcessError:
# We just want the top level dataset gone, no big deal.
Expand Down
9 changes: 7 additions & 2 deletions iocage_cli/snaplist.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,14 @@ def cli(header, jail, _long, _sort):
snap_list = ioc.IOCage(jail=jail).snap_list(_long, _sort)

if header:
table.header(["NAME", "CREATED", "RSIZE", "USED"])
if jail == 'ALL':
cols = ["JAIL"]
else:
cols = []
cols.extend(["NAME", "CREATED", "RSIZE", "USED"])
table.header(cols)
# We get an infinite float otherwise.
table.set_cols_dtype(["t", "t", "t", "t"])
table.set_cols_dtype(["t"]*len(cols))
table.add_rows(snap_list, header=False)
ioc_common.logit({
"level" : "INFO",
Expand Down
14 changes: 12 additions & 2 deletions iocage_cli/snapremove.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,23 @@

import click

import iocage_lib.ioc_common as ioc_common
import iocage_lib.iocage as ioc


@click.command(name="snapremove", help="Remove specified snapshot of a jail.")
@click.argument("jail")
@click.option("--name", "-n", help="The snapshot name. This will be what comes"
" after @", required=True)
def cli(jail, name):
@click.option("--force", "-f", is_flag=True, default=False,
help="Force removal (required for -n ALL)")
def cli(jail, name, force):
"""Removes a snapshot from a user supplied jail."""
ioc.IOCage(jail=jail).snap_remove(name)
if name == 'ALL' and not force:
ioc_common.logit({
"level": "EXCEPTION",
"message": 'Usage: iocage snapremove [OPTIONS] JAILS...\n'
'\nError: Mass snapshot deletion requires "force" (-f).'
})
skip_jails = jail != 'ALL'
ioc.IOCage(jail=jail, skip_jails=skip_jails).snap_remove(name)
3 changes: 2 additions & 1 deletion iocage_cli/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@
" after @", required=False)
def cli(jail, name):
"""Snapshot a jail."""
ioc.IOCage(jail=jail, skip_jails=True).snapshot(name)
skip_jails = jail != 'ALL'
ioc.IOCage(jail=jail, skip_jails=skip_jails).snapshot(name)
12 changes: 8 additions & 4 deletions iocage_lib/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import threading

from iocage_lib.zfs import (
all_properties, dataset_exists, get_all_dependents, get_dependents_with_depth,
all_properties, dataset_exists, get_all_dependents, get_dependents_with_depth, IOCAGE_POOL_PROP,
IOCAGE_PREFIX_PROP,
)


Expand Down Expand Up @@ -43,10 +44,13 @@ def iocage_activated_pool_internal(self, lock=True):
all_properties([p for p in pools], types=['filesystem'])
)
for p in filter(
lambda p: self.dataset_data.get(p, {}).get('org.freebsd.ioc:active') == 'yes',
lambda p: self.dataset_data.get(p, {}).get(IOCAGE_POOL_PROP) == 'yes',
pools
):
self.ioc_pool = p
self.ioc_prefix = self.dataset_data.get(
self.ioc_pool, {}
).get(IOCAGE_PREFIX_PROP, '')
return self.ioc_pool
finally:
if lock:
Expand All @@ -58,7 +62,7 @@ def iocage_activated_dataset(self):
ioc_pool = self.iocage_activated_pool_internal(lock=False)
if ioc_pool:
dependents = self.dependents_internal(ioc_pool, 1, lock=False)
ioc_ds = os.path.join(ioc_pool, 'iocage')
ioc_ds = os.path.join(ioc_pool, self.ioc_prefix, 'iocage')
if not self.ioc_dataset and ioc_pool and ioc_ds in dependents:
self.ioc_dataset = ioc_ds
return self.ioc_dataset
Expand All @@ -70,7 +74,7 @@ def datasets(self):
if not self.dataset_data or set(self.dataset_data) == set(self.pool_data):
ds = ''
if ioc_pool:
ds = os.path.join(ioc_pool, 'iocage')
ds = os.path.join(ioc_pool, self.ioc_prefix, 'iocage')
self.dataset_data.update(all_properties(
[ds] if ds and dataset_exists(ds) else [], recursive=True, types=['filesystem']
))
Expand Down
15 changes: 13 additions & 2 deletions iocage_lib/ioc_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@

from iocage_lib.cache import cache
from iocage_lib.dataset import Dataset
from iocage_lib.zfs import ZFSException
from iocage_lib.pools import Pool
from iocage_lib.zfs import ZFSException, IOCAGE_PREFIX_PROP

DATASET_CREATION_LOCK = threading.Lock()

Expand All @@ -51,6 +52,7 @@ def __init__(
silent=silent,
checking_datasets=True
).json_get_value("pool")
self.zpool = Pool(self.pool)
self.callback = callback
self.silent = silent

Expand All @@ -59,7 +61,8 @@ def __init__(

self.pool_root_dataset = Dataset(self.pool, cache=reset_cache)
self.iocage_dataset = Dataset(
os.path.join(self.pool, 'iocage'), cache=reset_cache
os.path.join(self.zpool.name, self.zpool.prefix, 'iocage'),
cache=reset_cache
)

if migrate:
Expand Down Expand Up @@ -87,6 +90,14 @@ def __check_datasets__(self):
datasets = ("iocage", "iocage/download", "iocage/images",
"iocage/jails", "iocage/log", "iocage/releases",
"iocage/templates")
if self.zpool.prefix != '':
prefix_split = self.zpool.prefix.split('/')
datasets = *(
os.path.join(*prefix_split[:n+1])
for n in range(len(prefix_split))
), *(
os.path.join(self.zpool.prefix, ioc_ds) for ioc_ds in datasets
)

for dataset in datasets:
zfs_dataset_name = f"{self.pool}/{dataset}"
Expand Down
17 changes: 11 additions & 6 deletions iocage_lib/ioc_clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@
import iocage_lib.ioc_destroy
import iocage_lib.ioc_json
import shutil
import os

from iocage_lib.dataset import Dataset
from iocage_lib.pools import Pool


class IOCClean:
"""Cleans datasets and snapshots of a given type."""

def __init__(self, callback=None, silent=False):
self.pool = iocage_lib.ioc_json.IOCJson().json_get_value('pool')
self.zpool = Pool(self.pool)
self.iocroot = iocage_lib.ioc_json.IOCJson(self.pool).json_get_value(
'iocroot')

Expand All @@ -52,7 +55,7 @@ def clean_jails(self):
silent=self.silent)

iocage_lib.ioc_destroy.IOCDestroy().destroy_jail(
f'{self.pool}/iocage/jails',
f'{self.iocroot}/jails',
clean=True
)

Expand All @@ -66,7 +69,7 @@ def clean_releases(self):
silent=self.silent)

iocage_lib.ioc_destroy.IOCDestroy().destroy_jail(
f'{self.pool}/iocage/download',
f'{self.iocroot}/download',
clean=True
)

Expand All @@ -78,7 +81,7 @@ def clean_releases(self):
silent=self.silent)

iocage_lib.ioc_destroy.IOCDestroy().destroy_jail(
f'{self.pool}/iocage/releases',
f'{self.iocroot}/releases',
clean=True)

def clean_all(self):
Expand All @@ -96,7 +99,9 @@ def clean_all(self):
silent=self.silent)

iocage_lib.ioc_destroy.IOCDestroy().__destroy_parse_datasets__(
f'{self.pool}/{dataset}', clean=True)
os.path.join(self.zpool.name, self.zpool.prefix, dataset),
clean=True
)

def clean_templates(self):
"""Cleans all templates and their respective children."""
Expand All @@ -108,7 +113,7 @@ def clean_templates(self):
silent=self.silent)

iocage_lib.ioc_destroy.IOCDestroy().__destroy_parse_datasets__(
f"{self.pool}/iocage/templates",
f"{self.iocroot}/templates",
clean=True)

def clean_images(self):
Expand All @@ -120,7 +125,7 @@ def clean_images(self):
_callback=self.callback,
silent=self.silent)

Dataset(f'{self.pool}/iocage/images').destroy(True, True)
Dataset(f'{self.iocroot}/images').destroy(True, True)

def clean_debug(self):
"""Removes the debug directory"""
Expand Down
Loading
Loading