diff --git a/subiquity/cmd/server.py b/subiquity/cmd/server.py index c5c5f11b..c2f29b20 100644 --- a/subiquity/cmd/server.py +++ b/subiquity/cmd/server.py @@ -16,8 +16,11 @@ import argparse import logging import os +import shlex import sys +import attr + from subiquitycore.log import setup_logger from .common import ( @@ -26,6 +29,30 @@ from .common import ( ) +@attr.s(auto_attribs=True) +class CommandLineParams: + _raw: str + _tokens: set = attr.Factory(set) + _values: dict = attr.Factory(dict) + + @classmethod + def from_cmdline(cls, cmdline): + r = cls(cmdline) + for tok in shlex.split(cmdline): + if '=' in tok: + k, v = tok.split('=', 1) + r._values[k] = v + else: + r._tokens.add(tok) + return r + + def __contains__(self, item): + return item in self._tokens + + def get(self, key, default=None): + return self._values.get(key, default) + + def make_server_args_parser(): parser = argparse.ArgumentParser( description='SUbiquity - Ubiquity for Servers', @@ -48,7 +75,9 @@ def make_server_args_parser(): 'or autoinstall data from cloud-init.')) with open('/proc/cmdline') as fp: cmdline = fp.read() - parser.add_argument('--kernel-cmdline', action='store', default=cmdline) + parser.add_argument( + '--kernel-cmdline', action='store', default=cmdline, + type=CommandLineParams.from_cmdline) parser.add_argument( '--snaps-from-examples', action='store_const', const=True, dest="snaps_from_examples", @@ -72,7 +101,7 @@ def make_server_args_parser(): default='.subiquity', help='in dryrun, control basedir of files') parser.add_argument( - '--storage-version', action='store', type=int, default=1) + '--storage-version', action='store', type=int) parser.add_argument( '--use-os-prober', action='store_true', default=False) return parser @@ -86,6 +115,9 @@ def main(): from subiquity.server.server import SubiquityServer parser = make_server_args_parser() opts = parser.parse_args(sys.argv[1:]) + if opts.storage_version is None: + opts.storage_version = int(opts.kernel_cmdline.get( + 'subiquity-storage-version', 1)) logdir = LOGDIR if opts.dry_run: if opts.snaps_from_examples is None: @@ -115,6 +147,7 @@ def main(): version = os.environ.get("SNAP_REVISION", "unknown") logger.info("Starting Subiquity server revision {}".format(version)) logger.info("Arguments passed: {}".format(sys.argv)) + logger.debug("Kernel commandline: {}".format(opts.kernel_cmdline)) server = SubiquityServer(opts, block_log_dir) diff --git a/subiquity/server/controllers/refresh.py b/subiquity/server/controllers/refresh.py index 4267ed0d..5cbac3ab 100644 --- a/subiquity/server/controllers/refresh.py +++ b/subiquity/server/controllers/refresh.py @@ -133,12 +133,11 @@ class RefreshController(SubiquityController): def get_refresh_channel(self): """Return the channel we should refresh subiquity to.""" - prefix = "subiquity-channel=" - for arg in self.app.kernel_cmdline: - if arg.startswith(prefix): - log.debug( - "get_refresh_channel: found %s on kernel cmdline", arg) - return arg[len(prefix):] + channel = self.app.kernel_cmdline.get('subiquity-channel') + if channel is not None: + log.debug( + "get_refresh_channel: found %s on kernel cmdline", channel) + return channel if 'channel' in self.ai_data: return self.ai_data['channel'] diff --git a/subiquity/server/server.py b/subiquity/server/server.py index 79e122ec..8af28d08 100644 --- a/subiquity/server/server.py +++ b/subiquity/server/server.py @@ -16,7 +16,6 @@ import asyncio import logging import os -import shlex import sys import time from typing import List, Optional @@ -304,7 +303,7 @@ class SubiquityServer(Application): self.prober = None else: self.prober = Prober(opts.machine_config, self.debug_flags) - self.kernel_cmdline = shlex.split(opts.kernel_cmdline) + self.kernel_cmdline = opts.kernel_cmdline if opts.snaps_from_examples: connection = FakeSnapdConnection( os.path.join( diff --git a/subiquity/server/tests/test_server.py b/subiquity/server/tests/test_server.py index e4f47180..a5994b73 100644 --- a/subiquity/server/tests/test_server.py +++ b/subiquity/server/tests/test_server.py @@ -33,7 +33,7 @@ class TestAutoinstallLoad(SubiTestCase): opts.dry_run = True opts.output_base = self.tempdir opts.machine_config = 'examples/simple.json' - opts.kernel_cmdline = '' + opts.kernel_cmdline = {} opts.autoinstall = None self.server = SubiquityServer(opts, None) self.server.base_model = Mock() diff --git a/system_setup/cmd/schema.py b/system_setup/cmd/schema.py index a95b216d..26866c9f 100644 --- a/system_setup/cmd/schema.py +++ b/system_setup/cmd/schema.py @@ -29,7 +29,7 @@ def make_app(): parser = make_server_args_parser() opts, unknown = parser.parse_known_args(['--dry-run']) opts.machine_config = NOPROBERARG - opts.kernel_cmdline = "" + opts.kernel_cmdline = {} opts.snaps_from_examples = False app = SystemSetupServer(opts, '') app.base_model = app.make_model() diff --git a/system_setup/cmd/server.py b/system_setup/cmd/server.py index d98d62dd..2a8ae0c6 100644 --- a/system_setup/cmd/server.py +++ b/system_setup/cmd/server.py @@ -56,7 +56,7 @@ def main(): opts = parser.parse_args(sys.argv[1:]) logdir = LOGDIR opts.snaps_from_examples = False - opts.kernel_cmdline = "" + opts.kernel_cmdline = {} opts.machine_config = NOPROBERARG if opts.dry_run: logdir = opts.output_base