From 02bd134f1c9ae9fba38bc492b8dd7367b402cb44 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Thu, 2 Feb 2017 10:51:46 -0600 Subject: [PATCH] Add --storage to install|run To have parity function with pull, we need to add --storage to install and run. This allows for overriding when atomic.type is defined. For example, if you pull an image that has atomic.type=system but you really want to store it on the docker backend. Closes: #861 Approved by: baude --- Atomic/backends/_docker.py | 1 - Atomic/backendutils.py | 3 ++- Atomic/install.py | 17 +++++++++++++++-- Atomic/run.py | 30 ++++++++++++++++++++++++------ bash/atomic | 23 +++++++++++++++++++++++ docs/atomic-install.1.md | 11 +++++++++++ docs/atomic-run.1.md | 6 ++++++ 7 files changed, 81 insertions(+), 10 deletions(-) diff --git a/Atomic/backends/_docker.py b/Atomic/backends/_docker.py index bebf594..8efe3ab 100644 --- a/Atomic/backends/_docker.py +++ b/Atomic/backends/_docker.py @@ -246,7 +246,6 @@ class DockerBackend(Backend): with open(path, 'rb') as f: self.d.load_image(data=f) return 0 -# remote_image_obj = self.make_remote_image(image) fq_name = remote_image_obj.fq_name local_image = self.has_image(image) if local_image is not None: diff --git a/Atomic/backendutils.py b/Atomic/backendutils.py index 337ff0f..f182c64 100644 --- a/Atomic/backendutils.py +++ b/Atomic/backendutils.py @@ -158,4 +158,5 @@ class BackendUtils(object): @staticmethod def message_backend_change(previous, new): write_out("\nNote: Switching from the '{}' backend to the '{}' backend based on the 'atomic.type' label in the " - "image. You can use --storage to override this behaviour.\n".format(previous, new)) \ No newline at end of file + "image. You can use --storage to override this behaviour.\n".format(previous, new)) + diff --git a/Atomic/install.py b/Atomic/install.py index 5ca5060..d898929 100644 --- a/Atomic/install.py +++ b/Atomic/install.py @@ -29,6 +29,9 @@ INSTALL_ARGS = ["run", "--name", "${NAME}", "${IMAGE}"] +ATOMIC_CONFIG = util.get_atomic_config() +_storage = ATOMIC_CONFIG.get('default_storage', "docker") + def cli(subparser): # atomic install installp = subparser.add_parser( @@ -40,6 +43,10 @@ def cli(subparser): "%s'" % Install.print_install()) installp.set_defaults(_class=Install, func='install') add_opt(installp) + installp.add_argument("--storage", dest="storage", default=None, + help=_("Specify the storage. Default is currently '%s'. You can" + " change the default by editing /etc/atomic.conf and changing" + " the 'default_storage' field." % _storage)) installp.add_argument("-n", "--name", dest="name", default=None, help=_("name of container")) installp.add_argument( @@ -80,6 +87,12 @@ class Install(Atomic): def install(self): if self.args.debug: util.write_out(str(self.args)) + storage_set = False if self.args.storage is None else True + storage = _storage if not storage_set else self.args.storage + args_system = getattr(self.args, 'system', None) + args_user= getattr(self.args, 'user', None) + if (args_system or args_user) and storage != 'ostree' and storage_set: + raise ValueError("The --system and --user options are only available for the 'ostree' storage.") be_utils = BackendUtils() try: # Check to see if the container already exists @@ -92,7 +105,7 @@ class Install(Atomic): if not util.is_user_mode(): raise ValueError("--user does not work for privileged user") return self.syscontainers.install_user_container(self.image, self.name) - elif self.system: + elif self.system or storage == 'ostree': return self.syscontainers.install(self.image, self.name) elif OSTREE_PRESENT and self.args.setvalues: raise ValueError("--set is valid only when used with --system or --user") @@ -106,7 +119,7 @@ class Install(Atomic): remote_image_obj = be.make_remote_image(self.args.image) # We found an atomic.type of system, therefore install it onto the ostree # backend - if remote_image_obj.is_system_type: + if remote_image_obj.is_system_type and not storage_set: be_utils.message_backend_change('docker', 'ostree') return self.syscontainers.install(self.image, self.name) be.pull_image(self.args.image, remote_image_obj, debug=self.args.debug) diff --git a/Atomic/run.py b/Atomic/run.py index 10b4706..003dc49 100644 --- a/Atomic/run.py +++ b/Atomic/run.py @@ -30,6 +30,10 @@ RUN_ARGS = ["-i", "--name", "${NAME}", "${IMAGE}"] +ATOMIC_CONFIG = util.get_atomic_config() +_storage = ATOMIC_CONFIG.get('default_storage', "docker") + + def cli(subparser): # atomic run runp = subparser.add_parser( @@ -41,6 +45,10 @@ def cli(subparser): runp.set_defaults(_class=Run, func='run') run_group = runp.add_mutually_exclusive_group() util.add_opt(runp) + runp.add_argument("--storage", dest="storage", default=None, + help=_("Specify the storage. Default is currently '%s'. You can" + " change the default by editing /etc/atomic.conf and changing" + " the 'default_storage' field." % _storage)) runp.add_argument("-n", "--name", dest="name", default=None, help=_("name of container")) runp.add_argument("--spc", default=False, action="store_true", @@ -70,23 +78,26 @@ class Run(Atomic): self.SPC_ARGS = SPC_ARGS def run(self): + storage_set = False if self.args.storage is None else True + storage = _storage if not storage_set else self.args.storage + be_utils = BackendUtils() if self.name: - be_utils = BackendUtils() try: be, con_obj = be_utils.get_backend_and_container_obj(self.name) return be.run(con_obj, atomic=self, args=self.args) except ValueError: pass + be = be_utils.get_backend_from_string(storage) db = DockerBackend() - img_object = db.has_image(self.image) - if img_object is None: + img_object = be.has_image(self.image) + if img_object is None and storage == 'docker': self.display("Need to pull %s" % self.image) remote_image_obj = db.make_remote_image(self.args.image) # If the image has a atomic.type of system, then we need to land # this in the ostree backend. Install it and then start it # because this is run - if remote_image_obj.is_system_type: + if remote_image_obj.is_system_type and not storage_set: be = be_utils.get_backend_from_string('ostree') be_utils.message_backend_change('docker', 'ostree') be.install(self.image, self.name) @@ -99,8 +110,15 @@ class Run(Atomic): img_object = db.has_image(self.image) except RegistryInspectError: raise ValueError("Unable to find image {}".format(self.image)) - - db.run(img_object, atomic=self, args=self.args) + if storage == 'ostree': + if img_object is None: + be.pull_image(self.args.image, None) + # For system containers, the run method really needs a container obj + con_obj = be.has_container(self.name) + if con_obj is None: + be.install(self.image, self.name) + img_object = be.has_container(self.name) + be.run(img_object, atomic=self, args=self.args) @staticmethod def print_run(): diff --git a/bash/atomic b/bash/atomic index 33ce2e2..18e7c99 100644 --- a/bash/atomic +++ b/bash/atomic @@ -489,6 +489,13 @@ _atomic_containers_delete() { local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") + case "$prev" in + --storage) + COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) + return 0 + ;; + esac + case "$cur" in -*) COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) @@ -654,12 +661,20 @@ _atomic_run() { --spc --display --quiet + --storage " [ "$command" = "run" ] && all_options="$all_options" local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") + case "$prev" in + --storage) + COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) + return 0 + ;; + esac + case "$prev" in $options_with_args_glob ) return @@ -688,6 +703,7 @@ _atomic_install() { --help --display --rootfs + --storage --system --set --user @@ -695,6 +711,13 @@ _atomic_install() { local options_with_args_glob=$(__atomic_to_extglob "$options_with_args") + case "$prev" in + --storage) + COMPREPLY=( $( compgen -W "docker ostree" -- "$cur" ) ) + return 0 + ;; + esac + case "$prev" in $options_with_args_glob ) return diff --git a/docs/atomic-install.1.md b/docs/atomic-install.1.md index bd9f339..15abc33 100644 --- a/docs/atomic-install.1.md +++ b/docs/atomic-install.1.md @@ -11,6 +11,7 @@ atomic-install - Execute Image Install Method [**-n**][**--name**[=*NAME*]] [**--rootfs**=*ROOTFS*] [**--set**=*NAME*=*VALUE*] +[**--storage**] [**--system**] IMAGE [ARG...] @@ -73,6 +74,12 @@ Set a value that is going to be used by a system container for its configuration and can be specified multiple times. It is used only by --system. OSTree is required for this feature to be available. +**--storage** +Allows you to override the default definition for the storage backend +where your image will reside if pulled. If the image is already local, +the --storage option will dictate where atomic should look for the image +prior to installing. Valid options are `docker` and `ostree`. + **--system** Install a system container. A system container is a container that is executed out of an systemd unit file early in boot, using runc. @@ -85,6 +92,10 @@ default under /var/lib/containers/atomic/ and generating the configuration files for runc and systemd. OSTree and runc are required for this feature to be available. +Note: If the image being pulled contains a label of `system.type=ostree`, +atomic will automatically substitute the storage backend to be ostree. This +can be overridden with the --storage option. + **--user** If running as non-root, specify to install the image from the current OSTree repository and manage it through systemd and bubblewrap. diff --git a/docs/atomic-run.1.md b/docs/atomic-run.1.md index 090e363..7dd7837 100644 --- a/docs/atomic-run.1.md +++ b/docs/atomic-run.1.md @@ -10,6 +10,7 @@ atomic-run - Execute container image run method [**--display**] [**-n**][**--name**[=*NAME*]] [**--spc**] +[**--storage**] [**--quiet**] IMAGE [COMMAND] [ARG...] @@ -70,6 +71,11 @@ NAME will default to the IMAGENAME if it is not specified. `/usr/bin/docker run -t -i --rm --privileged -v /:/host -v /run:/run --net=host --ipc=host --pid=host -e HOST=/host -e NAME=${NAME} -e IMAGE=${IMAGE} --name ${NAME} ${IMAGE}` +**-storage** + Allows you to override the default definition for the storage backend where your image will reside if pulled. If the image is already local, +the --storage option will dictate where atomic should look for the image prior to running. Valid options are `docker` and `ostree`. + + **--quiet** Run without verbose messaging (i.e. security warnings).