distcloud/distributedcloud/dccommon/drivers/openstack/vim.py
Al Bailey 845bd9a771 Add additional fields to API calls to NFV
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
2022-04-07 18:49:54 +00:00

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