Contributed by: Jan Pechanec
The Live Zone Reconfiguration, LZR for short, was introduced in Oracle Solaris 11.3. It allows for changing a configuration of a running zone without a need to reboot it. More precisely, it provides a way to:
- reconfigure a running zone to match persistent configuration of a zone maintained through zonecfg(8)
- edit the live configuration of a running zone instead of a persistent configuration on a stable storage
Up to Solaris 11.3, the LZR supported resources and properties like anet, capped-memory, pool, and others. For the complete list, see the solaris(5) and solaris-kz(5) manual pages on 11.3 as there are differences in what is supported by each brand. Please note that those manual pages were renamed in 11.4 Beta to zones_solaris(7) and zones_solaris-kz(7).
With the release of Oracle Solaris 11.4 Beta, the LZR now newly supports reconfiguration of dataset resources for the “solaris” branded zones — aka non-global zones (NGZs), or native zones.
This new feature in 11.4 will allow you to add and remove datasets to solaris branded zones on the fly, whereas such datasets will show up within the zone as ZFS pools that may be imported and exported using an established zpool(8) command.
In order to provide a coherent user interface and a good administrative experience, the decision was to use already existing NGZ command line interface to import a new virtual ZFS pool that has been made available to the running NGZ by the GZ administrator via adding a dataset resource using the LZR, and also to remove a dataset resource out of a running NGZ when no longer needed.
A short example will illustrate how to use this feature via applying a modified persistent configuration. First, create the dataset in the global zone, modify the native zone’s configuration, and apply the modifications:
global-zone# zfs create rpool/lzr1 global-zone# zonecfg -z tzone1 zonecfg:tzone1> add dataset zonecfg:tzone1:dataset> set name=rpool/lzr1 zonecfg:tzone1:dataset> end zonecfg:tzone1> commit zonecfg:tzone1> exit global-zone# zoneadm -z tzone1 apply zone 'tzone1': Checking: Adding dataset name=rpool/lzr1 zone 'tzone1': Applying the changes
Now log in to the tzone1 zone and import the newly added ZFS pool:
global-zone# zlogin tzone1
tzone1:~# zpool list
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
rpool 127G 32.0G 95.0G 25% 1.00x ONLINE -
tzone1:~# zpool import # will show pools available for import
pool: lzr1
id: 11612286362086021519
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
lzr1 ONLINE
c1d0 ONLINE
tzone1:~# zpool import lzr1
tzone1:~# zpool list
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
lzr1 127G 32.0G 95.0G 25% 1.00x ONLINE -
rpool 127G 32.0G 95.0G 25% 1.00x ONLINE -
tzone1:~# touch /lzr1/hello
tzone1:~# ls -l /lzr1/hello
-rw-r--r-- 1 root root 0 Jan 29 09:51 /lzr1/hello
The size of the imported lzr1 pool is same as how much space is available in the ZFS dataset rpool/lzr1 within the GZ.
Now trying to remove the dataset while it is still imported in the zone:
global-zone# zonecfg -z tzone1 zonecfg:tzone1> remove dataset 0 zonecfg:tzone1> commit zonecfg:tzone1> exit global-zone# zoneadm -z tzone1 apply zone 'tzone1': Checking: Removing dataset name=rpool/lzr1 zone 'tzone1': error: cannot remove dataset 'rpool/lzr1': not in exported state zoneadm: zone tzone1: failed to apply the configuration: zoneadmd(8) returned an error 1 (unspecified error) global-zone# echo $? 1
As you would probably expect, one cannot remove a dataset resource while the ZFS pool is in use within the zone. So, just redo after exporting the pool first:
tzone1:~# zpool export lzr1 tzone1:~# echo $? 0 global-zone# zoneadm -z tzone1 apply zone 'tzone1': Checking: Removing dataset name=rpool/lzr1 zone 'tzone1': Applying the changes
Alternatively, you could only update the in-memory configuration via “zonecfg -z tzone1 -r“. The configuration is applied on commit:
global-zone# zonecfg -z tzone1 remove dataset 0 global-zone# zonecfg -z tzone1 apply ... global-zone# zonecfg -z tzone1 -r zonecfg:tzone1> add dataset zonecfg:tzone1:dataset> set name=rpool/lzr1 zonecfg:tzone1:dataset> end zonecfg:tzone1> commit zone 'tzone1': Checking: Adding dataset name=rpool/lzr1 zone 'tzone1': Applying the changes
Within the tzone1 zone, you would now import the pool same way as before.
