diff --git a/iocage/Config/Jail/JailConfig.py b/iocage/Config/Jail/JailConfig.py index 5ffb4c3b..85867025 100644 --- a/iocage/Config/Jail/JailConfig.py +++ b/iocage/Config/Jail/JailConfig.py @@ -59,7 +59,7 @@ def update_special_property(self, name: str) -> None: """Triggered when a special property was updated.""" BaseConfig.update_special_property(self, name) - if (name == "ip6_addr") and (self.jail is not None): + if (name == "ip6_addr") and (self.jail.exists is True): rc_conf = self.jail.rc_conf rc_conf["rtsold_enable"] = "accept_rtadv" in str(self["ip6_addr"]) diff --git a/iocage/Config/Jail/Properties/Defaultrouter.py b/iocage/Config/Jail/Properties/Defaultrouter.py index aafee3f7..4873d3b6 100644 --- a/iocage/Config/Jail/Properties/Defaultrouter.py +++ b/iocage/Config/Jail/Properties/Defaultrouter.py @@ -78,6 +78,9 @@ def set( if isinstance(data, str) is True: data = iocage.helpers.parse_user_input(data) + if isinstance(data, (ipaddress.IPv4Address, ipaddress.IPv6Address)): + data = data._ip + if data is None: gateway = None self._ip = None diff --git a/iocage/Config/Jail/Properties/Resolver.py b/iocage/Config/Jail/Properties/Resolver.py index 1cbfa160..ee3dea9b 100644 --- a/iocage/Config/Jail/Properties/Resolver.py +++ b/iocage/Config/Jail/Properties/Resolver.py @@ -143,6 +143,8 @@ def set( skip_on_error: bool=False ) -> None: """Clear and set all nameservers.""" + if isinstance(value, ResolverProp): + value = value._entries.copy() error_log_level = "warn" if (skip_on_error is True) else "error" self._entries.clear() method = self._get_method(value) diff --git a/iocage/Datasets.py b/iocage/Datasets.py index f2a686ab..695d8fa1 100644 --- a/iocage/Datasets.py +++ b/iocage/Datasets.py @@ -129,6 +129,11 @@ def pkg(self) -> libzfs.ZFSDataset: """Get or create the pkg cache.""" return self._get_or_create_dataset("pkg") + @property + def templates(self) -> libzfs.ZFSDataset: + """Get or create the legacy iocage templates dataset.""" + return self._get_or_create_dataset("templates") + def _get_or_create_dataset( self, asset_name: str diff --git a/iocage/Jail.py b/iocage/Jail.py index ca1ec982..52bbe596 100644 --- a/iocage/Jail.py +++ b/iocage/Jail.py @@ -23,6 +23,7 @@ # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """iocage Jail module.""" +import itertools import typing import os import random @@ -326,7 +327,7 @@ def __init__( } if "id" in data.keys(): - data["id"] = self._resolve_name(data["id"]) + dataset, data["id"] = self._resolve_name(data["id"]) JailResource.__init__( self, @@ -2014,8 +2015,9 @@ def _get_absolute_path_from_jail_asset( return iocage.Types.AbsolutePath(f"{self.root_path}{value}") - def _resolve_name(self, text: str) -> str: - + def _resolve_name(self, text: str) -> typing.Tuple[ + libzfs.ZFSDataset, str + ]: if (text is None) or (len(text) == 0): raise iocage.errors.JailNotSupplied(logger=self.logger) @@ -2027,16 +2029,19 @@ def _resolve_name(self, text: str) -> str: root_datasets = resource_selector.filter_datasets(self.host.datasets) for datasets_key, datasets in root_datasets.items(): - for dataset in list(datasets.jails.children): + for dataset in itertools.chain( + datasets.jails.children, + datasets.templates.children + ): dataset_name = str( - dataset.name[(len(datasets.jails.name) + 1):] - ) + dataset.name + ).split('/')[-1] humanreadable_name = iocage.helpers.to_humanreadable_name( dataset_name ) possible_names = [dataset_name, humanreadable_name] if resource_selector.name in possible_names: - return dataset_name + return dataset, dataset_name raise iocage.errors.JailNotFound(text, logger=self.logger) diff --git a/iocage/Jails.py b/iocage/Jails.py index de8d06d9..cae5897e 100644 --- a/iocage/Jails.py +++ b/iocage/Jails.py @@ -61,7 +61,7 @@ def __init__( iocage.ListableResource.ListableResource.__init__( self, sources=self.host.datasets, - namespace="jails", + namespace=["jails", "templates"], filters=filters, zfs=zfs, logger=logger diff --git a/iocage/ListableResource.py b/iocage/ListableResource.py index 901955bf..51540822 100644 --- a/iocage/ListableResource.py +++ b/iocage/ListableResource.py @@ -25,6 +25,7 @@ """iocage Resource module.""" import typing import libzfs +import itertools import abc import iocage.Filter @@ -42,7 +43,7 @@ class ListableResource(list): def __init__( self, sources: 'iocage.Datasets.Datasets', - namespace: typing.Optional[str]=None, + namespace: typing.Optional[typing.Union[list, str]]=None, filters: typing.Optional['iocage.Filter.Terms']=None, logger: typing.Optional['iocage.Logger.Logger']=None, zfs: typing.Optional['iocage.ZFS.ZFS']=None, @@ -53,6 +54,8 @@ def __init__( self.logger = iocage.helpers_object.init_logger(self, logger) self.zfs = iocage.helpers_object.init_zfs(self, zfs) + if isinstance(namespace, str): + namespace = [namespace] self.namespace = namespace self.sources = sources self.filters = filters @@ -81,7 +84,7 @@ def __iter__( self ) -> typing.Generator['iocage.Resource.Resource', None, None]: """Return an iterator over the child datasets.""" - if self.namespace is None: + if not self.namespace: raise iocage.errors.ListableResourceNamespaceUndefined( logger=self.logger ) @@ -94,8 +97,12 @@ def __iter__( if (filters.match_source(root_name) is False): # skip when the resources defined source does not match continue - children = root_datasets.__getattribute__(self.namespace).children - for child_dataset in children: + + children = [ + root_datasets.__getattribute__(n).children + for n in self.namespace + ] + for child_dataset in itertools.chain(*children): name = self._get_asset_name_from_dataset(child_dataset) if has_filters and (filters.match_key("name", name) is False): # Skip all jails that do not even match the name