blob: 57197c204800222470b4d592343932c5f470f0e0 [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
Brad Bishopd7bf8c12018-02-25 22:55:05 -050025
26from collections import namedtuple
Patrick Williamsc124f4f2015-09-15 14:41:29 -050027from distutils import spawn
28
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
50bitbake_exe = spawn.find_executable('bitbake')
51if 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
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500162 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500163 logger.info("Building wic-tools...\n")
Brad Bishop40320b12019-03-26 16:08:25 -0400164 subprocess.check_call(["bitbake", "wic-tools"])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165 native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500166
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500167 if not native_sysroot:
168 raise WicError("Unable to find the location of the native tools sysroot")
169
170 wks_file = options.wks_file
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500171
172 if not wks_file.endswith(".wks"):
173 wks_file = engine.find_canned_image(scripts_path, wks_file)
174 if not wks_file:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175 raise WicError("No image named %s found, exiting. (Use 'wic list images' "
176 "to list available images, or specify a fully-qualified OE "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500177 "kickstart (.wks) filename)" % options.wks_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500178
179 if not options.image_name:
180 rootfs_dir = ''
181 if 'ROOTFS_DIR' in options.rootfs_dir:
182 rootfs_dir = options.rootfs_dir['ROOTFS_DIR']
183 bootimg_dir = options.bootimg_dir
184 kernel_dir = options.kernel_dir
185 native_sysroot = options.native_sysroot
186 if rootfs_dir and not os.path.isdir(rootfs_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187 raise WicError("--rootfs-dir (-r) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500188 if not os.path.isdir(bootimg_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189 raise WicError("--bootimg-dir (-b) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500190 if not os.path.isdir(kernel_dir):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500191 raise WicError("--kernel-dir (-k) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500192 if not os.path.isdir(native_sysroot):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500193 raise WicError("--native-sysroot (-n) not found, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194 else:
195 not_found = not_found_dir = ""
196 if not os.path.isdir(rootfs_dir):
197 (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir)
198 elif not os.path.isdir(kernel_dir):
199 (not_found, not_found_dir) = ("kernel-dir", kernel_dir)
200 elif not os.path.isdir(native_sysroot):
201 (not_found, not_found_dir) = ("native-sysroot", native_sysroot)
202 if not_found:
203 if not not_found_dir:
204 not_found_dir = "Completely missing artifact - wrong image (.wks) used?"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 logger.info("Build artifacts not found, exiting.")
206 logger.info(" (Please check that the build artifacts for the machine")
207 logger.info(" selected in local.conf actually exist and that they")
208 logger.info(" are the correct artifacts for the image (.wks file)).\n")
209 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 -0500210
211 krootfs_dir = options.rootfs_dir
212 if krootfs_dir is None:
213 krootfs_dir = {}
214 krootfs_dir['ROOTFS_DIR'] = rootfs_dir
215
216 rootfs_dir = rootfs_dir_to_args(krootfs_dir)
217
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500218 logger.info("Creating image(s)...\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500219 engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500220 native_sysroot, options)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221
222
223def wic_list_subcommand(args, usage_str):
224 """
225 Command-line handling for listing available images.
226 The real work is done by image.engine.wic_list()
227 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500228 if not engine.wic_list(args, scripts_path):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500229 raise WicError("Bad list arguments, exiting")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230
231
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500232def wic_ls_subcommand(args, usage_str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500234 Command-line handling for list content of images.
235 The real work is done by engine.wic_ls()
236 """
237 engine.wic_ls(args, args.native_sysroot)
238
239def wic_cp_subcommand(args, usage_str):
240 """
241 Command-line handling for copying files/dirs to images.
242 The real work is done by engine.wic_cp()
243 """
244 engine.wic_cp(args, args.native_sysroot)
245
246def wic_rm_subcommand(args, usage_str):
247 """
248 Command-line handling for removing files/dirs from images.
249 The real work is done by engine.wic_rm()
250 """
251 engine.wic_rm(args, args.native_sysroot)
252
253def wic_write_subcommand(args, usage_str):
254 """
255 Command-line handling for writing images.
256 The real work is done by engine.wic_write()
257 """
258 engine.wic_write(args, args.native_sysroot)
259
260def wic_help_subcommand(args, usage_str):
261 """
262 Command-line handling for help subcommand to keep the current
263 structure of the function definitions.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500264 """
265 pass
266
267
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500268def wic_help_topic_subcommand(usage_str, help_str):
269 """
270 Display function for help 'sub-subcommands'.
271 """
272 print(help_str)
273 return
274
275
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500276wic_help_topic_usage = """
277"""
278
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500279helptopics = {
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500280 "plugins": [wic_help_topic_subcommand,
281 wic_help_topic_usage,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500282 hlp.wic_plugins_help],
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500283 "overview": [wic_help_topic_subcommand,
284 wic_help_topic_usage,
285 hlp.wic_overview_help],
286 "kickstart": [wic_help_topic_subcommand,
287 wic_help_topic_usage,
288 hlp.wic_kickstart_help],
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500289 "create": [wic_help_topic_subcommand,
290 wic_help_topic_usage,
291 hlp.wic_create_help],
292 "ls": [wic_help_topic_subcommand,
293 wic_help_topic_usage,
294 hlp.wic_ls_help],
295 "cp": [wic_help_topic_subcommand,
296 wic_help_topic_usage,
297 hlp.wic_cp_help],
298 "rm": [wic_help_topic_subcommand,
299 wic_help_topic_usage,
300 hlp.wic_rm_help],
301 "write": [wic_help_topic_subcommand,
302 wic_help_topic_usage,
303 hlp.wic_write_help],
304 "list": [wic_help_topic_subcommand,
305 wic_help_topic_usage,
306 hlp.wic_list_help]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500307}
308
309
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500310def wic_init_parser_create(subparser):
311 subparser.add_argument("wks_file")
312
313 subparser.add_argument("-o", "--outdir", dest="outdir", default='.',
314 help="name of directory to create image in")
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600315 subparser.add_argument("-w", "--workdir",
316 help="temporary workdir to use for intermediate files")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500317 subparser.add_argument("-e", "--image-name", dest="image_name",
318 help="name of the image to use the artifacts from "
319 "e.g. core-image-sato")
320 subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction,
321 help="path to the /rootfs dir to use as the "
322 ".wks rootfs source")
323 subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir",
324 help="path to the dir containing the boot artifacts "
325 "(e.g. /EFI or /syslinux dirs) to use as the "
326 ".wks bootimg source")
327 subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir",
328 help="path to the dir containing the kernel to use "
329 "in the .wks bootimg")
330 subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot",
331 help="path to the native sysroot containing the tools "
332 "to use to build the image")
333 subparser.add_argument("-s", "--skip-build-check", dest="build_check",
334 action="store_false", default=True, help="skip the build check")
335 subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs")
336 subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"),
337 dest='compressor',
338 help="compress image with specified compressor")
339 subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap")
340 subparser.add_argument("--no-fstab-update" ,action="store_true",
341 help="Do not change fstab file.")
342 subparser.add_argument("-v", "--vars", dest='vars_dir',
343 help="directory with <image>.env files that store "
344 "bitbake variables")
345 subparser.add_argument("-D", "--debug", dest="debug", action="store_true",
346 default=False, help="output debug information")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800347 subparser.add_argument("-i", "--imager", dest="imager",
348 default="direct", help="the wic imager plugin")
Andrew Geissler5199d832021-09-24 16:47:35 -0500349 subparser.add_argument("--extra-space", type=int, dest="extra_space",
350 default=0, help="additional free disk space to add to the image")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500351 return
352
353
354def wic_init_parser_list(subparser):
355 subparser.add_argument("list_type",
356 help="can be 'images' or 'source-plugins' "
357 "to obtain a list. "
358 "If value is a valid .wks image file")
359 subparser.add_argument("help_for", default=[], nargs='*',
360 help="If 'list_type' is a valid .wks image file "
361 "this value can be 'help' to show the help information "
362 "defined inside the .wks file")
363 return
364
365def imgtype(arg):
366 """
367 Custom type for ArgumentParser
368 Converts path spec to named tuple: (image, partition, path)
369 """
370 image = arg
371 part = path = None
372 if ':' in image:
373 image, part = image.split(':')
374 if '/' in part:
375 part, path = part.split('/', 1)
376 if not path:
377 path = '/'
378
379 if not os.path.isfile(image):
380 err = "%s is not a regular file or symlink" % image
381 raise argparse.ArgumentTypeError(err)
382
383 return namedtuple('ImgType', 'image part path')(image, part, path)
384
385def wic_init_parser_ls(subparser):
386 subparser.add_argument("path", type=imgtype,
387 help="image spec: <image>[:<vfat partition>[<path>]]")
388 subparser.add_argument("-n", "--native-sysroot",
389 help="path to the native sysroot containing the tools")
390
391def imgpathtype(arg):
392 img = imgtype(arg)
393 if img.part is None:
394 raise argparse.ArgumentTypeError("partition number is not specified")
395 return img
396
397def wic_init_parser_cp(subparser):
398 subparser.add_argument("src",
Andrew Geissler82c905d2020-04-13 13:39:40 -0500399 help="image spec: <image>:<vfat partition>[<path>] or <file>")
400 subparser.add_argument("dest",
401 help="image spec: <image>:<vfat partition>[<path>] or <file>")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500402 subparser.add_argument("-n", "--native-sysroot",
403 help="path to the native sysroot containing the tools")
404
405def wic_init_parser_rm(subparser):
406 subparser.add_argument("path", type=imgpathtype,
407 help="path: <image>:<vfat partition><path>")
408 subparser.add_argument("-n", "--native-sysroot",
409 help="path to the native sysroot containing the tools")
Brad Bishop6dbb3162019-11-25 09:41:34 -0500410 subparser.add_argument("-r", dest="recursive_delete", action="store_true", default=False,
411 help="remove directories and their contents recursively, "
412 " this only applies to ext* partition")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500413
414def expandtype(rules):
415 """
416 Custom type for ArgumentParser
417 Converts expand rules to the dictionary {<partition>: size}
418 """
419 if rules == 'auto':
420 return {}
421 result = {}
Brad Bishopc342db32019-05-15 21:57:59 -0400422 for rule in rules.split(','):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500423 try:
424 part, size = rule.split(':')
425 except ValueError:
426 raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule)
427
428 if not part.isdigit():
429 raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule)
430
431 # validate size
432 multiplier = 1
433 for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]:
434 if size.upper().endswith(suffix):
435 multiplier = mult
436 size = size[:-1]
437 break
438 if not size.isdigit():
439 raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule)
440
441 result[int(part)] = int(size) * multiplier
442
443 return result
444
445def wic_init_parser_write(subparser):
446 subparser.add_argument("image",
447 help="path to the wic image")
448 subparser.add_argument("target",
449 help="target file or device")
450 subparser.add_argument("-e", "--expand", type=expandtype,
451 help="expand rules: auto or <partition>:<size>[,<partition>:<size>]")
452 subparser.add_argument("-n", "--native-sysroot",
453 help="path to the native sysroot containing the tools")
454
455def wic_init_parser_help(subparser):
456 helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage)
457 for helptopic in helptopics:
458 helpparsers.add_parser(helptopic, help=helptopics[helptopic][2])
459 return
460
461
462subcommands = {
463 "create": [wic_create_subcommand,
464 hlp.wic_create_usage,
465 hlp.wic_create_help,
466 wic_init_parser_create],
467 "list": [wic_list_subcommand,
468 hlp.wic_list_usage,
469 hlp.wic_list_help,
470 wic_init_parser_list],
471 "ls": [wic_ls_subcommand,
472 hlp.wic_ls_usage,
473 hlp.wic_ls_help,
474 wic_init_parser_ls],
475 "cp": [wic_cp_subcommand,
476 hlp.wic_cp_usage,
477 hlp.wic_cp_help,
478 wic_init_parser_cp],
479 "rm": [wic_rm_subcommand,
480 hlp.wic_rm_usage,
481 hlp.wic_rm_help,
482 wic_init_parser_rm],
483 "write": [wic_write_subcommand,
484 hlp.wic_write_usage,
485 hlp.wic_write_help,
486 wic_init_parser_write],
487 "help": [wic_help_subcommand,
488 wic_help_topic_usage,
489 hlp.wic_help_help,
490 wic_init_parser_help]
491}
492
493
494def init_parser(parser):
495 parser.add_argument("--version", action="version",
496 version="%(prog)s {version}".format(version=__version__))
Brad Bishopc342db32019-05-15 21:57:59 -0400497 parser.add_argument("-D", "--debug", dest="debug", action="store_true",
498 default=False, help="output debug information")
499
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500500 subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage)
501 for subcmd in subcommands:
502 subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2])
503 subcommands[subcmd][3](subparser)
504
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500505class WicArgumentParser(argparse.ArgumentParser):
506 def format_help(self):
507 return hlp.wic_help
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500508
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500509def main(argv):
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500510 parser = WicArgumentParser(
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500511 description="wic version %s" % __version__)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500512
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500513 init_parser(parser)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500514
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500515 args = parser.parse_args(argv)
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500516
Brad Bishopc342db32019-05-15 21:57:59 -0400517 if args.debug:
518 logger.setLevel(logging.DEBUG)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500519
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500520 if "command" in vars(args):
521 if args.command == "help":
522 if args.help_topic is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500523 parser.print_help()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500524 elif args.help_topic in helptopics:
525 hlpt = helptopics[args.help_topic]
526 hlpt[0](hlpt[1], hlpt[2])
527 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500528
Andrew Geissler82c905d2020-04-13 13:39:40 -0500529 # validate wic cp src and dest parameter to identify which one of it is
530 # image and cast it into imgtype
531 if args.command == "cp":
532 if ":" in args.dest:
533 args.dest = imgtype(args.dest)
534 elif ":" in args.src:
535 args.src = imgtype(args.src)
536 else:
537 raise argparse.ArgumentTypeError("no image or partition number specified.")
538
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500539 return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands)
540
541
542if __name__ == "__main__":
543 try:
544 sys.exit(main(sys.argv[1:]))
545 except WicError as err:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500546 print()
547 logger.error(err)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500548 sys.exit(1)