Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
systemsmanagement:Uyuni:Snapshots:2022.12
cobbler
fix_v2_migration_script.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix_v2_migration_script.patch of Package cobbler
Index: cobbler-3.3.3/scripts/migrate-data-v2-to-v3.py =================================================================== --- cobbler-3.3.3.orig/scripts/migrate-data-v2-to-v3.py +++ cobbler-3.3.3/scripts/migrate-data-v2-to-v3.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 +import argparse import os import glob import simplejson @@ -7,6 +8,54 @@ import subprocess import cobbler.api as capi +from cobbler.settings.migrations.V3_3_0 import backup_dir + + +COBBLER_COLLECTION_PATH = "/var/lib/cobbler/collections/" +COBBLER_TEMPLATES_PATH = "/var/lib/cobbler/templates" + +OLD_COBBLER_TEMPLATES_PATH = "/var/lib/cobbler/kickstarts" +OLD_RHN_TEMPLATES_PATH = "/var/lib/rhn/kickstarts" +OLD_AUTOINSTALL_TEMPLATES_PATH = "/var/lib/cobbler/autoinstall_templates" + +TEMPLATES_PATHS = [ + COBBLER_TEMPLATES_PATH, + OLD_COBBLER_TEMPLATES_PATH, + OLD_RHN_TEMPLATES_PATH, + OLD_AUTOINSTALL_TEMPLATES_PATH, +] + +parser = argparse.ArgumentParser() +parser.add_argument( + "--noapi", + action="store_true", + help="Do not try to connect to Cobbler API", + default=False, +) +parser.add_argument( + "--noconfigs", + action="store_true", + help="Do not use use old config.d collections dir schema", + default=False, +) +parser.add_argument( + "-c", + "--collections-path", + help="Path to Cobbler collections to migrate", + default="/var/lib/cobbler/config/", +) +parser.add_argument( + "--only-fix-autoinstall", + action="store_true", + help="Run migration of collections only for autoinstall attribute (Implies: --noapi --noconfigs)", + default=False, +) + +args = parser.parse_args() +if args.only_fix_autoinstall: + args.noapi = True + args.noconfigs = True + def serialize_item(collection, item): """ @@ -16,9 +65,11 @@ def serialize_item(collection, item): @param item dictionary """ - filename = "/var/lib/cobbler/collections/%s/%s" % (collection, item['name']) + filename = os.path.join( + COBBLER_COLLECTION_PATH, "%s/%s" % (collection, item["name"]) + ) - if capi.CobblerAPI().settings().serializer_pretty_json: + if not args.noapi and capi.CobblerAPI().settings().serializer_pretty_json: sort_keys = True indent = 4 else: @@ -32,16 +83,19 @@ def serialize_item(collection, item): fd.close() + def deserialize_raw_old(collection_types): results = [] - all_files = glob.glob("/var/lib/cobbler/config/%s/*" % collection_types) + all_files = glob.glob( + os.path.join(args.collections_path, "%s/*" % collection_types) + ) for f in all_files: fd = open(f) json_data = fd.read() - _dict = simplejson.loads(json_data, encoding='utf-8') + _dict = simplejson.loads(json_data, encoding="utf-8") results.append(_dict) fd.close() return results @@ -54,9 +108,10 @@ def substitute_paths(value): new_value.append(substitute_paths(item)) value = new_value elif isinstance(value, str): - value = value.replace('/ks_mirror/','/distro_mirror/') + value = value.replace("/ks_mirror/", "/distro_mirror/") return value + def transform_key(key, value): if key in transform: ret_value = transform[key](value) @@ -65,73 +120,210 @@ def transform_key(key, value): return substitute_paths(ret_value) + # Keys to add to various collections add = { - "distros": { - "boot_loader": "grub", - }, - "profiles": { - "next_server": "<<inherit>>", - }, - "systems": { - "boot_loader": "<<inherit>>", - "next_server": "<<inherit>>", - "power_identity_file": "", - "power_options": "", - "serial_baud_rate": "", - "serial_device": "", - }, + "distros": { + "boot_loader": "grub", + }, + "profiles": { + "next_server": "<<inherit>>", + }, + "systems": { + "boot_loader": "<<inherit>>", + "next_server": "<<inherit>>", + "power_identity_file": "", + "power_options": "", + "serial_baud_rate": "", + "serial_device": "", + }, } # Keys to remove remove = [ - "ldap_enabled", - "ldap_type", - "monit_enabled", - "redhat_management_server", - "template_remote_kickstarts", + "ldap_enabled", + "ldap_type", + "monit_enabled", + "redhat_management_server", + "template_remote_kickstarts", ] # Keys to rename rename = { - "kickstart": "autoinstall", - "ks_meta": "autoinstall_meta", + "kickstart": "autoinstall", + "ks_meta": "autoinstall_meta", } + +def _fix_autoinstall(path): + # Absolute path, we need to calculate the relative path against its template dir + # Examples seen: + # - "" (empty string) + # - <<inherit>> + # - /upload/something.cfg + # - upload/something.cfg + # - /var/lib/rhn/kickstarts/upload/something.cfg + # - /var/lib/cobbler/kickstarts/upload/something.cfg + # - /var/lib/cobbler/autoinstall_templates/default.ks + # + + # Empty string found. Nothing to do. + if not path: + return path + + # Absolute path found + if os.path.isabs(path): + for tp in TEMPLATES_PATHS: + if path.startswith(tp): + # Migrate absolute path to relative path. + # Example: /var/lib/cobbler/kickstarts/upload/something.cfg -> upload/something.cfg + new_path = os.path.relpath(path, tp) + print( + " * Migrate absolute autoinstall path: {} to {}".format( + path, new_path + ) + ) + return new_path + + # Wrong absolute path found - maybe this is actually a relative path + # where we need to remove the initial slash. + # We check first if file would exist on the template paths to validate the migration + # Example: /upload/something.cfg -> upload/something.cfg + elif os.path.isfile(os.path.join(tp, path.lstrip("/"))): + return path.lstrip("/") + + # Absolute path outside of expected template paths. + # We do not migrate the content and warn user. + print( + " * ERROR: Migrate absolute autoinstall path: {} was not possible. " + "Cannot find file.".format(path) + ) + print( + " * Please fix 'autoinstall' attribute for this collection manually." + ) + return path + + # Here the value is already relative path. It might be wrong and we need to fix it + else: + for tp in TEMPLATES_PATHS: + if os.path.isfile(os.path.join(tp, path)): + # The value is correct, nothing to do + return path + + # Here, it means the file is not found, probably wrong and we need to + # figure out where the file is really located. + # In case we find a collision, so different possible candidates + # then we raise an error and do nothing. + items_found = [] + new_path = None + for tp in TEMPLATES_PATHS: + for curdir, subdirs, files in os.walk(tp): + if os.path.basename(path) in files: + # We fix the wrong value and set the correct one + # in case there is not collisions + # Example: something.cfg -> upload/something.cfg + # Example: foobar/something.cfg -> upload/something.cfg + items_found.append(os.path.join(curdir, os.path.basename(path))) + if not new_path: + new_path = os.path.relpath( + os.path.join(curdir, os.path.basename(path)), tp + ) + + # Collisions in names -> raise error and do nothing + if len(items_found) > 1: + print( + " * ERROR: Migrate relative autoinstall: {} was not possible as" + "there are multiple candidates for this file.".format(path) + ) + for item in items_found: + print(" -- {}".format(item)) + print( + " * Please fix 'autoinstall' attribute manually for this collection. " + "Put a path which is relative to /var/lib/cobbler/templates" + ) + return path + # Template file found and no collisions -> return the fixed value + elif new_path: + print( + " * Fixed wrong value for autoinstall path: {} to {}".format( + path, new_path + ) + ) + return new_path + + # At this point, we didn't find the template + # so we return same value and do not migrate it + if path != "<<inherit>>": + print( + " * ERROR: Migrate relative autoinstall: {} was not possible. " + "Cannot find file.".format(path) + ) + print( + " * Please fix 'autoinstall' attribute for this collection manually." + ) + return path + + # Keys to transform - use new key name if renamed transform = { - "autoinstall": os.path.basename, + "autoinstall": _fix_autoinstall, } +# Create a backup of stored collections before performing migration +print("Creating a backup of %s" % args.collections_path) +backup_dir(args.collections_path) + # Convert the old collections to new collections -for old_type in ['distros.d','files.d','images.d','mgmtclasses.d','packages.d','profiles.d','repos.d','systems.d']: +for old_type in [ + "distros.d", + "files.d", + "images.d", + "mgmtclasses.d", + "packages.d", + "profiles.d", + "repos.d", + "systems.d", +]: new_type = old_type[:-2] + + # Bypass old collection.d folder schema + if args.noconfigs: + old_type = new_type + # Load old files old_collection = deserialize_raw_old(old_type) print("Processing %s:" % old_type) for old_item in old_collection: - print(" Processing %s" % old_item['name']) + print(" Processing %s" % old_item["name"]) new_item = {} for key in old_item: - if key in remove: - continue - if key in rename: - new_item[rename[key]] = transform_key(rename[key], old_item[key]) - continue + if not args.only_fix_autoinstall: + if key in remove: + continue + if key in rename: + new_item[rename[key]] = transform_key(rename[key], old_item[key]) + continue new_item[key] = transform_key(key, old_item[key]) - if new_type in add: - new_item.update(add[new_type]) + if not args.only_fix_autoinstall: + if new_type in add: + new_item.update(add[new_type]) + + # Switch "virtio26" and "generic26" OS version to "generic" distro breed + if new_item.get("os_version") in ["generic26", "virtio26"]: + new_item["breed"] = "generic" serialize_item(new_type, new_item) path_rename = [ - ("/var/lib/cobbler/kickstarts", "/var/lib/cobbler/templates"), - ("/var/www/cobbler/ks_mirror", "/var/www/cobbler/distro_mirror"), + (OLD_AUTOINSTALL_TEMPLATES_PATH, COBBLER_TEMPLATES_PATH), + (OLD_RHN_TEMPLATES_PATH, COBBLER_TEMPLATES_PATH), + (OLD_COBBLER_TEMPLATES_PATH, COBBLER_TEMPLATES_PATH), + ("/var/www/cobbler/ks_mirror", "/var/www/cobbler/distro_mirror"), ] # Copy paths for old_path, new_path in path_rename: if os.path.isdir(old_path): - subprocess.run(["cp", "-al", "%s/*" % old_path, "%s/" % new_path], shell=True) + subprocess.run("cp -al %s/* %s/" % (old_path, new_path), shell=True)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor