Files
distcloud/distributedcloud/dcmanager/api/controllers/v1/subcloud_deploy.py
Li Zhu ad1f05ac5f Add release optionality to subcloud add/reinstall
Add an optional --release parameter to subcloud add and reinstall
commands to enable release optionality in subcloud add and subcloud
reinstall.

Test Plan:
1. Verify successful subcloud add which includes remote install with
specified (previous/current) release
2. Verify successful subcloud reinstall with the specified
(previous/current) release
3. Verify the subcloud is successfully installed with the active
release when the release parameter is absent
4. Verify the subcloud is successfully reinstalled with the active
release when the release parameter is absent
5. Verify the subcloud install request was rejected
when the software_version in the install_values doesn't
match the specified release
6. Verify the subcloud install/reinstall request was rejected
when the kubernetes_version value specified in the subcloud bootstrap
yaml file doesn't match the value of the fresh_install_k8s_version of
the specified previous release

Depends-On: https://review.opendev.org/c/starlingx/utilities/+/878545
            https://review.opendev.org/c/starlingx/ansible-playbooks/+/878922

Story: 2010611
Task: 47684

Signed-off-by: lzhu1 <li.zhu@windriver.com>
Change-Id: Ic4193c2901d8bfa485eeb683c08422d946802bcb
2023-04-03 00:12:39 +00:00

159 lines
5.7 KiB
Python

# All Rights Reserved.
#
# 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.
#
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import os
from oslo_config import cfg
from oslo_log import log as logging
import http.client as httpclient
import pecan
from pecan import expose
from pecan import request
from dccommon import consts as dccommon_consts
from dcmanager.api.controllers import restcomm
from dcmanager.api.policies import subcloud_deploy as subcloud_deploy_policy
from dcmanager.api import policy
from dcmanager.common import consts
from dcmanager.common.i18n import _
from dcmanager.common import utils
import tsconfig.tsconfig as tsc
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
LOCK_NAME = 'SubcloudDeployController'
class SubcloudDeployController(object):
def __init__(self):
super(SubcloudDeployController, self).__init__()
@staticmethod
def _upload_files(dir_path, file_option, file_item, binary):
prefix = file_option + '_'
# create the version directory if it does not exist
if not os.path.isdir(dir_path):
os.mkdir(dir_path, 0o755)
else:
# check if the file exists, if so remove it
filename = utils.get_filename_by_prefix(dir_path, prefix)
if filename is not None:
os.remove(dir_path + '/' + filename)
# upload the new file
file_item.file.seek(0, os.SEEK_SET)
contents = file_item.file.read()
fn = os.path.join(dir_path, prefix + os.path.basename(
file_item.filename))
if binary:
dst = open(fn, 'wb')
dst.write(contents)
else:
dst = os.open(fn, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
os.write(dst, contents)
@expose(generic=True, template='json')
def index(self):
# Route the request to specific methods with parameters
pass
@utils.synchronized(LOCK_NAME)
@index.when(method='POST', template='json')
def post(self):
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "upload", {},
restcomm.extract_credentials_for_policy())
deploy_dicts = dict()
missing_options = set()
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
if f not in request.POST:
missing_options.add(f)
# The API will only accept three types of input scenarios:
# 1. DEPLOY_PLAYBOOK, DEPLOY_OVERRIDES, and DEPLOY_CHART
# 2. DEPLOY_PLAYBOOK, DEPLOY_OVERRIDES, DEPLOY_CHART, and DEPLOY_PRESTAGE
# 3. DEPLOY_PRESTAGE
size = len(missing_options)
if len(missing_options) > 0:
if ((consts.DEPLOY_PRESTAGE in missing_options and size != 1) or
(consts.DEPLOY_PRESTAGE not in missing_options and size != 3)):
missing_str = str()
for missing in missing_options:
if missing is not consts.DEPLOY_PRESTAGE:
missing_str += '--%s ' % missing
error_msg = "error: argument %s is required" % missing_str.rstrip()
pecan.abort(httpclient.BAD_REQUEST, error_msg)
software_version = tsc.SW_VERSION
if request.POST.get('release'):
software_version = request.POST.get('release')
deploy_dicts['software_version'] = software_version
dir_path = os.path.join(dccommon_consts.DEPLOY_DIR, software_version)
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
if f not in request.POST:
continue
file_item = request.POST[f]
filename = getattr(file_item, 'filename', '')
if not filename:
pecan.abort(httpclient.BAD_REQUEST,
_("No %s file uploaded" % f))
binary = False
if f == consts.DEPLOY_CHART:
binary = True
try:
self._upload_files(dir_path, f, file_item, binary)
except Exception as e:
pecan.abort(httpclient.INTERNAL_SERVER_ERROR,
_("Failed to upload %s file: %s" % (f, e)))
deploy_dicts.update({f: filename})
return deploy_dicts
@index.when(method='GET', template='json')
def get(self, release=None):
"""Get the subcloud deploy files that has been uploaded and stored.
:param release: release version
"""
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "get", {},
restcomm.extract_credentials_for_policy())
deploy_dicts = dict()
if not release:
release = tsc.SW_VERSION
deploy_dicts['software_version'] = release
dir_path = os.path.join(dccommon_consts.DEPLOY_DIR, release)
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
filename = None
if os.path.isdir(dir_path):
prefix = f + '_'
filename = utils.get_filename_by_prefix(dir_path, prefix)
if filename is not None:
filename = filename.replace(prefix, '', 1)
deploy_dicts.update({f: filename})
return dict(subcloud_deploy=deploy_dicts)