845bd9a771
The nfv_client on the system controller supports additional user / domain / tenant arguments to its strategy API calls. The DC code will now pass those additional arguments. There are several implementation details to note: 1) The strategy calls are all done by dcmanager. 2) The session object can only return UUIDs so the values for user, domain and tenant are constants. 3) Doing an extra API request to correlate the UUIDs to the known constants would add extra cost, and will only be necessary if the other DC users make use of vim client in the future. 4) The API is changed locally in the client code and attributes are passed through HTTP headers. This means this change does not break when connecting to subclouds that are not running the latest DC or NFV code. Test Plan: PASS: Perform a DC patch strategy (where the subcloud is running older code and does not the nfv_client code changes). Verify the logs are not shown, and there are no issues. PASS: Perform a DC patch strategy (where the subcloud is up to date and does have the nfv_client code change). Verify the logs are shown and there are no issues. Story: 2009824 Task: 44885 Signed-off-by: Al Bailey <al.bailey@windriver.com> Change-Id: I115c74df9986e2d9d5c4d0feea4f5c83d95ad2f1
195 lines
6.5 KiB
Python
195 lines
6.5 KiB
Python
# Copyright 2016 Ericsson AB
|
|
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
|
|
from oslo_log import log
|
|
|
|
from nfv_client.openstack import sw_update
|
|
|
|
from dccommon import consts
|
|
from dccommon.drivers import base
|
|
from dccommon import exceptions
|
|
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
STRATEGY_NAME_FW_UPDATE = 'fw-update'
|
|
STRATEGY_NAME_KUBE_ROOTCA_UPDATE = 'kube-rootca-update'
|
|
STRATEGY_NAME_KUBE_UPGRADE = 'kube-upgrade'
|
|
STRATEGY_NAME_SW_PATCH = 'sw-patch'
|
|
STRATEGY_NAME_SW_UPGRADE = 'sw-upgrade'
|
|
|
|
APPLY_TYPE_SERIAL = 'serial'
|
|
APPLY_TYPE_PARALLEL = 'parallel'
|
|
APPLY_TYPE_IGNORE = 'ignore'
|
|
|
|
INSTANCE_ACTION_MIGRATE = 'migrate'
|
|
INSTANCE_ACTION_STOP_START = 'stop-start'
|
|
|
|
ALARM_RESTRICTIONS_STRICT = 'strict'
|
|
ALARM_RESTRICTIONS_RELAXED = 'relaxed'
|
|
|
|
SW_UPDATE_OPTS_CONST_DEFAULT = {
|
|
"name": consts.SW_UPDATE_DEFAULT_TITLE,
|
|
"storage-apply-type": APPLY_TYPE_PARALLEL,
|
|
"worker-apply-type": APPLY_TYPE_PARALLEL,
|
|
"max-parallel-workers": 10,
|
|
"default-instance-action": INSTANCE_ACTION_MIGRATE,
|
|
"alarm-restriction-type": ALARM_RESTRICTIONS_RELAXED,
|
|
"created-at": None,
|
|
"updated-at": None}
|
|
|
|
STATE_INITIAL = 'initial'
|
|
STATE_BUILDING = 'building'
|
|
STATE_BUILD_FAILED = 'build-failed'
|
|
STATE_BUILD_TIMEOUT = 'build-timeout'
|
|
STATE_READY_TO_APPLY = 'ready-to-apply'
|
|
STATE_APPLYING = 'applying'
|
|
STATE_APPLY_FAILED = 'apply-failed'
|
|
STATE_APPLY_TIMEOUT = 'apply-timeout'
|
|
STATE_APPLIED = 'applied'
|
|
STATE_ABORTING = 'aborting'
|
|
STATE_ABORT_FAILED = 'abort-failed'
|
|
STATE_ABORT_TIMEOUT = 'abort-timeout'
|
|
STATE_ABORTED = 'aborted'
|
|
|
|
# The exception message when vim authorization fails
|
|
VIM_AUTHORIZATION_FAILED = "Authorization failed"
|
|
|
|
|
|
class VimClient(base.DriverBase):
|
|
"""VIM driver."""
|
|
|
|
def __init__(self, region, session, endpoint=None):
|
|
try:
|
|
# The nfv_client doesn't support a session, so we need to
|
|
# get an endpoint and token.
|
|
if endpoint is None:
|
|
self.endpoint = session.get_endpoint(
|
|
service_type='nfv',
|
|
region_name=region,
|
|
interface=consts.KS_ENDPOINT_ADMIN)
|
|
else:
|
|
self.endpoint = endpoint
|
|
|
|
self.token = session.get_token()
|
|
# session.get_user_id() returns a UUID
|
|
# that always corresponds to 'dcmanager'
|
|
self.username = consts.DCMANAGER_USER_NAME
|
|
# session object does not provide a domain query
|
|
# The only domain used for dcmanager is 'default'
|
|
self.user_domain_name = 'default'
|
|
# session.get_project_id() returns a UUID
|
|
# that always corresponds to 'services'
|
|
self.tenant = consts.SERVICES_USER_NAME
|
|
|
|
except exceptions.ServiceUnavailable:
|
|
raise
|
|
|
|
def create_strategy(self,
|
|
strategy_name,
|
|
storage_apply_type,
|
|
worker_apply_type,
|
|
max_parallel_worker_hosts,
|
|
default_instance_action,
|
|
alarm_restrictions,
|
|
**kwargs):
|
|
"""Create orchestration strategy"""
|
|
|
|
url = self.endpoint
|
|
strategy = sw_update.create_strategy(
|
|
self.token, url,
|
|
strategy_name=strategy_name,
|
|
controller_apply_type=APPLY_TYPE_SERIAL,
|
|
storage_apply_type=storage_apply_type,
|
|
swift_apply_type=APPLY_TYPE_IGNORE,
|
|
worker_apply_type=worker_apply_type,
|
|
max_parallel_worker_hosts=max_parallel_worker_hosts,
|
|
default_instance_action=default_instance_action,
|
|
alarm_restrictions=alarm_restrictions,
|
|
username=self.username,
|
|
user_domain_name=self.user_domain_name,
|
|
tenant=self.tenant,
|
|
**kwargs)
|
|
if not strategy:
|
|
raise Exception("Strategy:(%s) creation failed" % strategy_name)
|
|
|
|
LOG.debug("Strategy created: %s" % strategy)
|
|
return strategy
|
|
|
|
def get_strategy(self, strategy_name, raise_error_if_missing=True):
|
|
"""Get the current orchestration strategy"""
|
|
|
|
url = self.endpoint
|
|
strategy = sw_update.get_strategies(
|
|
self.token, url,
|
|
strategy_name=strategy_name,
|
|
username=self.username,
|
|
user_domain_name=self.user_domain_name,
|
|
tenant=self.tenant)
|
|
if not strategy:
|
|
if raise_error_if_missing:
|
|
raise Exception("Get strategy failed")
|
|
|
|
LOG.debug("Strategy: %s" % strategy)
|
|
return strategy
|
|
|
|
def delete_strategy(self, strategy_name):
|
|
"""Delete the current orchestration strategy"""
|
|
|
|
url = self.endpoint
|
|
success = sw_update.delete_strategy(
|
|
self.token, url,
|
|
strategy_name=strategy_name,
|
|
username=self.username,
|
|
user_domain_name=self.user_domain_name,
|
|
tenant=self.tenant)
|
|
if not success:
|
|
raise Exception("Delete strategy failed")
|
|
|
|
LOG.debug("Strategy deleted")
|
|
|
|
def apply_strategy(self, strategy_name):
|
|
"""Apply the current orchestration strategy"""
|
|
|
|
url = self.endpoint
|
|
strategy = sw_update.apply_strategy(
|
|
self.token, url,
|
|
strategy_name=strategy_name,
|
|
username=self.username,
|
|
user_domain_name=self.user_domain_name,
|
|
tenant=self.tenant)
|
|
if not strategy:
|
|
raise Exception("Strategy apply failed")
|
|
|
|
LOG.debug("Strategy applied: %s" % strategy)
|
|
return strategy
|
|
|
|
def abort_strategy(self, strategy_name):
|
|
"""Abort the current orchestration strategy"""
|
|
|
|
url = self.endpoint
|
|
strategy = sw_update.abort_strategy(
|
|
self.token, url,
|
|
strategy_name=strategy_name,
|
|
stage_id=None,
|
|
username=self.username,
|
|
user_domain_name=self.user_domain_name,
|
|
tenant=self.tenant)
|
|
if not strategy:
|
|
raise Exception("Strategy abort failed")
|
|
|
|
LOG.debug("Strategy aborted: %s" % strategy)
|
|
return strategy
|