blob: 06e0b48db071a0b1f70edc2698ce39cc7a209038 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002#
3# Copyright (c) 2013, Intel Corporation.
Patrick Williamsc124f4f2015-09-15 14:41:29 -05004#
Brad Bishopc342db32019-05-15 21:57:59 -04005# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -05006#
7# DESCRIPTION 'wic' is the OpenEmbedded Image Creator that users can
8# use to generate bootable images. Invoking it without any arguments
9# will display help screens for the 'wic' command and list the
10# available 'wic' subcommands. Invoking a subcommand without any
11# arguments will likewise display help screens for the specified
12# subcommand. Please use that interface for detailed help.
13#
14# AUTHORS
15# Tom Zanussi <tom.zanussi (at] linux.intel.com>
16#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017__version__ = "0.2.0"
18
19# Python Standard Library modules
20import os
21import sys
Brad Bishopd7bf8c12018-02-25 22:55:05 -050022import argparse
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023import logging
Brad Bishop40320b12019-03-26 16:08:25 -040024import subprocess
Andrew Geissler595f6302022-01-24 19:11:47 +000025import shutil
Brad Bishopd7bf8c12018-02-25 22:55:05 -050026
27from collections import namedtuple
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028
29# External modules
Brad Bishop316dfdd2018-06-25 12:45:53 -040030scripts_path = os.path.dirname(os.path.realpath(__file__))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031lib_path = scripts_path + '/lib'
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050032sys.path.insert(0, lib_path)
Brad Bishop316dfdd2018-06-25 12:45:53 -040033import scriptpath
34scriptpath.add_oe_lib_path()
35
36# Check whether wic is running within eSDK environment
37sdkroot = scripts_path
38if os.environ.get('SDKTARGETSYSROOT'):
39 while sdkroot != '' and sdkroot != os.sep:
40 if os.path.exists(os.path.join(sdkroot, '.devtoolbase')):
41 # Set BUILDDIR for wic to work within eSDK
42 os.environ['BUILDDIR'] = sdkroot
43 # .devtoolbase only exists within eSDK
44 # If found, initialize bitbake path for eSDK environment and append to PATH
45 sdkroot = os.path.join(os.path.dirname(scripts_path), 'bitbake', 'bin')
46 os.environ['PATH'] += ":" + sdkroot
47 break
48 sdkroot = os.path.dirname(sdkroot)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049
Andrew Geissler595f6302022-01-24 19:11:47 +000050bitbake_exe = shutil.which('bitbake')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051if bitbake_exe:
Brad Bishop316dfdd2018-06-25 12:45:53 -040052 bitbake_path = scriptpath.add_bitbake_lib_path()
Brad Bishop40320b12019-03-26 16:08:25 -040053 import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050054
Brad Bishop6e60e8b2018-02-01 10:27:11 -050055from wic import WicError
Brad Bishopd7bf8c12018-02-25 22:55:05 -050056from wic.misc import get_bitbake_var, BB_VARS
Patrick Williamsc124f4f2015-09-15 14:41:29 -050057from wic import engine
58from wic import help as hlp
59
Brad Bishop6e60e8b2018-02-01 10:27:11 -050060
61def wic_logger():
62 """Create and convfigure wic logger."""
63 logger = logging.getLogger('wic')
64 logger.setLevel(logging.INFO)
65
66 handler = logging.StreamHandler()
67
68 formatter = logging.Formatter('%(levelname)s: %(message)s')
69 handler.setFormatter(formatter)
70
71 logger.addHandler(handler)
72
73 return logger
74
75logger = wic_logger()
76
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077def rootfs_dir_to_args(krootfs_dir):
78 """
79 Get a rootfs_dir dict and serialize to string
80 """
81 rootfs_dir = ''
82 for key, val in krootfs_dir.items():
83 rootfs_dir += ' '
84 rootfs_dir += '='.join([key, val])
85 return rootfs_dir.strip()
86
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087
Brad Bishopd7bf8c12018-02-25 22:55:05 -050088class RootfsArgAction(argparse.Action):
89 def __init__(self, **kwargs):
90 super().__init__(**kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091
Brad Bishopd7bf8c12018-02-25 22:55:05 -050092 def __call__(self, parser, namespace, value, option_string=None):
93 if not "rootfs_dir" in vars(namespace) or \
94 not type(namespace.__dict__['rootfs_dir']) is dict:
95 namespace.__dict__['rootfs_dir'] = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096
Brad Bishopd7bf8c12018-02-25 22:55:05 -050097 if '=' in value:
98 (key, rootfs_dir) = value.split('=')
99 else:
100 key = 'ROOTFS_DIR'
101 rootfs_dir = value
102
103 namespace.__dict__['rootfs_dir'][key] = rootfs_dir
104
105
106def wic_create_subcommand(options, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107 """
108 Command-line handling for image creation. The real work is done
109 by image.engine.wic_create()
110 """
Brad Bishop40320b12019-03-26 16:08:25 -0400111 if options.build_rootfs and not bitbake_exe:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500112 raise WicError("Can't build rootfs as bitbake is not in the $PATH")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113
114 if not options.image_name:
115 missed = []
116 for val, opt in [(options.rootfs_dir, 'rootfs-dir'),
117 (options.bootimg_dir, 'bootimg-dir'),
118 (options.kernel_dir, 'kernel-dir'),
119 (options.native_sysroot, 'native-sysroot')]:
120 if not val:
121 missed.append(opt)
122 if missed:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500123 raise WicError("The following build artifacts are not specified: %s" %
124 ", ".join(missed))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500125
126 if options.image_name:
127 BB_VARS.default_image = options.image_name
128 else:
129 options.build_check = False
130
131 if options.vars_dir:
132 BB_VARS.vars_dir = options.vars_dir
133
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500134 if options.build_check and not engine.verify_build_env():
135 raise WicError("Couldn't verify build environment, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500136
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500137 if options.debug:
138 logger.setLevel(logging.DEBUG)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139
140 if options.image_name:
141 if options.build_rootfs:
142 argv = ["bitbake", options.image_name]
143 if options.debug:
144 argv.append("--debug")
145
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500146 logger.info("Building rootfs...\n")
Brad Bishop40320b12019-03-26 16:08:25 -0400147 subprocess.check_call(argv)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500148
149 rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name)
150 kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500151 bootimg_dir = get_bitbake_var("STAGING_DATADIR", options.image_name)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500152
153 native_sysroot = options.native_sysroot
154 if options.vars_dir and not native_sysroot:
155 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", options.image_name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156 else:
157 if options.build_rootfs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500158 raise WicError("Image name is not specified, exiting. "
159 "(Use -e/--image-name to specify it)")
160 native_sysroot = options.native_sysroot
161
Andrew Geissler9aee5002022-03-30 16:27:02 +0000162 if options.kernel_dir:
163 kernel_dir = options.kernel_dir
164
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500165 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500166 logger.info("Building wic-tools...\n")
Brad Bishop40320b12019-03-26 16:08:25 -0400167 subprocess.check_call(["bitbake", "wic-tools"])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500168 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500169
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500170 if not native_sysroot:
171 raise WicError("Unable to find the location of the native tools sysroot")
172
173 wks_file = options.wks_file
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174
175 if not wks_file.endswith(".wks"):
176 wks_file = engine.find_canned_image(scripts_path, wks_file)
177 if not wks_file:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500178 raise WicError("No image named %s found, exiting. (Use 'wic list images' "
179 "to list available images, or specify a fully-qualified OE "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500180 "kickstart (.wks) filename)" % options.wks_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500181
182 if not options.image_name:
183 rootfs_dir = ''
184 if 'ROOTFS_DIR' in options.rootfs_dir:
185 rootfs_dir = options.rootfs_dir['ROOTFS_DIR']
186 bootimg_dir = options.bootimg_dir
187 kernel_dir = options.kernel_dir
188 native_sysroot = options.native_sysroot
189 if rootfs_dir and not os.path.isdir(rootfs_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500190 raise WicError("--rootfs-dir (-r) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500191 if not os.path.isdir(bootimg_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500192 raise WicError("--bootimg-dir (-b) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500193 if not os.path.isdir(kernel_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500194 raise WicError("--kernel-dir (-k) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 if not os.path.isdir(native_sysroot):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500196 raise WicError("--native-sysroot (-n) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197 else:
198 not_found = not_found_dir = ""
199 if not os.path.isdir(rootfs_dir):
200 (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir)
201 elif not os.path.isdir(kernel_dir):
202 (not_found, not_found_dir) = ("kernel-dir", kernel_dir)
203 elif not os.path.isdir(native_sysroot):
204 (not_found, not_found_dir) = ("native-sysroot", native_sysroot)
205 if not_found:
206 if not not_found_dir:
207 not_found_dir = "Completely missing artifact - wrong image (.wks) used?"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500208 logger.info("Build artifacts not found, exiting.")
209 logger.info(" (Please check that the build artifacts for the machine")
210 logger.info(" selected in local.conf actually exist and that they")
211 logger.info(" are the correct artifacts for the image (.wks file)).\n")
Andrew Geissler615f2f12022-07-15 14:00:58 -0500212 raise WicError("The artifact that couldn't be found was %s:\n %s" % (not_found, not_found_dir))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500213
214 krootfs_dir = options.rootfs_dir
215 if krootfs_dir is None:
216 krootfs_dir = {}
217 krootfs_dir['ROOTFS_DIR'] = rootfs_dir
218
219 rootfs_dir = rootfs_dir_to_args(krootfs_dir)
220
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500221 logger.info("Creating image(s)...\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500223 native_sysroot, options)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500224
225
226def wic_list_subcommand(args, usage_str):
227 """
228 Command-line handling for listing available images.
229 The real work is done by image.engine.wic_list()
230 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 if not engine.wic_list(args, scripts_path):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500232 raise WicError("Bad list arguments, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233
234
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500235def wic_ls_subcommand(args, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500236 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500237 Command-line handling for list content of images.
238 The real work is done by engine.wic_ls()
239 """
240 engine.wic_ls(args, args.native_sysroot)
241
242def wic_cp_subcommand(args, usage_str):
243 """
244 Command-line handling for copying files/dirs to images.
245 The real work is done by engine.wic_cp()
246 """
247 engine.wic_cp(args, args.native_sysroot)
248
249def wic_rm_subcommand(args, usage_str):
250 """
251 Command-line handling for removing files/dirs from images.
252 The real work is done by engine.wic_rm()
253 """
254 engine.wic_rm(args, args.native_sysroot)
255
256def wic_write_subcommand(args, usage_str):
257 """
258 Command-line handling for writing images.
259 The real work is done by engine.wic_write()
260 """
261 engine.wic_write(args, args.native_sysroot)
262
263def wic_help_subcommand(args, usage_str):
264 """
265 Command-line handling for help subcommand to keep the current
266 structure of the function definitions.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500267 """
268 pass
269
270
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500271def wic_help_topic_subcommand(usage_str, help_str):
272 """
273 Display function for help 'sub-subcommands'.
274 """
275 print(help_str)
276 return
277
278
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500279wic_help_topic_usage = """
280"""
281
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500282helptopics = {
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500283 "plugins": [wic_help_topic_subcommand,
284 wic_help_topic_usage,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500285 hlp.wic_plugins_help],
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500286 "overview": [wic_help_topic_subcommand,
287 wic_help_topic_usage,
288 hlp.wic_overview_help],
289 "kickstart": [wic_help_topic_subcommand,
290 wic_help_topic_usage,
291 hlp.wic_kickstart_help],
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500292 "create": [wic_help_topic_subcommand,
293 wic_help_topic_usage,
294 hlp.wic_create_help],
295 "ls": [wic_help_topic_subcommand,
296 wic_help_topic_usage,
297 hlp.wic_ls_help],
298 "cp": [wic_help_topic_subcommand,
299 wic_help_topic_usage,
300 hlp.wic_cp_help],
301 "rm": [wic_help_topic_subcommand,
302 wic_help_topic_usage,
303 hlp.wic_rm_help],
304 "write": [wic_help_topic_subcommand,
305 wic_help_topic_usage,
306 hlp.wic_write_help],
307 "list": [wic_help_topic_subcommand,
308 wic_help_topic_usage,
309 hlp.wic_list_help]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500310}
311
312
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500313def wic_init_parser_create(subparser):
314 subparser.add_argument("wks_file")
315
316 subparser.add_argument("-o", "--outdir", dest="outdir", default='.',
317 help="name of directory to create image in")
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600318 subparser.add_argument("-w", "--workdir",
319 help="temporary workdir to use for intermediate files")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500320 subparser.add_argument("-e", "--image-name", dest="image_name",
321 help="name of the image to use the artifacts from "
322 "e.g. core-image-sato")
323 subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction,
324 help="path to the /rootfs dir to use as the "
325 ".wks rootfs source")
326 subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir",
327 help="path to the dir containing the boot artifacts "
328 "(e.g. /EFI or /syslinux dirs) to use as the "
329 ".wks bootimg source")
330 subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir",
331 help="path to the dir containing the kernel to use "
332 "in the .wks bootimg")
333 subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot",
334 help="path to the native sysroot containing the tools "
335 "to use to build the image")
336 subparser.add_argument("-s", "--skip-build-check", dest="build_check",
337 action="store_false", default=True, help="skip the build check")
338 subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs")
339 subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"),
340 dest='compressor',
341 help="compress image with specified compressor")
342 subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap")
343 subparser.add_argument("--no-fstab-update" ,action="store_true",
344 help="Do not change fstab file.")
345 subparser.add_argument("-v", "--vars", dest='vars_dir',
346 help="directory with <image>.env files that store "
347 "bitbake variables")
348 subparser.add_argument("-D", "--debug", dest="debug", action="store_true",
349 default=False, help="output debug information")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800350 subparser.add_argument("-i", "--imager", dest="imager",
351 default="direct", help="the wic imager plugin")
Andrew Geissler5199d832021-09-24 16:47:35 -0500352 subparser.add_argument("--extra-space", type=int, dest="extra_space",
353 default=0, help="additional free disk space to add to the image")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500354 return
355
356
357def wic_init_parser_list(subparser):
358 subparser.add_argument("list_type",
359 help="can be 'images' or 'source-plugins' "
360 "to obtain a list. "
361 "If value is a valid .wks image file")
362 subparser.add_argument("help_for", default=[], nargs='*',
363 help="If 'list_type' is a valid .wks image file "
364 "this value can be 'help' to show the help information "
365 "defined inside the .wks file")
366 return
367
368def imgtype(arg):
369 """
370 Custom type for ArgumentParser
371 Converts path spec to named tuple: (image, partition, path)
372 """
373 image = arg
374 part = path = None
375 if ':' in image:
376 image, part = image.split(':')
377 if '/' in part:
378 part, path = part.split('/', 1)
379 if not path:
380 path = '/'
381
382 if not os.path.isfile(image):
383 err = "%s is not a regular file or symlink" % image
384 raise argparse.ArgumentTypeError(err)
385
386 return namedtuple('ImgType', 'image part path')(image, part, path)
387
388def wic_init_parser_ls(subparser):
389 subparser.add_argument("path", type=imgtype,
390 help="image spec: <image>[:<vfat partition>[<path>]]")
391 subparser.add_argument("-n", "--native-sysroot",
392 help="path to the native sysroot containing the tools")
393
394def imgpathtype(arg):
395 img = imgtype(arg)
396 if img.part is None:
397 raise argparse.ArgumentTypeError("partition number is not specified")
398 return img
399
400def wic_init_parser_cp(subparser):
401 subparser.add_argument("src",
Andrew Geissler82c905d2020-04-13 13:39:40 -0500402 help="image spec: <image>:<vfat partition>[<path>] or <file>")
403 subparser.add_argument("dest",
404 help="image spec: <image>:<vfat partition>[<path>] or <file>")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500405 subparser.add_argument("-n", "--native-sysroot",
406 help="path to the native sysroot containing the tools")
407
408def wic_init_parser_rm(subparser):
409 subparser.add_argument("path", type=imgpathtype,
410 help="path: <image>:<vfat partition><path>")
411 subparser.add_argument("-n", "--native-sysroot",
412 help="path to the native sysroot containing the tools")
Brad Bishop6dbb3162019-11-25 09:41:34 -0500413 subparser.add_argument("-r", dest="recursive_delete", action="store_true", default=False,
414 help="remove directories and their contents recursively, "
415 " this only applies to ext* partition")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500416
417def expandtype(rules):
418 """
419 Custom type for ArgumentParser
420 Converts expand rules to the dictionary {<partition>: size}
421 """
422 if rules == 'auto':
423 return {}
424 result = {}
Brad Bishopc342db32019-05-15 21:57:59 -0400425 for rule in rules.split(','):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500426 try:
427 part, size = rule.split(':')
428 except ValueError:
429 raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule)
430
431 if not part.isdigit():
432 raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule)
433
434 # validate size
435 multiplier = 1
436 for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]:
437 if size.upper().endswith(suffix):
438 multiplier = mult
439 size = size[:-1]
440 break
441 if not size.isdigit():
442 raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule)
443
444 result[int(part)] = int(size) * multiplier
445
446 return result
447
448def wic_init_parser_write(subparser):
449 subparser.add_argument("image",
450 help="path to the wic image")
451 subparser.add_argument("target",
452 help="target file or device")
453 subparser.add_argument("-e", "--expand", type=expandtype,
454 help="expand rules: auto or <partition>:<size>[,<partition>:<size>]")
455 subparser.add_argument("-n", "--native-sysroot",
456 help="path to the native sysroot containing the tools")
457
458def wic_init_parser_help(subparser):
459 helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage)
460 for helptopic in helptopics:
461 helpparsers.add_parser(helptopic, help=helptopics[helptopic][2])
462 return
463
464
465subcommands = {
466 "create": [wic_create_subcommand,
467 hlp.wic_create_usage,
468 hlp.wic_create_help,
469 wic_init_parser_create],
470 "list": [wic_list_subcommand,
471 hlp.wic_list_usage,
472 hlp.wic_list_help,
473 wic_init_parser_list],
474 "ls": [wic_ls_subcommand,
475 hlp.wic_ls_usage,
476 hlp.wic_ls_help,
477 wic_init_parser_ls],
478 "cp": [wic_cp_subcommand,
479 hlp.wic_cp_usage,
480 hlp.wic_cp_help,
481 wic_init_parser_cp],
482 "rm": [wic_rm_subcommand,
483 hlp.wic_rm_usage,
484 hlp.wic_rm_help,
485 wic_init_parser_rm],
486 "write": [wic_write_subcommand,
487 hlp.wic_write_usage,
488 hlp.wic_write_help,
489 wic_init_parser_write],
490 "help": [wic_help_subcommand,
491 wic_help_topic_usage,
492 hlp.wic_help_help,
493 wic_init_parser_help]
494}
495
496
497def init_parser(parser):
498 parser.add_argument("--version", action="version",
499 version="%(prog)s {version}".format(version=__version__))
Brad Bishopc342db32019-05-15 21:57:59 -0400500 parser.add_argument("-D", "--debug", dest="debug", action="store_true",
501 default=False, help="output debug information")
502
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500503 subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage)
504 for subcmd in subcommands:
505 subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2])
506 subcommands[subcmd][3](subparser)
507
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500508class WicArgumentParser(argparse.ArgumentParser):
509 def format_help(self):
510 return hlp.wic_help
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500511
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500512def main(argv):
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500513 parser = WicArgumentParser(
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500514 description="wic version %s" % __version__)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500515
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500516 init_parser(parser)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500517
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500518 args = parser.parse_args(argv)
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500519
Brad Bishopc342db32019-05-15 21:57:59 -0400520 if args.debug:
521 logger.setLevel(logging.DEBUG)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500522
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500523 if "command" in vars(args):
524 if args.command == "help":
525 if args.help_topic is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500526 parser.print_help()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500527 elif args.help_topic in helptopics:
528 hlpt = helptopics[args.help_topic]
529 hlpt[0](hlpt[1], hlpt[2])
530 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500531
Andrew Geissler82c905d2020-04-13 13:39:40 -0500532 # validate wic cp src and dest parameter to identify which one of it is
533 # image and cast it into imgtype
534 if args.command == "cp":
535 if ":" in args.dest:
536 args.dest = imgtype(args.dest)
537 elif ":" in args.src:
538 args.src = imgtype(args.src)
539 else:
540 raise argparse.ArgumentTypeError("no image or partition number specified.")
541
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500542 return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands)
543
544
545if __name__ == "__main__":
546 try:
547 sys.exit(main(sys.argv[1:]))
548 except WicError as err:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500549 print()
550 logger.error(err)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500551 sys.exit(1)