diff --git a/README.md b/README.md index b067f7a349ab221bc0264f1128d6bd820217291a..38c8bb3a01c6a58290c5775072189206af314d5e 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,18 @@ This script automates the process of updating images of operating systems in Ope ### Currently the supported OS are: -- CentOS 7 -- CentOS 8 -- Debian 9 +- CentOS 8stream +- Debian 9stream - Debian 10 - Debian 11 -- Fedora 32 -- Fedora 33 -- Fedora 34 -- Ubuntu 16.04 +- Debian 12 +- Fedora 37 +- Fedora 38 +- RockyLinux 8 +- RockyLinux 9 - Ubuntu 18.04 - Ubuntu 20.04 +- Ubuntu 22.04 Installation ------------ @@ -36,11 +37,11 @@ Source the `admin` credentials to gain access to `OpenStack` commands: Execute the script - $ python3 update-images.py + $ python3 update-images.py [-v] [-p <patterns>] [-f] [-w] ### Execution example - $ python3 update-images.py + $ python3 update-images.py -w Download... From: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 To: downloads/centos7-1505262668.qcow2 @@ -73,9 +74,10 @@ After updating the images, update the simplestreams catalog: Pipeline -------- -1. Fetch from config.yaml the url -2. Download locally (in 'download' folder) the updated qcow2 of specified operating system -3. Upload the qcow2 image on glance using openstack-cli commands +1. Fetch from config.yaml the url: filter by name using -p switch +2. Download locally (in 'download' folder) the updated qcow2 of specified + operating system: force download with -f switch +3. Upload the qcow2 image on glance using openstack-cli commands: requires -w switch Notes ----- diff --git a/update-images.py b/update-images.py index c7963845f43e5aae4c525aa6ba2af3630011bad4..5a9d1f8930e0a98f206e62c904bae49421b76f7b 100755 --- a/update-images.py +++ b/update-images.py @@ -8,6 +8,7 @@ import os from pprint import pprint import shade import subprocess +import argparse from tqdm import tqdm @@ -28,6 +29,33 @@ def download_from_url(url, output_file): pbar.close() return file_size +##### + +parser = argparse.ArgumentParser( + description="Download and update cloud images.") +parser.add_argument("-p", "--patterns", + help="Comma-separated string of patterns matching desired image names") +parser.add_argument("-f", "--force", + help="Ignore times, force download", action='store_true') +parser.add_argument("-w", "--write", + help="Update OpenStack Glance, write image (default=false)", + action='store_true') +parser.add_argument("-v", "--verbose", + help="Set VERBOSE logging level", action='store_true') +opts = parser.parse_args() + +namePatterns = [] +if opts.patterns: + namePatterns = opts.patterns.lower().split(',') + print("INFO: only select images matching following string:",namePatterns) + +if opts.force: + print("INFO: force option is set, force download images") +if opts.write: + print("INFO: write option is set, update Glance") +else: + print("INFO: write option NOT set, not updating Glance") + config = None with open('config.yml') as fh_config: config = yaml.safe_load(fh_config) @@ -40,20 +68,37 @@ if not os.path.isdir(download_dir): openstack_cloud_connection = shade.openstack_cloud() for image_key in sorted(config['images'].keys()): - print("=== Image name: {}".format(image_key)) + doThis = 1 + if len(namePatterns): + doThis = 0 + for np in namePatterns: + thisName = config['images'][image_key]['name'] + if np in thisName.lower(): + print("=== Found image name: {}".format(thisName)) + doThis = 1 + if doThis: + print("=== Process Image key: {}".format(image_key)) + else: + print("=== Skip Image key: {}".format(image_key)) + continue + if not 'url' in config['images'][image_key]: - print("skipping...") + print("skipping... ",config['images'][image_key],"no URL provided") continue url = config['images'][image_key]['url'] request_response = requests_session.head(url, allow_redirects=True) request_response.raise_for_status() http_last_modified = request_response.headers['Last-Modified'] - last_modified_time = datetime.datetime.strptime(http_last_modified, '%a, %d %b %Y %H:%M:%S GMT') + last_modified_time = datetime.datetime.strptime(http_last_modified, + '%a, %d %b %Y %H:%M:%S GMT') image_name = config['images'][image_key]['name'] image = openstack_cloud_connection.get_image(name_or_id=image_name) - download = False + if opts.force: + download = True + else: + download = False dateNow = datetime.datetime.now() dateNowStr = dateNow.strftime("%Y/%m/%d") descNewImg = "%s: downloaded from %s" % (dateNowStr, url) @@ -67,12 +112,16 @@ for image_key in sorted(config['images'].keys()): if last_modified_time > last_update: download = True + else: + print(" --- not downloading (image update time)") if 'metadata' in image and 'last_modified' in image['metadata']: last_modified_from_image = datetime.datetime.strptime(image['metadata']['last_modified'], '%Y-%m-%d %H:%M:%S') if last_modified_time > last_modified_from_image: download = True + else: + print(" --- not downloading (image metadata)") if download: # Add to description field @@ -82,9 +131,12 @@ for image_key in sorted(config['images'].keys()): descOldImg = "%s \n %s" % (descOldImg, descCur) # Rename image, update description, set image as private image_name_old = "%s %s" % (image_name, dateNowStr) - print ("Rename old image, set private, update description: \n \t openstack image set --private --property description=\"{}\" --name \"{}\" {}".format(descOldImg[:30], image_name_old, image['id'])) - subprocess.call("openstack image set --private --property description=\"{}\" --name \"{}\" {}".format(descOldImg, image_name_old, image['id']), shell=True) - + if opts.write: + print ("Rename old image, set private, update description: \n \t openstack image set --private --property description=\"{}\" --name \"{}\" {}".format(descOldImg[:30], image_name_old, image['id'])) + subprocess.call("openstack image set --private --property description=\"{}\" --name \"{}\" {}".format(descOldImg, image_name_old, image['id']), shell=True) + else: + print ("WRITE_UNSET: would rename old image, set private, update description: \n \t openstack image set --private --property description=\"{}\" --name \"{}\" {}".format(descOldImg[:30], image_name_old, image['id'])) + if download: download_image_file = download_dir download_image_file += image_key @@ -115,12 +167,13 @@ for image_key in sorted(config['images'].keys()): argsDict.update({'meta':tagDict}) print("Args dictionary: {}".format(argsDict)) - time0 = int(time.time()) - openstack_cloud_connection.create_image(image_name, - filename=download_image_file, - disk_format=config['images'][image_key]['disk_format'], - description=descNewImg, - **argsDict, - wait=True,is_public=True) - time1 = int(time.time()) - print("Uploaded to Glance in {} seconds".format(time1-time0)) + if opts.write: + time0 = int(time.time()) + openstack_cloud_connection.create_image(image_name, + filename=download_image_file, + disk_format=config['images'][image_key]['disk_format'], + description=descNewImg, + **argsDict, + wait=True,is_public=True) + time1 = int(time.time()) + print("Uploaded to Glance in {} seconds".format(time1-time0))