293 lines
12 KiB
Python
293 lines
12 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright (c) 2020 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
import sys
|
|
import yaml
|
|
|
|
from sysinv.common import constants
|
|
from sysinv.common import service
|
|
from sysinv.conductor import rpcapi as conductor_rpcapi
|
|
from sysinv.db import api
|
|
from sysinv.openstack.common import context
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
|
|
# Log and config
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
def local_registry_list(filename, included_apps, include_all_apps=False):
|
|
""" Save the list of images present in the local registry
|
|
to a file in yaml format.
|
|
|
|
:param filename: name of the file to save to.
|
|
:param include_apps: list of applications for which images are saved in yaml format.
|
|
:param include_all_apps: if True then the list of apps images will include all apps
|
|
regardless of include_apps list.
|
|
"""
|
|
|
|
ctxt = context.get_admin_context()
|
|
rpcapi = conductor_rpcapi.ConductorAPI(
|
|
topic=conductor_rpcapi.MANAGER_TOPIC)
|
|
|
|
# Save local registry images tags
|
|
image_name_tag_list = []
|
|
temp_image_name_list = rpcapi.docker_registry_image_list(ctxt)
|
|
if not temp_image_name_list:
|
|
raise Exception("Image list could not be retrieved "
|
|
"from local registry")
|
|
|
|
for temp_image_name in temp_image_name_list:
|
|
image_name = temp_image_name.get('name', None)
|
|
if image_name:
|
|
temp_image_tags = rpcapi.docker_registry_image_tags(ctxt,
|
|
image_name)
|
|
|
|
for image_name_tag in temp_image_tags:
|
|
image_tag = image_name_tag.get('tag', None)
|
|
if image_tag:
|
|
image_name_tag_list.append("%s:%s" % (image_name, image_tag))
|
|
|
|
# Retrieve the images used by apps that should be excluded from yaml file
|
|
excluded_images = []
|
|
if not include_all_apps:
|
|
apps_images = rpcapi.docker_get_apps_images(ctxt).items()
|
|
if not apps_images:
|
|
raise Exception("Apps image list could not be retrieved")
|
|
for app, images in apps_images:
|
|
if included_apps is None or app not in included_apps:
|
|
excluded_images.extend(images)
|
|
|
|
# Exclude apps images
|
|
image_name_tag_list = list(set(image_name_tag_list) - set(excluded_images))
|
|
|
|
data = {}
|
|
data.update({'images': image_name_tag_list})
|
|
|
|
try:
|
|
with open(filename, 'w') as outfile:
|
|
yaml.safe_dump(data, outfile, default_flow_style=False)
|
|
except Exception as e:
|
|
LOG.error("Error with local_registry_list: %s", e)
|
|
sys.exit(1)
|
|
|
|
|
|
def create_host_overrides(filename):
|
|
try:
|
|
dbapi = api.get_instance()
|
|
data = {}
|
|
|
|
# Get the distributed cloud role info
|
|
system = dbapi.isystem_get_one()
|
|
if system.distributed_cloud_role:
|
|
data.update({'distributed_cloud_role': system.distributed_cloud_role})
|
|
else:
|
|
data.update({'distributed_cloud_role': 'none'})
|
|
|
|
# region_config and region_name are overriden for subclouds
|
|
if (system.distributed_cloud_role and
|
|
system.distributed_cloud_role == constants.DISTRIBUTED_CLOUD_ROLE_SUBCLOUD):
|
|
data.update({'region_config': True})
|
|
data.update({'region_name': system.region_name})
|
|
|
|
data.update({'system_mode': system.system_mode})
|
|
if system.location:
|
|
data.update({'location': system.location})
|
|
if system.description:
|
|
data.update({'description': system.description})
|
|
|
|
# Get the DNS info
|
|
dns = dbapi.idns_get_one()
|
|
if dns.nameservers:
|
|
dns_list = dns.nameservers.split(',')
|
|
data.update({'dns_servers': dns_list})
|
|
|
|
# Get the address pool info
|
|
pools = dbapi.address_pools_get_all()
|
|
for pool in pools:
|
|
subnet = pool.network + '/' + str(pool.prefix)
|
|
range_start = pool.ranges[0][0].encode('utf-8')
|
|
range_end = pool.ranges[0][-1].encode('utf-8')
|
|
|
|
if pool.name == 'pxeboot':
|
|
pool_data = {'pxeboot_subnet': subnet,
|
|
'pxeboot_start_address': range_start,
|
|
'pxeboot_end_address': range_end,
|
|
'pxeboot_floating_address': pool.floating_address,
|
|
'pxeboot_node_0_address': pool.controller0_address,
|
|
'pxeboot_node_1_address': pool.controller1_address
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'management':
|
|
pool_data = {'management_subnet': subnet,
|
|
'management_start_address': range_start,
|
|
'management_end_address': range_end,
|
|
'management_floating_address': pool.floating_address,
|
|
'management_node_0_address': pool.controller0_address,
|
|
'management_node_1_address': pool.controller1_address
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'multicast-subnet':
|
|
pool_data = {'management_multicast_subnet': subnet,
|
|
'management_multicast_start_address': range_start,
|
|
'management_multicast_end_address': range_end
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'cluster-host-subnet':
|
|
pool_data = {'cluster_host_subnet': subnet,
|
|
'cluster_host_start_address': range_start,
|
|
'cluster_host_end_address': range_end,
|
|
'cluster_host_floating_address': pool.floating_address,
|
|
'cluster_host_node_0_address': pool.controller0_address,
|
|
'cluster_host_node_1_address': pool.controller1_address
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'cluster-pod-subnet':
|
|
pool_data = {'cluster_pod_subnet': subnet,
|
|
'cluster_pod_start_address': range_start,
|
|
'cluster_pod_end_address': range_end
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'cluster-service-subnet':
|
|
pool_data = {'cluster_service_subnet': subnet,
|
|
'cluster_sevice_start_address': range_start,
|
|
'cluster_service_end_address': range_end
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'oam':
|
|
pool_data = {'external_oam_subnet': subnet,
|
|
'external_oam_start_address': range_start,
|
|
'external_oam_end_address': range_end,
|
|
'external_oam_floating_address': pool.floating_address,
|
|
'external_oam_gateway_address': pool.gateway_address
|
|
}
|
|
data.update(pool_data)
|
|
|
|
system = dbapi.isystem_get_one()
|
|
if system.system_mode != constants.SYSTEM_MODE_SIMPLEX:
|
|
pool_data = {'external_oam_node_0_address': pool.controller0_address,
|
|
'external_oam_node_1_address': pool.controller1_address,
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'system-controller-subnet':
|
|
pool_data = {'system_controller_subnet': subnet,
|
|
'system_controller_floating_address': pool.floating_address,
|
|
}
|
|
data.update(pool_data)
|
|
|
|
elif pool.name == 'system-controller-oam-subnet':
|
|
pool_data = {'system_controller_oam_subnet': subnet,
|
|
'system_controller_oam_floating_address': pool.floating_address,
|
|
}
|
|
data.update(pool_data)
|
|
|
|
docker_list = dbapi.service_parameter_get_all(service=constants.SERVICE_TYPE_DOCKER,
|
|
section=constants.SERVICE_PARAM_SECTION_DOCKER_PROXY)
|
|
for docker in docker_list:
|
|
# Get the docker no-proxy info if it exists
|
|
if docker.name == constants.SERVICE_PARAM_NAME_DOCKER_NO_PROXY:
|
|
# Remove the open and close parenthesis if address is IPV6
|
|
_value = docker.value.strip("[]")
|
|
no_proxy_list = _value.split(',')
|
|
data.update({'docker_no_proxy': no_proxy_list})
|
|
|
|
# Get the docker http_proxy info if it exists
|
|
elif docker.name == constants.SERVICE_PARAM_NAME_DOCKER_HTTP_PROXY:
|
|
data.update({'docker_http_proxy': docker.value})
|
|
|
|
# Get the docker https_proxy info if it exists
|
|
elif docker.name == constants.SERVICE_PARAM_NAME_DOCKER_HTTPS_PROXY:
|
|
data.update({'docker_https_proxy': docker.value})
|
|
|
|
# Save collected information in file
|
|
with open(filename, 'w') as outfile:
|
|
yaml.safe_dump(data, outfile, default_flow_style=False)
|
|
except Exception as e:
|
|
LOG.error("Error with create_host_overrides: %s", e)
|
|
sys.exit(1)
|
|
|
|
|
|
VALID_NOTIFICATION_VALUES = list(constants.HOOK_PARAMETERS_MAP.keys())
|
|
NOTIFICATION_ACTION_SUCCESS_VALUES = {'success': True,
|
|
'failure': False}
|
|
|
|
|
|
def send_notification(operation, success):
|
|
if operation not in VALID_NOTIFICATION_VALUES:
|
|
LOG.error("Invalid notification '{}'.".format(operation))
|
|
sys.exit(2)
|
|
ctx = context.get_admin_context()
|
|
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
|
|
ok, app = rpcapi.backup_restore_lifecycle_actions(ctx, operation, success)
|
|
if not ok:
|
|
if app is not None:
|
|
LOG.error("Operation '{}' was aborted by '{}' appliction.".format(operation, app))
|
|
sys.stderr.write(app)
|
|
sys.exit(1)
|
|
else:
|
|
LOG.error("Error while performing operation '{}'.".format(operation))
|
|
sys.exit(2)
|
|
|
|
|
|
def add_action_parsers(subparsers):
|
|
|
|
parser = subparsers.add_parser('create-host-overrides')
|
|
parser.set_defaults(func=create_host_overrides)
|
|
parser.add_argument('filename', nargs='?')
|
|
|
|
parser = subparsers.add_parser('local-registry-list')
|
|
parser.set_defaults(func=local_registry_list)
|
|
parser.add_argument('filename', nargs='?')
|
|
parser.add_argument('--all-apps', action='store_true', default=False)
|
|
parser.add_argument('--apps', nargs='*', required=False, default=None)
|
|
|
|
parser = subparsers.add_parser('notify')
|
|
parser.set_defaults(func=send_notification)
|
|
parser.add_argument('operation')
|
|
parser.add_argument('success',
|
|
choices=list(NOTIFICATION_ACTION_SUCCESS_VALUES.keys()),
|
|
default='success',
|
|
nargs='?')
|
|
|
|
|
|
CONF.register_cli_opt(
|
|
cfg.SubCommandOpt('action',
|
|
title='actions',
|
|
help='Perform sysinv operations',
|
|
handler=add_action_parsers))
|
|
|
|
|
|
def main():
|
|
service.prepare_service(sys.argv)
|
|
|
|
if CONF.action.name == 'create-host-overrides':
|
|
if not CONF.action.filename:
|
|
LOG.error("filename is required")
|
|
else:
|
|
CONF.action.func(CONF.action.filename)
|
|
elif CONF.action.name == 'local-registry-list':
|
|
if not CONF.action.filename:
|
|
LOG.error("filename is required")
|
|
else:
|
|
CONF.action.func(CONF.action.filename, CONF.action.apps, CONF.action.all_apps)
|
|
elif CONF.action.name == 'notify':
|
|
success = NOTIFICATION_ACTION_SUCCESS_VALUES[CONF.action.success]
|
|
CONF.action.func(CONF.action.operation, success)
|
|
else:
|
|
CONF.action.func()
|