libioc icon indicating copy to clipboard operation
libioc copied to clipboard

ioc rename with stricter rules than create

Open urosgruber opened this issue 7 years ago • 11 comments

While doing ioc rename ioc/consul-agent-0 ioc/consul-client-0 I got error message Invalid jail name: Names have to begin and end with an alphanumeric character Looks like mismatch in validation

urosgruber avatar Oct 13 '18 18:10 urosgruber

@urosgruber it is not possible rename jails across iocage root datasets, which is why it must not be defined in the target name. Anyhow there are a few learnings from your experience we can make:

  • The error message needs to be specific and should mention whether the source or target name did not match the requirements
  • Renaming from a iocage root dataset to the same one should be accepted input
  • The error message when renaming across iocage root datasets needs to be descriptive or
    • We can export and import the jail (without the compression step) to the target dataset. This would imply that the release gets fetched if it does not exist on the remote dataset or we develop a mechanism that transfers the existing one before importing the jail

gronke avatar Oct 13 '18 21:10 gronke

Not sure if this is related but I tried without dataset and it failed with device busy message, I checked mounts and since jail (template) was stopped I thought ok I'll unmount. After that I get this on every command I use.

Traceback (most recent call last):
  File "/usr/local/bin/ioc", line 10, in <module>
    sys.dd:exit(cli())
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/ioc/destroy.py", line 101, in cli
    logger=logger
  File "/usr/local/lib/python3.6/site-packages/iocage/Jails.py", line 105, in __iter__
    for jail in iterator:
  File "/usr/local/lib/python3.6/site-packages/iocage/ListableResource.py", line 105, in __iter__
    resource = self._get_resource_from_dataset(child_dataset)
  File "/usr/local/lib/python3.6/site-packages/iocage/ListableResource.py", line 131, in _get_resource_from_dataset
    return self._create_resource_instance(dataset)
  File "/usr/local/lib/python3.6/site-packages/iocage/Jails.py", line 86, in _create_resource_instance
    zfs=self.zfs
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 367, in __init__
    self.config.read(data=self.read_config(), skip_on_error=True)
  File "/usr/local/lib/python3.6/site-packages/iocage/Resource.py", line 332, in read_config
    data = self.config_handler.read()  # type: typing.Dict[str, typing.Any]
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 2045, in __getattribute__
    return object.__getattribute__(self, key)
  File "/usr/local/lib/python3.6/site-packages/iocage/Resource.py", line 338, in config_handler
    handler = object.__getattribute__(self, f"config_{self.config_type}")
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 2045, in __getattribute__
    return object.__getattribute__(self, key)
  File "/usr/local/lib/python3.6/site-packages/iocage/Resource.py", line 247, in config_type
    self._config_type = self._detect_config_type()
  File "/usr/local/lib/python3.6/site-packages/iocage/Resource.py", line 260, in _detect_config_type
    if self.config_json.exists is True:
  File "/usr/local/lib/python3.6/site-packages/iocage/Config/Prototype.py", line 124, in exists
    return os.path.isfile(self.file)
  File "/usr/local/lib/python3.6/site-packages/iocage/Config/Dataset.py", line 62, in file
    return str(os.path.join(self.dataset.mountpoint, self._file))
  File "/usr/local/lib/python3.6/posixpath.py", line 80, in join
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType

So ioc is unusable at that stage. After mounting dataset back with zfs mount it started to work again. Maybe everything around this and rename is related to the fact I'm trying to rename template jail from which I already created new jails.

urosgruber avatar Oct 14 '18 09:10 urosgruber

iocage does not attempt to mount your datasets if they are unmounted, which explains the TypeError: expected str, bytes or os.PathLike object, not NoneType.

It should be possible though to rename a template, even though datasets were cloned from the templates root dataset (deletion does not work though). @urosgruber you could try to manually rename the template - if you succeed, please let me know which commands you executed to do so, so that we can compare the steps to the renaming feature of libiocage.

gronke avatar Oct 14 '18 09:10 gronke

Here are the steps I did with the output

root@:/ioc/jails # ioc stop consul-client-0
root@:/ioc/jails # zfs rename sys/ioc/jails/consul-agent-template sys/ioc/jails/consul-client-template
cannot unmount '/ioc/jails/consul-client-0/root': Device busy

root@:/ioc/jails # zfs unmount sys/ioc/jails/consul-agent-template
root@:/ioc/jails # zfs unmount sys/ioc/jails/consul-client-0
cannot unmount '/ioc/jails/consul-client-0/root': Device busy

root@:/ioc/jails # zfs unmount sys/ioc/jails/consul-client-0/root
cannot unmount '/ioc/jails/consul-client-0/root': Device busy

root@:/ioc/jails # cd
root@:~ # zfs unmount sys/ioc/jails/consul-client-0/root
root@:~ # zfs unmount sys/ioc/jails/consul-client-0
root@:~ # zfs rename sys/ioc/jails/consul-agent-template sys/ioc/jails/consul-client-template
root@:~ # zfs mount sys/ioc/jails/consul-client-template
root@:~ # zfs mount sys/ioc/jails/consul-client-template/root
root@:~ # zfs mount sys/ioc/jails/consul-client-0
root@:~ # zfs mount sys/ioc/jails/consul-client-0/root
root@:~ # ioc start ioc start ioc/consul-client-0

After that it looks like rename was ok, but as you can see from the commands this was not possible without stopping jail created from this template. I know that this might not be even good idea to rename the template but rather creating new one and then recreate all existing jails from that new template.

And note. Not sure why device was busy while I was inside /ioc/jails folder.

urosgruber avatar Oct 14 '18 09:10 urosgruber

The fact that consul-client-0 was running should not affect your ability to rename the template it was created from. The only relation they have is caused by the clone operation with sys/ioc/jails/consul-agent-template/root being the origin of sys/ioc/jails/consul-client-0/root.

I don't get why you were unable to zfs unmount sys/ioc/jails/consul-client-0/root while being in the /ioc/jails directory. Nevertheless no interaction (umount) with the consul-client-0 jail's datasets should be required to rename the template.

@problame this seems to be your area of expertise. Do you mind telling us what we did wrong?

gronke avatar Oct 14 '18 10:10 gronke

There shouldn't be a reason if (and as far as I can tell this is the case) /ioc/jails is not the mountpoint of any of the unmounted filesystems. My only guess is that the stop operation returned too early (i.e. some process still running inside the dying jail for a few secs after ioc stop exited)

problame avatar Oct 14 '18 21:10 problame

My only guess is that the stop operation returned too early (i.e. some process still running inside the dying jail for a few secs after ioc stop exited)

There are no operations pending after stopping a jail. @problame thanks for commenting. @urosgruber could you please further investigate and help me to reproduce the behavior?

gronke avatar Oct 16 '18 17:10 gronke

@gronke will do. Just let me first find the issue with some networking to unblock my team. I'll do a fresh install in case there is some problem on current environment.

urosgruber avatar Oct 16 '18 18:10 urosgruber

My only guess is that the stop operation returned too early (i.e. some process still running inside the dying jail for a few secs after ioc stop exited)

There are no operations pending after stopping a jail. @problame thanks for commenting.

and yet, we have to wait for zfs to settle after a stop in our regression tests, before we can delete the zfs dataset

igalic avatar Oct 16 '18 22:10 igalic

@gronke ok here it is. So foo1 was created from bar-template There was no problem with me being inside /ioc/jails. But as you can see stop on all jails created from the template is inevitable. I think the only missing thing is to support heaving dataset in the name to be able to define which template to use and as you noted above to check if source and target datasets are the same.

root:/ioc/jails # ioc start foo1
Jail 'foo1' is already running
root:/ioc/jails # ioc rename bar-template moo-template
Traceback (most recent call last):
  File "/usr/local/bin/ioc", line 10, in <module>
    sys.dd:exit(cli())
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/ioc/rename.py", line 55, in cli
    print_function(ioc_jail.rename(name))
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 2091, in rename
    return list(JailGenerator.rename(self, *args, **kwargs))
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 1061, in rename
    raise e
  File "/usr/local/lib/python3.6/site-packages/iocage/Jail.py", line 1058, in rename
    raise event.error
  File "/usr/local/lib/python3.6/site-packages/iocage/Storage.py", line 123, in _rename_dataset
    dataset.rename(new_dataset_name)
  File "libzfs.pyx", line 2211, in libzfs.ZFSObject.rename
libzfs.ZFSException: Device busy
root:/ioc/jails # ioc stop foo1
[+] JailDestroy@ioc/foo1: OK [0.056s]
foo1 stopped
root:/ioc/jails # ioc rename bar-template moo-template
[+] JailRename@ioc/bar-template: OK [0.113s]
  [+] ZFSDatasetRename@sys/ioc/jails/bar-template: OK [0.029s]
  [+] ZFSSnapshotRename@sys/ioc/jails/moo-template: OK [0.035s]
  [+] JailFstabUpdate@ioc/moo-template: OK [0.048s]
root:/ioc/jails # ioc start foo1
[+] JailResolverConfig: OK [0.001s]
[+] JailLaunch@ioc/foo1: OK [0.179s]
foo1 running as JID 68

I also tried using export and import to a different dataset and it didn't work. But that is different issue I believe. I just wanted to have same template on both datasets instead of running provisioning script over blank template.

urosgruber avatar Oct 17 '18 19:10 urosgruber

This snippet reproduces the issue without iocage being involved:

root@freebsd-11-2 /tmp # zfs create zroot/source
root@freebsd-11-2 /tmp # zfs snapshot zroot/source@snap
root@freebsd-11-2 /tmp # zfs clone zroot/source@snap zroot/target 
root@freebsd-11-2 /tmp # mount -t nullfs /zroot/target /tmp/foo
root@freebsd-11-2 /tmp # zfs rename zroot/source zroot/source2
cannot unmount '/zroot/target': Device busy

When a jail is created from a template it is cloned from the templates root dataset. As demonstrated above the NullFS mount of the target dataset prevents renaming the source dataset. Any ideas how to solve this?

gronke avatar Oct 18 '18 10:10 gronke