Source code for cfme.scripting.appliance

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""Script to encrypt config files.

Usage:

   scripts/encrypt_conf.py confname1 confname2 ... confnameN
   scripts/encrypt_conf.py credentials
"""
import click
import tempfile
from cached_property import cached_property
from cfme.utils import os
from cfme.utils.conf import cfme_data, env
from functools import partial
from cfme.utils.repo_gen import process_url, build_file


[docs]def get_appliance(appliance_ip): """Checks an appliance is not None and if so, loads the appropriate things""" from cfme.utils.appliance import IPAppliance, load_appliances_from_config, stack if not appliance_ip: app = load_appliances_from_config(env)[0] else: app = IPAppliance(hostname=appliance_ip) stack.push(app) # ensure safety from bad code, phase out later return app
@click.group(help='Helper commands for appliances') def main(): """Main appliance group""" pass @main.command('upgrade', help='Upgrades an appliance to latest Z-stream') @click.argument('appliance-ip', default=None, required=False) @click.option('--cfme-only', is_flag=True, help='Upgrade cfme packages only') @click.option('--update-to', default='5.9.z', help='Supported versions 5.8.1, 5.8.2, 5.8.z,' ' 5.9.1, 5.9.2, 5.9.z (.z means latest and default is 5.9.z)') def upgrade_appliance(appliance_ip, cfme_only, update_to): """Upgrades an appliance""" supported_version_repo_map = { '5.8.z': 'update_url_58', '5.8.0': 'update_url_580', '5.8.1': 'update_url_581', '5.8.2': 'update_url_582', '5.9.z': 'update_url_59', '5.9.0': 'update_url_590', '5.9.1': 'update_url_591', '5.9.2': 'update_url_592' } assert update_to in supported_version_repo_map, "{} is not a supported version".format( update_to ) update_url = supported_version_repo_map[update_to] if appliance_ip: print('Connecting to {}'.format(appliance_ip)) else: print('Fetching appliance from env.local.yaml') app = get_appliance(appliance_ip) assert app.version > '5.7', "{} is not supported, must be 5.7 or higher".format(app.version) print('Extending appliance partitions') app.db.extend_partition() urls = process_url(cfme_data['basic_info'][update_url]) output = build_file(urls) print('Adding update repo to appliance') with tempfile.NamedTemporaryFile('w') as f: f.write(output) f.flush() os.fsync(f.fileno()) app.ssh_client.put_file( f.name, '/etc/yum.repos.d/update.repo') cfme = '-y' if cfme_only: cfme = 'cfme -y' print('Stopping EVM') app.evmserverd.stop() print('Running yum update') result = app.ssh_client.run_command('yum update {}'.format(cfme), timeout=3600) assert result.success, "update failed {}".format(result.output) print('Running database migration') app.db.migrate() app.db.automate_reset() print('Restarting postgres service') app.db.restart_db_service() print('Starting EVM') app.start_evm_service() print('Waiting for webui') app.wait_for_web_ui() print('Appliance upgrade completed') @main.command('migrate', help='Restores/migrates database from file or downloaded') @click.argument('appliance-ip', default=None, required=True) @click.option('--db-url', default=None, help='Download a backup file') @click.option('--keys-url', default=None, help='URL for matching db v2key and GUID if available') @click.option('--backup', default=None, help='Location of local backup file, including file name') def backup_migrate(appliance_ip, db_url, keys_url, backup): """Restores and migrates database backup on an appliance""" print('Connecting to {}'.format(appliance_ip)) app = get_appliance(appliance_ip) if db_url: print('Downloading database backup') result = app.ssh_client.run_command( 'curl -o "/evm_db.backup" "{}"'.format(db_url), timeout=30) assert result.success, "Failed to download database: {}".format(result.output) backup = '/evm_db.backup' else: backup = backup print('Stopping EVM') app.evmserverd.stop() print('Dropping/Creating database') app.db.drop() app.db.create() print('Restoring database from backup') result = app.ssh_client.run_command( 'pg_restore -v --dbname=vmdb_production {}'.format(backup), timeout=600) assert result.success, "Failed to restore new database: {}".format(result.output) print('Running database migration') app.db.migrate() app.db.automate_reset() if keys_url: result = app.ssh_client.run_command( 'curl -o "/var/www/miq/vmdb/certs/v2_key" "{}v2_key"'.format(keys_url), timeout=15) assert result.success, "Failed to download v2_key: {}".format(result.output) result = app.ssh_client.run_command( 'curl -o "/var/www/miq/vmdb/GUID" "{}GUID"'.format(keys_url), timeout=15) assert result.success, "Failed to download GUID: {}".format(result.output) else: app.db.fix_auth_key() app.db.fix_auth_dbyml() print('Restarting postgres service') app.db.restart_db_service() print('Starting EVM') app.start_evm_service() print('Waiting for webui') app.wait_for_web_ui() print('Appliance upgrade completed') @main.command('reboot', help='Reboots the appliance') @click.argument('appliance_ip', default=None, required=False) @click.option('--wait-for-ui', is_flag=True, default=True) def reboot_appliance(appliance_ip, wait_for_ui): """Reboots an appliance""" app = get_appliance(appliance_ip) app.reboot(wait_for_ui) @main.command('setup-webmks', help='Setups VMware WebMKS on an appliance by downloading' 'and extracting SDK to required location') @click.argument('appliance_ip', default=None, required=False) def config_webmks(appliance_ip): appliance = get_appliance(appliance_ip) server_settings = appliance.server.settings server_settings.update_vmware_console({'console_type': 'VMware WebMKS'}) roles = server_settings.server_roles_db if 'websocket' in roles and not roles['websocket']: server_settings.enable_server_roles('websocket') # Useful Properties methods_to_install = [ 'is_db_enabled', 'managed_provider_names', 'miqqe_version', 'os_version', 'swap', 'miqqe_patch_applied']
[docs]def fn(method, *args, **kwargs): """Helper to access the right properties""" from cfme.utils.appliance import IPAppliance appliance_ip = kwargs.get('appliance_ip', None) app = get_appliance(appliance_ip) descriptor = getattr(IPAppliance, method) if isinstance(descriptor, (cached_property, property)): out = getattr(app, method) else: out = getattr(app, method)(*args, **kwargs) if out is not None: print(out)
for method in methods_to_install: command = click.Command( method.replace('_', '-'), short_help='Returns the {} property'.format(method), callback=partial(fn, method), params=[ click.Argument(['appliance_ip'], default=None, required=False)]) main.add_command(command) if __name__ == "__main__": main()