From 6465203918fe2de6c90d493e094fae8cfcaceeeb Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 3 Sep 2021 16:14:44 -0400 Subject: [PATCH] Add ability to pack and combine with a previous baseprofile For example, this is a good complement to unpack in a tethered environment: unpack profile-v1 /root/scratch #modify /root/scratch pack /root/scratch profile-v2 -b profile-v1 --- imgutil/imgutil | 72 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/imgutil/imgutil b/imgutil/imgutil index 6ba2d3dc..fd237a44 100644 --- a/imgutil/imgutil +++ b/imgutil/imgutil @@ -636,6 +636,7 @@ def main(): packp = sps.add_parser('pack', help='Pack a scratch directory to a diskless profile') packp.add_argument('scratchdir', help='Directory containing diskless root') packp.add_argument('profilename', help='The desired diskless OS profile name to pack the root into') + packp.add_argument('-b', '--baseprofile', help='Profile to copy extra info from, for example to make a new version of an existing profile, reference the previous one as baseprofile', default=None) capturep = sps.add_parser('capture', help='Capture an image for cloning from a running system') capturep.add_argument('node', help='Node to capture image from') capturep.add_argument('profilename', help='Profile name for captured image') @@ -960,6 +961,25 @@ def unpack_image(args): time.sleep(0.1) +def recursecp(source, targ): + if os.path.islink(source): + if os.path.exists(targ): + return + linktarg = os.readlink(source) + os.symlink(linktarg, targ) + if os.path.isdir(source): + if not os.path.exists(targ): + os.mkdir(targ) + for entry in os.listdir(source): + srcentry = os.path.join(source, entry) + targentry = os.path.join(targ, entry) + recursecp(srcentry, targentry) + elif os.path.exists(targ): + return + else: + shutil.copy2(source, targ) + + def pack_image(args): outdir = args.profilename if '/' in outdir: @@ -1008,28 +1028,36 @@ def pack_image(args): encrypt_image(tmploc, os.path.join(outdir, 'rootimg.sfs'), '{}/pending/rootimg.key'.format(privdir)) os.remove(tmploc) with open(os.path.join(outdir, 'build-info'), 'w') as buildinfo: - buildinfo.write('Packed from {} on {}\n'.format(args.scratchdir, datetime.datetime.now().strftime('%Y-%m-%dT%H:%M'))) - if distpath: - os.symlink(distpath, os.path.join(outdir, 'distribution')) - oshandler = fingerprint_host(args, args.scratchdir) - tryupdate = False - if oshandler: - prettyname = oshandler.osname - with open(os.path.join(args.scratchdir, 'etc/os-release')) as osr: - osrdata = osr.read().split('\n') - for line in osrdata: - if line.startswith('PRETTY_NAME="'): - prettyname = line.replace( - 'PRETTY_NAME=', '').replace('"', '') - label = '{0} ({1})'.format(prettyname, 'Diskless Boot') - with open(os.path.join(outdir, 'profile.yaml'), 'w') as profiley: - profiley.write('label: {0}\nkernelargs: quiet # confluent_imagemethod=untethered|tethered # tethered is default when unspecified to save on memory, untethered will use more ram, but will not have any ongoing runtime root fs dependency on the http servers.\n'.format(label)) - oscat = oshandler.oscategory - confdir = '/opt/confluent/lib/osdeploy/{}-diskless'.format(oscat) - os.symlink('{}/initramfs/addons.cpio'.format(confdir), - os.path.join(outdir, 'boot/initramfs/addons.cpio')) - if os.path.exists('{}/profiles/default'.format(confdir)): - copy_tree('{}/profiles/default'.format(confdir), outdir) + buildinfo.write('PACKEDFROM={}\nPACKDATE={}\n'.format(args.scratchdir, datetime.datetime.now().strftime('%Y-%m-%dT%H:%M'))) + if args.baseprofile: + buildinfo.write('BASEPROFILE={}\n'.format(args.baseprofile)) + if args.baseprofile: + if '/' not in args.baseprofile: + args.baseprofile = os.path.join('/var/lib/confluent/public/os', args.baseprofile) + recursecp(args.baseprofile, outdir) + tryupdate = True + else: + if distpath: + os.symlink(distpath, os.path.join(outdir, 'distribution')) + oshandler = fingerprint_host(args, args.scratchdir) + tryupdate = False + if oshandler: + prettyname = oshandler.osname + with open(os.path.join(args.scratchdir, 'etc/os-release')) as osr: + osrdata = osr.read().split('\n') + for line in osrdata: + if line.startswith('PRETTY_NAME="'): + prettyname = line.replace( + 'PRETTY_NAME=', '').replace('"', '') + label = '{0} ({1})'.format(prettyname, 'Diskless Boot') + with open(os.path.join(outdir, 'profile.yaml'), 'w') as profiley: + profiley.write('label: {0}\nkernelargs: quiet # confluent_imagemethod=untethered|tethered # tethered is default when unspecified to save on memory, untethered will use more ram, but will not have any ongoing runtime root fs dependency on the http servers.\n'.format(label)) + oscat = oshandler.oscategory + confdir = '/opt/confluent/lib/osdeploy/{}-diskless'.format(oscat) + os.symlink('{}/initramfs/addons.cpio'.format(confdir), + os.path.join(outdir, 'boot/initramfs/addons.cpio')) + if os.path.exists('{}/profiles/default'.format(confdir)): + copy_tree('{}/profiles/default'.format(confdir), outdir) tryupdate = True try: pwd.getpwnam('confluent')