Update tox pylint/pep8 for dcmanager
This commit enables the check of new pylint/pep8 violations. PYLINT - All convention related checks, except: - missing-class-docstring - missing-function-docstring - missing-module-docstring - consider-using-f-string - invalid-name - import-outside-toplevel - too-many-lines - consider-iterating-dictionary - unnecessary-lambda-assignment PEP8: - E117: over-indented - E123: closing bracket does not match indentation of opening bracket's line - E125: continuation line with the same indent as the next logical line - E305: expected 2 blank lines after class or function definition - E402: module level import not at top of file - E501: line too long - H216: flag use of third party mock Test Plan: 1. Perform `tox` command - Pass in py39, pylint, pep8 Closes-bug: 2033294 Change-Id: I635df8e809905cff582bd9d5eb57b91133560cf9 Signed-off-by: Hugo Brito <hugo.brito@windriver.com>
This commit is contained in:
parent
766f052295
commit
4438b8fd55
|
@ -22,127 +22,50 @@ load-plugins=
|
||||||
|
|
||||||
|
|
||||||
[MESSAGES CONTROL]
|
[MESSAGES CONTROL]
|
||||||
# Enable the message, report, category or checker with the given id(s). You can
|
|
||||||
# either give multiple identifier separated by comma (,) or put this option
|
|
||||||
# multiple time.
|
|
||||||
#
|
|
||||||
# Python3 checker:
|
|
||||||
#
|
|
||||||
# E1601: print-statement
|
|
||||||
# E1602: parameter-unpacking
|
|
||||||
# E1603: unpacking-in-except
|
|
||||||
# E1604: old-raise-syntax
|
|
||||||
# E1605: backtick
|
|
||||||
# E1609: import-star-module-level
|
|
||||||
# W1601: apply-builtin
|
|
||||||
# W1602: basestring-builtin
|
|
||||||
# W1603: buffer-builtin
|
|
||||||
# W1604: cmp-builtin
|
|
||||||
# W1605: coerce-builtin
|
|
||||||
# W1606: execfile-builtin
|
|
||||||
# W1607: file-builtin
|
|
||||||
# W1608: long-builtin
|
|
||||||
# W1609: raw_input-builtin
|
|
||||||
# W1610: reduce-builtin
|
|
||||||
# W1611: standarderror-builtin
|
|
||||||
# W1612: unicode-builtin
|
|
||||||
# W1613: xrange-builtin
|
|
||||||
# W1614: coerce-method
|
|
||||||
# W1615: delslice-method
|
|
||||||
# W1616: getslice-method
|
|
||||||
# W1617: setslice-method
|
|
||||||
# W1618: no-absolute-import
|
|
||||||
# W1619: old-division
|
|
||||||
# W1620: dict-iter-method
|
|
||||||
# W1621: dict-view-method
|
|
||||||
# W1622: next-method-called
|
|
||||||
# W1623: metaclass-assignment
|
|
||||||
# W1624: indexing-exception
|
|
||||||
# W1625: raising-string
|
|
||||||
# W1626: reload-builtin
|
|
||||||
# W1627: oct-method
|
|
||||||
# W1628: hex-method
|
|
||||||
# W1629: nonzero-method
|
|
||||||
# W1630: cmp-method
|
|
||||||
# W1632: input-builtin
|
|
||||||
# W1633: round-builtin
|
|
||||||
# W1634: intern-builtin
|
|
||||||
# W1635: unichr-builtin
|
|
||||||
# W1636: map-builtin-not-iterating
|
|
||||||
# W1637: zip-builtin-not-iterating
|
|
||||||
# W1638: range-builtin-not-iterating
|
|
||||||
# W1639: filter-builtin-not-iterating
|
|
||||||
# W1640: using-cmp-argument
|
|
||||||
# W1642: div-method
|
|
||||||
# W1643: idiv-method
|
|
||||||
# W1644: rdiv-method
|
|
||||||
# W1645: exception-message-attribute
|
|
||||||
# W1646: invalid-str-codec
|
|
||||||
# W1647: sys-max-int
|
|
||||||
# W1648: bad-python3-import
|
|
||||||
# W1649: deprecated-string-function
|
|
||||||
# W1650: deprecated-str-translate-call
|
|
||||||
# W1651: deprecated-itertools-function
|
|
||||||
# W1652: deprecated-types-field
|
|
||||||
# W1653: next-method-defined
|
|
||||||
# W1654: dict-items-not-iterating
|
|
||||||
# W1655: dict-keys-not-iterating
|
|
||||||
# W1656: dict-values-not-iterating
|
|
||||||
# W1657: deprecated-operator-function
|
|
||||||
# W1658: deprecated-urllib-function
|
|
||||||
# W1659: xreadlines-attribute
|
|
||||||
# W1660: deprecated-sys-function
|
|
||||||
# W1661: exception-escape
|
|
||||||
# W1662: comprehension-escape
|
|
||||||
enable=E1603,E1609,E1602,E1605,E1604,E1601,W1652,W1651,W1649,W1657,W1660,W1658,
|
|
||||||
W1659,W1623,W1622,W1620,W1621,W1645,W1624,W1648,W1625,W1611,W1662,W1661,
|
|
||||||
W1650,W1640,W1630,W1614,W1615,W1642,W1616,W1628,W1643,W1629,W1627,W1644,
|
|
||||||
W1617,W1601,W1602,W1603,W1604,W1605,W1654,W1655,W1656,W1619,W1606,W1607,
|
|
||||||
W1639,W1618,W1632,W1634,W1608,W1636,W1653,W1646,W1638,W1609,W1610,W1626,
|
|
||||||
W1633,W1647,W1635,W1612,W1613,W1637
|
|
||||||
|
|
||||||
# Disable the message, report, category or checker with the given id(s). You
|
# Disable the message, report, category or checker with the given id(s). You
|
||||||
# can either give multiple identifier separated by comma (,) or put this option
|
# can either give multiple identifier separated by comma (,) or put this option
|
||||||
# multiple time (only on the command line, not in the configuration file where
|
# multiple time (only on the command line, not in the configuration file where
|
||||||
# it should appear only once).
|
# it should appear only once).
|
||||||
# https://pylint.readthedocs.io/en/latest/user_guide/output.html#source-code-analysis-section
|
# https://pylint.readthedocs.io/en/latest/user_guide/output.html#source-code-analysis-section
|
||||||
# R detect Refactor for a "good practice" metric violation
|
# R detect Refactor for a "good practice" metric violation
|
||||||
# C detect Convention for coding standard violation
|
|
||||||
# W detect Warning for stylistic problems, or minor programming issues
|
# W detect Warning for stylistic problems, or minor programming issues
|
||||||
# W0102: dangerous-default-value
|
disable=R,fixme,
|
||||||
# W0105: pointless-string-statement
|
dangerous-default-value,
|
||||||
# W0107: unnecessary-pass
|
pointless-string-statement,
|
||||||
# W0123: eval-used
|
unnecessary-pass,
|
||||||
# W0201: attribute-defined-outside-init
|
eval-used,
|
||||||
# W0211: bad-staticmethod-argument
|
attribute-defined-outside-init,
|
||||||
# W0212: protected-access
|
bad-staticmethod-argument,
|
||||||
# W0221: arguments-differ
|
protected-access,
|
||||||
# W0223: abstract-method
|
arguments-differ,
|
||||||
# W0231: super-init-not-called
|
abstract-method,
|
||||||
# W0235: useless-super-delegation
|
super-init-not-called,
|
||||||
# W0311: bad-indentation
|
useless-super-delegation,
|
||||||
# W0402: deprecated-module
|
deprecated-module,
|
||||||
# W0603: global-statement
|
global-statement,
|
||||||
# W0612: unused-variable
|
unused-variable,
|
||||||
# W0613: unused-argument
|
unused-argument,
|
||||||
# W0621: redefined-outer-name
|
redefined-outer-name,
|
||||||
# W0622: redefined-builtin
|
redefined-builtin,
|
||||||
# W0631: undefined-loop-variable
|
undefined-loop-variable,
|
||||||
# W0703: broad-except
|
broad-except,
|
||||||
# W0706: try-except-raise
|
try-except-raise,
|
||||||
# W0707: raise-missing-from
|
raise-missing-from,
|
||||||
# W1113: keyword-arg-before-vararg
|
keyword-arg-before-vararg,
|
||||||
# W1201: logging-not-lazy
|
logging-not-lazy,
|
||||||
# W1401: anomalous-backslash-in-string
|
anomalous-backslash-in-string,
|
||||||
# W1406: redundant-u-string-prefix
|
redundant-u-string-prefix,
|
||||||
# W1514: unspecified-encoding
|
unspecified-encoding,
|
||||||
# W1618: no-absolute-import
|
no-absolute-import,
|
||||||
disable=C,R,fixme,
|
missing-class-docstring,
|
||||||
W0102,W0105,W0107,W0123,W0201,W0211,W0212,W0221,
|
missing-function-docstring,
|
||||||
W0223,W0231,W0235,W0311,W0402,W0603,W0612,W0613,
|
missing-module-docstring,
|
||||||
W0621,W0622,W0631,W0703,W0706,W0707,W1113,W1201,
|
consider-using-f-string,
|
||||||
W1401,W1406,W1514,W1618
|
invalid-name,
|
||||||
|
import-outside-toplevel,
|
||||||
|
too-many-lines,
|
||||||
|
consider-iterating-dictionary,
|
||||||
|
unnecessary-lambda-assignment
|
||||||
|
|
||||||
[REPORTS]
|
[REPORTS]
|
||||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2015 Huawei, Tech. Co,. Ltd.
|
# Copyright (c) 2015 Huawei, Tech. Co,. Ltd.
|
||||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -42,9 +42,9 @@ def setup_app(*args, **kwargs):
|
||||||
'errors': {
|
'errors': {
|
||||||
400: '/error',
|
400: '/error',
|
||||||
'__force_dict__': True
|
'__force_dict__': True
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pecan_config = pecan.configuration.conf_from_dict(config)
|
pecan_config = pecan.configuration.conf_from_dict(config)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
|
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
|
||||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -42,13 +42,13 @@ class RootController(object):
|
||||||
{
|
{
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"href": pecan.request.application_url + "/v1.0/"
|
"href": pecan.request.application_url + "/v1.0/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": "v1.0",
|
"id": "v1.0",
|
||||||
"updated": "2017-10-2"
|
"updated": "2017-10-2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@index.when(method='POST')
|
@index.when(method='POST')
|
||||||
@index.when(method='PUT')
|
@index.when(method='PUT')
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2017 Ericsson AB.
|
# Copyright (c) 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
# Copyright (c) 2017-2022, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -15,15 +15,15 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from pecan import expose
|
||||||
|
|
||||||
from dcmanager.api.controllers import restcomm
|
from dcmanager.api.controllers import restcomm
|
||||||
from dcmanager.api.policies import alarm_manager as alarm_manager_policy
|
from dcmanager.api.policies import alarm_manager as alarm_manager_policy
|
||||||
from dcmanager.api import policy
|
from dcmanager.api import policy
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from pecan import expose
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import http.client as httpclient
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
import http.client as httpclient
|
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import request
|
from pecan import request
|
||||||
|
@ -23,7 +24,6 @@ from pecan import request
|
||||||
from dcmanager.api.controllers import restcomm
|
from dcmanager.api.controllers import restcomm
|
||||||
from dcmanager.audit import rpcapi as audit_rpc_client
|
from dcmanager.audit import rpcapi as audit_rpc_client
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -150,7 +150,7 @@ class PeerGroupAssociationsController(restcomm.GenericPathController):
|
||||||
return False
|
return False
|
||||||
# Less than min or greater than max priority is not supported.
|
# Less than min or greater than max priority is not supported.
|
||||||
if val < MIN_PEER_GROUP_ASSOCIATION_PRIORITY or \
|
if val < MIN_PEER_GROUP_ASSOCIATION_PRIORITY or \
|
||||||
val > MAX_PEER_GROUP_ASSOCIATION_PRIORITY:
|
val > MAX_PEER_GROUP_ASSOCIATION_PRIORITY:
|
||||||
LOG.debug("Invalid Peer Group Priority out of support range: %s"
|
LOG.debug("Invalid Peer Group Priority out of support range: %s"
|
||||||
% peer_group_priority)
|
% peer_group_priority)
|
||||||
return False
|
return False
|
||||||
|
@ -187,7 +187,7 @@ class PeerGroupAssociationsController(restcomm.GenericPathController):
|
||||||
peer_group = db_api.subcloud_peer_group_get(context, peer_group_id)
|
peer_group = db_api.subcloud_peer_group_get(context, peer_group_id)
|
||||||
|
|
||||||
if peer_group_priority is not None and not \
|
if peer_group_priority is not None and not \
|
||||||
self._validate_peer_group_priority(peer_group_priority):
|
self._validate_peer_group_priority(peer_group_priority):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer_group_priority'))
|
_('Invalid peer_group_priority'))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -278,9 +278,12 @@ class PhasedSubcloudDeployController(object):
|
||||||
utils.get_management_gateway_address(payload)
|
utils.get_management_gateway_address(payload)
|
||||||
subcloud_dict['management-start-ip'] = \
|
subcloud_dict['management-start-ip'] = \
|
||||||
utils.get_management_start_address(payload)
|
utils.get_management_start_address(payload)
|
||||||
subcloud_dict['management-end-ip'] = utils.get_management_end_address(payload)
|
subcloud_dict['management-end-ip'] = \
|
||||||
|
utils.get_management_end_address(payload)
|
||||||
subcloud_dict['systemcontroller-gateway-ip'] = payload.get(
|
subcloud_dict['systemcontroller-gateway-ip'] = payload.get(
|
||||||
"systemcontroller_gateway_address", subcloud.systemcontroller_gateway_ip)
|
"systemcontroller_gateway_address",
|
||||||
|
subcloud.systemcontroller_gateway_ip
|
||||||
|
)
|
||||||
return subcloud_dict
|
return subcloud_dict
|
||||||
|
|
||||||
except RemoteError as e:
|
except RemoteError as e:
|
||||||
|
@ -425,10 +428,13 @@ class PhasedSubcloudDeployController(object):
|
||||||
# Consider the incoming release parameter only if install is one
|
# Consider the incoming release parameter only if install is one
|
||||||
# of the pending deploy states
|
# of the pending deploy states
|
||||||
if INSTALL in deploy_states_to_run:
|
if INSTALL in deploy_states_to_run:
|
||||||
unvalidated_sw_version = payload.get('release', subcloud.software_version)
|
unvalidated_sw_version = \
|
||||||
|
payload.get('release', subcloud.software_version)
|
||||||
else:
|
else:
|
||||||
LOG.debug('Disregarding release parameter for %s as installation is complete.'
|
LOG.debug(
|
||||||
% subcloud.name)
|
'Disregarding release parameter for %s as installation is complete.'
|
||||||
|
% subcloud.name
|
||||||
|
)
|
||||||
unvalidated_sw_version = subcloud.software_version
|
unvalidated_sw_version = subcloud.software_version
|
||||||
|
|
||||||
# get_sw_version will simply return back the passed
|
# get_sw_version will simply return back the passed
|
||||||
|
@ -474,9 +480,12 @@ class PhasedSubcloudDeployController(object):
|
||||||
utils.get_management_gateway_address(payload)
|
utils.get_management_gateway_address(payload)
|
||||||
subcloud_dict['management-start-ip'] = \
|
subcloud_dict['management-start-ip'] = \
|
||||||
utils.get_management_start_address(payload)
|
utils.get_management_start_address(payload)
|
||||||
subcloud_dict['management-end-ip'] = utils.get_management_end_address(payload)
|
subcloud_dict['management-end-ip'] = \
|
||||||
|
utils.get_management_end_address(payload)
|
||||||
subcloud_dict['systemcontroller-gateway-ip'] = payload.get(
|
subcloud_dict['systemcontroller-gateway-ip'] = payload.get(
|
||||||
"systemcontroller_gateway_address", subcloud.systemcontroller_gateway_ip)
|
"systemcontroller_gateway_address",
|
||||||
|
subcloud.systemcontroller_gateway_ip
|
||||||
|
)
|
||||||
return subcloud_dict
|
return subcloud_dict
|
||||||
except RemoteError as e:
|
except RemoteError as e:
|
||||||
pecan.abort(422, e.value)
|
pecan.abort(422, e.value)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022-2023 Wind River Systems, Inc.
|
# Copyright (c) 2022-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -98,7 +98,8 @@ class SubcloudBackupController(object):
|
||||||
if param in request.POST:
|
if param in request.POST:
|
||||||
file_item = request.POST[param]
|
file_item = request.POST[param]
|
||||||
file_item.file.seek(0, os.SEEK_SET)
|
file_item.file.seek(0, os.SEEK_SET)
|
||||||
data = utils.yaml_safe_load(file_item.file.read().decode('utf8'), param)
|
data = \
|
||||||
|
utils.yaml_safe_load(file_item.file.read().decode('utf8'), param)
|
||||||
payload.update({param: data})
|
payload.update({param: data})
|
||||||
del request.POST[param]
|
del request.POST[param]
|
||||||
|
|
||||||
|
@ -176,7 +177,8 @@ class SubcloudBackupController(object):
|
||||||
operation (string): Subcloud backup operation
|
operation (string): Subcloud backup operation
|
||||||
"""
|
"""
|
||||||
subclouds = request_entity.subclouds
|
subclouds = request_entity.subclouds
|
||||||
error_msg = _('Subcloud(s) must be in a valid state for backup %s.' % operation)
|
error_msg = _(
|
||||||
|
'Subcloud(s) must be in a valid state for backup %s.' % operation)
|
||||||
has_valid_subclouds = False
|
has_valid_subclouds = False
|
||||||
valid_subclouds = list()
|
valid_subclouds = list()
|
||||||
for subcloud in subclouds:
|
for subcloud in subclouds:
|
||||||
|
@ -361,8 +363,10 @@ class SubcloudBackupController(object):
|
||||||
payload.get('restore_values', {}).get('bootstrap_address', {})
|
payload.get('restore_values', {}).get('bootstrap_address', {})
|
||||||
|
|
||||||
if not isinstance(bootstrap_address_dict, dict):
|
if not isinstance(bootstrap_address_dict, dict):
|
||||||
pecan.abort(400, _('The bootstrap_address provided in restore_values '
|
pecan.abort(
|
||||||
'is in invalid format.'))
|
400, _('The bootstrap_address provided in restore_values '
|
||||||
|
'is in invalid format.')
|
||||||
|
)
|
||||||
|
|
||||||
restore_subclouds = self._validate_subclouds(
|
restore_subclouds = self._validate_subclouds(
|
||||||
request_entity, verb, bootstrap_address_dict)
|
request_entity, verb, bootstrap_address_dict)
|
||||||
|
@ -376,13 +380,16 @@ class SubcloudBackupController(object):
|
||||||
]
|
]
|
||||||
if subclouds_without_install_values:
|
if subclouds_without_install_values:
|
||||||
subclouds_str = ', '.join(subclouds_without_install_values)
|
subclouds_str = ', '.join(subclouds_without_install_values)
|
||||||
pecan.abort(400, _('The restore operation was requested with_install, '
|
pecan.abort(
|
||||||
'but the following subcloud(s) does not contain '
|
400, _('The restore operation was requested with_install, '
|
||||||
'install values: %s' % subclouds_str))
|
'but the following subcloud(s) does not contain '
|
||||||
|
'install values: %s' % subclouds_str)
|
||||||
|
)
|
||||||
# Confirm the requested or active load is still in dc-vault
|
# Confirm the requested or active load is still in dc-vault
|
||||||
payload['software_version'] = utils.get_sw_version(
|
payload['software_version'] = utils.get_sw_version(
|
||||||
payload.get('release'))
|
payload.get('release'))
|
||||||
matching_iso, err_msg = utils.get_matching_iso(payload['software_version'])
|
matching_iso, err_msg = \
|
||||||
|
utils.get_matching_iso(payload['software_version'])
|
||||||
if err_msg:
|
if err_msg:
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
pecan.abort(400, _(err_msg))
|
pecan.abort(400, _(err_msg))
|
||||||
|
@ -391,8 +398,10 @@ class SubcloudBackupController(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# local update to deploy_status - this is just for CLI response
|
# local update to deploy_status - this is just for CLI response
|
||||||
|
# pylint: disable-next=consider-using-enumerate
|
||||||
for i in range(len(restore_subclouds)):
|
for i in range(len(restore_subclouds)):
|
||||||
restore_subclouds[i].deploy_status = consts.DEPLOY_STATE_PRE_RESTORE
|
restore_subclouds[i].deploy_status = (
|
||||||
|
consts.DEPLOY_STATE_PRE_RESTORE)
|
||||||
message = self.dcmanager_rpc_client.restore_subcloud_backups(
|
message = self.dcmanager_rpc_client.restore_subcloud_backups(
|
||||||
context, payload)
|
context, payload)
|
||||||
return utils.subcloud_db_list_to_dict(restore_subclouds)
|
return utils.subcloud_db_list_to_dict(restore_subclouds)
|
||||||
|
|
|
@ -12,17 +12,16 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import http.client as httpclient
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
import http.client as httpclient
|
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import request
|
from pecan import request
|
||||||
|
@ -35,7 +34,6 @@ from dcmanager.common import consts
|
||||||
from dcmanager.common.i18n import _
|
from dcmanager.common.i18n import _
|
||||||
from dcmanager.common import utils
|
from dcmanager.common import utils
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -96,16 +94,19 @@ class SubcloudDeployController(object):
|
||||||
if len(missing_options) > 0:
|
if len(missing_options) > 0:
|
||||||
if ((consts.DEPLOY_PRESTAGE in missing_options and size != 1) or
|
if ((consts.DEPLOY_PRESTAGE in missing_options and size != 1) or
|
||||||
(consts.DEPLOY_PRESTAGE not in missing_options and size != 3)):
|
(consts.DEPLOY_PRESTAGE not in missing_options and size != 3)):
|
||||||
missing_str = str()
|
missing_str = str()
|
||||||
for missing in missing_options:
|
for missing in missing_options:
|
||||||
if missing is not consts.DEPLOY_PRESTAGE:
|
if missing is not consts.DEPLOY_PRESTAGE:
|
||||||
missing_str += '--%s ' % missing
|
missing_str += '--%s ' % missing
|
||||||
error_msg = "error: argument %s is required" % missing_str.rstrip()
|
error_msg = "error: argument %s is required" % missing_str.rstrip()
|
||||||
pecan.abort(httpclient.BAD_REQUEST, error_msg)
|
pecan.abort(httpclient.BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
deploy_dicts['software_version'] = utils.get_sw_version(request.POST.get('release'))
|
deploy_dicts['software_version'] = \
|
||||||
|
utils.get_sw_version(request.POST.get('release'))
|
||||||
|
|
||||||
dir_path = os.path.join(dccommon_consts.DEPLOY_DIR, deploy_dicts['software_version'])
|
dir_path = os.path.join(
|
||||||
|
dccommon_consts.DEPLOY_DIR, deploy_dicts['software_version']
|
||||||
|
)
|
||||||
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
if f not in request.POST:
|
if f not in request.POST:
|
||||||
continue
|
continue
|
||||||
|
@ -139,7 +140,9 @@ class SubcloudDeployController(object):
|
||||||
restcomm.extract_credentials_for_policy())
|
restcomm.extract_credentials_for_policy())
|
||||||
deploy_dicts = dict()
|
deploy_dicts = dict()
|
||||||
deploy_dicts['software_version'] = utils.get_sw_version(release)
|
deploy_dicts['software_version'] = utils.get_sw_version(release)
|
||||||
dir_path = os.path.join(dccommon_consts.DEPLOY_DIR, deploy_dicts['software_version'])
|
dir_path = os.path.join(
|
||||||
|
dccommon_consts.DEPLOY_DIR, deploy_dicts['software_version']
|
||||||
|
)
|
||||||
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
filename = None
|
filename = None
|
||||||
if os.path.isdir(dir_path):
|
if os.path.isdir(dir_path):
|
||||||
|
@ -159,10 +162,13 @@ class SubcloudDeployController(object):
|
||||||
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "delete", {},
|
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "delete", {},
|
||||||
restcomm.extract_credentials_for_policy())
|
restcomm.extract_credentials_for_policy())
|
||||||
|
|
||||||
is_prestage_images = request.params.get('prestage_images', '').lower() == 'true'
|
is_prestage_images = \
|
||||||
is_deployment_files = request.params.get('deployment_files', '').lower() == 'true'
|
request.params.get('prestage_images', '').lower() == 'true'
|
||||||
|
is_deployment_files = \
|
||||||
|
request.params.get('deployment_files', '').lower() == 'true'
|
||||||
|
|
||||||
dir_path = os.path.join(dccommon_consts.DEPLOY_DIR, utils.get_sw_version(release))
|
dir_path = \
|
||||||
|
os.path.join(dccommon_consts.DEPLOY_DIR, utils.get_sw_version(release))
|
||||||
if not os.path.isdir(dir_path):
|
if not os.path.isdir(dir_path):
|
||||||
pecan.abort(httpclient.NOT_FOUND,
|
pecan.abort(httpclient.NOT_FOUND,
|
||||||
_("Directory not found: %s" % dir_path))
|
_("Directory not found: %s" % dir_path))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2017 Ericsson AB.
|
# Copyright (c) 2017 Ericsson AB.
|
||||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
# Copyright (c) 2020-2022, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -15,12 +15,11 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import http.client as httpclient
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_db import exception as db_exc
|
from oslo_db import exception as db_exc
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_messaging import RemoteError
|
from oslo_messaging import RemoteError
|
||||||
|
|
||||||
import http.client as httpclient
|
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import request
|
from pecan import request
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import http.client as httpclient
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_db import exception as db_exc
|
from oslo_db import exception as db_exc
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_messaging import RemoteError
|
from oslo_messaging import RemoteError
|
||||||
|
|
||||||
import http.client as httpclient
|
|
||||||
import json
|
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import request
|
from pecan import request
|
||||||
import uuid
|
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
||||||
|
@ -140,7 +142,8 @@ class SubcloudPeerGroupsController(restcomm.GenericPathController):
|
||||||
if group is None:
|
if group is None:
|
||||||
pecan.abort(httpclient.NOT_FOUND, _("Subcloud Peer Group not found"))
|
pecan.abort(httpclient.NOT_FOUND, _("Subcloud Peer Group not found"))
|
||||||
if verb is None:
|
if verb is None:
|
||||||
subcloud_peer_group_dict = db_api.subcloud_peer_group_db_model_to_dict(group)
|
subcloud_peer_group_dict = \
|
||||||
|
db_api.subcloud_peer_group_db_model_to_dict(group)
|
||||||
return subcloud_peer_group_dict
|
return subcloud_peer_group_dict
|
||||||
elif verb == 'subclouds':
|
elif verb == 'subclouds':
|
||||||
# Return only the subclouds for this subcloud peer group
|
# Return only the subclouds for this subcloud peer group
|
||||||
|
@ -285,29 +288,31 @@ class SubcloudPeerGroupsController(restcomm.GenericPathController):
|
||||||
if (peer_group_name is not None and
|
if (peer_group_name is not None and
|
||||||
not utils.validate_name(peer_group_name,
|
not utils.validate_name(peer_group_name,
|
||||||
prohibited_name_list=['none'])):
|
prohibited_name_list=['none'])):
|
||||||
pecan.abort(httpclient.BAD_REQUEST, _('Invalid peer-group-name'))
|
pecan.abort(httpclient.BAD_REQUEST, _('Invalid peer-group-name'))
|
||||||
if (group_priority is not None and
|
if (group_priority is not None and
|
||||||
not self._validate_group_priority(group_priority)):
|
not self._validate_group_priority(group_priority)):
|
||||||
pecan.abort(httpclient.BAD_REQUEST, _('Invalid group-priority'))
|
pecan.abort(httpclient.BAD_REQUEST, _('Invalid group-priority'))
|
||||||
if group_state and not self._validate_group_state(group_state):
|
if group_state and not self._validate_group_state(group_state):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid group-state'))
|
_('Invalid group-state'))
|
||||||
if (max_subcloud_rehoming is not None and
|
if (max_subcloud_rehoming is not None and
|
||||||
not self._validate_max_subcloud_rehoming(max_subcloud_rehoming)):
|
not self._validate_max_subcloud_rehoming(max_subcloud_rehoming)):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid max-subcloud-rehoming'))
|
_('Invalid max-subcloud-rehoming'))
|
||||||
if (system_leader_id and
|
if (system_leader_id and
|
||||||
not self._validate_system_leader_id(system_leader_id)):
|
not self._validate_system_leader_id(system_leader_id)):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid system-leader-id'))
|
_('Invalid system-leader-id'))
|
||||||
if (system_leader_name is not None and
|
if (system_leader_name is not None and
|
||||||
not utils.validate_name(system_leader_name)):
|
not utils.validate_name(system_leader_name)):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid system-leader-name'))
|
_('Invalid system-leader-name'))
|
||||||
if (migration_status and
|
if (migration_status and
|
||||||
migration_status.lower() not in [consts.PEER_GROUP_MIGRATING,
|
migration_status.lower() not in [
|
||||||
consts.PEER_GROUP_MIGRATION_COMPLETE,
|
consts.PEER_GROUP_MIGRATING,
|
||||||
consts.PEER_GROUP_MIGRATION_NONE]):
|
consts.PEER_GROUP_MIGRATION_COMPLETE,
|
||||||
|
consts.PEER_GROUP_MIGRATION_NONE
|
||||||
|
]):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid migration_status'))
|
_('Invalid migration_status'))
|
||||||
|
|
||||||
|
@ -322,7 +327,9 @@ class SubcloudPeerGroupsController(restcomm.GenericPathController):
|
||||||
system_leader_id=system_leader_id,
|
system_leader_id=system_leader_id,
|
||||||
system_leader_name=system_leader_name,
|
system_leader_name=system_leader_name,
|
||||||
migration_status=migration_status)
|
migration_status=migration_status)
|
||||||
return db_api.subcloud_peer_group_db_model_to_dict(updated_peer_group)
|
return db_api.subcloud_peer_group_db_model_to_dict(
|
||||||
|
updated_peer_group
|
||||||
|
)
|
||||||
except RemoteError as e:
|
except RemoteError as e:
|
||||||
pecan.abort(httpclient.UNPROCESSABLE_ENTITY, e.value)
|
pecan.abort(httpclient.UNPROCESSABLE_ENTITY, e.value)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -427,31 +434,31 @@ class SubcloudPeerGroupsController(restcomm.GenericPathController):
|
||||||
payload = json.loads(request.body)
|
payload = json.loads(request.body)
|
||||||
if 'peer_uuid' not in payload:
|
if 'peer_uuid' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing peer_uuid' %
|
'%s, missing peer_uuid' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'peer_group_name' not in payload:
|
if 'peer_group_name' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing peer_group_name' %
|
'%s, missing peer_group_name' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'group_priority' not in payload:
|
if 'group_priority' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing group_priority' %
|
'%s, missing group_priority' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'group_state' not in payload:
|
if 'group_state' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing group_state' %
|
'%s, missing group_state' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'system_leader_id' not in payload:
|
if 'system_leader_id' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing system_leader_id' %
|
'%s, missing system_leader_id' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'system_leader_name' not in payload:
|
if 'system_leader_name' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing system_leader_name' %
|
'%s, missing system_leader_name' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
if 'migration_status' not in payload:
|
if 'migration_status' not in payload:
|
||||||
pecan.abort(400, _('Unable to audit peer group '
|
pecan.abort(400, _('Unable to audit peer group '
|
||||||
'%s, missing migration_status' %
|
'%s, missing migration_status' %
|
||||||
group.peer_group_name))
|
group.peer_group_name))
|
||||||
try:
|
try:
|
||||||
msg = self.rpc_client.peer_group_audit_notify(
|
msg = self.rpc_client.peer_group_audit_notify(
|
||||||
|
|
|
@ -17,29 +17,32 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
from requests_toolbelt.multipart import decoder
|
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import keyring
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import keyring
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_messaging import RemoteError
|
from oslo_messaging import RemoteError
|
||||||
import re
|
|
||||||
|
from requests_toolbelt.multipart import decoder
|
||||||
|
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import request
|
from pecan import request
|
||||||
|
|
||||||
|
from fm_api.constants import FM_ALARM_ID_UNSYNCHRONIZED_RESOURCE
|
||||||
|
|
||||||
|
from keystoneauth1 import exceptions as keystone_exceptions
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack.fm import FmClient
|
from dccommon.drivers.openstack.fm import FmClient
|
||||||
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
|
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
|
||||||
from dccommon import exceptions as dccommon_exceptions
|
from dccommon import exceptions as dccommon_exceptions
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as keystone_exceptions
|
|
||||||
|
|
||||||
from dcmanager.api.controllers import restcomm
|
from dcmanager.api.controllers import restcomm
|
||||||
from dcmanager.api.policies import subclouds as subclouds_policy
|
from dcmanager.api.policies import subclouds as subclouds_policy
|
||||||
from dcmanager.api import policy
|
from dcmanager.api import policy
|
||||||
|
@ -52,8 +55,6 @@ from dcmanager.common import utils
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
|
|
||||||
from dcmanager.rpc import client as rpc_client
|
from dcmanager.rpc import client as rpc_client
|
||||||
from fm_api.constants import FM_ALARM_ID_UNSYNCHRONIZED_RESOURCE
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -263,7 +264,9 @@ class SubcloudsController(object):
|
||||||
LOG.error(message)
|
LOG.error(message)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_deploy_config_sync_status(self, context, subcloud_name, keystone_client):
|
def _get_deploy_config_sync_status(
|
||||||
|
self, context, subcloud_name, keystone_client
|
||||||
|
):
|
||||||
"""Get the deploy configuration insync status of the subcloud """
|
"""Get the deploy configuration insync status of the subcloud """
|
||||||
detected_alarms = None
|
detected_alarms = None
|
||||||
try:
|
try:
|
||||||
|
@ -371,7 +374,7 @@ class SubcloudsController(object):
|
||||||
|
|
||||||
if subcloud_status:
|
if subcloud_status:
|
||||||
subcloud_status_list.append(
|
subcloud_status_list.append(
|
||||||
db_api.subcloud_endpoint_status_db_model_to_dict( # noqa
|
db_api.subcloud_endpoint_status_db_model_to_dict(
|
||||||
subcloud_status))
|
subcloud_status))
|
||||||
subcloud_list[-1][
|
subcloud_list[-1][
|
||||||
consts.ENDPOINT_SYNC_STATUS] = subcloud_status_list
|
consts.ENDPOINT_SYNC_STATUS] = subcloud_status_list
|
||||||
|
@ -380,7 +383,7 @@ class SubcloudsController(object):
|
||||||
subcloud_status_list = []
|
subcloud_status_list = []
|
||||||
if subcloud_status:
|
if subcloud_status:
|
||||||
subcloud_status_list.append(
|
subcloud_status_list.append(
|
||||||
db_api.subcloud_endpoint_status_db_model_to_dict( # noqa
|
db_api.subcloud_endpoint_status_db_model_to_dict(
|
||||||
subcloud_status))
|
subcloud_status))
|
||||||
|
|
||||||
subcloud_list.append(subcloud_dict)
|
subcloud_list.append(subcloud_dict)
|
||||||
|
@ -457,13 +460,15 @@ class SubcloudsController(object):
|
||||||
if detail is not None:
|
if detail is not None:
|
||||||
oam_floating_ip = "unavailable"
|
oam_floating_ip = "unavailable"
|
||||||
deploy_config_sync_status = "unknown"
|
deploy_config_sync_status = "unknown"
|
||||||
if subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE:
|
if (subcloud.availability_status ==
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE):
|
||||||
|
|
||||||
# Get the keystone client that will be used
|
# Get the keystone client that will be used
|
||||||
# for _get_deploy_config_sync_status and _get_oam_addresses
|
# for _get_deploy_config_sync_status and _get_oam_addresses
|
||||||
sc_ks_client = psd_common.get_ks_client(subcloud_region)
|
sc_ks_client = psd_common.get_ks_client(subcloud_region)
|
||||||
oam_addresses = self._get_oam_addresses(context,
|
oam_addresses = self._get_oam_addresses(
|
||||||
subcloud_region, sc_ks_client)
|
context, subcloud_region, sc_ks_client
|
||||||
|
)
|
||||||
if oam_addresses is not None:
|
if oam_addresses is not None:
|
||||||
oam_floating_ip = oam_addresses.oam_floating_ip
|
oam_floating_ip = oam_addresses.oam_floating_ip
|
||||||
|
|
||||||
|
@ -472,9 +477,11 @@ class SubcloudsController(object):
|
||||||
if deploy_config_state is not None:
|
if deploy_config_state is not None:
|
||||||
deploy_config_sync_status = deploy_config_state
|
deploy_config_sync_status = deploy_config_state
|
||||||
|
|
||||||
extra_details = {"oam_floating_ip": oam_floating_ip,
|
extra_details = {
|
||||||
"deploy_config_sync_status": deploy_config_sync_status,
|
"oam_floating_ip": oam_floating_ip,
|
||||||
"region_name": subcloud_region}
|
"deploy_config_sync_status": deploy_config_sync_status,
|
||||||
|
"region_name": subcloud_region
|
||||||
|
}
|
||||||
|
|
||||||
subcloud_dict.update(extra_details)
|
subcloud_dict.update(extra_details)
|
||||||
return subcloud_dict
|
return subcloud_dict
|
||||||
|
@ -594,26 +601,39 @@ class SubcloudsController(object):
|
||||||
# Rename the subcloud
|
# Rename the subcloud
|
||||||
new_subcloud_name = payload.get('name')
|
new_subcloud_name = payload.get('name')
|
||||||
if new_subcloud_name is not None:
|
if new_subcloud_name is not None:
|
||||||
# To be renamed the subcloud must be in unmanaged and valid deploy state
|
# To be renamed the subcloud must be in unmanaged and valid deploy
|
||||||
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED \
|
# state
|
||||||
or subcloud.deploy_status not in consts.STATES_FOR_SUBCLOUD_RENAME:
|
if (subcloud.management_state !=
|
||||||
msg = ('Subcloud %s must be unmanaged and in a valid deploy state '
|
dccommon_consts.MANAGEMENT_UNMANAGED or
|
||||||
'for the subcloud rename operation.' % subcloud.name)
|
subcloud.deploy_status not in
|
||||||
|
consts.STATES_FOR_SUBCLOUD_RENAME):
|
||||||
|
msg = (
|
||||||
|
'Subcloud %s must be unmanaged and in a valid deploy state '
|
||||||
|
'for the subcloud rename operation.' %
|
||||||
|
subcloud.name
|
||||||
|
)
|
||||||
pecan.abort(400, msg)
|
pecan.abort(400, msg)
|
||||||
|
|
||||||
# Validates new name
|
# Validates new name
|
||||||
if not utils.is_subcloud_name_format_valid(new_subcloud_name):
|
if not utils.is_subcloud_name_format_valid(new_subcloud_name):
|
||||||
pecan.abort(400, _("new name must contain alphabetic characters"))
|
pecan.abort(
|
||||||
|
400, _("new name must contain alphabetic characters")
|
||||||
|
)
|
||||||
|
|
||||||
# Checks if new subcloud name is the same as the current subcloud
|
# Checks if new subcloud name is the same as the current subcloud
|
||||||
if new_subcloud_name == subcloud.name:
|
if new_subcloud_name == subcloud.name:
|
||||||
pecan.abort(400, _('Provided subcloud name %s is the same as the '
|
pecan.abort(
|
||||||
'current subcloud %s. A different name is '
|
400, _('Provided subcloud name %s is the same as the '
|
||||||
'required to rename the subcloud' %
|
'current subcloud %s. A different name is '
|
||||||
(new_subcloud_name, subcloud.name)))
|
'required to rename the subcloud' %
|
||||||
|
(new_subcloud_name, subcloud.name))
|
||||||
|
)
|
||||||
|
|
||||||
|
error_msg = (
|
||||||
|
'Unable to rename subcloud %s with their region %s to %s' %
|
||||||
|
(subcloud.name, subcloud.region_name, new_subcloud_name)
|
||||||
|
)
|
||||||
|
|
||||||
error_msg = ('Unable to rename subcloud %s with their region %s to %s' %
|
|
||||||
(subcloud.name, subcloud.region_name, new_subcloud_name))
|
|
||||||
try:
|
try:
|
||||||
LOG.info("Renaming subcloud %s to: %s\n" % (subcloud.name,
|
LOG.info("Renaming subcloud %s to: %s\n" % (subcloud.name,
|
||||||
new_subcloud_name))
|
new_subcloud_name))
|
||||||
|
@ -720,12 +740,14 @@ class SubcloudsController(object):
|
||||||
if pgrp.group_priority > 0:
|
if pgrp.group_priority > 0:
|
||||||
pecan.abort(400, _("Cannot set the subcloud to a peer"
|
pecan.abort(400, _("Cannot set the subcloud to a peer"
|
||||||
" group with non-zero priority."))
|
" group with non-zero priority."))
|
||||||
elif not (subcloud.deploy_status in [consts.DEPLOY_STATE_DONE,
|
elif not (
|
||||||
consts.PRESTAGE_STATE_COMPLETE]
|
subcloud.deploy_status in [
|
||||||
and subcloud.management_state ==
|
consts.DEPLOY_STATE_DONE,
|
||||||
dccommon_consts.MANAGEMENT_MANAGED
|
consts.PRESTAGE_STATE_COMPLETE
|
||||||
and subcloud.availability_status ==
|
] and subcloud.management_state ==
|
||||||
dccommon_consts.AVAILABILITY_ONLINE):
|
dccommon_consts.MANAGEMENT_MANAGED
|
||||||
|
and subcloud.availability_status ==
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE):
|
||||||
pecan.abort(400, _("Only subclouds that are "
|
pecan.abort(400, _("Only subclouds that are "
|
||||||
"managed and online can be "
|
"managed and online can be "
|
||||||
"added to a peer group."))
|
"added to a peer group."))
|
||||||
|
@ -770,13 +792,15 @@ class SubcloudsController(object):
|
||||||
payload = psd_common.get_request_data(
|
payload = psd_common.get_request_data(
|
||||||
request, subcloud, SUBCLOUD_REDEPLOY_GET_FILE_CONTENTS)
|
request, subcloud, SUBCLOUD_REDEPLOY_GET_FILE_CONTENTS)
|
||||||
|
|
||||||
if (subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE or
|
if (subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE
|
||||||
subcloud.management_state == dccommon_consts.MANAGEMENT_MANAGED):
|
or subcloud.management_state ==
|
||||||
|
dccommon_consts.MANAGEMENT_MANAGED):
|
||||||
msg = _('Cannot re-deploy an online and/or managed subcloud')
|
msg = _('Cannot re-deploy an online and/or managed subcloud')
|
||||||
LOG.warning(msg)
|
LOG.warning(msg)
|
||||||
pecan.abort(400, msg)
|
pecan.abort(400, msg)
|
||||||
|
|
||||||
payload['software_version'] = utils.get_sw_version(payload.get('release'))
|
payload['software_version'] = \
|
||||||
|
utils.get_sw_version(payload.get('release'))
|
||||||
|
|
||||||
# Don't load previously stored bootstrap_values if they are present in
|
# Don't load previously stored bootstrap_values if they are present in
|
||||||
# the request, as this would override the already loaded values from it.
|
# the request, as this would override the already loaded values from it.
|
||||||
|
@ -831,8 +855,10 @@ class SubcloudsController(object):
|
||||||
'Please use /v1.0/subcloud-backup/restore'))
|
'Please use /v1.0/subcloud-backup/restore'))
|
||||||
|
|
||||||
elif verb == "reconfigure":
|
elif verb == "reconfigure":
|
||||||
pecan.abort(410, _('This API is deprecated. '
|
pecan.abort(
|
||||||
'Please use /v1.0/phased-subcloud-deploy/{subcloud}/configure'))
|
410, _('This API is deprecated. Please use '
|
||||||
|
'/v1.0/phased-subcloud-deploy/{subcloud}/configure')
|
||||||
|
)
|
||||||
|
|
||||||
elif verb == "reinstall":
|
elif verb == "reinstall":
|
||||||
pecan.abort(410, _('This API is deprecated. '
|
pecan.abort(410, _('This API is deprecated. '
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -132,7 +132,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
|
|
||||||
def _validate_manager_endpoint(self, endpoint):
|
def _validate_manager_endpoint(self, endpoint):
|
||||||
if not endpoint or len(endpoint) >= MAX_SYSTEM_PEER_MANAGER_ENDPOINT_LEN or \
|
if not endpoint or len(endpoint) >= MAX_SYSTEM_PEER_MANAGER_ENDPOINT_LEN or \
|
||||||
not endpoint.startswith(("http", "https")):
|
not endpoint.startswith(("http", "https")):
|
||||||
LOG.debug("Invalid manager_endpoint: %s" % endpoint)
|
LOG.debug("Invalid manager_endpoint: %s" % endpoint)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
@ -176,7 +176,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
|
|
||||||
# We do not support less than min or greater than max
|
# We do not support less than min or greater than max
|
||||||
if val < MIN_SYSTEM_PEER_HEARTBEAT_INTERVAL or \
|
if val < MIN_SYSTEM_PEER_HEARTBEAT_INTERVAL or \
|
||||||
val > MAX_SYSTEM_PEER_HEARTBEAT_INTERVAL:
|
val > MAX_SYSTEM_PEER_HEARTBEAT_INTERVAL:
|
||||||
LOG.debug("Invalid heartbeat_interval: %s" % heartbeat_interval)
|
LOG.debug("Invalid heartbeat_interval: %s" % heartbeat_interval)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
@ -193,15 +193,14 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
|
|
||||||
# We do not support less than min or greater than max
|
# We do not support less than min or greater than max
|
||||||
if val < MIN_SYSTEM_PEER_HEARTBEAT_FAILURE_THRESHOLD or \
|
if val < MIN_SYSTEM_PEER_HEARTBEAT_FAILURE_THRESHOLD or \
|
||||||
val > MAX_SYSTEM_PEER_HEARTBEAT_FAILURE_THRESHOLD:
|
val > MAX_SYSTEM_PEER_HEARTBEAT_FAILURE_THRESHOLD:
|
||||||
LOG.debug("Invalid heartbeat_failure_threshold: %s" %
|
LOG.debug("Invalid heartbeat_failure_threshold: %s" %
|
||||||
heartbeat_failure_threshold)
|
heartbeat_failure_threshold)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _validate_heartbeat_failure_policy(self, heartbeat_failure_policy):
|
def _validate_heartbeat_failure_policy(self, heartbeat_failure_policy):
|
||||||
if heartbeat_failure_policy not in \
|
if heartbeat_failure_policy not in SYSTEM_PEER_HEARTBEAT_FAILURE_POLICY_LIST:
|
||||||
SYSTEM_PEER_HEARTBEAT_FAILURE_POLICY_LIST:
|
|
||||||
LOG.debug("Invalid heartbeat_failure_policy: %s" %
|
LOG.debug("Invalid heartbeat_failure_policy: %s" %
|
||||||
heartbeat_failure_policy)
|
heartbeat_failure_policy)
|
||||||
return False
|
return False
|
||||||
|
@ -219,7 +218,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
|
|
||||||
# We do not support less than min or greater than max
|
# We do not support less than min or greater than max
|
||||||
if val < MIN_SYSTEM_PEER_HEARTBEAT_MAINTENACE_TIMEOUT or \
|
if val < MIN_SYSTEM_PEER_HEARTBEAT_MAINTENACE_TIMEOUT or \
|
||||||
val > MAX_SYSTEM_PEER_HEARTBEAT_MAINTENACE_TIMEOUT:
|
val > MAX_SYSTEM_PEER_HEARTBEAT_MAINTENACE_TIMEOUT:
|
||||||
LOG.debug("Invalid heartbeat_maintenance_timeout: %s" %
|
LOG.debug("Invalid heartbeat_maintenance_timeout: %s" %
|
||||||
heartbeat_maintenance_timeout)
|
heartbeat_maintenance_timeout)
|
||||||
return False
|
return False
|
||||||
|
@ -287,7 +286,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
payload.get('heartbeat_failure_threshold')
|
payload.get('heartbeat_failure_threshold')
|
||||||
if heartbeat_failure_threshold is not None:
|
if heartbeat_failure_threshold is not None:
|
||||||
if not self._validate_heartbeat_failure_threshold(
|
if not self._validate_heartbeat_failure_threshold(
|
||||||
heartbeat_failure_threshold):
|
heartbeat_failure_threshold):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_failure_threshold'))
|
_('Invalid peer heartbeat_failure_threshold'))
|
||||||
kwargs['heartbeat_failure_threshold'] = heartbeat_failure_threshold
|
kwargs['heartbeat_failure_threshold'] = heartbeat_failure_threshold
|
||||||
|
@ -295,7 +294,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
heartbeat_failure_policy = payload.get('heartbeat_failure_policy')
|
heartbeat_failure_policy = payload.get('heartbeat_failure_policy')
|
||||||
if heartbeat_failure_policy:
|
if heartbeat_failure_policy:
|
||||||
if not self._validate_heartbeat_failure_policy(
|
if not self._validate_heartbeat_failure_policy(
|
||||||
heartbeat_failure_policy):
|
heartbeat_failure_policy):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_failure_policy'))
|
_('Invalid peer heartbeat_failure_policy'))
|
||||||
kwargs['heartbeat_failure_policy'] = heartbeat_failure_policy
|
kwargs['heartbeat_failure_policy'] = heartbeat_failure_policy
|
||||||
|
@ -304,7 +303,7 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
payload.get('heartbeat_maintenance_timeout')
|
payload.get('heartbeat_maintenance_timeout')
|
||||||
if heartbeat_maintenance_timeout is not None:
|
if heartbeat_maintenance_timeout is not None:
|
||||||
if not self._validate_heartbeat_maintenance_timeout(
|
if not self._validate_heartbeat_maintenance_timeout(
|
||||||
heartbeat_maintenance_timeout):
|
heartbeat_maintenance_timeout):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_maintenance_timeout'))
|
_('Invalid peer heartbeat_maintenance_timeout'))
|
||||||
kwargs['heartbeat_maintenance_timeout'] = \
|
kwargs['heartbeat_maintenance_timeout'] = \
|
||||||
|
@ -419,19 +418,19 @@ class SystemPeersController(restcomm.GenericPathController):
|
||||||
|
|
||||||
if heartbeat_failure_threshold:
|
if heartbeat_failure_threshold:
|
||||||
if not self._validate_heartbeat_failure_threshold(
|
if not self._validate_heartbeat_failure_threshold(
|
||||||
heartbeat_failure_threshold):
|
heartbeat_failure_threshold):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_failure_threshold'))
|
_('Invalid peer heartbeat_failure_threshold'))
|
||||||
|
|
||||||
if heartbeat_failure_policy:
|
if heartbeat_failure_policy:
|
||||||
if not self._validate_heartbeat_failure_policy(
|
if not self._validate_heartbeat_failure_policy(
|
||||||
heartbeat_failure_policy):
|
heartbeat_failure_policy):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_failure_policy'))
|
_('Invalid peer heartbeat_failure_policy'))
|
||||||
|
|
||||||
if heartbeat_maintenance_timeout:
|
if heartbeat_maintenance_timeout:
|
||||||
if not self._validate_heartbeat_maintenance_timeout(
|
if not self._validate_heartbeat_maintenance_timeout(
|
||||||
heartbeat_maintenance_timeout):
|
heartbeat_maintenance_timeout):
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_('Invalid peer heartbeat_maintenance_timeout'))
|
_('Invalid peer heartbeat_maintenance_timeout'))
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:alarm_manager:%s'
|
POLICY_ROOT = 'dc_api:alarm_manager:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:peer_group_associations:%s'
|
POLICY_ROOT = 'dc_api:peer_group_associations:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:phased_subcloud_deploy:%s'
|
POLICY_ROOT = 'dc_api:phased_subcloud_deploy:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:subcloud_backup:%s'
|
POLICY_ROOT = 'dc_api:subcloud_backup:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022-2023 Wind River Systems, Inc.
|
# Copyright (c) 2022-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:subcloud_deploy:%s'
|
POLICY_ROOT = 'dc_api:subcloud_deploy:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:subcloud_groups:%s'
|
POLICY_ROOT = 'dc_api:subcloud_groups:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:subcloud_peer_groups:%s'
|
POLICY_ROOT = 'dc_api:subcloud_peer_groups:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022-2024 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:subclouds:%s'
|
POLICY_ROOT = 'dc_api:subclouds:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:sw_update_options:%s'
|
POLICY_ROOT = 'dc_api:sw_update_options:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:sw_update_strategy:%s'
|
POLICY_ROOT = 'dc_api:sw_update_strategy:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dcmanager.api.policies import base
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from dcmanager.api.policies import base
|
||||||
|
|
||||||
POLICY_ROOT = 'dc_api:system_peers:%s'
|
POLICY_ROOT = 'dc_api:system_peers:%s'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,18 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
"""Policy Engine For DC."""
|
"""Policy Engine For DC."""
|
||||||
|
|
||||||
from dcmanager.api import policies as controller_policies
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
|
from dcmanager.api import policies as controller_policies
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
_ENFORCER = None
|
_ENFORCER = None
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
|
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,10 +42,10 @@ class AlarmAggregation(object):
|
||||||
LOG.error('Failed to update alarms for %s error: %s' % (name, e))
|
LOG.error('Failed to update alarms for %s error: %s' % (name, e))
|
||||||
|
|
||||||
def _set_cloud_status(self, alarm_dict):
|
def _set_cloud_status(self, alarm_dict):
|
||||||
if (alarm_dict.get('critical_alarms') > 0):
|
if alarm_dict.get('critical_alarms') > 0:
|
||||||
status = consts.ALARM_CRITICAL_STATUS
|
status = consts.ALARM_CRITICAL_STATUS
|
||||||
elif (alarm_dict.get('major_alarms') > 0) or\
|
elif (alarm_dict.get('major_alarms') > 0) or \
|
||||||
(alarm_dict.get('minor_alarms') > 0):
|
(alarm_dict.get('minor_alarms') > 0):
|
||||||
status = consts.ALARM_DEGRADED_STATUS
|
status = consts.ALARM_DEGRADED_STATUS
|
||||||
else:
|
else:
|
||||||
status = consts.ALARM_OK_STATUS
|
status = consts.ALARM_OK_STATUS
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021-2023 Wind River Systems, Inc.
|
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -31,7 +32,9 @@ class Auditor(object):
|
||||||
|
|
||||||
def set_subcloud_endpoint_in_sync(self, sc_name, sc_region):
|
def set_subcloud_endpoint_in_sync(self, sc_name, sc_region):
|
||||||
"""Set the endpoint sync status of this subcloud to be in sync"""
|
"""Set the endpoint sync status of this subcloud to be in sync"""
|
||||||
self._set_subcloud_sync_status(sc_name, sc_region, dccommon_consts.SYNC_STATUS_IN_SYNC)
|
self._set_subcloud_sync_status(
|
||||||
|
sc_name, sc_region, dccommon_consts.SYNC_STATUS_IN_SYNC
|
||||||
|
)
|
||||||
|
|
||||||
def set_subcloud_endpoint_out_of_sync(self, sc_name, sc_region):
|
def set_subcloud_endpoint_out_of_sync(self, sc_name, sc_region):
|
||||||
"""Set the endpoint sync status of this subcloud to be out of sync"""
|
"""Set the endpoint sync status of this subcloud to be out of sync"""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -112,16 +112,12 @@ class FirmwareAudit(object):
|
||||||
# Filter images which have been applied on RegionOne
|
# Filter images which have been applied on RegionOne
|
||||||
for image in local_device_images:
|
for image in local_device_images:
|
||||||
if image.applied:
|
if image.applied:
|
||||||
filtered_images.append(FirmwareAuditData(image.bitstream_type,
|
filtered_images.append(FirmwareAuditData(
|
||||||
image.bitstream_id,
|
image.bitstream_type, image.bitstream_id, image.bmc,
|
||||||
image.bmc,
|
image.retimer_included, image.key_signature,
|
||||||
image.retimer_included,
|
image.revoke_key_id, image.applied, image.pci_vendor,
|
||||||
image.key_signature,
|
image.pci_device, image.applied_labels
|
||||||
image.revoke_key_id,
|
))
|
||||||
image.applied,
|
|
||||||
image.pci_vendor,
|
|
||||||
image.pci_device,
|
|
||||||
image.applied_labels))
|
|
||||||
LOG.debug("RegionOne applied_images: %s" % filtered_images)
|
LOG.debug("RegionOne applied_images: %s" % filtered_images)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception('Cannot retrieve device images for RegionOne, '
|
LOG.exception('Cannot retrieve device images for RegionOne, '
|
||||||
|
@ -133,24 +129,33 @@ class FirmwareAudit(object):
|
||||||
label_key, label_value):
|
label_key, label_value):
|
||||||
for device_label in subcloud_host_device_label_list:
|
for device_label in subcloud_host_device_label_list:
|
||||||
if device_label.pcidevice_uuid and \
|
if device_label.pcidevice_uuid and \
|
||||||
device_uuid == device_label.pcidevice_uuid and \
|
device_uuid == device_label.pcidevice_uuid and \
|
||||||
label_key == device_label.label_key and \
|
label_key == device_label.label_key and \
|
||||||
label_value == device_label.label_value:
|
label_value == device_label.label_value:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _check_image_match(self,
|
def _check_image_match(self, subcloud_image, system_controller_image):
|
||||||
subcloud_image,
|
if (
|
||||||
system_controller_image):
|
(
|
||||||
if ((system_controller_image.bitstream_type == consts.BITSTREAM_TYPE_ROOT_KEY and
|
system_controller_image.bitstream_type ==
|
||||||
system_controller_image.key_signature == subcloud_image.key_signature) or
|
consts.BITSTREAM_TYPE_ROOT_KEY and
|
||||||
(system_controller_image.bitstream_type == consts.BITSTREAM_TYPE_FUNCTIONAL and
|
system_controller_image.key_signature == subcloud_image.key_signature
|
||||||
system_controller_image.bitstream_id == subcloud_image.bitstream_id and
|
) or (
|
||||||
system_controller_image.bmc == subcloud_image.bmc and
|
system_controller_image.bitstream_type ==
|
||||||
system_controller_image.retimer_included == subcloud_image.retimer_included) or
|
consts.BITSTREAM_TYPE_FUNCTIONAL and
|
||||||
(system_controller_image.bitstream_type == consts.BITSTREAM_TYPE_KEY_REVOCATION and
|
system_controller_image.bitstream_id ==
|
||||||
system_controller_image.revoke_key_id == subcloud_image.revoke_key_id)):
|
subcloud_image.bitstream_id and
|
||||||
return True
|
system_controller_image.bmc == subcloud_image.bmc and
|
||||||
|
system_controller_image.retimer_included ==
|
||||||
|
subcloud_image.retimer_included
|
||||||
|
) or (
|
||||||
|
system_controller_image.bitstream_type ==
|
||||||
|
consts.BITSTREAM_TYPE_KEY_REVOCATION and
|
||||||
|
system_controller_image.revoke_key_id == subcloud_image.revoke_key_id
|
||||||
|
)
|
||||||
|
):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _check_subcloud_device_has_image(self,
|
def _check_subcloud_device_has_image(self,
|
||||||
|
@ -197,7 +202,7 @@ class FirmwareAudit(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if image.pci_vendor == device.pvendor_id and \
|
if image.pci_vendor == device.pvendor_id and \
|
||||||
image.pci_device == device.pdevice_id:
|
image.pci_device == device.pdevice_id:
|
||||||
device_image_state = None
|
device_image_state = None
|
||||||
subcloud_image = None
|
subcloud_image = None
|
||||||
for device_image_state_obj in subcloud_device_image_states:
|
for device_image_state_obj in subcloud_device_image_states:
|
||||||
|
@ -220,7 +225,7 @@ class FirmwareAudit(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if device_image_state and \
|
if device_image_state and \
|
||||||
device_image_state.status != "completed":
|
device_image_state.status != "completed":
|
||||||
# If device image state is not completed it means
|
# If device image state is not completed it means
|
||||||
# that the image has not been written to the device yet
|
# that the image has not been written to the device yet
|
||||||
return False
|
return False
|
||||||
|
@ -303,12 +308,10 @@ class FirmwareAudit(object):
|
||||||
for image in audit_data:
|
for image in audit_data:
|
||||||
# audit_data will be a dict from passing through RPC, so objectify
|
# audit_data will be a dict from passing through RPC, so objectify
|
||||||
image = FirmwareAuditData.from_dict(image)
|
image = FirmwareAuditData.from_dict(image)
|
||||||
proceed = self._check_subcloud_device_has_image(subcloud_name,
|
proceed = self._check_subcloud_device_has_image(
|
||||||
sysinv_client,
|
subcloud_name, sysinv_client, image, enabled_host_device_list,
|
||||||
image,
|
subcloud_device_image_states, subcloud_device_label_list
|
||||||
enabled_host_device_list,
|
)
|
||||||
subcloud_device_image_states,
|
|
||||||
subcloud_device_label_list)
|
|
||||||
if not proceed:
|
if not proceed:
|
||||||
out_of_sync = True
|
out_of_sync = True
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021-2023 Wind River Systems, Inc.
|
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -114,7 +114,7 @@ class KubeRootcaUpdateAudit(Auditor):
|
||||||
# the distributed cloud and the subcloud running on old software
|
# the distributed cloud and the subcloud running on old software
|
||||||
# version that cannot search for the k8s root CA cert id.
|
# version that cannot search for the k8s root CA cert id.
|
||||||
if dccommon_utils.is_centos(subcloud.software_version) or \
|
if dccommon_utils.is_centos(subcloud.software_version) or \
|
||||||
not subcloud.rehomed:
|
not subcloud.rehomed:
|
||||||
self.subcloud_audit_alarm_based(subcloud_name, subcloud_region,
|
self.subcloud_audit_alarm_based(subcloud_name, subcloud_region,
|
||||||
session)
|
session)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as keystone_exceptions
|
from keystoneauth1 import exceptions as keystone_exceptions
|
||||||
|
@ -25,7 +24,6 @@ from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
||||||
from dccommon.drivers.openstack import software_v1
|
from dccommon.drivers.openstack import software_v1
|
||||||
from dccommon.drivers.openstack.software_v1 import SoftwareClient
|
from dccommon.drivers.openstack.software_v1 import SoftwareClient
|
||||||
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
|
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
|
||||||
|
|
||||||
from dcmanager.common import utils
|
from dcmanager.common import utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -155,7 +153,8 @@ class PatchAudit(object):
|
||||||
m_os_ks_client = OpenStackDriver(
|
m_os_ks_client = OpenStackDriver(
|
||||||
region_name=dccommon_consts.DEFAULT_REGION_NAME,
|
region_name=dccommon_consts.DEFAULT_REGION_NAME,
|
||||||
region_clients=None).keystone_client
|
region_clients=None).keystone_client
|
||||||
patching_endpoint = m_os_ks_client.endpoint_cache.get_endpoint('patching')
|
patching_endpoint = m_os_ks_client.endpoint_cache.get_endpoint(
|
||||||
|
'patching')
|
||||||
sysinv_endpoint = m_os_ks_client.endpoint_cache.get_endpoint('sysinv')
|
sysinv_endpoint = m_os_ks_client.endpoint_cache.get_endpoint('sysinv')
|
||||||
patching_client = PatchingClient(
|
patching_client = PatchingClient(
|
||||||
dccommon_consts.DEFAULT_REGION_NAME, m_os_ks_client.session,
|
dccommon_consts.DEFAULT_REGION_NAME, m_os_ks_client.session,
|
||||||
|
@ -195,10 +194,14 @@ class PatchAudit(object):
|
||||||
return PatchAuditData(regionone_patches, applied_patch_ids,
|
return PatchAuditData(regionone_patches, applied_patch_ids,
|
||||||
committed_patch_ids, regionone_software_version)
|
committed_patch_ids, regionone_software_version)
|
||||||
|
|
||||||
def subcloud_audit(self, subcloud_name, subcloud_region, audit_data, software_audit_data,
|
def subcloud_audit(
|
||||||
do_load_audit):
|
self, subcloud_name, subcloud_region, audit_data, software_audit_data,
|
||||||
|
do_load_audit
|
||||||
|
):
|
||||||
if software_audit_data:
|
if software_audit_data:
|
||||||
self.subcloud_software_audit(subcloud_name, subcloud_region, software_audit_data)
|
self.subcloud_software_audit(
|
||||||
|
subcloud_name, subcloud_region, software_audit_data
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.subcloud_patch_audit(subcloud_name, subcloud_region, audit_data,
|
self.subcloud_patch_audit(subcloud_name, subcloud_region, audit_data,
|
||||||
do_load_audit)
|
do_load_audit)
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import eventlet
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from tsconfig.tsconfig import CONFIG_PATH
|
|
||||||
|
|
||||||
|
import eventlet
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from tsconfig.tsconfig import CONFIG_PATH
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack import sysinv_v1
|
from dccommon.drivers.openstack import sysinv_v1
|
||||||
|
|
||||||
from dcmanager.audit import firmware_audit
|
from dcmanager.audit import firmware_audit
|
||||||
from dcmanager.audit import kube_rootca_update_audit
|
from dcmanager.audit import kube_rootca_update_audit
|
||||||
from dcmanager.audit import kubernetes_audit
|
from dcmanager.audit import kubernetes_audit
|
||||||
|
@ -81,7 +79,8 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
super(SubcloudAuditManager, self).__init__(
|
super(SubcloudAuditManager, self).__init__(
|
||||||
service_name="subcloud_audit_manager")
|
service_name="subcloud_audit_manager")
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
self.audit_worker_rpc_client = dcmanager_audit_rpc_client.ManagerAuditWorkerClient()
|
self.audit_worker_rpc_client = (
|
||||||
|
dcmanager_audit_rpc_client.ManagerAuditWorkerClient())
|
||||||
# Number of audits since last subcloud state update
|
# Number of audits since last subcloud state update
|
||||||
self.audit_count = SUBCLOUD_STATE_UPDATE_ITERATIONS - 2
|
self.audit_count = SUBCLOUD_STATE_UPDATE_ITERATIONS - 2
|
||||||
# Number of patch audits
|
# Number of patch audits
|
||||||
|
@ -100,11 +99,13 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
def _add_missing_endpoints(self):
|
def _add_missing_endpoints(self):
|
||||||
# Update this flag file based on the most recent new endpoint
|
# Update this flag file based on the most recent new endpoint
|
||||||
file_path_list = []
|
file_path_list = []
|
||||||
file_path_list.append(os.path.join(CONFIG_PATH,
|
file_path_list.append(os.path.join(
|
||||||
'.kube_rootca_update_endpoint_added'))
|
CONFIG_PATH, '.kube_rootca_update_endpoint_added')
|
||||||
|
)
|
||||||
if cfg.CONF.use_usm:
|
if cfg.CONF.use_usm:
|
||||||
file_path_list.append(os.path.join(CONFIG_PATH,
|
file_path_list.append(os.path.join(
|
||||||
'.usm_endpoint_added'))
|
CONFIG_PATH, '.usm_endpoint_added')
|
||||||
|
)
|
||||||
for file_path in file_path_list:
|
for file_path in file_path_list:
|
||||||
# If file exists on the controller, all the endpoints have been
|
# If file exists on the controller, all the endpoints have been
|
||||||
# added to DB since last time an endpoint was added
|
# added to DB since last time an endpoint was added
|
||||||
|
@ -118,7 +119,9 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
subcloud.id)
|
subcloud.id)
|
||||||
# Use set difference to find missing endpoints
|
# Use set difference to find missing endpoints
|
||||||
if cfg.CONF.use_usm:
|
if cfg.CONF.use_usm:
|
||||||
endpoint_type_set = set(dccommon_consts.ENDPOINT_TYPES_LIST_USM)
|
endpoint_type_set = set(
|
||||||
|
dccommon_consts.ENDPOINT_TYPES_LIST_USM
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
endpoint_type_set = set(dccommon_consts.ENDPOINT_TYPES_LIST)
|
endpoint_type_set = set(dccommon_consts.ENDPOINT_TYPES_LIST)
|
||||||
subcloud_set = set()
|
subcloud_set = set()
|
||||||
|
@ -265,17 +268,18 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
SubcloudAuditManager.force_patch_audit):
|
SubcloudAuditManager.force_patch_audit):
|
||||||
LOG.info("Trigger load audit")
|
LOG.info("Trigger load audit")
|
||||||
audit_load = True
|
audit_load = True
|
||||||
if (self.patch_audit_count % 4 == 1):
|
if self.patch_audit_count % 4 == 1:
|
||||||
LOG.info("Trigger firmware audit")
|
LOG.info("Trigger firmware audit")
|
||||||
audit_firmware = True
|
audit_firmware = True
|
||||||
# Reset force_firmware_audit only when firmware audit has been fired
|
# Reset force_firmware_audit only when firmware audit has been fired
|
||||||
SubcloudAuditManager.reset_force_firmware_audit()
|
SubcloudAuditManager.reset_force_firmware_audit()
|
||||||
if (self.patch_audit_count % KUBERNETES_AUDIT_RATE == 1):
|
if self.patch_audit_count % KUBERNETES_AUDIT_RATE == 1:
|
||||||
LOG.info("Trigger kubernetes audit")
|
LOG.info("Trigger kubernetes audit")
|
||||||
audit_kubernetes = True
|
audit_kubernetes = True
|
||||||
# Reset force_kubernetes_audit only when kubernetes audit has been fired
|
# Reset force_kubernetes_audit only when kubernetes audit has been
|
||||||
|
# fired
|
||||||
SubcloudAuditManager.reset_force_kubernetes_audit()
|
SubcloudAuditManager.reset_force_kubernetes_audit()
|
||||||
if (self.patch_audit_count % KUBE_ROOTCA_UPDATE_AUDIT_RATE == 1):
|
if self.patch_audit_count % KUBE_ROOTCA_UPDATE_AUDIT_RATE == 1:
|
||||||
LOG.info("Trigger kube rootca update audit")
|
LOG.info("Trigger kube rootca update audit")
|
||||||
audit_kube_rootca_updates = True
|
audit_kube_rootca_updates = True
|
||||||
# Reset force_kube_rootca_update_audit only if audit is fired
|
# Reset force_kube_rootca_update_audit only if audit is fired
|
||||||
|
@ -319,7 +323,8 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
if audit_patch:
|
if audit_patch:
|
||||||
if cfg.CONF.use_usm:
|
if cfg.CONF.use_usm:
|
||||||
# Query RegionOne releases
|
# Query RegionOne releases
|
||||||
software_audit_data = self.patch_audit.get_software_regionone_audit_data()
|
software_audit_data = \
|
||||||
|
self.patch_audit.get_software_regionone_audit_data()
|
||||||
else:
|
else:
|
||||||
# Query RegionOne patches and software version
|
# Query RegionOne patches and software version
|
||||||
patch_audit_data = self.patch_audit.get_regionone_audit_data()
|
patch_audit_data = self.patch_audit.get_regionone_audit_data()
|
||||||
|
@ -396,7 +401,8 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
self.context, last_audit_fixup_threshold)
|
self.context, last_audit_fixup_threshold)
|
||||||
end = datetime.datetime.utcnow()
|
end = datetime.datetime.utcnow()
|
||||||
if num_fixed > 0:
|
if num_fixed > 0:
|
||||||
LOG.info('Fixed up subcloud audit timestamp for %s subclouds.' % num_fixed)
|
LOG.info(
|
||||||
|
'Fixed up subcloud audit timestamp for %s subclouds.' % num_fixed)
|
||||||
LOG.info('Fixup took %s seconds' % (end - start))
|
LOG.info('Fixup took %s seconds' % (end - start))
|
||||||
|
|
||||||
subcloud_ids = []
|
subcloud_ids = []
|
||||||
|
@ -452,7 +458,8 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
kube_rootca_update_audit_data))
|
kube_rootca_update_audit_data))
|
||||||
|
|
||||||
# We want a chunksize of at least 1 so add the number of workers.
|
# We want a chunksize of at least 1 so add the number of workers.
|
||||||
chunksize = (len(subcloud_audits) + CONF.audit_worker_workers) // CONF.audit_worker_workers
|
chunksize = (len(subcloud_audits) + CONF.audit_worker_workers) // (
|
||||||
|
CONF.audit_worker_workers)
|
||||||
for audit in subcloud_audits:
|
for audit in subcloud_audits:
|
||||||
subcloud_ids.append(audit.subcloud_id)
|
subcloud_ids.append(audit.subcloud_id)
|
||||||
if len(subcloud_ids) == chunksize:
|
if len(subcloud_ids) == chunksize:
|
||||||
|
@ -466,7 +473,10 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
do_openstack_audit,
|
do_openstack_audit,
|
||||||
kube_rootca_update_audit_data,
|
kube_rootca_update_audit_data,
|
||||||
software_audit_data)
|
software_audit_data)
|
||||||
LOG.debug('Sent subcloud audit request message for subclouds: %s' % subcloud_ids)
|
LOG.debug(
|
||||||
|
'Sent subcloud audit request message for subclouds: %s' %
|
||||||
|
subcloud_ids
|
||||||
|
)
|
||||||
subcloud_ids = []
|
subcloud_ids = []
|
||||||
if len(subcloud_ids) > 0:
|
if len(subcloud_ids) > 0:
|
||||||
# We've got a partial batch...send it off for processing.
|
# We've got a partial batch...send it off for processing.
|
||||||
|
@ -479,6 +489,9 @@ class SubcloudAuditManager(manager.Manager):
|
||||||
do_openstack_audit,
|
do_openstack_audit,
|
||||||
kube_rootca_update_audit_data,
|
kube_rootca_update_audit_data,
|
||||||
software_audit_data)
|
software_audit_data)
|
||||||
LOG.debug('Sent final subcloud audit request message for subclouds: %s' % subcloud_ids)
|
LOG.debug(
|
||||||
|
'Sent final subcloud audit request message for subclouds: %s' %
|
||||||
|
subcloud_ids
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
LOG.debug('Done sending audit request messages.')
|
LOG.debug('Done sending audit request messages.')
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -23,7 +22,6 @@ from oslo_log import log as logging
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
||||||
|
|
||||||
from dcmanager.audit import alarm_aggregation
|
from dcmanager.audit import alarm_aggregation
|
||||||
from dcmanager.audit import firmware_audit
|
from dcmanager.audit import firmware_audit
|
||||||
from dcmanager.audit import kube_rootca_update_audit
|
from dcmanager.audit import kube_rootca_update_audit
|
||||||
|
@ -131,8 +129,9 @@ class SubcloudAuditWorkerManager(manager.Manager):
|
||||||
subcloud.deploy_status)) or (
|
subcloud.deploy_status)) or (
|
||||||
(subcloud.deploy_status in [
|
(subcloud.deploy_status in [
|
||||||
consts.DEPLOY_STATE_INSTALLING,
|
consts.DEPLOY_STATE_INSTALLING,
|
||||||
consts.DEPLOY_STATE_REHOME_PENDING]) and
|
consts.DEPLOY_STATE_REHOME_PENDING])
|
||||||
subcloud.availability_status == dccommon_consts.AVAILABILITY_OFFLINE):
|
and subcloud.availability_status ==
|
||||||
|
dccommon_consts.AVAILABILITY_OFFLINE):
|
||||||
LOG.debug("Skip subcloud %s audit, deploy_status: %s" %
|
LOG.debug("Skip subcloud %s audit, deploy_status: %s" %
|
||||||
(subcloud.name, subcloud.deploy_status))
|
(subcloud.name, subcloud.deploy_status))
|
||||||
# This DB API call will set the "audit_finished_at" timestamp
|
# This DB API call will set the "audit_finished_at" timestamp
|
||||||
|
@ -399,7 +398,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
|
||||||
|
|
||||||
except keystone_exceptions.NotFound:
|
except keystone_exceptions.NotFound:
|
||||||
if subcloud.first_identity_sync_complete \
|
if subcloud.first_identity_sync_complete \
|
||||||
and avail_status_current == dccommon_consts.AVAILABILITY_ONLINE:
|
and avail_status_current == dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
# The first identity sync is already complete
|
# The first identity sync is already complete
|
||||||
# Therefore this is an error
|
# Therefore this is an error
|
||||||
LOG.error("Identity or Platform endpoint for online "
|
LOG.error("Identity or Platform endpoint for online "
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021, 2024 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
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The right to copy, distribute, modify, or otherwise make use
|
# The right to copy, distribute, modify, or otherwise make use
|
||||||
|
@ -26,17 +27,17 @@ def request_subcloud_audits(context,
|
||||||
audit_firmware=False,
|
audit_firmware=False,
|
||||||
audit_kubernetes=False,
|
audit_kubernetes=False,
|
||||||
audit_kube_rootca=False):
|
audit_kube_rootca=False):
|
||||||
values = {}
|
values = {}
|
||||||
if update_subcloud_state:
|
if update_subcloud_state:
|
||||||
values['state_update_requested'] = True
|
values['state_update_requested'] = True
|
||||||
if audit_patch:
|
if audit_patch:
|
||||||
values['patch_audit_requested'] = True
|
values['patch_audit_requested'] = True
|
||||||
if audit_load:
|
if audit_load:
|
||||||
values['load_audit_requested'] = True
|
values['load_audit_requested'] = True
|
||||||
if audit_firmware:
|
if audit_firmware:
|
||||||
values['firmware_audit_requested'] = True
|
values['firmware_audit_requested'] = True
|
||||||
if audit_kubernetes:
|
if audit_kubernetes:
|
||||||
values['kubernetes_audit_requested'] = True
|
values['kubernetes_audit_requested'] = True
|
||||||
if audit_kube_rootca:
|
if audit_kube_rootca:
|
||||||
values['kube_rootca_update_audit_requested'] = True
|
values['kube_rootca_update_audit_requested'] = True
|
||||||
db_api.subcloud_audits_update_all(context, values)
|
db_api.subcloud_audits_update_all(context, values)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -19,24 +19,25 @@
|
||||||
# see http://git.openstack.org/cgit/openstack/ironic/tree/ironic/cmd/api.py
|
# see http://git.openstack.org/cgit/openstack/ironic/tree/ironic/cmd/api.py
|
||||||
|
|
||||||
|
|
||||||
|
import logging as std_logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch(os=False)
|
eventlet.monkey_patch(os=False)
|
||||||
|
|
||||||
from oslo_config import cfg
|
# pylint: disable=wrong-import-position
|
||||||
from oslo_log import log as logging
|
from oslo_config import cfg # noqa: E402
|
||||||
from oslo_service import systemd
|
from oslo_log import log as logging # noqa: E402
|
||||||
from oslo_service import wsgi
|
from oslo_service import systemd # noqa: E402
|
||||||
|
from oslo_service import wsgi # noqa: E402
|
||||||
|
|
||||||
import logging as std_logging
|
from dcmanager.api import api_config # noqa: E402
|
||||||
|
from dcmanager.api import app # noqa: E402
|
||||||
|
from dcmanager.common import config # noqa: E402
|
||||||
|
from dcmanager.common import messaging # noqa: E402
|
||||||
|
from dcorch.common import messaging as dcorch_messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
from dcmanager.api import api_config
|
|
||||||
from dcmanager.api import app
|
|
||||||
|
|
||||||
from dcmanager.common import config
|
|
||||||
from dcmanager.common import messaging
|
|
||||||
from dcorch.common import messaging as dcorch_messaging
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
config.register_options()
|
config.register_options()
|
||||||
LOG = logging.getLogger('dcmanager.api')
|
LOG = logging.getLogger('dcmanager.api')
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
@ -19,14 +21,15 @@ DC Manager Audit Service.
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from oslo_config import cfg
|
# pylint: disable=wrong-import-position
|
||||||
from oslo_i18n import _lazy
|
from oslo_config import cfg # noqa: E402
|
||||||
from oslo_log import log as logging
|
from oslo_i18n import _lazy # noqa: E402
|
||||||
from oslo_service import service
|
from oslo_log import log as logging # noqa: E402
|
||||||
|
from oslo_service import service # noqa: E402
|
||||||
from dcmanager.common import config
|
|
||||||
from dcmanager.common import messaging
|
|
||||||
|
|
||||||
|
from dcmanager.common import config # noqa: E402
|
||||||
|
from dcmanager.common import messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
_lazy.enable_lazy()
|
_lazy.enable_lazy()
|
||||||
config.register_options()
|
config.register_options()
|
||||||
|
@ -55,5 +58,6 @@ def main():
|
||||||
|
|
||||||
launcher.wait()
|
launcher.wait()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
@ -19,14 +21,15 @@ DC Manager Audit Worker Service.
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from oslo_config import cfg
|
# pylint: disable=wrong-import-position
|
||||||
from oslo_i18n import _lazy
|
from oslo_config import cfg # noqa: E402
|
||||||
from oslo_log import log as logging
|
from oslo_i18n import _lazy # noqa: E402
|
||||||
from oslo_service import service
|
from oslo_log import log as logging # noqa: E402
|
||||||
|
from oslo_service import service # noqa: E402
|
||||||
from dcmanager.common import config
|
|
||||||
from dcmanager.common import messaging
|
|
||||||
|
|
||||||
|
from dcmanager.common import config # noqa: E402
|
||||||
|
from dcmanager.common import messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
_lazy.enable_lazy()
|
_lazy.enable_lazy()
|
||||||
config.register_options()
|
config.register_options()
|
||||||
|
@ -55,5 +58,6 @@ def main():
|
||||||
|
|
||||||
launcher.wait()
|
launcher.wait()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -51,6 +53,7 @@ def add_command_parsers(subparsers):
|
||||||
parser.add_argument('version', nargs='?')
|
parser.add_argument('version', nargs='?')
|
||||||
parser.add_argument('current_version', nargs='?')
|
parser.add_argument('current_version', nargs='?')
|
||||||
|
|
||||||
|
|
||||||
command_opt = cfg.SubCommandOpt('command',
|
command_opt = cfg.SubCommandOpt('command',
|
||||||
title='Commands',
|
title='Commands',
|
||||||
help='Show available commands.',
|
help='Show available commands.',
|
||||||
|
@ -76,5 +79,6 @@ def main():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.exit("ERROR: %s" % e)
|
sys.exit("ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
# Copyright (c) 2017-2021, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
@ -18,18 +20,20 @@ DC Manager Engine Server.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-position
|
||||||
|
from oslo_config import cfg # noqa: E402
|
||||||
|
from oslo_i18n import _lazy # noqa: E402
|
||||||
|
from oslo_log import log as logging # noqa: E402
|
||||||
|
from oslo_service import service # noqa: E402
|
||||||
|
|
||||||
|
from dcmanager.common import config # noqa: E402
|
||||||
|
from dcmanager.common import consts # noqa: E402
|
||||||
|
from dcmanager.common import messaging # noqa: E402
|
||||||
|
from dcorch.common import messaging as dcorch_messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_i18n import _lazy
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from oslo_service import service
|
|
||||||
|
|
||||||
from dcmanager.common import config
|
|
||||||
from dcmanager.common import consts
|
|
||||||
from dcmanager.common import messaging
|
|
||||||
from dcorch.common import messaging as dcorch_messaging
|
|
||||||
|
|
||||||
_lazy.enable_lazy()
|
_lazy.enable_lazy()
|
||||||
config.register_options()
|
config.register_options()
|
||||||
config.register_keystone_options()
|
config.register_keystone_options()
|
||||||
|
@ -59,5 +63,6 @@ def main():
|
||||||
# srv.create_periodic_tasks()
|
# srv.create_periodic_tasks()
|
||||||
launcher.wait()
|
launcher.wait()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
|
@ -19,14 +21,15 @@ DC Manager Orchestrator Service.
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from oslo_config import cfg
|
# pylint: disable=wrong-import-position
|
||||||
from oslo_i18n import _lazy
|
from oslo_config import cfg # noqa: E402
|
||||||
from oslo_log import log as logging
|
from oslo_i18n import _lazy # noqa: E402
|
||||||
from oslo_service import service
|
from oslo_log import log as logging # noqa: E402
|
||||||
|
from oslo_service import service # noqa: E402
|
||||||
from dcmanager.common import config
|
|
||||||
from dcmanager.common import messaging
|
|
||||||
|
|
||||||
|
from dcmanager.common import config # noqa: E402
|
||||||
|
from dcmanager.common import messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger('dcmanager.orchestrator')
|
LOG = logging.getLogger('dcmanager.orchestrator')
|
||||||
|
@ -54,5 +57,6 @@ def main():
|
||||||
|
|
||||||
launcher.wait()
|
launcher.wait()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# The right to copy, distribute, modify, or otherwise make use
|
# The right to copy, distribute, modify, or otherwise make use
|
||||||
# of this software may be licensed only pursuant to the terms
|
# of this software may be licensed only pursuant to the terms
|
||||||
|
@ -26,14 +26,16 @@ DC Manager State Engine Server.
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from oslo_config import cfg
|
# pylint: disable=wrong-import-position
|
||||||
from oslo_i18n import _lazy
|
from oslo_config import cfg # noqa: E402
|
||||||
from oslo_log import log as logging
|
from oslo_i18n import _lazy # noqa: E402
|
||||||
from oslo_service import service
|
from oslo_log import log as logging # noqa: E402
|
||||||
|
from oslo_service import service # noqa: E402
|
||||||
|
|
||||||
from dcmanager.common import config
|
from dcmanager.common import config # noqa: E402
|
||||||
from dcmanager.common import messaging
|
from dcmanager.common import messaging # noqa: E402
|
||||||
from dcorch.common import messaging as dcorch_messaging
|
from dcorch.common import messaging as dcorch_messaging # noqa: E402
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
_lazy.enable_lazy()
|
_lazy.enable_lazy()
|
||||||
config.register_options()
|
config.register_options()
|
||||||
|
@ -65,5 +67,6 @@ def main():
|
||||||
launcher = service.launch(cfg.CONF, srv, workers=cfg.CONF.state_workers)
|
launcher = service.launch(cfg.CONF, srv, workers=cfg.CONF.state_workers)
|
||||||
launcher.wait()
|
launcher.wait()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
# Copyright (c) 2016 Ericsson AB.
|
# Copyright (c) 2016 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
RPC_API_VERSION = "1.0"
|
RPC_API_VERSION = "1.0"
|
||||||
|
@ -397,9 +399,10 @@ BITSTREAM_TYPE_KEY_REVOCATION = 'key-revocation'
|
||||||
# Platform Backup size default in MB
|
# Platform Backup size default in MB
|
||||||
DEFAULT_PERSISTENT_SIZE = 30000
|
DEFAULT_PERSISTENT_SIZE = 30000
|
||||||
|
|
||||||
# Retry values to be used when platform requests fail due to temporary unavailability, which
|
# Retry values to be used when platform requests fail due to temporary
|
||||||
# may occur during some orchestration steps. The sleep duration and number of retries are shorter,
|
# unavailability, which may occur during some orchestration steps. The sleep
|
||||||
# since these should only occur if a service is being restarted
|
# duration and number of retries are shorter, since these should only occur if a
|
||||||
|
# service is being restarted
|
||||||
PLATFORM_RETRY_MAX_ATTEMPTS = 5
|
PLATFORM_RETRY_MAX_ATTEMPTS = 5
|
||||||
PLATFORM_RETRY_SLEEP_MILLIS = 5000
|
PLATFORM_RETRY_SLEEP_MILLIS = 5000
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,29 @@
|
||||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
# Copyright (c) 2017-2022, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
import pecan
|
|
||||||
from pecan import hooks
|
|
||||||
import re
|
import re
|
||||||
from six.moves.urllib.parse import urlparse
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from oslo_context import context as base_context
|
from oslo_context import context as base_context
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
import pecan
|
||||||
|
from pecan import hooks
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
from dcmanager.api.policies import base as base_policy
|
from dcmanager.api.policies import base as base_policy
|
||||||
from dcmanager.api import policy
|
from dcmanager.api import policy
|
||||||
|
@ -52,7 +54,6 @@ class RequestContext(base_context.RequestContext):
|
||||||
user_domain_name=None, project_domain_name=None,
|
user_domain_name=None, project_domain_name=None,
|
||||||
auth_token_info=None, region_name=None, roles=None,
|
auth_token_info=None, region_name=None, roles=None,
|
||||||
password=None, **kwargs):
|
password=None, **kwargs):
|
||||||
|
|
||||||
"""Initializer of request context."""
|
"""Initializer of request context."""
|
||||||
# We still have 'tenant' param because oslo_context still use it.
|
# We still have 'tenant' param because oslo_context still use it.
|
||||||
# pylint: disable=E1123
|
# pylint: disable=E1123
|
||||||
|
@ -244,8 +245,8 @@ class AuditLoggingHook(hooks.PecanHook):
|
||||||
# [req-088ed3b6-a2c9-483e-b2ad-f1b2d03e06e6
|
# [req-088ed3b6-a2c9-483e-b2ad-f1b2d03e06e6
|
||||||
# 3d76d3c1376744e8ad9916a6c3be3e5f
|
# 3d76d3c1376744e8ad9916a6c3be3e5f
|
||||||
# ca53e70c76d847fd860693f8eb301546]
|
# ca53e70c76d847fd860693f8eb301546]
|
||||||
# When the ctx is defined, the formatter (defined in common/log.py) requires that keys
|
# When the ctx is defined, the formatter (defined in common/log.py) requires
|
||||||
# request_id, user, tenant be defined within the ctx
|
# that keys request_id, user, tenant be defined within the ctx
|
||||||
ctx = {'request_id': request_id,
|
ctx = {'request_id': request_id,
|
||||||
'user': user_id,
|
'user': user_id,
|
||||||
'tenant': tenant_id}
|
'tenant': tenant_id}
|
||||||
|
@ -261,4 +262,5 @@ class AuditLoggingHook(hooks.PecanHook):
|
||||||
auditLOG.exception("Exception in AuditLoggingHook on event 'after'")
|
auditLOG.exception("Exception in AuditLoggingHook on event 'after'")
|
||||||
|
|
||||||
def on_error(self, state, e):
|
def on_error(self, state, e):
|
||||||
auditLOG.exception("Exception in AuditLoggingHook passed to event 'on_error': " + str(e))
|
auditLOG.exception("Exception in AuditLoggingHook passed to event "
|
||||||
|
"'on_error': " + str(e))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
# Copyright 2015 Ericsson AB.
|
# Copyright 2015 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -39,14 +39,14 @@ class DCManagerException(Exception):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
try:
|
try:
|
||||||
super(DCManagerException, self).__init__(self.message % kwargs) # pylint: disable=W1645
|
super(DCManagerException, self).__init__(self.message % kwargs)
|
||||||
self.msg = self.message % kwargs # pylint: disable=W1645
|
self.msg = self.message % kwargs # pylint: disable=W1645
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception() as ctxt:
|
with excutils.save_and_reraise_exception() as ctxt:
|
||||||
if not self.use_fatal_exceptions():
|
if not self.use_fatal_exceptions():
|
||||||
ctxt.reraise = False
|
ctxt.reraise = False
|
||||||
# at least get the core message out if something happened
|
# at least get the core message out if something happened
|
||||||
super(DCManagerException, self).__init__(self.message) # pylint: disable=W1645
|
super(DCManagerException, self).__init__(self.message)
|
||||||
|
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
|
@ -259,6 +259,7 @@ class PrestagePreCheckFailedException(DCManagerException):
|
||||||
the subcloud can be skipped during orchestrated prestage
|
the subcloud can be skipped during orchestrated prestage
|
||||||
operations.
|
operations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, subcloud, details, orch_skip=False):
|
def __init__(self, subcloud, details, orch_skip=False):
|
||||||
self.orch_skip = orch_skip
|
self.orch_skip = orch_skip
|
||||||
# Subcloud can be none if we are failing
|
# Subcloud can be none if we are failing
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 2010 United States Government as represented by the
|
# Copyright 2010 United States Government as represented by the
|
||||||
# Administrator of the National Aeronautics and Space Administration.
|
# Administrator of the National Aeronautics and Space Administration.
|
||||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -72,7 +72,6 @@ class Manager(PeriodicTasks):
|
||||||
return self.run_periodic_tasks(context, raise_on_error=raise_on_error)
|
return self.run_periodic_tasks(context, raise_on_error=raise_on_error)
|
||||||
|
|
||||||
def init_host(self):
|
def init_host(self):
|
||||||
|
|
||||||
"""init_host
|
"""init_host
|
||||||
|
|
||||||
Hook to do additional manager initialization when one requests
|
Hook to do additional manager initialization when one requests
|
||||||
|
@ -84,7 +83,6 @@ class Manager(PeriodicTasks):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def cleanup_host(self):
|
def cleanup_host(self):
|
||||||
|
|
||||||
"""cleanup_host
|
"""cleanup_host
|
||||||
|
|
||||||
Hook to do cleanup work when the service shuts down.
|
Hook to do cleanup work when the service shuts down.
|
||||||
|
@ -94,7 +92,6 @@ class Manager(PeriodicTasks):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def pre_start_hook(self):
|
def pre_start_hook(self):
|
||||||
|
|
||||||
"""pre_start_hook
|
"""pre_start_hook
|
||||||
|
|
||||||
Hook to provide the manager the ability to do additional
|
Hook to provide the manager the ability to do additional
|
||||||
|
@ -107,7 +104,6 @@ class Manager(PeriodicTasks):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def post_start_hook(self):
|
def post_start_hook(self):
|
||||||
|
|
||||||
"""post_start_hook
|
"""post_start_hook
|
||||||
|
|
||||||
Hook to provide the manager the ability to do additional
|
Hook to provide the manager the ability to do additional
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -241,13 +241,13 @@ def validate_subcloud_config(context, payload, operation=None,
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
pecan.abort(400, _("management_end_address invalid: %s") % e)
|
pecan.abort(400, _("management_end_address invalid: %s") % e)
|
||||||
|
|
||||||
if not management_start_ip < management_end_ip:
|
if management_start_ip > management_end_ip:
|
||||||
pecan.abort(
|
pecan.abort(
|
||||||
400,
|
400,
|
||||||
_("management_start_address not less than "
|
_("management_start_address greater than "
|
||||||
"management_end_address"))
|
"management_end_address"))
|
||||||
|
|
||||||
if not len(netaddr.IPRange(management_start_ip, management_end_ip)) >= \
|
if len(netaddr.IPRange(management_start_ip, management_end_ip)) < \
|
||||||
MIN_MANAGEMENT_ADDRESSES:
|
MIN_MANAGEMENT_ADDRESSES:
|
||||||
pecan.abort(
|
pecan.abort(
|
||||||
400,
|
400,
|
||||||
|
@ -379,13 +379,13 @@ def validate_admin_network_config(admin_subnet_str,
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
pecan.abort(400, _("admin_end_address invalid: %s") % e)
|
pecan.abort(400, _("admin_end_address invalid: %s") % e)
|
||||||
|
|
||||||
if not admin_start_ip < admin_end_ip:
|
if admin_start_ip > admin_end_ip:
|
||||||
pecan.abort(
|
pecan.abort(
|
||||||
400,
|
400,
|
||||||
_("admin_start_address not less than "
|
_("admin_start_address greater than "
|
||||||
"admin_end_address"))
|
"admin_end_address"))
|
||||||
|
|
||||||
if not len(netaddr.IPRange(admin_start_ip, admin_end_ip)) >= \
|
if len(netaddr.IPRange(admin_start_ip, admin_end_ip)) < \
|
||||||
MIN_ADMIN_ADDRESSES:
|
MIN_ADMIN_ADDRESSES:
|
||||||
pecan.abort(
|
pecan.abort(
|
||||||
400,
|
400,
|
||||||
|
@ -975,7 +975,9 @@ def populate_payload_with_pre_existing_data(payload: dict,
|
||||||
msg = _("Required %s file was not provided and it was not "
|
msg = _("Required %s file was not provided and it was not "
|
||||||
"previously available.") % value
|
"previously available.") % value
|
||||||
pecan.abort(400, msg)
|
pecan.abort(400, msg)
|
||||||
payload.update(dict(list(existing_values.items()) + list(payload.items())))
|
payload.update(
|
||||||
|
dict(list(existing_values.items()) + list(payload.items()))
|
||||||
|
)
|
||||||
elif value == consts.DEPLOY_CONFIG:
|
elif value == consts.DEPLOY_CONFIG:
|
||||||
if not payload.get(consts.DEPLOY_CONFIG):
|
if not payload.get(consts.DEPLOY_CONFIG):
|
||||||
fn = get_config_file_path(subcloud.name, value)
|
fn = get_config_file_path(subcloud.name, value)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
# Copyright (c) 2017, 2019, 2021, 2022 Wind River Systems, Inc.
|
# Copyright (c) 2017, 2019, 2021, 2022, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
|
@ -27,6 +27,7 @@ class Mapping(object):
|
||||||
for key, value in mapping.items():
|
for key, value in mapping.items():
|
||||||
self.reverse_mapping[value] = key
|
self.reverse_mapping[value] = key
|
||||||
|
|
||||||
|
|
||||||
_SINGLETON_MAPPING = Mapping({
|
_SINGLETON_MAPPING = Mapping({
|
||||||
ATTR_NOT_SPECIFIED: "@@**ATTR_NOT_SPECIFIED**@@",
|
ATTR_NOT_SPECIFIED: "@@**ATTR_NOT_SPECIFIED**@@",
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,43 +1,46 @@
|
||||||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import grp
|
import grp
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import netaddr
|
|
||||||
import os
|
import os
|
||||||
import pecan
|
|
||||||
import pwd
|
import pwd
|
||||||
import re
|
import re
|
||||||
import resource as sys_resource
|
|
||||||
import six.moves
|
|
||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
import tsconfig.tsconfig as tsc
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import resource as sys_resource
|
||||||
import xml.etree.ElementTree as ElementTree
|
import xml.etree.ElementTree as ElementTree
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
import pecan
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as keystone_exceptions
|
from keystoneauth1 import exceptions as keystone_exceptions
|
||||||
|
import netaddr
|
||||||
from oslo_concurrency import lockutils
|
from oslo_concurrency import lockutils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_serialization import base64
|
from oslo_serialization import base64
|
||||||
|
import six.moves
|
||||||
|
import tsconfig.tsconfig as tsc
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
||||||
|
@ -249,43 +252,41 @@ def get_sw_update_strategy_extra_args(context, update_type=None):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def get_sw_update_opts(context,
|
def get_sw_update_opts(context, for_sw_update=False, subcloud_id=None):
|
||||||
for_sw_update=False, subcloud_id=None):
|
"""Get sw update options for a subcloud
|
||||||
"""Get sw update options for a subcloud
|
|
||||||
|
|
||||||
:param context: request context object.
|
:param context: request context object.
|
||||||
:param for_sw_update: return the default options if subcloud options
|
:param for_sw_update: return the default options if subcloud options
|
||||||
are empty. Useful for retrieving sw update
|
are empty. Useful for retrieving sw update
|
||||||
options on application of patch strategy.
|
options on application of patch strategy.
|
||||||
:param subcloud_id: id of subcloud.
|
:param subcloud_id: id of subcloud.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if subcloud_id is None:
|
if subcloud_id is None:
|
||||||
# Requesting defaults. Return constants if no entry in db.
|
# Requesting defaults. Return constants if no entry in db.
|
||||||
|
sw_update_opts_ref = db_api.sw_update_opts_default_get(context)
|
||||||
|
if not sw_update_opts_ref:
|
||||||
|
sw_update_opts_dict = vim.SW_UPDATE_OPTS_CONST_DEFAULT
|
||||||
|
return sw_update_opts_dict
|
||||||
|
else:
|
||||||
|
# requesting subcloud options
|
||||||
|
sw_update_opts_ref = db_api.sw_update_opts_get(context, subcloud_id)
|
||||||
|
if sw_update_opts_ref:
|
||||||
|
subcloud_name = db_api.subcloud_get(context, subcloud_id).name
|
||||||
|
return db_api.sw_update_opts_w_name_db_model_to_dict(
|
||||||
|
sw_update_opts_ref, subcloud_name)
|
||||||
|
elif for_sw_update:
|
||||||
sw_update_opts_ref = db_api.sw_update_opts_default_get(context)
|
sw_update_opts_ref = db_api.sw_update_opts_default_get(context)
|
||||||
if not sw_update_opts_ref:
|
if not sw_update_opts_ref:
|
||||||
sw_update_opts_dict = vim.SW_UPDATE_OPTS_CONST_DEFAULT
|
sw_update_opts_dict = vim.SW_UPDATE_OPTS_CONST_DEFAULT
|
||||||
return sw_update_opts_dict
|
return sw_update_opts_dict
|
||||||
else:
|
else:
|
||||||
# requesting subcloud options
|
raise exceptions.SubcloudPatchOptsNotFound(
|
||||||
sw_update_opts_ref = db_api.sw_update_opts_get(context,
|
subcloud_id=subcloud_id)
|
||||||
subcloud_id)
|
|
||||||
if sw_update_opts_ref:
|
|
||||||
subcloud_name = db_api.subcloud_get(context, subcloud_id).name
|
|
||||||
return db_api.sw_update_opts_w_name_db_model_to_dict(
|
|
||||||
sw_update_opts_ref, subcloud_name)
|
|
||||||
elif for_sw_update:
|
|
||||||
sw_update_opts_ref = db_api.sw_update_opts_default_get(context)
|
|
||||||
if not sw_update_opts_ref:
|
|
||||||
sw_update_opts_dict = vim.SW_UPDATE_OPTS_CONST_DEFAULT
|
|
||||||
return sw_update_opts_dict
|
|
||||||
else:
|
|
||||||
raise exceptions.SubcloudPatchOptsNotFound(
|
|
||||||
subcloud_id=subcloud_id)
|
|
||||||
|
|
||||||
return db_api.sw_update_opts_w_name_db_model_to_dict(
|
return db_api.sw_update_opts_w_name_db_model_to_dict(
|
||||||
sw_update_opts_ref, dccommon_consts.SW_UPDATE_DEFAULT_TITLE)
|
sw_update_opts_ref, dccommon_consts.SW_UPDATE_DEFAULT_TITLE)
|
||||||
|
|
||||||
|
|
||||||
def ensure_lock_path():
|
def ensure_lock_path():
|
||||||
|
@ -618,8 +619,8 @@ def subcloud_peer_group_get_by_ref(context, group_ref):
|
||||||
|
|
||||||
|
|
||||||
def subcloud_db_list_to_dict(subclouds):
|
def subcloud_db_list_to_dict(subclouds):
|
||||||
return {'subclouds': [db_api.subcloud_db_model_to_dict(subcloud)
|
return {'subclouds':
|
||||||
for subcloud in subclouds]}
|
[db_api.subcloud_db_model_to_dict(subcloud) for subcloud in subclouds]}
|
||||||
|
|
||||||
|
|
||||||
def get_oam_addresses(subcloud, sc_ks_client):
|
def get_oam_addresses(subcloud, sc_ks_client):
|
||||||
|
@ -811,7 +812,7 @@ def find_ansible_error_msg(subcloud_name, log_file, stage=None):
|
||||||
else:
|
else:
|
||||||
files_for_search.append(log_file)
|
files_for_search.append(log_file)
|
||||||
|
|
||||||
if (len(files_for_search) < 2):
|
if len(files_for_search) < 2:
|
||||||
cmd_list = ([cmd_1, cmd_2, files_for_search[0]])
|
cmd_list = ([cmd_1, cmd_2, files_for_search[0]])
|
||||||
else:
|
else:
|
||||||
cmd_list = ([cmd_1, cmd_2, files_for_search[0], files_for_search[1]])
|
cmd_list = ([cmd_1, cmd_2, files_for_search[0], files_for_search[1]])
|
||||||
|
@ -858,7 +859,6 @@ def get_failed_task(files):
|
||||||
|
|
||||||
Returns a string with the task and date
|
Returns a string with the task and date
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cmd_1 = 'awk'
|
cmd_1 = 'awk'
|
||||||
# awk command to get the information about last failed task.
|
# awk command to get the information about last failed task.
|
||||||
# Match expression starting with 'TASK [' and ending with
|
# Match expression starting with 'TASK [' and ending with
|
||||||
|
@ -873,7 +873,7 @@ def get_failed_task(files):
|
||||||
''')
|
''')
|
||||||
# necessary check since is possible to have
|
# necessary check since is possible to have
|
||||||
# the error in rotated ansible log
|
# the error in rotated ansible log
|
||||||
if (len(files) < 2):
|
if len(files) < 2:
|
||||||
awk_cmd = ([cmd_1, cmd_2, files[0]])
|
awk_cmd = ([cmd_1, cmd_2, files[0]])
|
||||||
else:
|
else:
|
||||||
awk_cmd = ([cmd_1, cmd_2, files[0], files[1]])
|
awk_cmd = ([cmd_1, cmd_2, files[0], files[1]])
|
||||||
|
@ -903,9 +903,7 @@ def summarize_message(error_msg):
|
||||||
|
|
||||||
Returns a brief message.
|
Returns a brief message.
|
||||||
"""
|
"""
|
||||||
list_of_strings_to_search_for = [
|
list_of_strings_to_search_for = ['msg:', 'fail', 'error', 'cmd', 'stderr']
|
||||||
'msg:', 'fail', 'error', 'cmd', 'stderr'
|
|
||||||
]
|
|
||||||
brief_message = []
|
brief_message = []
|
||||||
for line in error_msg:
|
for line in error_msg:
|
||||||
for s in list_of_strings_to_search_for:
|
for s in list_of_strings_to_search_for:
|
||||||
|
@ -933,10 +931,9 @@ def is_valid_for_backup_operation(operation, subcloud, bootstrap_address_dict=No
|
||||||
|
|
||||||
|
|
||||||
def _is_valid_for_backup_create(subcloud):
|
def _is_valid_for_backup_create(subcloud):
|
||||||
|
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE \
|
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE \
|
||||||
or subcloud.management_state != dccommon_consts.MANAGEMENT_MANAGED \
|
or subcloud.management_state != dccommon_consts.MANAGEMENT_MANAGED \
|
||||||
or subcloud.deploy_status not in consts.VALID_DEPLOY_STATES_FOR_BACKUP:
|
or subcloud.deploy_status not in consts.VALID_DEPLOY_STATES_FOR_BACKUP:
|
||||||
msg = ('Subcloud %s must be online, managed and have valid '
|
msg = ('Subcloud %s must be online, managed and have valid '
|
||||||
'deploy-status for the subcloud-backup '
|
'deploy-status for the subcloud-backup '
|
||||||
'create operation.' % subcloud.name)
|
'create operation.' % subcloud.name)
|
||||||
|
@ -946,9 +943,8 @@ def _is_valid_for_backup_create(subcloud):
|
||||||
|
|
||||||
|
|
||||||
def _is_valid_for_backup_delete(subcloud):
|
def _is_valid_for_backup_delete(subcloud):
|
||||||
|
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE \
|
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE \
|
||||||
or subcloud.management_state != dccommon_consts.MANAGEMENT_MANAGED:
|
or subcloud.management_state != dccommon_consts.MANAGEMENT_MANAGED:
|
||||||
msg = ('Subcloud %s must be online and managed for the subcloud-backup'
|
msg = ('Subcloud %s must be online and managed for the subcloud-backup'
|
||||||
' delete operation with --local-only option.' % subcloud.name)
|
' delete operation with --local-only option.' % subcloud.name)
|
||||||
raise exceptions.ValidateFail(msg)
|
raise exceptions.ValidateFail(msg)
|
||||||
|
@ -967,7 +963,7 @@ def _is_valid_for_backup_restore(subcloud, bootstrap_address_dict=None):
|
||||||
has_inventory_file = os.path.exists(ansible_subcloud_inventory_file)
|
has_inventory_file = os.path.exists(ansible_subcloud_inventory_file)
|
||||||
|
|
||||||
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED \
|
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED \
|
||||||
or subcloud.deploy_status in consts.INVALID_DEPLOY_STATES_FOR_RESTORE:
|
or subcloud.deploy_status in consts.INVALID_DEPLOY_STATES_FOR_RESTORE:
|
||||||
msg = ('Subcloud %s must be unmanaged and in a valid deploy state '
|
msg = ('Subcloud %s must be unmanaged and in a valid deploy state '
|
||||||
'for the subcloud-backup restore operation.' % subcloud.name)
|
'for the subcloud-backup restore operation.' % subcloud.name)
|
||||||
elif not (has_bootstrap_address or has_install_values or has_inventory_file):
|
elif not (has_bootstrap_address or has_install_values or has_inventory_file):
|
||||||
|
@ -1401,7 +1397,9 @@ def get_sw_version(release=None):
|
||||||
|
|
||||||
|
|
||||||
def validate_release_version_supported(release_version_to_check):
|
def validate_release_version_supported(release_version_to_check):
|
||||||
"""Given a release version, check whether it's supported by the current active version.
|
"""Given a release version, check whether it's supported by the current active
|
||||||
|
|
||||||
|
version.
|
||||||
|
|
||||||
:param release_version_to_check: version string to validate
|
:param release_version_to_check: version string to validate
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2015 Ericsson AB.
|
# Copyright (c) 2015 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Interface for database access.
|
Interface for database access.
|
||||||
|
|
||||||
|
@ -136,13 +137,12 @@ def subcloud_create(context, name, description, location, software_version,
|
||||||
systemcontroller_gateway_ip, deploy_status, error_description,
|
systemcontroller_gateway_ip, deploy_status, error_description,
|
||||||
region_name, openstack_installed, group_id, data_install=None):
|
region_name, openstack_installed, group_id, data_install=None):
|
||||||
"""Create a subcloud."""
|
"""Create a subcloud."""
|
||||||
return IMPL.subcloud_create(context, name, description, location,
|
return IMPL.subcloud_create(
|
||||||
software_version,
|
context, name, description, location, software_version, management_subnet,
|
||||||
management_subnet, management_gateway_ip,
|
management_gateway_ip, management_start_ip, management_end_ip,
|
||||||
management_start_ip, management_end_ip,
|
systemcontroller_gateway_ip, deploy_status, error_description, region_name,
|
||||||
systemcontroller_gateway_ip, deploy_status,
|
openstack_installed, group_id, data_install
|
||||||
error_description, region_name, openstack_installed, group_id,
|
)
|
||||||
data_install)
|
|
||||||
|
|
||||||
|
|
||||||
def subcloud_get(context, subcloud_id):
|
def subcloud_get(context, subcloud_id):
|
||||||
|
@ -185,29 +185,26 @@ def subcloud_get_all_with_status(context):
|
||||||
return IMPL.subcloud_get_all_with_status(context)
|
return IMPL.subcloud_get_all_with_status(context)
|
||||||
|
|
||||||
|
|
||||||
def subcloud_update(context, subcloud_id, management_state=None,
|
def subcloud_update(
|
||||||
availability_status=None, software_version=None, name=None,
|
context, subcloud_id, management_state=None, availability_status=None,
|
||||||
description=None, management_subnet=None, management_gateway_ip=None,
|
software_version=None, name=None, description=None, management_subnet=None,
|
||||||
management_start_ip=None, management_end_ip=None,
|
management_gateway_ip=None, management_start_ip=None, management_end_ip=None,
|
||||||
location=None, audit_fail_count=None,
|
location=None, audit_fail_count=None, deploy_status=None, backup_status=None,
|
||||||
deploy_status=None, backup_status=None,
|
backup_datetime=None, error_description=None, openstack_installed=None,
|
||||||
backup_datetime=None, error_description=None,
|
group_id=None, data_install=None, data_upgrade=None,
|
||||||
openstack_installed=None, group_id=None,
|
first_identity_sync_complete=None, systemcontroller_gateway_ip=None,
|
||||||
data_install=None, data_upgrade=None,
|
peer_group_id=None, rehome_data=None, rehomed=None
|
||||||
first_identity_sync_complete=None,
|
):
|
||||||
systemcontroller_gateway_ip=None,
|
|
||||||
peer_group_id=None, rehome_data=None, rehomed=None):
|
|
||||||
"""Update a subcloud or raise if it does not exist."""
|
"""Update a subcloud or raise if it does not exist."""
|
||||||
return IMPL.subcloud_update(context, subcloud_id, management_state,
|
return IMPL.subcloud_update(
|
||||||
availability_status, software_version, name,
|
context, subcloud_id, management_state, availability_status,
|
||||||
description, management_subnet, management_gateway_ip,
|
software_version, name, description, management_subnet,
|
||||||
management_start_ip, management_end_ip, location,
|
management_gateway_ip, management_start_ip, management_end_ip, location,
|
||||||
audit_fail_count, deploy_status, backup_status,
|
audit_fail_count, deploy_status, backup_status, backup_datetime,
|
||||||
backup_datetime, error_description, openstack_installed,
|
error_description, openstack_installed, group_id, data_install, data_upgrade,
|
||||||
group_id, data_install, data_upgrade,
|
first_identity_sync_complete, systemcontroller_gateway_ip, peer_group_id,
|
||||||
first_identity_sync_complete,
|
rehome_data, rehomed
|
||||||
systemcontroller_gateway_ip, peer_group_id,
|
)
|
||||||
rehome_data, rehomed)
|
|
||||||
|
|
||||||
|
|
||||||
def subcloud_bulk_update_by_ids(context, subcloud_ids, update_form):
|
def subcloud_bulk_update_by_ids(context, subcloud_ids, update_form):
|
||||||
|
@ -220,8 +217,6 @@ def subcloud_destroy(context, subcloud_id):
|
||||||
return IMPL.subcloud_destroy(context, subcloud_id)
|
return IMPL.subcloud_destroy(context, subcloud_id)
|
||||||
|
|
||||||
|
|
||||||
###################
|
|
||||||
|
|
||||||
def subcloud_status_create(context, subcloud_id, endpoint_type):
|
def subcloud_status_create(context, subcloud_id, endpoint_type):
|
||||||
"""Create a subcloud status for an endpoint_type."""
|
"""Create a subcloud status for an endpoint_type."""
|
||||||
return IMPL.subcloud_status_create(context, subcloud_id, endpoint_type)
|
return IMPL.subcloud_status_create(context, subcloud_id, endpoint_type)
|
||||||
|
@ -261,7 +256,6 @@ def subcloud_endpoint_status_db_model_to_dict(subcloud_status):
|
||||||
|
|
||||||
|
|
||||||
def subcloud_status_get(context, subcloud_id, endpoint_type):
|
def subcloud_status_get(context, subcloud_id, endpoint_type):
|
||||||
|
|
||||||
"""Retrieve the subcloud status for an endpoint
|
"""Retrieve the subcloud status for an endpoint
|
||||||
|
|
||||||
Will raise if subcloud does not exist.
|
Will raise if subcloud does not exist.
|
||||||
|
@ -766,7 +760,6 @@ def sw_update_opts_update(context, subcloud_id,
|
||||||
max_parallel_workers=None,
|
max_parallel_workers=None,
|
||||||
alarm_restriction_type=None,
|
alarm_restriction_type=None,
|
||||||
default_instance_action=None):
|
default_instance_action=None):
|
||||||
|
|
||||||
"""Update sw update options or raise if it does not exist."""
|
"""Update sw update options or raise if it does not exist."""
|
||||||
return IMPL.sw_update_opts_update(context, subcloud_id,
|
return IMPL.sw_update_opts_update(context, subcloud_id,
|
||||||
storage_apply_type,
|
storage_apply_type,
|
||||||
|
@ -806,7 +799,6 @@ def sw_update_opts_default_update(context,
|
||||||
max_parallel_workers=None,
|
max_parallel_workers=None,
|
||||||
alarm_restriction_type=None,
|
alarm_restriction_type=None,
|
||||||
default_instance_action=None):
|
default_instance_action=None):
|
||||||
|
|
||||||
"""Update default sw update options."""
|
"""Update default sw update options."""
|
||||||
return IMPL.sw_update_opts_default_update(context,
|
return IMPL.sw_update_opts_default_update(context,
|
||||||
storage_apply_type,
|
storage_apply_type,
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Copyright (c) 2015 Ericsson AB.
|
# Copyright (c) 2015 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -20,7 +20,6 @@ Implementation of SQLAlchemy backend.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import sqlalchemy
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ from oslo_db.sqlalchemy import enginefacade
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
import sqlalchemy
|
||||||
from sqlalchemy import desc
|
from sqlalchemy import desc
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from sqlalchemy.orm.exc import MultipleResultsFound
|
from sqlalchemy.orm.exc import MultipleResultsFound
|
||||||
|
@ -198,12 +197,14 @@ def subcloud_audits_get_all_need_audit(context, last_audit_threshold):
|
||||||
with read_session() as session:
|
with read_session() as session:
|
||||||
result = session.query(models.SubcloudAudits).\
|
result = session.query(models.SubcloudAudits).\
|
||||||
filter_by(deleted=0).\
|
filter_by(deleted=0).\
|
||||||
filter(models.SubcloudAudits.audit_started_at <= models.SubcloudAudits.audit_finished_at).\
|
filter(models.SubcloudAudits.audit_started_at <=
|
||||||
|
models.SubcloudAudits.audit_finished_at).\
|
||||||
filter((models.SubcloudAudits.audit_finished_at < last_audit_threshold) |
|
filter((models.SubcloudAudits.audit_finished_at < last_audit_threshold) |
|
||||||
(models.SubcloudAudits.patch_audit_requested == true()) |
|
(models.SubcloudAudits.patch_audit_requested == true()) |
|
||||||
(models.SubcloudAudits.firmware_audit_requested == true()) |
|
(models.SubcloudAudits.firmware_audit_requested == true()) |
|
||||||
(models.SubcloudAudits.load_audit_requested == true()) |
|
(models.SubcloudAudits.load_audit_requested == true()) |
|
||||||
(models.SubcloudAudits.kube_rootca_update_audit_requested == true()) |
|
(models.SubcloudAudits.kube_rootca_update_audit_requested ==
|
||||||
|
true()) |
|
||||||
(models.SubcloudAudits.kubernetes_audit_requested == true())).\
|
(models.SubcloudAudits.kubernetes_audit_requested == true())).\
|
||||||
all()
|
all()
|
||||||
return result
|
return result
|
||||||
|
@ -334,10 +335,9 @@ def subcloud_get_by_region_name(context, region_name):
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def subcloud_get_by_name_or_region_name(context, name):
|
def subcloud_get_by_name_or_region_name(context, name):
|
||||||
result = model_query(context, models.Subcloud). \
|
result = model_query(context, models.Subcloud).filter_by(deleted=0).filter(
|
||||||
filter_by(deleted=0). \
|
or_(models.Subcloud.name == name, models.Subcloud.region_name == name)
|
||||||
filter(or_(models.Subcloud.name == name, models.Subcloud.region_name == name)). \
|
).first()
|
||||||
first()
|
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
raise exception.SubcloudNameOrRegionNameNotFound(name=name)
|
raise exception.SubcloudNameOrRegionNameNotFound(name=name)
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
# Copyright (c) 2015 Ericsson AB.
|
# Copyright (c) 2015 Ericsson AB.
|
||||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
# Copyright (c) 2017-2021, 2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
|
from dccommon.drivers.openstack import vim
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
def upgrade(migrate_engine):
|
||||||
meta = sqlalchemy.MetaData()
|
meta = sqlalchemy.MetaData()
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -58,7 +60,8 @@ def upgrade(migrate_engine):
|
||||||
subcloud_list = list(subclouds.select().where(subclouds.c.deleted == 0)
|
subcloud_list = list(subclouds.select().where(subclouds.c.deleted == 0)
|
||||||
.order_by(subclouds.c.id).execute())
|
.order_by(subclouds.c.id).execute())
|
||||||
for subcloud in subcloud_list:
|
for subcloud in subcloud_list:
|
||||||
subcloud_audits.insert().execute({'subcloud_id': subcloud['id']}) # pylint: disable=no-value-for-parameter
|
# pylint: disable-next=no-value-for-parameter
|
||||||
|
subcloud_audits.insert().execute({'subcloud_id': subcloud['id']})
|
||||||
|
|
||||||
|
|
||||||
def downgrade(migrate_engine):
|
def downgrade(migrate_engine):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2015 Ericsson AB
|
# Copyright (c) 2015 Ericsson AB
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
SQLAlchemy models for dcmanager data.
|
SQLAlchemy models for dcmanager data.
|
||||||
"""
|
"""
|
||||||
|
@ -22,26 +23,20 @@ import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from oslo_db.sqlalchemy import models
|
from oslo_db.sqlalchemy import models
|
||||||
|
|
||||||
from sqlalchemy.orm import backref
|
|
||||||
from sqlalchemy.orm import relationship
|
|
||||||
from sqlalchemy.orm import session as orm_session
|
|
||||||
|
|
||||||
from sqlalchemy import Boolean
|
from sqlalchemy import Boolean
|
||||||
from sqlalchemy import Column
|
from sqlalchemy import Column
|
||||||
from sqlalchemy import DateTime
|
from sqlalchemy import DateTime
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy import ForeignKey
|
from sqlalchemy import ForeignKey
|
||||||
from sqlalchemy import Integer
|
from sqlalchemy import Integer
|
||||||
|
from sqlalchemy.orm import backref
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
from sqlalchemy.orm import session as orm_session
|
||||||
from sqlalchemy import String
|
from sqlalchemy import String
|
||||||
from sqlalchemy import Text
|
from sqlalchemy import Text
|
||||||
|
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
|
||||||
from sqlalchemy.types import TypeDecorator
|
from sqlalchemy.types import TypeDecorator
|
||||||
from sqlalchemy.types import VARCHAR
|
from sqlalchemy.types import VARCHAR
|
||||||
|
|
||||||
|
|
||||||
# from dcmanager.common import consts
|
|
||||||
|
|
||||||
BASE = declarative_base()
|
BASE = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,14 +204,17 @@ class SubcloudAudits(BASE, DCManagerBase):
|
||||||
subcloud_id = Column(Integer,
|
subcloud_id = Column(Integer,
|
||||||
ForeignKey('subclouds.id', ondelete='CASCADE'),
|
ForeignKey('subclouds.id', ondelete='CASCADE'),
|
||||||
unique=True)
|
unique=True)
|
||||||
audit_started_at = Column(DateTime(timezone=False), default=datetime.datetime.min)
|
audit_started_at = Column(DateTime(timezone=False),
|
||||||
audit_finished_at = Column(DateTime(timezone=False), default=datetime.datetime.min)
|
default=datetime.datetime.min)
|
||||||
|
audit_finished_at = Column(DateTime(timezone=False),
|
||||||
|
default=datetime.datetime.min)
|
||||||
state_update_requested = Column(Boolean, nullable=False, default=False)
|
state_update_requested = Column(Boolean, nullable=False, default=False)
|
||||||
patch_audit_requested = Column(Boolean, nullable=False, default=False)
|
patch_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
load_audit_requested = Column(Boolean, nullable=False, default=False)
|
load_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
firmware_audit_requested = Column(Boolean, nullable=False, default=False)
|
firmware_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
kubernetes_audit_requested = Column(Boolean, nullable=False, default=False)
|
kubernetes_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
kube_rootca_update_audit_requested = Column(Boolean, nullable=False, default=False)
|
kube_rootca_update_audit_requested = Column(Boolean, nullable=False,
|
||||||
|
default=False)
|
||||||
spare_audit_requested = Column(Boolean, nullable=False, default=False)
|
spare_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
spare2_audit_requested = Column(Boolean, nullable=False, default=False)
|
spare2_audit_requested = Column(Boolean, nullable=False, default=False)
|
||||||
reserved = Column(Text)
|
reserved = Column(Text)
|
||||||
|
|
|
@ -29,6 +29,7 @@ LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
class PeerGroupAuditManager(manager.Manager):
|
class PeerGroupAuditManager(manager.Manager):
|
||||||
"""Manages audit related tasks."""
|
"""Manages audit related tasks."""
|
||||||
|
|
||||||
def __init__(self, subcloud_manager, peer_group_id, *args, **kwargs):
|
def __init__(self, subcloud_manager, peer_group_id, *args, **kwargs):
|
||||||
LOG.debug(_('PeerGroupAuditManager initialization...'))
|
LOG.debug(_('PeerGroupAuditManager initialization...'))
|
||||||
super().__init__(service_name="peer_group_audit_manager",
|
super().__init__(service_name="peer_group_audit_manager",
|
||||||
|
@ -117,7 +118,7 @@ class PeerGroupAuditManager(manager.Manager):
|
||||||
# deploy status to consts.DEPLOY_STATE_REHOME_PENDING to stop cert-mon
|
# deploy status to consts.DEPLOY_STATE_REHOME_PENDING to stop cert-mon
|
||||||
# audits.
|
# audits.
|
||||||
if remote_peer_group.get("migration_status") == \
|
if remote_peer_group.get("migration_status") == \
|
||||||
consts.PEER_GROUP_MIGRATING:
|
consts.PEER_GROUP_MIGRATING:
|
||||||
# Unmanaged all local subclouds of peer group
|
# Unmanaged all local subclouds of peer group
|
||||||
LOG.info("Unmanaged all local subclouds of peer group %s "
|
LOG.info("Unmanaged all local subclouds of peer group %s "
|
||||||
"since remote is in migrating state" %
|
"since remote is in migrating state" %
|
||||||
|
@ -130,7 +131,7 @@ class PeerGroupAuditManager(manager.Manager):
|
||||||
# an already unmanaged subcloud, so the deploy status
|
# an already unmanaged subcloud, so the deploy status
|
||||||
# update must be done separately
|
# update must be done separately
|
||||||
if subcloud.management_state != \
|
if subcloud.management_state != \
|
||||||
dccommon_consts.MANAGEMENT_UNMANAGED:
|
dccommon_consts.MANAGEMENT_UNMANAGED:
|
||||||
# Unmanage and update the deploy-status
|
# Unmanage and update the deploy-status
|
||||||
LOG.info("Unmanaging and setting the local subcloud "
|
LOG.info("Unmanaging and setting the local subcloud "
|
||||||
f"{subcloud.name} deploy status to "
|
f"{subcloud.name} deploy status to "
|
||||||
|
@ -160,7 +161,7 @@ class PeerGroupAuditManager(manager.Manager):
|
||||||
# get remote subclouds. For 'managed+online' subclouds,
|
# get remote subclouds. For 'managed+online' subclouds,
|
||||||
# set 'unmanaged+secondary' to local on same subclouds
|
# set 'unmanaged+secondary' to local on same subclouds
|
||||||
elif remote_peer_group.get("migration_status") == \
|
elif remote_peer_group.get("migration_status") == \
|
||||||
consts.PEER_GROUP_MIGRATION_COMPLETE:
|
consts.PEER_GROUP_MIGRATION_COMPLETE or self.require_audit_flag:
|
||||||
remote_subclouds = \
|
remote_subclouds = \
|
||||||
self._get_subclouds_by_peer_group_from_system_peer(
|
self._get_subclouds_by_peer_group_from_system_peer(
|
||||||
system_peer,
|
system_peer,
|
||||||
|
@ -182,7 +183,7 @@ class PeerGroupAuditManager(manager.Manager):
|
||||||
# There will be an exception when unmanage
|
# There will be an exception when unmanage
|
||||||
# a subcloud in 'unamaged' state.
|
# a subcloud in 'unamaged' state.
|
||||||
if subcloud.management_state != \
|
if subcloud.management_state != \
|
||||||
dccommon_consts.MANAGEMENT_UNMANAGED:
|
dccommon_consts.MANAGEMENT_UNMANAGED:
|
||||||
self.subcloud_manager.update_subcloud(
|
self.subcloud_manager.update_subcloud(
|
||||||
self.context,
|
self.context,
|
||||||
subcloud.id,
|
subcloud.id,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -131,17 +131,21 @@ class PeerMonitor(object):
|
||||||
self._raise_failure()
|
self._raise_failure()
|
||||||
db_api.system_peer_update(
|
db_api.system_peer_update(
|
||||||
self.context, self.peer.id,
|
self.context, self.peer.id,
|
||||||
availability_state=consts.SYSTEM_PEER_AVAILABILITY_STATE_UNAVAILABLE)
|
availability_state= # noqa: E251
|
||||||
|
consts.SYSTEM_PEER_AVAILABILITY_STATE_UNAVAILABLE
|
||||||
|
)
|
||||||
failure_count = 0
|
failure_count = 0
|
||||||
self._set_require_audit_flag_to_associated_peer_groups()
|
self._set_require_audit_flag_to_associated_peer_groups()
|
||||||
else:
|
else:
|
||||||
failure_count = 0
|
failure_count = 0
|
||||||
self._audit_local_peer_groups(remote_pg_list)
|
self._audit_local_peer_groups(remote_pg_list)
|
||||||
if self.peer.availability_state != \
|
if self.peer.availability_state != \
|
||||||
consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE:
|
consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE:
|
||||||
db_api.system_peer_update(
|
db_api.system_peer_update(
|
||||||
self.context, self.peer.id,
|
self.context, self.peer.id,
|
||||||
availability_state=consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE)
|
availability_state= # noqa: E251
|
||||||
|
consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE
|
||||||
|
)
|
||||||
LOG.info("DC %s back online, clear alarm" %
|
LOG.info("DC %s back online, clear alarm" %
|
||||||
self.peer.peer_name)
|
self.peer.peer_name)
|
||||||
self._clear_failure()
|
self._clear_failure()
|
||||||
|
@ -167,9 +171,8 @@ class PeerMonitor(object):
|
||||||
# Audit for require_audit_flag is True or
|
# Audit for require_audit_flag is True or
|
||||||
# Remote peer group is in 'complete' state.
|
# Remote peer group is in 'complete' state.
|
||||||
if (pgam_obj.require_audit_flag
|
if (pgam_obj.require_audit_flag
|
||||||
or remote_peer_group.get("migration_status")
|
or remote_peer_group.get("migration_status") ==
|
||||||
== consts.PEER_GROUP_MIGRATION_COMPLETE
|
consts.PEER_GROUP_MIGRATION_COMPLETE):
|
||||||
):
|
|
||||||
pgam_obj.audit_peer_group_from_system(
|
pgam_obj.audit_peer_group_from_system(
|
||||||
self.peer, remote_peer_group, peer_group)
|
self.peer, remote_peer_group, peer_group)
|
||||||
else:
|
else:
|
||||||
|
@ -191,7 +194,7 @@ class PeerMonitor(object):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def _clean_peer_group_audit_threads(self):
|
def _clean_peer_group_audit_threads(self):
|
||||||
for peer_group_id in self.peer_group_audit_obj_map:
|
for peer_group_id, _ in self.peer_group_audit_obj_map.items():
|
||||||
pgam_obj = \
|
pgam_obj = \
|
||||||
self.peer_group_audit_obj_map[peer_group_id]
|
self.peer_group_audit_obj_map[peer_group_id]
|
||||||
pgam_obj.stop()
|
pgam_obj.stop()
|
||||||
|
@ -235,6 +238,7 @@ class PeerMonitor(object):
|
||||||
|
|
||||||
class PeerMonitorManager(manager.Manager):
|
class PeerMonitorManager(manager.Manager):
|
||||||
"""Manages tasks related to peer monitor."""
|
"""Manages tasks related to peer monitor."""
|
||||||
|
|
||||||
def __init__(self, subcloud_manager):
|
def __init__(self, subcloud_manager):
|
||||||
LOG.debug('PeerMonitorManager initialization...')
|
LOG.debug('PeerMonitorManager initialization...')
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
import six
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import functools
|
import six
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
|
@ -159,16 +162,18 @@ class DCManagerService(service.Service):
|
||||||
# get subcloud by region name
|
# get subcloud by region name
|
||||||
LOG.debug("Handling get_subcloud_name_by_region_name request for "
|
LOG.debug("Handling get_subcloud_name_by_region_name request for "
|
||||||
"region: %s" % subcloud_region)
|
"region: %s" % subcloud_region)
|
||||||
subcloud = self.subcloud_manager.get_subcloud_name_by_region_name(context,
|
subcloud = self.subcloud_manager.get_subcloud_name_by_region_name(
|
||||||
subcloud_region)
|
context, subcloud_region
|
||||||
|
)
|
||||||
return subcloud
|
return subcloud
|
||||||
|
|
||||||
@request_context
|
@request_context
|
||||||
def update_subcloud(self, context, subcloud_id, management_state=None,
|
def update_subcloud(
|
||||||
description=None, location=None,
|
self, context, subcloud_id, management_state=None, description=None,
|
||||||
group_id=None, data_install=None, force=None,
|
location=None, group_id=None, data_install=None, force=None,
|
||||||
deploy_status=None,
|
deploy_status=None, peer_group_id=None, bootstrap_values=None,
|
||||||
peer_group_id=None, bootstrap_values=None, bootstrap_address=None):
|
bootstrap_address=None
|
||||||
|
):
|
||||||
# Updates a subcloud
|
# Updates a subcloud
|
||||||
LOG.info("Handling update_subcloud request for: %s" % subcloud_id)
|
LOG.info("Handling update_subcloud request for: %s" % subcloud_id)
|
||||||
subcloud = self.subcloud_manager.update_subcloud(context, subcloud_id,
|
subcloud = self.subcloud_manager.update_subcloud(context, subcloud_id,
|
||||||
|
@ -188,9 +193,8 @@ class DCManagerService(service.Service):
|
||||||
def update_subcloud_with_network_reconfig(self, context, subcloud_id, payload):
|
def update_subcloud_with_network_reconfig(self, context, subcloud_id, payload):
|
||||||
LOG.info("Handling update_subcloud_with_network_reconfig request for: %s",
|
LOG.info("Handling update_subcloud_with_network_reconfig request for: %s",
|
||||||
subcloud_id)
|
subcloud_id)
|
||||||
return self.subcloud_manager.update_subcloud_with_network_reconfig(context,
|
return self.subcloud_manager.update_subcloud_with_network_reconfig(
|
||||||
subcloud_id,
|
context, subcloud_id, payload)
|
||||||
payload)
|
|
||||||
|
|
||||||
@run_in_thread
|
@run_in_thread
|
||||||
@request_context
|
@request_context
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
@ -95,7 +96,8 @@ ANSIBLE_SUBCLOUD_UPDATE_PLAYBOOK = \
|
||||||
# the support of rehoming a subcloud with a software version below 22.12
|
# the support of rehoming a subcloud with a software version below 22.12
|
||||||
ANSIBLE_VALIDATE_KEYSTONE_PASSWORD_SCRIPT = \
|
ANSIBLE_VALIDATE_KEYSTONE_PASSWORD_SCRIPT = \
|
||||||
consts.ANSIBLE_CURRENT_VERSION_BASE_PATH + \
|
consts.ANSIBLE_CURRENT_VERSION_BASE_PATH + \
|
||||||
'/roles/rehome-subcloud/update-keystone-data/files/validate_keystone_passwords.sh'
|
'/roles/rehome-subcloud/update-keystone-data/files/' + \
|
||||||
|
'validate_keystone_passwords.sh'
|
||||||
|
|
||||||
USERS_TO_REPLICATE = [
|
USERS_TO_REPLICATE = [
|
||||||
'sysinv',
|
'sysinv',
|
||||||
|
@ -344,14 +346,15 @@ class SubcloudManager(manager.Manager):
|
||||||
software_version if software_version else SW_VERSION]
|
software_version if software_version else SW_VERSION]
|
||||||
return bootstrap_command
|
return bootstrap_command
|
||||||
|
|
||||||
def compose_config_command(self, subcloud_name, ansible_subcloud_inventory_file, payload):
|
def compose_config_command(
|
||||||
|
self, subcloud_name, ansible_subcloud_inventory_file, payload):
|
||||||
config_command = [
|
config_command = [
|
||||||
"ansible-playbook", payload[consts.DEPLOY_PLAYBOOK],
|
"ansible-playbook", payload[consts.DEPLOY_PLAYBOOK],
|
||||||
"-e", "@%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
"-e", "@%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
||||||
subcloud_name + '_deploy_values.yml',
|
subcloud_name + '_deploy_values.yml',
|
||||||
"-i", ansible_subcloud_inventory_file,
|
"-i", ansible_subcloud_inventory_file,
|
||||||
"--limit", subcloud_name
|
"--limit", subcloud_name
|
||||||
]
|
]
|
||||||
return config_command
|
return config_command
|
||||||
|
|
||||||
def compose_backup_command(self, subcloud_name, ansible_subcloud_inventory_file):
|
def compose_backup_command(self, subcloud_name, ansible_subcloud_inventory_file):
|
||||||
|
@ -359,34 +362,42 @@ class SubcloudManager(manager.Manager):
|
||||||
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_CREATE_PLAYBOOK,
|
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_CREATE_PLAYBOOK,
|
||||||
"-i", ansible_subcloud_inventory_file,
|
"-i", ansible_subcloud_inventory_file,
|
||||||
"--limit", subcloud_name,
|
"--limit", subcloud_name,
|
||||||
"-e", "subcloud_bnr_overrides=%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
"-e",
|
||||||
subcloud_name + "_backup_create_values.yml"]
|
"subcloud_bnr_overrides=%s" % (
|
||||||
|
dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" + subcloud_name +
|
||||||
|
"_backup_create_values.yml"
|
||||||
|
)
|
||||||
|
]
|
||||||
return backup_command
|
return backup_command
|
||||||
|
|
||||||
def compose_backup_delete_command(self, subcloud_name,
|
def compose_backup_delete_command(self, subcloud_name,
|
||||||
ansible_subcloud_inventory_file=None):
|
ansible_subcloud_inventory_file=None):
|
||||||
backup_command = [
|
backup_command = [
|
||||||
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_DELETE_PLAYBOOK,
|
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_DELETE_PLAYBOOK,
|
||||||
"-e", "subcloud_bnr_overrides=%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
"-e", "subcloud_bnr_overrides=%s" %
|
||||||
subcloud_name + "_backup_delete_values.yml"]
|
dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
||||||
|
subcloud_name + "_backup_delete_values.yml"
|
||||||
|
]
|
||||||
if ansible_subcloud_inventory_file:
|
if ansible_subcloud_inventory_file:
|
||||||
# Backup stored in subcloud storage
|
# Backup stored in subcloud storage
|
||||||
backup_command.extend(("-i", ansible_subcloud_inventory_file,
|
backup_command.extend(("-i", ansible_subcloud_inventory_file,
|
||||||
"--limit", subcloud_name))
|
"--limit", subcloud_name))
|
||||||
else:
|
else:
|
||||||
# Backup stored in central storage
|
# Backup stored in central storage
|
||||||
backup_command.extend(("-e", "inventory_hostname=%s" % subcloud_name))
|
backup_command.extend(("-e", "inventory_hostname=%s" % subcloud_name))
|
||||||
return backup_command
|
return backup_command
|
||||||
|
|
||||||
def compose_backup_restore_command(self, subcloud_name, ansible_subcloud_inventory_file):
|
def compose_backup_restore_command(
|
||||||
|
self, subcloud_name, ansible_subcloud_inventory_file):
|
||||||
backup_command = [
|
backup_command = [
|
||||||
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_RESTORE_PLAYBOOK,
|
"ansible-playbook", ANSIBLE_SUBCLOUD_BACKUP_RESTORE_PLAYBOOK,
|
||||||
"-i", ansible_subcloud_inventory_file,
|
"-i", ansible_subcloud_inventory_file,
|
||||||
"--limit", subcloud_name,
|
"--limit", subcloud_name,
|
||||||
"-e", "subcloud_bnr_overrides=%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
"-e", "subcloud_bnr_overrides=%s" % (
|
||||||
subcloud_name + "_backup_restore_values.yml"]
|
dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" + subcloud_name +
|
||||||
|
"_backup_restore_values.yml"
|
||||||
|
)
|
||||||
|
]
|
||||||
return backup_command
|
return backup_command
|
||||||
|
|
||||||
def compose_update_command(self, subcloud_name, ansible_subcloud_inventory_file):
|
def compose_update_command(self, subcloud_name, ansible_subcloud_inventory_file):
|
||||||
|
@ -395,8 +406,11 @@ class SubcloudManager(manager.Manager):
|
||||||
"-i", ansible_subcloud_inventory_file,
|
"-i", ansible_subcloud_inventory_file,
|
||||||
"--limit", subcloud_name,
|
"--limit", subcloud_name,
|
||||||
"--timeout", UPDATE_PLAYBOOK_TIMEOUT,
|
"--timeout", UPDATE_PLAYBOOK_TIMEOUT,
|
||||||
"-e", "subcloud_update_overrides=%s" % dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" +
|
"-e", "subcloud_update_overrides=%s" % (
|
||||||
subcloud_name + "_update_values.yml"]
|
dccommon_consts.ANSIBLE_OVERRIDES_PATH + "/" + subcloud_name +
|
||||||
|
"_update_values.yml"
|
||||||
|
)
|
||||||
|
]
|
||||||
return subcloud_update_command
|
return subcloud_update_command
|
||||||
|
|
||||||
def compose_rehome_command(self, subcloud_name, subcloud_region,
|
def compose_rehome_command(self, subcloud_name, subcloud_region,
|
||||||
|
@ -447,7 +461,7 @@ class SubcloudManager(manager.Manager):
|
||||||
while True:
|
while True:
|
||||||
offline_seconds = time.monotonic() - job_done_ts
|
offline_seconds = time.monotonic() - job_done_ts
|
||||||
if subcloud.availability_status == \
|
if subcloud.availability_status == \
|
||||||
dccommon_consts.AVAILABILITY_OFFLINE:
|
dccommon_consts.AVAILABILITY_OFFLINE:
|
||||||
if offline_seconds >= consts.BATCH_REHOME_MGMT_STATES_TIMEOUT:
|
if offline_seconds >= consts.BATCH_REHOME_MGMT_STATES_TIMEOUT:
|
||||||
LOG.warning("Skip trying to manage subcloud: %s, "
|
LOG.warning("Skip trying to manage subcloud: %s, "
|
||||||
"wait online timeout [%d]" %
|
"wait online timeout [%d]" %
|
||||||
|
@ -487,7 +501,7 @@ class SubcloudManager(manager.Manager):
|
||||||
self.context, association.system_peer_id)
|
self.context, association.system_peer_id)
|
||||||
# Get 'available' system peer
|
# Get 'available' system peer
|
||||||
if system_peer.availability_state != \
|
if system_peer.availability_state != \
|
||||||
consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE:
|
consts.SYSTEM_PEER_AVAILABILITY_STATE_AVAILABLE:
|
||||||
LOG.warning("Peer system %s offline, skip checking" %
|
LOG.warning("Peer system %s offline, skip checking" %
|
||||||
system_peer.peer_name)
|
system_peer.peer_name)
|
||||||
continue
|
continue
|
||||||
|
@ -607,16 +621,19 @@ class SubcloudManager(manager.Manager):
|
||||||
# subcloud_ref could be int type id.
|
# subcloud_ref could be int type id.
|
||||||
subcloud = utils.subcloud_get_by_ref(context, str(subcloud_ref))
|
subcloud = utils.subcloud_get_by_ref(context, str(subcloud_ref))
|
||||||
if not subcloud:
|
if not subcloud:
|
||||||
LOG.error("Failed to migrate, non-existent subcloud %s" % subcloud_ref)
|
LOG.error(
|
||||||
|
"Failed to migrate, non-existent subcloud %s" % subcloud_ref
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if 'sysadmin_password' not in payload:
|
if 'sysadmin_password' not in payload:
|
||||||
LOG.error("Failed to migrate subcloud: %s, must provide sysadmin_password" %
|
LOG.error("Failed to migrate subcloud: %s, must provide "
|
||||||
subcloud.name)
|
"sysadmin_password" % subcloud.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
if subcloud.deploy_status not in [consts.DEPLOY_STATE_SECONDARY,
|
if subcloud.deploy_status not in [
|
||||||
consts.DEPLOY_STATE_REHOME_FAILED,
|
consts.DEPLOY_STATE_SECONDARY, consts.DEPLOY_STATE_REHOME_FAILED,
|
||||||
consts.DEPLOY_STATE_REHOME_PREP_FAILED]:
|
consts.DEPLOY_STATE_REHOME_PREP_FAILED
|
||||||
|
]:
|
||||||
LOG.error("Failed to migrate subcloud: %s, "
|
LOG.error("Failed to migrate subcloud: %s, "
|
||||||
"must be in secondary or rehome failure state" %
|
"must be in secondary or rehome failure state" %
|
||||||
subcloud.name)
|
subcloud.name)
|
||||||
|
@ -628,7 +645,8 @@ class SubcloudManager(manager.Manager):
|
||||||
rehome_data = json.loads(subcloud.rehome_data)
|
rehome_data = json.loads(subcloud.rehome_data)
|
||||||
saved_payload = rehome_data['saved_payload']
|
saved_payload = rehome_data['saved_payload']
|
||||||
# Update sysadmin_password
|
# Update sysadmin_password
|
||||||
sysadmin_password = base64.b64decode(payload['sysadmin_password']).decode('utf-8')
|
sysadmin_password = \
|
||||||
|
base64.b64decode(payload['sysadmin_password']).decode('utf-8')
|
||||||
saved_payload['sysadmin_password'] = sysadmin_password
|
saved_payload['sysadmin_password'] = sysadmin_password
|
||||||
# Decode admin_password
|
# Decode admin_password
|
||||||
if 'admin_password' in saved_payload:
|
if 'admin_password' in saved_payload:
|
||||||
|
@ -814,7 +832,8 @@ class SubcloudManager(manager.Manager):
|
||||||
:param subcloud_id: id of the subcloud
|
:param subcloud_id: id of the subcloud
|
||||||
:param payload: subcloud configuration
|
:param payload: subcloud configuration
|
||||||
"""
|
"""
|
||||||
LOG.info(f"Adding subcloud {payload['name']} with region {payload['region_name']}.")
|
LOG.info(f"Adding subcloud {payload['name']} with region "
|
||||||
|
f"{payload['region_name']}.")
|
||||||
|
|
||||||
rehoming = payload.get('migrate', '').lower() == "true"
|
rehoming = payload.get('migrate', '').lower() == "true"
|
||||||
secondary = (payload.get('secondary', '').lower() == "true")
|
secondary = (payload.get('secondary', '').lower() == "true")
|
||||||
|
@ -1202,8 +1221,9 @@ class SubcloudManager(manager.Manager):
|
||||||
:param payload: subcloud resume payload
|
:param payload: subcloud resume payload
|
||||||
:param deploy_states_to_run: deploy phases pending execution
|
:param deploy_states_to_run: deploy phases pending execution
|
||||||
"""
|
"""
|
||||||
LOG.info("Resuming deployment of subcloud %s. Deploy phases to be executed: %s"
|
LOG.info(
|
||||||
% (subcloud_name, ', '.join(deploy_states_to_run)))
|
"Resuming deployment of subcloud %s. Deploy phases to be executed: %s" %
|
||||||
|
(subcloud_name, ', '.join(deploy_states_to_run)))
|
||||||
|
|
||||||
self.run_deploy_phases(context, subcloud_id, payload,
|
self.run_deploy_phases(context, subcloud_id, payload,
|
||||||
deploy_states_to_run,
|
deploy_states_to_run,
|
||||||
|
@ -1294,7 +1314,8 @@ class SubcloudManager(manager.Manager):
|
||||||
:param payload: subcloud configuration
|
:param payload: subcloud configuration
|
||||||
:param rehoming: flag indicating if this is part of a rehoming operation
|
:param rehoming: flag indicating if this is part of a rehoming operation
|
||||||
:param initial_deployment: initial_deployment flag from subcloud inventory
|
:param initial_deployment: initial_deployment flag from subcloud inventory
|
||||||
:param return_as_dict: converts the subcloud DB object to a dict before returning
|
:param return_as_dict: converts the subcloud DB object to a dict before
|
||||||
|
returning
|
||||||
:return: resulting subcloud DB object or dictionary
|
:return: resulting subcloud DB object or dictionary
|
||||||
"""
|
"""
|
||||||
LOG.info("Creating subcloud %s." % payload['name'])
|
LOG.info("Creating subcloud %s." % payload['name'])
|
||||||
|
@ -1454,7 +1475,8 @@ class SubcloudManager(manager.Manager):
|
||||||
if 'admin_password' in original_payload:
|
if 'admin_password' in original_payload:
|
||||||
# Encode admin_password
|
# Encode admin_password
|
||||||
original_payload['admin_password'] = base64.b64encode(
|
original_payload['admin_password'] = base64.b64encode(
|
||||||
original_payload['admin_password'].encode("utf-8")).decode('utf-8')
|
original_payload['admin_password'].encode("utf-8")
|
||||||
|
).decode('utf-8')
|
||||||
bootstrap_info = utils.create_subcloud_rehome_data_template()
|
bootstrap_info = utils.create_subcloud_rehome_data_template()
|
||||||
bootstrap_info['saved_payload'] = original_payload
|
bootstrap_info['saved_payload'] = original_payload
|
||||||
rehome_data = json.dumps(bootstrap_info)
|
rehome_data = json.dumps(bootstrap_info)
|
||||||
|
@ -1914,11 +1936,13 @@ class SubcloudManager(manager.Manager):
|
||||||
return subcloud, success
|
return subcloud, success
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _build_subcloud_operation_notice(operation, failed_subclouds, invalid_subclouds):
|
def _build_subcloud_operation_notice(
|
||||||
|
operation, failed_subclouds, invalid_subclouds):
|
||||||
invalid_subcloud_names = [subcloud.name for subcloud in invalid_subclouds]
|
invalid_subcloud_names = [subcloud.name for subcloud in invalid_subclouds]
|
||||||
failed_subcloud_names = [subcloud.name for subcloud in failed_subclouds]
|
failed_subcloud_names = [subcloud.name for subcloud in failed_subclouds]
|
||||||
|
|
||||||
notice = "Subcloud backup %s operation completed with warnings:\n" % operation
|
notice = (
|
||||||
|
"Subcloud backup %s operation completed with warnings:\n" % operation)
|
||||||
if invalid_subclouds:
|
if invalid_subclouds:
|
||||||
notice += ("The following subclouds were skipped for local backup "
|
notice += ("The following subclouds were skipped for local backup "
|
||||||
"%s operation: %s."
|
"%s operation: %s."
|
||||||
|
@ -2417,15 +2441,21 @@ class SubcloudManager(manager.Manager):
|
||||||
# both controllers.
|
# both controllers.
|
||||||
management_subnet = netaddr.IPNetwork(subcloud.management_subnet)
|
management_subnet = netaddr.IPNetwork(subcloud.management_subnet)
|
||||||
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
|
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
|
||||||
sysinv_client = SysinvClient(dccommon_consts.DEFAULT_REGION_NAME, keystone_client.session,
|
sysinv_client = SysinvClient(
|
||||||
endpoint=endpoint)
|
dccommon_consts.DEFAULT_REGION_NAME,
|
||||||
cached_regionone_data = self._get_cached_regionone_data(keystone_client, sysinv_client)
|
keystone_client.session,
|
||||||
|
endpoint=endpoint
|
||||||
|
)
|
||||||
|
cached_regionone_data = self._get_cached_regionone_data(
|
||||||
|
keystone_client, sysinv_client)
|
||||||
for mgmt_if_uuid in cached_regionone_data['mgmt_interface_uuids']:
|
for mgmt_if_uuid in cached_regionone_data['mgmt_interface_uuids']:
|
||||||
sysinv_client.delete_route(mgmt_if_uuid,
|
sysinv_client.delete_route(
|
||||||
str(management_subnet.ip),
|
mgmt_if_uuid,
|
||||||
management_subnet.prefixlen,
|
str(management_subnet.ip),
|
||||||
str(netaddr.IPAddress(subcloud.systemcontroller_gateway_ip)),
|
management_subnet.prefixlen,
|
||||||
1)
|
str(netaddr.IPAddress(subcloud.systemcontroller_gateway_ip)),
|
||||||
|
1
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _delete_subcloud_cert(subcloud_region):
|
def _delete_subcloud_cert(subcloud_region):
|
||||||
|
@ -2558,7 +2588,7 @@ class SubcloudManager(manager.Manager):
|
||||||
mkey = list(data.keys())[0]
|
mkey = list(data.keys())[0]
|
||||||
|
|
||||||
if mkey in data and 'hosts' in data[mkey] and \
|
if mkey in data and 'hosts' in data[mkey] and \
|
||||||
cur_sc_name in data[mkey]['hosts']:
|
cur_sc_name in data[mkey]['hosts']:
|
||||||
|
|
||||||
data[mkey]['hosts'][new_sc_name] = \
|
data[mkey]['hosts'][new_sc_name] = \
|
||||||
data[mkey]['hosts'].pop(cur_sc_name)
|
data[mkey]['hosts'].pop(cur_sc_name)
|
||||||
|
@ -2758,8 +2788,11 @@ class SubcloudManager(manager.Manager):
|
||||||
# it's necessary to save it first, then put it back after
|
# it's necessary to save it first, then put it back after
|
||||||
# after bootstrap_values is updated.
|
# after bootstrap_values is updated.
|
||||||
if 'bootstrap-address' in rehome_data_dict['saved_payload']:
|
if 'bootstrap-address' in rehome_data_dict['saved_payload']:
|
||||||
_bootstrap_address = rehome_data_dict['saved_payload']['bootstrap-address']
|
_bootstrap_address = \
|
||||||
bootstrap_values_dict = yaml.load(bootstrap_values, Loader=yaml.SafeLoader)
|
rehome_data_dict['saved_payload']['bootstrap-address']
|
||||||
|
bootstrap_values_dict = yaml.load(
|
||||||
|
bootstrap_values, Loader=yaml.SafeLoader
|
||||||
|
)
|
||||||
|
|
||||||
# remove sysadmin_password,ansible_ssh_pass,ansible_become_pass
|
# remove sysadmin_password,ansible_ssh_pass,ansible_become_pass
|
||||||
# encode admin_password
|
# encode admin_password
|
||||||
|
@ -2771,11 +2804,13 @@ class SubcloudManager(manager.Manager):
|
||||||
del bootstrap_values_dict['ansible_become_pass']
|
del bootstrap_values_dict['ansible_become_pass']
|
||||||
if 'admin_password' in bootstrap_values_dict:
|
if 'admin_password' in bootstrap_values_dict:
|
||||||
bootstrap_values_dict['admin_password'] = base64.b64encode(
|
bootstrap_values_dict['admin_password'] = base64.b64encode(
|
||||||
bootstrap_values_dict['admin_password'].encode("utf-8")).decode('utf-8')
|
bootstrap_values_dict['admin_password'].encode("utf-8")
|
||||||
|
).decode('utf-8')
|
||||||
rehome_data_dict['saved_payload'] = bootstrap_values_dict
|
rehome_data_dict['saved_payload'] = bootstrap_values_dict
|
||||||
# put bootstrap_address back into rehome_data_dict
|
# put bootstrap_address back into rehome_data_dict
|
||||||
if _bootstrap_address:
|
if _bootstrap_address:
|
||||||
rehome_data_dict['saved_payload']['bootstrap-address'] = _bootstrap_address
|
rehome_data_dict['saved_payload'][
|
||||||
|
'bootstrap-address'] = _bootstrap_address
|
||||||
|
|
||||||
# update bootstrap_address
|
# update bootstrap_address
|
||||||
if bootstrap_address:
|
if bootstrap_address:
|
||||||
|
@ -2784,7 +2819,8 @@ class SubcloudManager(manager.Manager):
|
||||||
resource='subcloud',
|
resource='subcloud',
|
||||||
msg='Cannot update bootstrap_address into rehome data, '
|
msg='Cannot update bootstrap_address into rehome data, '
|
||||||
'need to import bootstrap_values first')
|
'need to import bootstrap_values first')
|
||||||
rehome_data_dict['saved_payload']['bootstrap-address'] = bootstrap_address
|
rehome_data_dict['saved_payload'][
|
||||||
|
'bootstrap-address'] = bootstrap_address
|
||||||
|
|
||||||
rehome_data = None
|
rehome_data = None
|
||||||
if rehome_data_dict:
|
if rehome_data_dict:
|
||||||
|
@ -3195,7 +3231,9 @@ class SubcloudManager(manager.Manager):
|
||||||
try:
|
try:
|
||||||
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Failed to get subcloud by region name: %s" % subcloud_region)
|
LOG.exception(
|
||||||
|
"Failed to get subcloud by region name: %s" % subcloud_region
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -3256,9 +3294,10 @@ class SubcloudManager(manager.Manager):
|
||||||
return prestage.prestage_subcloud(context, payload)
|
return prestage.prestage_subcloud(context, payload)
|
||||||
|
|
||||||
@utils.synchronized("regionone-data-cache", external=False)
|
@utils.synchronized("regionone-data-cache", external=False)
|
||||||
def _get_cached_regionone_data(self, regionone_keystone_client, regionone_sysinv_client=None):
|
def _get_cached_regionone_data(
|
||||||
if (not SubcloudManager.regionone_data or
|
self, regionone_keystone_client, regionone_sysinv_client=None):
|
||||||
SubcloudManager.regionone_data['expiry'] <= datetime.datetime.utcnow()):
|
if (not SubcloudManager.regionone_data or SubcloudManager.regionone_data[
|
||||||
|
'expiry'] <= datetime.datetime.utcnow()):
|
||||||
user_list = regionone_keystone_client.get_enabled_users(id_only=False)
|
user_list = regionone_keystone_client.get_enabled_users(id_only=False)
|
||||||
for user in user_list:
|
for user in user_list:
|
||||||
if user.name == dccommon_consts.ADMIN_USER_NAME:
|
if user.name == dccommon_consts.ADMIN_USER_NAME:
|
||||||
|
@ -3268,15 +3307,18 @@ class SubcloudManager(manager.Manager):
|
||||||
elif user.name == dccommon_consts.DCMANAGER_USER_NAME:
|
elif user.name == dccommon_consts.DCMANAGER_USER_NAME:
|
||||||
SubcloudManager.regionone_data['dcmanager_user_id'] = user.id
|
SubcloudManager.regionone_data['dcmanager_user_id'] = user.id
|
||||||
|
|
||||||
project_list = regionone_keystone_client.get_enabled_projects(id_only=False)
|
project_list = regionone_keystone_client.get_enabled_projects(
|
||||||
|
id_only=False)
|
||||||
for project in project_list:
|
for project in project_list:
|
||||||
if project.name == dccommon_consts.ADMIN_PROJECT_NAME:
|
if project.name == dccommon_consts.ADMIN_PROJECT_NAME:
|
||||||
SubcloudManager.regionone_data['admin_project_id'] = project.id
|
SubcloudManager.regionone_data['admin_project_id'] = project.id
|
||||||
elif project.name == dccommon_consts.SERVICES_USER_NAME:
|
elif project.name == dccommon_consts.SERVICES_USER_NAME:
|
||||||
SubcloudManager.regionone_data['services_project_id'] = project.id
|
SubcloudManager.regionone_data['services_project_id'] = \
|
||||||
|
project.id
|
||||||
|
|
||||||
if regionone_sysinv_client is None:
|
if regionone_sysinv_client is None:
|
||||||
endpoint = regionone_keystone_client.endpoint_cache.get_endpoint('sysinv')
|
endpoint = regionone_keystone_client.endpoint_cache.get_endpoint(
|
||||||
|
'sysinv')
|
||||||
regionone_sysinv_client = SysinvClient(
|
regionone_sysinv_client = SysinvClient(
|
||||||
dccommon_consts.DEFAULT_REGION_NAME,
|
dccommon_consts.DEFAULT_REGION_NAME,
|
||||||
regionone_keystone_client.session,
|
regionone_keystone_client.session,
|
||||||
|
@ -3289,8 +3331,8 @@ class SubcloudManager(manager.Manager):
|
||||||
controller.hostname)
|
controller.hostname)
|
||||||
if mgmt_interface is not None:
|
if mgmt_interface is not None:
|
||||||
mgmt_interface_uuids.append(mgmt_interface.uuid)
|
mgmt_interface_uuids.append(mgmt_interface.uuid)
|
||||||
SubcloudManager.regionone_data['mgmt_interface_uuids'] = mgmt_interface_uuids
|
SubcloudManager.regionone_data['mgmt_interface_uuids'] = \
|
||||||
|
mgmt_interface_uuids
|
||||||
SubcloudManager.regionone_data['mgmt_pool'] = \
|
SubcloudManager.regionone_data['mgmt_pool'] = \
|
||||||
regionone_sysinv_client.get_management_address_pool()
|
regionone_sysinv_client.get_management_address_pool()
|
||||||
SubcloudManager.regionone_data['oam_addresses'] = \
|
SubcloudManager.regionone_data['oam_addresses'] = \
|
||||||
|
@ -3298,7 +3340,8 @@ class SubcloudManager(manager.Manager):
|
||||||
|
|
||||||
SubcloudManager.regionone_data['expiry'] = \
|
SubcloudManager.regionone_data['expiry'] = \
|
||||||
datetime.datetime.utcnow() + datetime.timedelta(hours=1)
|
datetime.datetime.utcnow() + datetime.timedelta(hours=1)
|
||||||
LOG.info("RegionOne cached data updated %s" % SubcloudManager.regionone_data)
|
LOG.info(
|
||||||
|
"RegionOne cached data updated %s" % SubcloudManager.regionone_data)
|
||||||
|
|
||||||
cached_regionone_data = SubcloudManager.regionone_data
|
cached_regionone_data = SubcloudManager.regionone_data
|
||||||
return cached_regionone_data
|
return cached_regionone_data
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -116,7 +116,8 @@ class SystemPeerManager(manager.Manager):
|
||||||
"""
|
"""
|
||||||
if SystemPeerManager.get_subcloud_deploy_status(subcloud) not in (
|
if SystemPeerManager.get_subcloud_deploy_status(subcloud) not in (
|
||||||
consts.DEPLOY_STATE_SECONDARY_FAILED,
|
consts.DEPLOY_STATE_SECONDARY_FAILED,
|
||||||
consts.DEPLOY_STATE_SECONDARY):
|
consts.DEPLOY_STATE_SECONDARY
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -305,7 +306,7 @@ class SystemPeerManager(manager.Manager):
|
||||||
|
|
||||||
validation = self._is_valid_for_subcloud_sync(subcloud)
|
validation = self._is_valid_for_subcloud_sync(subcloud)
|
||||||
if validation != VERIFY_SUBCLOUD_SYNC_IGNORE and \
|
if validation != VERIFY_SUBCLOUD_SYNC_IGNORE and \
|
||||||
validation != VERIFY_SUBCLOUD_SYNC_VALID:
|
validation != VERIFY_SUBCLOUD_SYNC_VALID:
|
||||||
LOG.error(validation)
|
LOG.error(validation)
|
||||||
error_msg[subcloud_name] = validation
|
error_msg[subcloud_name] = validation
|
||||||
continue
|
continue
|
||||||
|
@ -675,7 +676,7 @@ class SystemPeerManager(manager.Manager):
|
||||||
LOG.info(f"Deleted Subcloud Peer Group {peer_group_name} "
|
LOG.info(f"Deleted Subcloud Peer Group {peer_group_name} "
|
||||||
f"on peer site.")
|
f"on peer site.")
|
||||||
except dccommon_exceptions.\
|
except dccommon_exceptions.\
|
||||||
SubcloudPeerGroupDeleteFailedAssociated:
|
SubcloudPeerGroupDeleteFailedAssociated:
|
||||||
LOG.error(f"Subcloud Peer Group {peer_group_name} "
|
LOG.error(f"Subcloud Peer Group {peer_group_name} "
|
||||||
"delete failed as it is associated with System "
|
"delete failed as it is associated with System "
|
||||||
"Peer on peer site.")
|
"Peer on peer site.")
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import datetime
|
import datetime
|
||||||
import threading
|
import threading
|
||||||
|
@ -196,7 +197,8 @@ class OrchThread(threading.Thread):
|
||||||
return state_operator(
|
return state_operator(
|
||||||
region_name=OrchThread.get_region_name(strategy_step))
|
region_name=OrchThread.get_region_name(strategy_step))
|
||||||
|
|
||||||
def strategy_step_update(self, subcloud_id, state=None, details=None, stage=None):
|
def strategy_step_update(
|
||||||
|
self, subcloud_id, state=None, details=None, stage=None):
|
||||||
"""Update the strategy step in the DB
|
"""Update the strategy step in the DB
|
||||||
|
|
||||||
Sets the start and finished timestamp if necessary, based on state.
|
Sets the start and finished timestamp if necessary, based on state.
|
||||||
|
@ -219,9 +221,10 @@ class OrchThread(threading.Thread):
|
||||||
finished_at=finished_at)
|
finished_at=finished_at)
|
||||||
|
|
||||||
def _delete_subcloud_worker(self, region, subcloud_id):
|
def _delete_subcloud_worker(self, region, subcloud_id):
|
||||||
db_api.strategy_step_update(self.context,
|
db_api.strategy_step_update(
|
||||||
subcloud_id,
|
self.context,
|
||||||
stage=consts.STAGE_SUBCLOUD_ORCHESTRATION_PROCESSED)
|
subcloud_id,
|
||||||
|
stage=consts.STAGE_SUBCLOUD_ORCHESTRATION_PROCESSED)
|
||||||
if region in self.subcloud_workers:
|
if region in self.subcloud_workers:
|
||||||
# The orchestration for this subcloud has either
|
# The orchestration for this subcloud has either
|
||||||
# completed/failed/aborted, remove it from the
|
# completed/failed/aborted, remove it from the
|
||||||
|
@ -387,8 +390,8 @@ class OrchThread(threading.Thread):
|
||||||
continue
|
continue
|
||||||
elif strategy_step.state == \
|
elif strategy_step.state == \
|
||||||
consts.STRATEGY_STATE_INITIAL:
|
consts.STRATEGY_STATE_INITIAL:
|
||||||
if sw_update_strategy.max_parallel_subclouds > len(self.subcloud_workers) \
|
if sw_update_strategy.max_parallel_subclouds > \
|
||||||
and not stop:
|
len(self.subcloud_workers) and not stop:
|
||||||
# Don't start upgrading this subcloud if it has been
|
# Don't start upgrading this subcloud if it has been
|
||||||
# unmanaged by the user. If orchestration was already
|
# unmanaged by the user. If orchestration was already
|
||||||
# started, it will be allowed to complete.
|
# started, it will be allowed to complete.
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.orchestrator.orch_thread import OrchThread
|
from dcmanager.orchestrator.orch_thread import OrchThread
|
||||||
|
@ -28,7 +30,6 @@ from dcmanager.orchestrator.states.patch.job_data import PatchJobData
|
||||||
from dcmanager.orchestrator.states.patch.pre_check import PreCheckState
|
from dcmanager.orchestrator.states.patch.pre_check import PreCheckState
|
||||||
from dcmanager.orchestrator.states.patch.updating_patches import \
|
from dcmanager.orchestrator.states.patch.updating_patches import \
|
||||||
UpdatingPatchesState
|
UpdatingPatchesState
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# All Rights Reserved.
|
||||||
# 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
|
# 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
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
#
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# implied.
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# See the License for the specific language governing permissions and
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# limitations under the License.
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
from oslo_service import service
|
from oslo_service import service
|
||||||
|
import six
|
||||||
|
|
||||||
from dccommon.subprocess_cleanup import SubprocessCleanup
|
from dccommon.subprocess_cleanup import SubprocessCleanup
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
|
@ -120,8 +121,8 @@ class CreatingVIMStrategyState(BaseState):
|
||||||
raise_error_if_missing=True)
|
raise_error_if_missing=True)
|
||||||
|
|
||||||
# Check for skip criteria where a failed 'build' might be expected
|
# Check for skip criteria where a failed 'build' might be expected
|
||||||
skip_state = self.skip_check(strategy_step, # pylint: disable=assignment-from-none
|
# pylint: disable-next=assignment-from-none
|
||||||
subcloud_strategy)
|
skip_state = self.skip_check(strategy_step, subcloud_strategy)
|
||||||
if skip_state is not None:
|
if skip_state is not None:
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Skip forward to state:(%s)" % skip_state)
|
"Skip forward to state:(%s)" % skip_state)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
# Copyright (c) 2020, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
|
@ -30,7 +31,8 @@ class ApplyingVIMStrategyState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(ApplyingVIMStrategyState, self).__init__(
|
super(ApplyingVIMStrategyState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_FINISHING_FW_UPDATE, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_FINISHING_FW_UPDATE,
|
||||||
|
region_name=region_name)
|
||||||
self.max_failed_queries = DEFAULT_MAX_FAILED_QUERIES
|
self.max_failed_queries = DEFAULT_MAX_FAILED_QUERIES
|
||||||
self.wait_attempts = DEFAULT_MAX_WAIT_ATTEMPTS
|
self.wait_attempts = DEFAULT_MAX_WAIT_ATTEMPTS
|
||||||
self.wait_interval = WAIT_INTERVAL
|
self.wait_interval = WAIT_INTERVAL
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
# Copyright (c) 2020, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
|
@ -21,7 +22,8 @@ class CreatingVIMStrategyState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(CreatingVIMStrategyState, self).__init__(
|
super(CreatingVIMStrategyState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_APPLYING_FW_UPDATE_STRATEGY, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_APPLYING_FW_UPDATE_STRATEGY,
|
||||||
|
region_name=region_name)
|
||||||
# max time to wait for the strategy to be built (in seconds)
|
# max time to wait for the strategy to be built (in seconds)
|
||||||
# is: sleep_duration * max_queries
|
# is: sleep_duration * max_queries
|
||||||
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
|
@ -107,7 +108,8 @@ class FinishingFwUpdateState(BaseState):
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
if fail_counter >= self.max_failed_queries:
|
if fail_counter >= self.max_failed_queries:
|
||||||
raise Exception("Timeout waiting to query subcloud device image info")
|
raise Exception(
|
||||||
|
"Timeout waiting to query subcloud device image info")
|
||||||
fail_counter += 1
|
fail_counter += 1
|
||||||
time.sleep(self.failed_sleep_duration)
|
time.sleep(self.failed_sleep_duration)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
# Copyright (c) 2020-2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
|
@ -20,7 +21,8 @@ class ImportingFirmwareState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(ImportingFirmwareState, self).__init__(
|
super(ImportingFirmwareState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_CREATING_FW_UPDATE_STRATEGY, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_CREATING_FW_UPDATE_STRATEGY,
|
||||||
|
region_name=region_name)
|
||||||
|
|
||||||
def _image_in_list(self, image, image_list):
|
def _image_in_list(self, image, image_list):
|
||||||
# todo(abailey): FUTURE. There may be other ways that two images can
|
# todo(abailey): FUTURE. There may be other ways that two images can
|
||||||
|
@ -139,8 +141,8 @@ class ImportingFirmwareState(BaseState):
|
||||||
# However, it may not have been applied to this device
|
# However, it may not have been applied to this device
|
||||||
device_image_state = None
|
device_image_state = None
|
||||||
for device_image_state_obj in subcloud_device_image_states:
|
for device_image_state_obj in subcloud_device_image_states:
|
||||||
if device_image_state_obj.pcidevice_uuid == device.uuid\
|
if device_image_state_obj.pcidevice_uuid == device.uuid \
|
||||||
and device_image_state_obj.image_uuid == image.uuid:
|
and device_image_state_obj.image_uuid == image.uuid:
|
||||||
device_image_state = device_image_state_obj
|
device_image_state = device_image_state_obj
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
# Copyright (c) 2020, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# Device Image Status - duplicated from sysinv/common/device.py
|
# Device Image Status - duplicated from sysinv/common/device.py
|
||||||
|
@ -105,7 +106,7 @@ def determine_image_fields(image):
|
||||||
'bmc',
|
'bmc',
|
||||||
'retimer_included']
|
'retimer_included']
|
||||||
fields = dict((k, str(v)) for (k, v) in vars(image).items()
|
fields = dict((k, str(v)) for (k, v) in vars(image).items()
|
||||||
if k in field_list and not (v is None))
|
if k in field_list and v)
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,10 +117,10 @@ def check_for_label_match(subcloud_host_device_label_list,
|
||||||
# todo(abailey): should this compare pci_device_uuid or vendor/device
|
# todo(abailey): should this compare pci_device_uuid or vendor/device
|
||||||
for device_label in subcloud_host_device_label_list:
|
for device_label in subcloud_host_device_label_list:
|
||||||
if device_label.pcidevice_uuid and \
|
if device_label.pcidevice_uuid and \
|
||||||
device_uuid == device_label.pcidevice_uuid and \
|
device_uuid == device_label.pcidevice_uuid and \
|
||||||
label_key == device_label.label_key and \
|
label_key == device_label.label_key and \
|
||||||
label_value == device_label.label_value:
|
label_value == device_label.label_value:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dccommon.consts import DEFAULT_REGION_NAME
|
from dccommon.consts import DEFAULT_REGION_NAME
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
@ -48,7 +49,9 @@ class CreatingVIMKubeUpgradeStrategyState(CreatingVIMStrategyState):
|
||||||
if to_version is None:
|
if to_version is None:
|
||||||
sys_kube_versions = \
|
sys_kube_versions = \
|
||||||
self.get_sysinv_client(DEFAULT_REGION_NAME).get_kube_versions()
|
self.get_sysinv_client(DEFAULT_REGION_NAME).get_kube_versions()
|
||||||
to_version = dcmanager_utils.get_active_kube_version(sys_kube_versions)
|
to_version = dcmanager_utils.get_active_kube_version(
|
||||||
|
sys_kube_versions
|
||||||
|
)
|
||||||
if to_version is None:
|
if to_version is None:
|
||||||
# No active target kube version on the system controller means
|
# No active target kube version on the system controller means
|
||||||
# the system controller is part-way through a kube upgrade
|
# the system controller is part-way through a kube upgrade
|
||||||
|
@ -59,7 +62,9 @@ class CreatingVIMKubeUpgradeStrategyState(CreatingVIMStrategyState):
|
||||||
kube_versions = \
|
kube_versions = \
|
||||||
self.get_sysinv_client(region).get_kube_versions()
|
self.get_sysinv_client(region).get_kube_versions()
|
||||||
target_kube_version = \
|
target_kube_version = \
|
||||||
dcmanager_utils.select_available_kube_version(kube_versions, to_version)
|
dcmanager_utils.select_available_kube_version(
|
||||||
|
kube_versions, to_version
|
||||||
|
)
|
||||||
|
|
||||||
# Get the update options
|
# Get the update options
|
||||||
opts_dict = dcmanager_utils.get_sw_update_opts(
|
opts_dict = dcmanager_utils.get_sw_update_opts(
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from dccommon.consts import DEFAULT_REGION_NAME
|
from dccommon.consts import DEFAULT_REGION_NAME
|
||||||
|
@ -14,8 +15,8 @@ from dcmanager.common import utils
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
from dcmanager.orchestrator.states.base import BaseState
|
from dcmanager.orchestrator.states.base import BaseState
|
||||||
|
|
||||||
# These following alarms can occur during a vim orchestrated k8s upgrade on the subcloud.
|
# These following alarms can occur during a vim orchestrated k8s upgrade on the
|
||||||
# By ignoring the alarms, subcloud k8s upgrade can be
|
# subcloud. By ignoring the alarms, subcloud k8s upgrade can be
|
||||||
# retried after a failure using DC orchestrator.
|
# retried after a failure using DC orchestrator.
|
||||||
ALARM_IGNORE_LIST = ['100.003', '200.001', '700.004', '750.006',
|
ALARM_IGNORE_LIST = ['100.003', '200.001', '700.004', '750.006',
|
||||||
'900.007', '900.401']
|
'900.007', '900.401']
|
||||||
|
@ -45,7 +46,8 @@ class KubeUpgradePreCheckState(BaseState):
|
||||||
rather than the 'available' version in the subcloud. This allows
|
rather than the 'available' version in the subcloud. This allows
|
||||||
a partially upgraded subcloud to be skipped.
|
a partially upgraded subcloud to be skipped.
|
||||||
"""
|
"""
|
||||||
system_health = self.get_sysinv_client(self.region_name).get_kube_upgrade_health()
|
system_health = self.get_sysinv_client(
|
||||||
|
self.region_name).get_kube_upgrade_health()
|
||||||
fails = re.findall("\[Fail\]", system_health)
|
fails = re.findall("\[Fail\]", system_health)
|
||||||
failed_alarm_check = re.findall("No alarms: \[Fail\]", system_health)
|
failed_alarm_check = re.findall("No alarms: \[Fail\]", system_health)
|
||||||
no_mgmt_alarms = re.findall("\[0\] of which are management affecting",
|
no_mgmt_alarms = re.findall("\[0\] of which are management affecting",
|
||||||
|
@ -57,17 +59,19 @@ class KubeUpgradePreCheckState(BaseState):
|
||||||
for alarm in alarms:
|
for alarm in alarms:
|
||||||
if alarm.alarm_id not in ALARM_IGNORE_LIST:
|
if alarm.alarm_id not in ALARM_IGNORE_LIST:
|
||||||
if alarm.mgmt_affecting == "True":
|
if alarm.mgmt_affecting == "True":
|
||||||
error_desc_msg = ("Kubernetes upgrade health check failed due to alarm %s. "
|
error_desc_msg = (
|
||||||
"Kubernetes upgrade health: \n %s" %
|
"Kubernetes upgrade health check failed due to alarm "
|
||||||
(alarm.alarm_id, system_health))
|
"%s. Kubernetes upgrade health: \n %s" % (
|
||||||
|
alarm.alarm_id, system_health))
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=error_desc_msg)
|
error_description=error_desc_msg)
|
||||||
self.error_log(strategy_step, "\n" + system_health)
|
self.error_log(strategy_step, "\n" + system_health)
|
||||||
raise Exception(("Kubernetes upgrade health check failed due to alarm %s. "
|
raise Exception((
|
||||||
"Please run 'system health-query-kube-upgrade' "
|
"Kubernetes upgrade health check failed due to alarm "
|
||||||
"command on the subcloud or %s on central for details." %
|
"%s. Please run 'system health-query-kube-upgrade' "
|
||||||
(alarm.alarm_id, ERROR_DESC_CMD)))
|
"command on the subcloud or %s on central for details." %
|
||||||
|
(alarm.alarm_id, ERROR_DESC_CMD)))
|
||||||
else:
|
else:
|
||||||
error_desc_msg = ("Kubernetes upgrade health check failed. \n %s" %
|
error_desc_msg = ("Kubernetes upgrade health check failed. \n %s" %
|
||||||
system_health)
|
system_health)
|
||||||
|
@ -114,7 +118,9 @@ class KubeUpgradePreCheckState(BaseState):
|
||||||
subcloud_kube_versions = \
|
subcloud_kube_versions = \
|
||||||
self.get_sysinv_client(self.region_name).get_kube_versions()
|
self.get_sysinv_client(self.region_name).get_kube_versions()
|
||||||
target_version = \
|
target_version = \
|
||||||
utils.select_available_kube_version(subcloud_kube_versions, to_version)
|
utils.select_available_kube_version(
|
||||||
|
subcloud_kube_versions, to_version
|
||||||
|
)
|
||||||
self.debug_log(strategy_step,
|
self.debug_log(strategy_step,
|
||||||
"Pre-Check. Available Kubernetes upgrade:(%s)"
|
"Pre-Check. Available Kubernetes upgrade:(%s)"
|
||||||
% target_version)
|
% target_version)
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dccommon.drivers.openstack import patching_v1
|
from dccommon.drivers.openstack import patching_v1
|
||||||
from dcmanager.common import utils
|
from dcmanager.common import utils
|
||||||
from dcmanager.orchestrator.orch_thread import OrchThread
|
from dcmanager.orchestrator.orch_thread import OrchThread
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -22,7 +22,7 @@ class PreCheckState(BaseState):
|
||||||
alarms = self.get_fm_client(self.region_name).get_alarms()
|
alarms = self.get_fm_client(self.region_name).get_alarms()
|
||||||
for alarm in alarms:
|
for alarm in alarms:
|
||||||
if alarm.mgmt_affecting == "True" and \
|
if alarm.mgmt_affecting == "True" and \
|
||||||
alarm.alarm_id not in ignored_alarms:
|
alarm.alarm_id not in ignored_alarms:
|
||||||
return True
|
return True
|
||||||
# No management affecting alarms
|
# No management affecting alarms
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -42,7 +42,7 @@ class DeployStartState(BaseState):
|
||||||
|
|
||||||
# Find the max version deployed on the SystemController
|
# Find the max version deployed on the SystemController
|
||||||
max_version = None
|
max_version = None
|
||||||
for release_id in deployed_releases:
|
for release_id, _ in deployed_releases.items():
|
||||||
release_sw_version = deployed_releases[release_id]['sw_version']
|
release_sw_version = deployed_releases[release_id]['sw_version']
|
||||||
if max_version is None or release_sw_version > max_version:
|
if max_version is None or release_sw_version > max_version:
|
||||||
max_version = release_sw_version
|
max_version = release_sw_version
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -30,8 +30,10 @@ class FinishStrategyState(BaseState):
|
||||||
state=software_v1.COMMITTED
|
state=software_v1.COMMITTED
|
||||||
)
|
)
|
||||||
|
|
||||||
self.debug_log(strategy_step,
|
self.debug_log(
|
||||||
"regionone_committed_releases: %s" % regionone_committed_releases)
|
strategy_step,
|
||||||
|
"regionone_committed_releases: %s" % regionone_committed_releases
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
software_client = self.get_software_client(self.region_name)
|
software_client = self.get_software_client(self.region_name)
|
||||||
|
@ -66,8 +68,9 @@ class FinishStrategyState(BaseState):
|
||||||
try:
|
try:
|
||||||
software_client.delete(releases_to_delete)
|
software_client.delete(releases_to_delete)
|
||||||
except Exception:
|
except Exception:
|
||||||
message = ("Cannot delete releases from subcloud. Please see logs for"
|
message = \
|
||||||
" details.")
|
("Cannot delete releases from subcloud. Please see logs for"
|
||||||
|
" details.")
|
||||||
self.exception_log(strategy_step, message)
|
self.exception_log(strategy_step, message)
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -128,14 +128,16 @@ class UploadState(BaseState):
|
||||||
|
|
||||||
if iso_release in subcloud_releases:
|
if iso_release in subcloud_releases:
|
||||||
if potential_missing_patches:
|
if potential_missing_patches:
|
||||||
# Retrieve patches that are present in the system controller and
|
# Retrieve patches that are present in the system
|
||||||
# not in the subcloud after uploading load to the subcloud.
|
# controller and not in the subcloud after uploading
|
||||||
|
# load to the subcloud.
|
||||||
missing_patches = self. \
|
missing_patches = self. \
|
||||||
_find_missing_patches(subcloud_releases,
|
_find_missing_patches(subcloud_releases,
|
||||||
potential_missing_patches)
|
potential_missing_patches)
|
||||||
|
|
||||||
if missing_patches:
|
if missing_patches:
|
||||||
message = (f"Release files {missing_patches} are missing")
|
message = \
|
||||||
|
(f"Release files {missing_patches} are missing")
|
||||||
self.error_log(strategy_step, message)
|
self.error_log(strategy_step, message)
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
break
|
break
|
||||||
|
@ -148,14 +150,19 @@ class UploadState(BaseState):
|
||||||
else:
|
else:
|
||||||
# No load was uploaded therefore the patches are really missing.
|
# No load was uploaded therefore the patches are really missing.
|
||||||
if potential_missing_patches:
|
if potential_missing_patches:
|
||||||
message = (f"Release files {potential_missing_patches} are missing")
|
message = \
|
||||||
|
(f"Release files {potential_missing_patches} are missing")
|
||||||
self.error_log(strategy_step, message)
|
self.error_log(strategy_step, message)
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
|
|
||||||
if upload_only:
|
if upload_only:
|
||||||
self.info_log(strategy_step,
|
self.info_log(
|
||||||
(f"{consts.EXTRA_ARGS_UPLOAD_ONLY} option enabled, skipping"
|
strategy_step,
|
||||||
f" forward to state:({consts.STRATEGY_STATE_COMPLETE})"))
|
(
|
||||||
|
f"{consts.EXTRA_ARGS_UPLOAD_ONLY} option enabled, skipping"
|
||||||
|
f" forward to state:({consts.STRATEGY_STATE_COMPLETE})"
|
||||||
|
)
|
||||||
|
)
|
||||||
return consts.STRATEGY_STATE_COMPLETE
|
return consts.STRATEGY_STATE_COMPLETE
|
||||||
|
|
||||||
return self.next_state
|
return self.next_state
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
# Copyright (c) 2020-2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
@ -49,8 +50,10 @@ class SwactHostState(BaseState):
|
||||||
active_host = self.get_sysinv_client(region).get_host(self.active)
|
active_host = self.get_sysinv_client(region).get_host(self.active)
|
||||||
standby_host = self.get_sysinv_client(region).get_host(self.standby)
|
standby_host = self.get_sysinv_client(region).get_host(self.standby)
|
||||||
|
|
||||||
# if the desired active host is already the Active Controller, no need for action
|
# if the desired active host is already the Active Controller, no need for
|
||||||
if active_host.capabilities.get('Personality') == consts.PERSONALITY_CONTROLLER_ACTIVE:
|
# action
|
||||||
|
if active_host.capabilities.get('Personality') == \
|
||||||
|
consts.PERSONALITY_CONTROLLER_ACTIVE:
|
||||||
msg = "Host: %s already the active controller." % (self.active)
|
msg = "Host: %s already the active controller." % (self.active)
|
||||||
self.info_log(strategy_step, msg)
|
self.info_log(strategy_step, msg)
|
||||||
return self.next_state
|
return self.next_state
|
||||||
|
@ -71,7 +74,8 @@ class SwactHostState(BaseState):
|
||||||
try:
|
try:
|
||||||
# query the administrative state to see if it is the new state.
|
# query the administrative state to see if it is the new state.
|
||||||
host = self.get_sysinv_client(region).get_host(self.active)
|
host = self.get_sysinv_client(region).get_host(self.active)
|
||||||
if host.capabilities.get('Personality') == consts.PERSONALITY_CONTROLLER_ACTIVE:
|
if host.capabilities.get('Personality') == \
|
||||||
|
consts.PERSONALITY_CONTROLLER_ACTIVE:
|
||||||
msg = "Host: %s is now the active controller." % (self.active)
|
msg = "Host: %s is now the active controller." % (self.active)
|
||||||
self.info_log(strategy_step, msg)
|
self.info_log(strategy_step, msg)
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import retrying
|
import retrying
|
||||||
|
@ -113,7 +114,8 @@ class UnlockHostState(BaseState):
|
||||||
try:
|
try:
|
||||||
# query the administrative state to see if it is the new state.
|
# query the administrative state to see if it is the new state.
|
||||||
host = self.get_sysinv_client(
|
host = self.get_sysinv_client(
|
||||||
strategy_step.subcloud.region_name).get_host(self.target_hostname)
|
strategy_step.subcloud.region_name
|
||||||
|
).get_host(self.target_hostname)
|
||||||
if self.check_host_ready(host):
|
if self.check_host_ready(host):
|
||||||
# Success. Break out of the loop.
|
# Success. Break out of the loop.
|
||||||
msg = "Host: %s is now: %s %s %s" % (self.target_hostname,
|
msg = "Host: %s is now: %s %s %s" % (self.target_hostname,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
@ -29,7 +30,8 @@ class ActivatingUpgradeState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(ActivatingUpgradeState, self).__init__(
|
super(ActivatingUpgradeState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_COMPLETING_UPGRADE, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_COMPLETING_UPGRADE,
|
||||||
|
region_name=region_name)
|
||||||
# max time to wait (in seconds) is: sleep_duration * max_queries
|
# max time to wait (in seconds) is: sleep_duration * max_queries
|
||||||
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
||||||
self.max_queries = DEFAULT_MAX_QUERIES
|
self.max_queries = DEFAULT_MAX_QUERIES
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
# Copyright (c) 2020-2022, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
import retrying
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import retrying
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.common.exceptions import StrategyStoppedException
|
from dcmanager.common.exceptions import StrategyStoppedException
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
from dcmanager.orchestrator.states.base import BaseState
|
from dcmanager.orchestrator.states.base import BaseState
|
||||||
|
|
||||||
|
|
||||||
# Max time: 10 minutes = 60 queries x 10 seconds between each query
|
# Max time: 10 minutes = 60 queries x 10 seconds between each query
|
||||||
DEFAULT_MAX_QUERIES = 60
|
DEFAULT_MAX_QUERIES = 60
|
||||||
DEFAULT_SLEEP_DURATION = 10
|
DEFAULT_SLEEP_DURATION = 10
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
@ -53,7 +54,8 @@ class DeletingLoadState(BaseState):
|
||||||
|
|
||||||
# Get a sysinv client each time. It will automatically renew the
|
# Get a sysinv client each time. It will automatically renew the
|
||||||
# token if it is about to expire.
|
# token if it is about to expire.
|
||||||
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
|
sysinv_client = \
|
||||||
|
self.get_sysinv_client(strategy_step.subcloud.region_name)
|
||||||
if len(sysinv_client.get_loads()) == 1:
|
if len(sysinv_client.get_loads()) == 1:
|
||||||
msg = "Load %s deleted." % load_version
|
msg = "Load %s deleted." % load_version
|
||||||
self.info_log(strategy_step, msg)
|
self.info_log(strategy_step, msg)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dccommon.drivers.openstack import patching_v1
|
from dccommon.drivers.openstack import patching_v1
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.common.exceptions import StrategyStoppedException
|
from dcmanager.common.exceptions import StrategyStoppedException
|
||||||
|
@ -46,8 +47,9 @@ class FinishingPatchStrategyState(BaseState):
|
||||||
state=patching_v1.PATCH_STATE_COMMITTED
|
state=patching_v1.PATCH_STATE_COMMITTED
|
||||||
)
|
)
|
||||||
|
|
||||||
self.debug_log(strategy_step,
|
self.debug_log(
|
||||||
"regionone_committed_patches: %s" % regionone_committed_patches)
|
strategy_step,
|
||||||
|
"regionone_committed_patches: %s" % regionone_committed_patches)
|
||||||
|
|
||||||
committed_patch_ids = list()
|
committed_patch_ids = list()
|
||||||
for patch_id in regionone_committed_patches.keys():
|
for patch_id in regionone_committed_patches.keys():
|
||||||
|
@ -77,8 +79,9 @@ class FinishingPatchStrategyState(BaseState):
|
||||||
elif subcloud_patches[patch_id]['patchstate'] == \
|
elif subcloud_patches[patch_id]['patchstate'] == \
|
||||||
patching_v1.PATCH_STATE_APPLIED:
|
patching_v1.PATCH_STATE_APPLIED:
|
||||||
if patch_id in committed_patch_ids:
|
if patch_id in committed_patch_ids:
|
||||||
self.info_log(strategy_step,
|
self.info_log(
|
||||||
"Patch %s will be committed in subcloud" % patch_id)
|
strategy_step,
|
||||||
|
"Patch %s will be committed in subcloud" % patch_id)
|
||||||
patches_to_commit.append(patch_id)
|
patches_to_commit.append(patch_id)
|
||||||
|
|
||||||
if patches_to_delete:
|
if patches_to_delete:
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon.exceptions import LoadMaxReached
|
from dccommon.exceptions import LoadMaxReached
|
||||||
|
@ -31,7 +32,8 @@ class ImportingLoadState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(ImportingLoadState, self).__init__(
|
super(ImportingLoadState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_UPDATING_PATCHES, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_UPDATING_PATCHES,
|
||||||
|
region_name=region_name)
|
||||||
# max time to wait (in seconds) is: sleep_duration * max_queries
|
# max time to wait (in seconds) is: sleep_duration * max_queries
|
||||||
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
||||||
self.max_queries = DEFAULT_MAX_QUERIES
|
self.max_queries = DEFAULT_MAX_QUERIES
|
||||||
|
@ -91,8 +93,9 @@ class ImportingLoadState(BaseState):
|
||||||
break
|
break
|
||||||
|
|
||||||
counter += 1
|
counter += 1
|
||||||
self.debug_log(strategy_step,
|
self.debug_log(
|
||||||
"Waiting for load %s to complete, iter=%d" % (request_type, counter))
|
strategy_step,
|
||||||
|
"Waiting for load %s to complete, iter=%d" % (request_type, counter))
|
||||||
if counter >= self.max_queries:
|
if counter >= self.max_queries:
|
||||||
raise Exception("Timeout waiting for %s to complete"
|
raise Exception("Timeout waiting for %s to complete"
|
||||||
% request_type)
|
% request_type)
|
||||||
|
@ -111,7 +114,8 @@ class ImportingLoadState(BaseState):
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Load:%s already found" % target_version)
|
"Load:%s already found" % target_version)
|
||||||
return True, load_info
|
return True, load_info
|
||||||
elif load.state == consts.IMPORTED_LOAD_STATE or load.state == consts.ERROR_LOAD_STATE:
|
elif load.state == consts.IMPORTED_LOAD_STATE or \
|
||||||
|
load.state == consts.ERROR_LOAD_STATE:
|
||||||
load_info['load_id'] = load.id
|
load_info['load_id'] = load.id
|
||||||
load_info['load_version'] = load.software_version
|
load_info['load_version'] = load.software_version
|
||||||
|
|
||||||
|
@ -139,8 +143,8 @@ class ImportingLoadState(BaseState):
|
||||||
if load_id_to_be_deleted is not None:
|
if load_id_to_be_deleted is not None:
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Deleting load %s..." % load_id_to_be_deleted)
|
"Deleting load %s..." % load_id_to_be_deleted)
|
||||||
self.get_sysinv_client(
|
self.get_sysinv_client(strategy_step.subcloud.region_name).\
|
||||||
strategy_step.subcloud.region_name).delete_load(load_id_to_be_deleted)
|
delete_load(load_id_to_be_deleted)
|
||||||
req_info['type'] = LOAD_DELETE_REQUEST_TYPE
|
req_info['type'] = LOAD_DELETE_REQUEST_TYPE
|
||||||
self._wait_for_request_to_complete(strategy_step, req_info)
|
self._wait_for_request_to_complete(strategy_step, req_info)
|
||||||
|
|
||||||
|
@ -151,14 +155,17 @@ class ImportingLoadState(BaseState):
|
||||||
if subcloud_type == consts.SYSTEM_MODE_SIMPLEX:
|
if subcloud_type == consts.SYSTEM_MODE_SIMPLEX:
|
||||||
# For simplex we only import the load record, not the entire ISO
|
# For simplex we only import the load record, not the entire ISO
|
||||||
loads = self._read_from_cache(REGION_ONE_SYSTEM_LOAD_CACHE_TYPE)
|
loads = self._read_from_cache(REGION_ONE_SYSTEM_LOAD_CACHE_TYPE)
|
||||||
matches = [load for load in loads if load.software_version == target_version]
|
matches = [
|
||||||
|
load for load in loads if load.software_version == target_version]
|
||||||
target_load = matches[0].to_dict()
|
target_load = matches[0].to_dict()
|
||||||
# Send only the required fields
|
# Send only the required fields
|
||||||
creation_keys = ['software_version', 'compatible_version', 'required_patches']
|
creation_keys = ['software_version',
|
||||||
|
'compatible_version',
|
||||||
|
'required_patches']
|
||||||
target_load = {key: target_load[key] for key in creation_keys}
|
target_load = {key: target_load[key] for key in creation_keys}
|
||||||
try:
|
try:
|
||||||
load = self.get_sysinv_client(
|
load = self.get_sysinv_client(strategy_step.subcloud.region_name).\
|
||||||
strategy_step.subcloud.region_name).import_load_metadata(target_load)
|
import_load_metadata(target_load)
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Load: %s is now: %s" % (
|
"Load: %s is now: %s" % (
|
||||||
load.software_version, load.state))
|
load.software_version, load.state))
|
||||||
|
@ -178,28 +185,34 @@ class ImportingLoadState(BaseState):
|
||||||
|
|
||||||
load_import_retry_counter += 1
|
load_import_retry_counter += 1
|
||||||
try:
|
try:
|
||||||
# ISO and SIG files are found in the vault under a version directory
|
# ISO and SIG files are found in the vault under a version
|
||||||
|
# directory
|
||||||
self.info_log(strategy_step, "Getting vault load files...")
|
self.info_log(strategy_step, "Getting vault load files...")
|
||||||
iso_path, sig_path = utils.get_vault_load_files(target_version)
|
iso_path, sig_path = utils.get_vault_load_files(target_version)
|
||||||
|
|
||||||
if not iso_path:
|
if not iso_path:
|
||||||
message = ("Failed to get upgrade load info for subcloud %s" %
|
message = (
|
||||||
strategy_step.subcloud.name)
|
"Failed to get upgrade load info for subcloud %s" %
|
||||||
|
strategy_step.subcloud.name)
|
||||||
raise Exception(message)
|
raise Exception(message)
|
||||||
|
|
||||||
# Call the API. import_load blocks until the load state is 'importing'
|
# Call the API. import_load blocks until the load state is
|
||||||
|
# 'importing'
|
||||||
self.info_log(strategy_step, "Sending load import request...")
|
self.info_log(strategy_step, "Sending load import request...")
|
||||||
load = self.get_sysinv_client(
|
load = self.get_sysinv_client(
|
||||||
strategy_step.subcloud.region_name).import_load(iso_path, sig_path)
|
strategy_step.subcloud.region_name
|
||||||
|
).import_load(iso_path, sig_path)
|
||||||
|
|
||||||
break
|
break
|
||||||
except VaultLoadMissingError:
|
except VaultLoadMissingError:
|
||||||
raise
|
raise
|
||||||
except LoadMaxReached:
|
except LoadMaxReached:
|
||||||
# A prior import request may have encountered an exception but the request actually
|
# A prior import request may have encountered an exception but
|
||||||
# continued with the import operation in the subcloud. This has been observed when performing
|
# the request actually continued with the import operation in the
|
||||||
# multiple parallel upgrade in which resource/link may be saturated. In such case allow continue
|
# subcloud. This has been observed when performing multiple
|
||||||
# for further checks (i.e. at wait_for_request_to_complete)
|
# parallel upgrade in which resource/link may be saturated.
|
||||||
|
# In such case allow continue for further checks
|
||||||
|
# (i.e. at wait_for_request_to_complete)
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Load at max number of loads")
|
"Load at max number of loads")
|
||||||
break
|
break
|
||||||
|
@ -209,13 +222,14 @@ class ImportingLoadState(BaseState):
|
||||||
(e, load_import_retry_counter))
|
(e, load_import_retry_counter))
|
||||||
if load_import_retry_counter >= self.max_load_import_retries:
|
if load_import_retry_counter >= self.max_load_import_retries:
|
||||||
self.error_log(strategy_step, str(e))
|
self.error_log(strategy_step, str(e))
|
||||||
raise Exception("Failed to import load. Please check sysinv.log on "
|
raise Exception("Failed to import load. Please check "
|
||||||
"the subcloud for details.")
|
"sysinv.log on the subcloud for details.")
|
||||||
|
|
||||||
time.sleep(self.sleep_duration)
|
time.sleep(self.sleep_duration)
|
||||||
|
|
||||||
if load is None:
|
if load is None:
|
||||||
_, load_info = self._get_subcloud_load_info(strategy_step, target_version)
|
_, load_info = self._get_subcloud_load_info(
|
||||||
|
strategy_step, target_version)
|
||||||
load_id = load_info.get('load_id')
|
load_id = load_info.get('load_id')
|
||||||
software_version = load_info['load_version']
|
software_version = load_info['load_version']
|
||||||
else:
|
else:
|
||||||
|
@ -228,14 +242,16 @@ class ImportingLoadState(BaseState):
|
||||||
if software_version != target_version:
|
if software_version != target_version:
|
||||||
raise Exception("The imported load was not the expected version.")
|
raise Exception("The imported load was not the expected version.")
|
||||||
try:
|
try:
|
||||||
self.info_log(strategy_step,
|
self.info_log(
|
||||||
"Load import request accepted, load software version = %s"
|
strategy_step,
|
||||||
% software_version)
|
"Load import request accepted, load software version = %s"
|
||||||
|
% software_version)
|
||||||
req_info['load_id'] = load_id
|
req_info['load_id'] = load_id
|
||||||
req_info['load_version'] = target_version
|
req_info['load_version'] = target_version
|
||||||
req_info['type'] = LOAD_IMPORT_REQUEST_TYPE
|
req_info['type'] = LOAD_IMPORT_REQUEST_TYPE
|
||||||
self.info_log(strategy_step,
|
self.info_log(
|
||||||
"Waiting for state to change from importing to imported...")
|
strategy_step,
|
||||||
|
"Waiting for state to change from importing to imported...")
|
||||||
self._wait_for_request_to_complete(strategy_step, req_info)
|
self._wait_for_request_to_complete(strategy_step, req_info)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error_log(strategy_step, str(e))
|
self.error_log(strategy_step, str(e))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.common import exceptions
|
from dcmanager.common import exceptions
|
||||||
|
@ -52,9 +53,10 @@ class InstallingLicenseState(BaseState):
|
||||||
return self.next_state
|
return self.next_state
|
||||||
else:
|
else:
|
||||||
# An unexpected error occurred querying the license
|
# An unexpected error occurred querying the license
|
||||||
message = ('An unexpected error occurred querying the license %s. Detail: %s' %
|
message = (
|
||||||
(dccommon_consts.SYSTEM_CONTROLLER_NAME,
|
'An unexpected error occurred querying the license %s. '
|
||||||
target_error))
|
'Detail: %s' % (dccommon_consts.SYSTEM_CONTROLLER_NAME,
|
||||||
|
target_error))
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=message[0:consts.ERROR_DESCRIPTION_LENGTH])
|
error_description=message[0:consts.ERROR_DESCRIPTION_LENGTH])
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -47,7 +48,8 @@ class MigratingDataState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(MigratingDataState, self).__init__(
|
super(MigratingDataState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_0, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_0,
|
||||||
|
region_name=region_name)
|
||||||
|
|
||||||
self.max_api_queries = DEFAULT_MAX_API_QUERIES
|
self.max_api_queries = DEFAULT_MAX_API_QUERIES
|
||||||
self.api_sleep_duration = DEFAULT_API_SLEEP
|
self.api_sleep_duration = DEFAULT_API_SLEEP
|
||||||
|
@ -141,8 +143,9 @@ class MigratingDataState(BaseState):
|
||||||
strategy_step.subcloud.name + consts.INVENTORY_FILE_POSTFIX)
|
strategy_step.subcloud.name + consts.INVENTORY_FILE_POSTFIX)
|
||||||
log_file = os.path.join(consts.DC_ANSIBLE_LOG_DIR, subcloud.name) + \
|
log_file = os.path.join(consts.DC_ANSIBLE_LOG_DIR, subcloud.name) + \
|
||||||
'_playbook_output.log'
|
'_playbook_output.log'
|
||||||
# Send skip_patching=true to prevent the playbook from applying any patches present in the
|
# Send skip_patching=true to prevent the playbook from applying any patches
|
||||||
# upgrade_data. All the required patches will be included in the generated install iso.
|
# present in the upgrade_data. All the required patches will be included in
|
||||||
|
# the generated install iso.
|
||||||
data_migrating_cmd = [
|
data_migrating_cmd = [
|
||||||
"ansible-playbook", ANSIBLE_UPGRADE_PLAYBOOK,
|
"ansible-playbook", ANSIBLE_UPGRADE_PLAYBOOK,
|
||||||
"-i", ansible_subcloud_inventory_file, "-e",
|
"-i", ansible_subcloud_inventory_file, "-e",
|
||||||
|
@ -156,7 +159,8 @@ class MigratingDataState(BaseState):
|
||||||
# Two error messages: one for subcloud error description and logs and
|
# Two error messages: one for subcloud error description and logs and
|
||||||
# one for orchestrator strategy_step detail (shorter than the previous).
|
# one for orchestrator strategy_step detail (shorter than the previous).
|
||||||
msg_subcloud = utils.find_ansible_error_msg(
|
msg_subcloud = utils.find_ansible_error_msg(
|
||||||
strategy_step.subcloud.name, log_file, consts.DEPLOY_STATE_MIGRATING_DATA)
|
strategy_step.subcloud.name, log_file,
|
||||||
|
consts.DEPLOY_STATE_MIGRATING_DATA)
|
||||||
# Get script output in case it is available
|
# Get script output in case it is available
|
||||||
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
|
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
|
||||||
failure = ('%s \n%s' % (error_msg, msg_subcloud))
|
failure = ('%s \n%s' % (error_msg, msg_subcloud))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -40,10 +41,12 @@ class PreCheckState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(PreCheckState, self).__init__(
|
super(PreCheckState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_INSTALLING_LICENSE, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_INSTALLING_LICENSE,
|
||||||
|
region_name=region_name)
|
||||||
|
|
||||||
def _check_health(self, strategy_step, subcloud_sysinv_client, subcloud_fm_client,
|
def _check_health(
|
||||||
host, upgrades):
|
self, strategy_step, subcloud_sysinv_client, subcloud_fm_client,
|
||||||
|
host, upgrades):
|
||||||
|
|
||||||
# Check system upgrade health
|
# Check system upgrade health
|
||||||
#
|
#
|
||||||
|
@ -112,21 +115,22 @@ class PreCheckState(BaseState):
|
||||||
if not failed_alarm_check:
|
if not failed_alarm_check:
|
||||||
# Health check failure: no alarms involved
|
# Health check failure: no alarms involved
|
||||||
#
|
#
|
||||||
# These could be Kubernetes or other related failure(s) which has not been been
|
# These could be Kubernetes or other related failure(s) which has not
|
||||||
# converted into an alarm condition.
|
# been been converted into an alarm condition.
|
||||||
error_desc_msg = ("System upgrade health check failed. \n %s" %
|
error_desc_msg = ("System upgrade health check failed. \n %s" %
|
||||||
fails)
|
fails)
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=error_desc_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
|
error_description=error_desc_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
|
||||||
details = ("System upgrade health check failed. Please run 'system health-query-upgrade' "
|
details = (
|
||||||
"command on the subcloud or %s on central for details"
|
"System upgrade health check failed. Please run "
|
||||||
% (consts.ERROR_DESC_CMD))
|
"'system health-query-upgrade' command on the subcloud or %s "
|
||||||
|
"on central for details" % (consts.ERROR_DESC_CMD))
|
||||||
self.error_log(strategy_step, "\n" + system_health)
|
self.error_log(strategy_step, "\n" + system_health)
|
||||||
raise PreCheckFailedException(
|
raise PreCheckFailedException(
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
details=details,
|
details=details,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Health check failure: one or more alarms
|
# Health check failure: one or more alarms
|
||||||
if (upgrades and (len(fails) == len(alarm_ignore_list))):
|
if (upgrades and (len(fails) == len(alarm_ignore_list))):
|
||||||
|
@ -139,38 +143,42 @@ class PreCheckState(BaseState):
|
||||||
for alarm in alarms:
|
for alarm in alarms:
|
||||||
if alarm.alarm_id not in alarm_ignore_list:
|
if alarm.alarm_id not in alarm_ignore_list:
|
||||||
if alarm.mgmt_affecting == "True":
|
if alarm.mgmt_affecting == "True":
|
||||||
error_desc_msg = ("System upgrade health check failed due to alarm %s. "
|
error_desc_msg = (
|
||||||
"System upgrade health: \n %s" %
|
"System upgrade health check failed due to "
|
||||||
(alarm.alarm_id, system_health))
|
"alarm %s. System upgrade health: \n %s" %
|
||||||
|
(alarm.alarm_id, system_health))
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=error_desc_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
|
error_description=error_desc_msg[
|
||||||
details = ("System upgrade health check failed due to alarm %s. "
|
0:consts.ERROR_DESCRIPTION_LENGTH])
|
||||||
"Please run 'system health-query-upgrade' "
|
details = (
|
||||||
"command on the subcloud or %s on central for details." %
|
"System upgrade health check failed due to "
|
||||||
(alarm.alarm_id, consts.ERROR_DESC_CMD))
|
"alarm %s. Please run 'system health-query-upgrade' "
|
||||||
|
"command on the subcloud or %s on central for "
|
||||||
|
"details." % (alarm.alarm_id, consts.ERROR_DESC_CMD))
|
||||||
self.error_log(strategy_step, "\n" + system_health)
|
self.error_log(strategy_step, "\n" + system_health)
|
||||||
raise PreCheckFailedException(
|
raise PreCheckFailedException(
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
details=details,
|
details=details,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Multiple failures
|
# Multiple failures
|
||||||
error_desc_msg = ("System upgrade health check failed due to multiple failures. "
|
error_desc_msg = (
|
||||||
"Health: \n %s" %
|
"System upgrade health check failed due to multiple failures. "
|
||||||
(system_health))
|
"Health: \n %s" % system_health)
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=error_desc_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
|
error_description=error_desc_msg[
|
||||||
details = ("System upgrade health check failed due to multiple failures. "
|
0:consts.ERROR_DESCRIPTION_LENGTH])
|
||||||
"Please run 'system health-query-upgrade' command on the "
|
details = (
|
||||||
"subcloud or %s on central for details." %
|
"System upgrade health check failed due to multiple failures. "
|
||||||
(consts.ERROR_DESC_CMD))
|
"Please run 'system health-query-upgrade' command on the "
|
||||||
|
"subcloud or %s on central for details." % consts.ERROR_DESC_CMD)
|
||||||
self.error_log(strategy_step, "\n" + system_health)
|
self.error_log(strategy_step, "\n" + system_health)
|
||||||
raise PreCheckFailedException(
|
raise PreCheckFailedException(
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
details=details,
|
details=details,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _check_scratch(self, strategy_step, subcloud_sysinv_client, host):
|
def _check_scratch(self, strategy_step, subcloud_sysinv_client, host):
|
||||||
scratch_fs = subcloud_sysinv_client.get_host_filesystem(
|
scratch_fs = subcloud_sysinv_client.get_host_filesystem(
|
||||||
|
@ -182,7 +190,7 @@ class PreCheckState(BaseState):
|
||||||
raise PreCheckFailedException(
|
raise PreCheckFailedException(
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
details=details,
|
details=details,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _perform_subcloud_online_checks(self, strategy_step, subcloud_sysinv_client,
|
def _perform_subcloud_online_checks(self, strategy_step, subcloud_sysinv_client,
|
||||||
subcloud_fm_client, host, upgrades):
|
subcloud_fm_client, host, upgrades):
|
||||||
|
@ -204,8 +212,10 @@ class PreCheckState(BaseState):
|
||||||
if subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
subcloud_sysinv_client = None
|
subcloud_sysinv_client = None
|
||||||
try:
|
try:
|
||||||
subcloud_sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
|
subcloud_sysinv_client = \
|
||||||
subcloud_fm_client = self.get_fm_client(strategy_step.subcloud.region_name)
|
self.get_sysinv_client(strategy_step.subcloud.region_name)
|
||||||
|
subcloud_fm_client = \
|
||||||
|
self.get_fm_client(strategy_step.subcloud.region_name)
|
||||||
except Exception:
|
except Exception:
|
||||||
# if getting the token times out, the orchestrator may have
|
# if getting the token times out, the orchestrator may have
|
||||||
# restarted and subcloud may be offline; so will attempt
|
# restarted and subcloud may be offline; so will attempt
|
||||||
|
@ -233,14 +243,15 @@ class PreCheckState(BaseState):
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
details=details)
|
details=details)
|
||||||
|
|
||||||
|
sc_status = subcloud.deploy_status
|
||||||
if (host.administrative == consts.ADMIN_LOCKED and
|
if (host.administrative == consts.ADMIN_LOCKED and
|
||||||
(subcloud.deploy_status == consts.DEPLOY_STATE_INSTALL_FAILED or
|
(sc_status == consts.DEPLOY_STATE_INSTALL_FAILED or
|
||||||
subcloud.deploy_status == consts.DEPLOY_STATE_PRE_INSTALL_FAILED)):
|
sc_status == consts.DEPLOY_STATE_PRE_INSTALL_FAILED)):
|
||||||
# If the subcloud is online but its deploy state is pre-install-failed
|
# If the subcloud is online but its deploy state is
|
||||||
# or install-failed and the subcloud host is locked, the upgrading
|
# pre-install-failed or install-failed and the subcloud host is
|
||||||
# simplex step must have failed early in the previous upgrade attempt.
|
# locked, the upgrading simplex step must have failed early in
|
||||||
# The pre-check should transition directly to upgrading simplex step in the
|
# the previous upgrade attempt. The pre-check should transition
|
||||||
# retry.
|
# directly to upgrading simplex step in the retry.
|
||||||
self.override_next_state(consts.STRATEGY_STATE_UPGRADING_SIMPLEX)
|
self.override_next_state(consts.STRATEGY_STATE_UPGRADING_SIMPLEX)
|
||||||
return self.next_state
|
return self.next_state
|
||||||
|
|
||||||
|
@ -256,103 +267,122 @@ class PreCheckState(BaseState):
|
||||||
host, upgrades)
|
host, upgrades)
|
||||||
|
|
||||||
if subcloud.deploy_status == consts.DEPLOY_STATE_UPGRADE_ACTIVATED:
|
if subcloud.deploy_status == consts.DEPLOY_STATE_UPGRADE_ACTIVATED:
|
||||||
# If the subcloud has completed upgrade activation, advance directly
|
# If the subcloud has completed upgrade activation,
|
||||||
# to completing step.
|
# advance directly to completing step.
|
||||||
self.override_next_state(consts.STRATEGY_STATE_COMPLETING_UPGRADE)
|
self.override_next_state(
|
||||||
elif subcloud.deploy_status == consts.DEPLOY_STATE_DATA_MIGRATION_FAILED:
|
consts.STRATEGY_STATE_COMPLETING_UPGRADE
|
||||||
|
)
|
||||||
|
elif subcloud.deploy_status == \
|
||||||
|
consts.DEPLOY_STATE_DATA_MIGRATION_FAILED:
|
||||||
# If the subcloud deploy status is data-migration-failed but
|
# If the subcloud deploy status is data-migration-failed but
|
||||||
# it is online and has passed subcloud online checks, it must have
|
# it is online and has passed subcloud online checks, it must
|
||||||
# timed out while waiting for the subcloud to unlock previously and
|
# have timed out while waiting for the subcloud to unlock
|
||||||
# has succesfully been unlocked since. Update the subcloud deploy
|
# previously and has succesfully been unlocked since. Update
|
||||||
# status and advance to activating upgrade step.
|
# the subcloud deploy status and advance to activating upgrade
|
||||||
|
# step.
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
deploy_status=consts.DEPLOY_STATE_MIGRATED)
|
deploy_status=consts.DEPLOY_STATE_MIGRATED)
|
||||||
self.override_next_state(consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
self.override_next_state(
|
||||||
|
consts.STRATEGY_STATE_ACTIVATING_UPGRADE
|
||||||
|
)
|
||||||
elif subcloud.deploy_status == consts.DEPLOY_STATE_MIGRATED:
|
elif subcloud.deploy_status == consts.DEPLOY_STATE_MIGRATED:
|
||||||
# If the subcloud deploy status is migrated but it is online, it
|
# If the subcloud deploy status is migrated but it is online, it
|
||||||
# must have undergone 2 upgrade attempts:
|
# must have undergone 2 upgrade attempts:
|
||||||
# - in 1st upgrade attempt: strategy timed out while waiting
|
# - in 1st upgrade attempt: strategy timed out while waiting
|
||||||
# for the subcloud to unlock
|
# for the subcloud to unlock
|
||||||
# - in 2nd upgrade attempt: the subcloud was unlocked successfully
|
# - in 2nd upgrade attempt: the subcloud was unlocked
|
||||||
# (with or without manual interventions) but failed to activate.
|
# successfully (with or without manual interventions) but
|
||||||
|
# failed to activate.
|
||||||
# Advance to activating upgrade step so activation can be retried
|
# Advance to activating upgrade step so activation can be retried
|
||||||
# after the manual intervention.
|
# after the manual intervention.
|
||||||
self.override_next_state(consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
self.override_next_state(
|
||||||
|
consts.STRATEGY_STATE_ACTIVATING_UPGRADE
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# Duplex case
|
# Duplex case
|
||||||
if upgrades:
|
if upgrades:
|
||||||
# If upgrade has started, skip subcloud online checks
|
# If upgrade has started, skip subcloud online checks
|
||||||
self.info_log(strategy_step, "Online subcloud checks skipped.")
|
self.info_log(strategy_step, "Online subcloud checks skipped.")
|
||||||
upgrade_state = upgrades[0].state
|
upgrade_state = upgrades[0].state
|
||||||
if(upgrade_state == consts.UPGRADE_STATE_DATA_MIGRATION_FAILED or
|
controllers_state = consts.UPGRADE_STATE_UPGRADING_CONTROLLERS
|
||||||
upgrade_state == consts.UPGRADE_STATE_DATA_MIGRATION):
|
migration_complete = consts.UPGRADE_STATE_DATA_MIGRATION_COMPLETE
|
||||||
|
|
||||||
|
if (upgrade_state == consts.UPGRADE_STATE_DATA_MIGRATION_FAILED
|
||||||
|
or upgrade_state == consts.UPGRADE_STATE_DATA_MIGRATION):
|
||||||
error_message = "upgrade state: %s" % upgrade_state
|
error_message = "upgrade state: %s" % upgrade_state
|
||||||
raise ManualRecoveryRequiredException(
|
raise ManualRecoveryRequiredException(
|
||||||
subcloud=strategy_step.subcloud.name,
|
subcloud=strategy_step.subcloud.name,
|
||||||
error_message=error_message)
|
error_message=error_message)
|
||||||
elif(upgrade_state == consts.UPGRADE_STATE_UPGRADING_CONTROLLERS or
|
elif (upgrade_state == controllers_state or
|
||||||
upgrade_state == consts.UPGRADE_STATE_DATA_MIGRATION_COMPLETE):
|
upgrade_state == migration_complete):
|
||||||
# At this point the subcloud is duplex, deploy state is complete
|
# At this point the subcloud is duplex, deploy state is
|
||||||
# and "system upgrade-show" on the subcloud indicates that the
|
# completeand "system upgrade-show" on the subcloud indicates
|
||||||
# upgrade state is "upgrading-controllers".
|
# that the upgrade state is "upgrading-controllers".
|
||||||
# If controller-1 is locked then we unlock it,
|
# If controller-1 is locked then we unlock it,
|
||||||
# if controller-0 is active we need to swact
|
# if controller-0 is active we need to swact
|
||||||
# else we can proceed to create the VIM strategy.
|
# else we can proceed to create the VIM strategy.
|
||||||
controller_1_host = subcloud_sysinv_client.get_host("controller-1")
|
controller_1_host = subcloud_sysinv_client.get_host(
|
||||||
|
"controller-1")
|
||||||
if controller_1_host.administrative == consts.ADMIN_LOCKED:
|
if controller_1_host.administrative == consts.ADMIN_LOCKED:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_1)
|
consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_1)
|
||||||
elif host.capabilities.get('Personality') == consts.PERSONALITY_CONTROLLER_ACTIVE:
|
elif host.capabilities.get('Personality') == \
|
||||||
|
consts.PERSONALITY_CONTROLLER_ACTIVE:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_1)
|
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_1)
|
||||||
else:
|
else:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_CREATING_VIM_UPGRADE_STRATEGY)
|
consts.STRATEGY_STATE_CREATING_VIM_UPGRADE_STRATEGY)
|
||||||
elif (upgrade_state == consts.UPGRADE_STATE_UPGRADING_HOSTS):
|
elif upgrade_state == consts.UPGRADE_STATE_UPGRADING_HOSTS:
|
||||||
# At this point the subcloud is duplex, deploy state is complete
|
# At this point the subcloud is duplex, deploy state is
|
||||||
# and "system upgrade-show" on the subcloud indicates that the
|
# complete and "system upgrade-show" on the subcloud
|
||||||
# upgrade state is "upgrading-hosts".
|
# indicates that theupgrade state is "upgrading-hosts".
|
||||||
# If both subcloud hosts are upgraded to the newer load,
|
# If both subcloud hosts are upgraded to the newer load,
|
||||||
# we resume the state machine from activate upgrade state.
|
# we resume the state machine from activate upgrade state.
|
||||||
# Otherwise, we resume from create the VIM strategy state.
|
# Otherwise, we resume from create the VIM strategy state.
|
||||||
|
# determine the version of the system controller in regionone
|
||||||
# determine the version of the system controller in region one
|
target_version = self._read_from_cache(
|
||||||
target_version = \
|
REGION_ONE_SYSTEM_INFO_CACHE_TYPE).software_version
|
||||||
self._read_from_cache(REGION_ONE_SYSTEM_INFO_CACHE_TYPE)\
|
|
||||||
.software_version
|
|
||||||
|
|
||||||
all_hosts_upgraded = True
|
all_hosts_upgraded = True
|
||||||
subcloud_hosts = self.get_sysinv_client(
|
subcloud_hosts = self.get_sysinv_client(
|
||||||
strategy_step.subcloud.region_name).get_hosts()
|
strategy_step.subcloud.region_name).get_hosts()
|
||||||
for subcloud_host in subcloud_hosts:
|
for subcloud_host in subcloud_hosts:
|
||||||
if(subcloud_host.software_load != target_version or
|
is_locked = (subcloud_host.administrative ==
|
||||||
subcloud_host.administrative == consts.ADMIN_LOCKED or
|
consts.ADMIN_LOCKED)
|
||||||
subcloud_host.operational == consts.OPERATIONAL_DISABLED):
|
is_disabled = (subcloud_host.operational ==
|
||||||
|
consts.OPERATIONAL_DISABLED)
|
||||||
|
create_vim_state = \
|
||||||
|
consts.STRATEGY_STATE_CREATING_VIM_UPGRADE_STRATEGY
|
||||||
|
if (subcloud_host.software_load != target_version or
|
||||||
|
is_locked or is_disabled):
|
||||||
all_hosts_upgraded = False
|
all_hosts_upgraded = False
|
||||||
self.override_next_state(
|
self.override_next_state(create_vim_state)
|
||||||
consts.STRATEGY_STATE_CREATING_VIM_UPGRADE_STRATEGY)
|
|
||||||
|
|
||||||
if all_hosts_upgraded:
|
if all_hosts_upgraded:
|
||||||
if host.capabilities.get('Personality') == consts.PERSONALITY_CONTROLLER_ACTIVE:
|
if host.capabilities.get('Personality') == \
|
||||||
|
consts.PERSONALITY_CONTROLLER_ACTIVE:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
||||||
else:
|
else:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_0)
|
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_0)
|
||||||
elif (upgrade_state == consts.UPGRADE_STATE_ACTIVATION_FAILED):
|
elif upgrade_state == consts.UPGRADE_STATE_ACTIVATION_FAILED:
|
||||||
if(host.capabilities.get('Personality') == consts.PERSONALITY_CONTROLLER_ACTIVE):
|
if (host.capabilities.get('Personality') ==
|
||||||
|
consts.PERSONALITY_CONTROLLER_ACTIVE):
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
consts.STRATEGY_STATE_ACTIVATING_UPGRADE)
|
||||||
else:
|
else:
|
||||||
self.override_next_state(
|
self.override_next_state(
|
||||||
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_0)
|
consts.STRATEGY_STATE_SWACTING_TO_CONTROLLER_0)
|
||||||
elif (upgrade_state == consts.UPGRADE_STATE_ACTIVATION_COMPLETE):
|
elif upgrade_state == consts.UPGRADE_STATE_ACTIVATION_COMPLETE:
|
||||||
self.override_next_state(consts.STRATEGY_STATE_COMPLETING_UPGRADE)
|
self.override_next_state(
|
||||||
|
consts.STRATEGY_STATE_COMPLETING_UPGRADE)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Perform subcloud online check for duplex and proceed to the next step
|
# Perform subcloud online check for duplex and proceed to the
|
||||||
# (i.e. installing license)
|
# next step (i.e. installing license)
|
||||||
self._perform_subcloud_online_checks(strategy_step,
|
self._perform_subcloud_online_checks(strategy_step,
|
||||||
subcloud_sysinv_client,
|
subcloud_sysinv_client,
|
||||||
subcloud_fm_client,
|
subcloud_fm_client,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dccommon.drivers.openstack.vim import ALARM_RESTRICTIONS_RELAXED
|
from dccommon.drivers.openstack.vim import ALARM_RESTRICTIONS_RELAXED
|
||||||
|
@ -96,10 +97,12 @@ class StartingUpgradeState(BaseState):
|
||||||
if upgrade_state in UPGRADE_RETRY_STATES:
|
if upgrade_state in UPGRADE_RETRY_STATES:
|
||||||
retry_counter += 1
|
retry_counter += 1
|
||||||
if retry_counter >= self.max_failed_retries:
|
if retry_counter >= self.max_failed_retries:
|
||||||
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
|
error_msg = utils.get_failure_msg(
|
||||||
|
strategy_step.subcloud.region_name)
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
error_description=error_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
|
error_description=error_msg[
|
||||||
|
0:consts.ERROR_DESCRIPTION_LENGTH])
|
||||||
details = ("Failed to start upgrade. Please "
|
details = ("Failed to start upgrade. Please "
|
||||||
"check sysinv.log on the subcloud or "
|
"check sysinv.log on the subcloud or "
|
||||||
"%s on central for details." %
|
"%s on central for details." %
|
||||||
|
@ -110,7 +113,8 @@ class StartingUpgradeState(BaseState):
|
||||||
% upgrade_state)
|
% upgrade_state)
|
||||||
try:
|
try:
|
||||||
self.get_sysinv_client(
|
self.get_sysinv_client(
|
||||||
strategy_step.subcloud.region_name).upgrade_start(force=force_flag)
|
strategy_step.subcloud.region_name).upgrade_start(
|
||||||
|
force=force_flag)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.warn_log(strategy_step,
|
self.warn_log(strategy_step,
|
||||||
"Encountered exception: %s, "
|
"Encountered exception: %s, "
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022-2023 Wind River Systems, Inc.
|
# Copyright (c) 2022-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
|
@ -48,14 +49,16 @@ class TransferCACertificateState(BaseState):
|
||||||
retry_counter = 0
|
retry_counter = 0
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
|
sysinv_client = \
|
||||||
|
self.get_sysinv_client(strategy_step.subcloud.region_name)
|
||||||
|
|
||||||
data = {'mode': 'openldap_ca'}
|
data = {'mode': 'openldap_ca'}
|
||||||
ldap_ca_cert, ldap_ca_key = utils.get_certificate_from_secret(
|
ldap_ca_cert, ldap_ca_key = utils.get_certificate_from_secret(
|
||||||
consts.OPENLDAP_CA_CERT_SECRET_NAME,
|
consts.OPENLDAP_CA_CERT_SECRET_NAME,
|
||||||
consts.CERT_NAMESPACE_PLATFORM_CA_CERTS)
|
consts.CERT_NAMESPACE_PLATFORM_CA_CERTS)
|
||||||
|
|
||||||
sysinv_client.update_certificate('', ldap_ca_cert + ldap_ca_key, data)
|
sysinv_client.update_certificate(
|
||||||
|
'', ldap_ca_cert + ldap_ca_key, data)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.warn_log(strategy_step,
|
self.warn_log(strategy_step,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -69,7 +70,8 @@ class UpdatingPatchesState(BaseState):
|
||||||
patching_v1.PATCH_STATE_APPLIED,
|
patching_v1.PATCH_STATE_APPLIED,
|
||||||
patching_v1.PATCH_STATE_COMMITTED]:
|
patching_v1.PATCH_STATE_COMMITTED]:
|
||||||
applied_patch_ids.append(patch_id)
|
applied_patch_ids.append(patch_id)
|
||||||
self.debug_log(strategy_step, "RegionOne applied_patch_ids: %s" % applied_patch_ids)
|
self.debug_log(strategy_step,
|
||||||
|
"RegionOne applied_patch_ids: %s" % applied_patch_ids)
|
||||||
|
|
||||||
region = self.get_region_name(strategy_step)
|
region = self.get_region_name(strategy_step)
|
||||||
# Retrieve all the patches that are present in this subcloud.
|
# Retrieve all the patches that are present in this subcloud.
|
||||||
|
@ -96,7 +98,7 @@ class UpdatingPatchesState(BaseState):
|
||||||
if subcloud_patches[patch_id]['repostate'] == \
|
if subcloud_patches[patch_id]['repostate'] == \
|
||||||
patching_v1.PATCH_STATE_APPLIED:
|
patching_v1.PATCH_STATE_APPLIED:
|
||||||
if subcloud_patches[patch_id]['patchstate'] != \
|
if subcloud_patches[patch_id]['patchstate'] != \
|
||||||
patching_v1.PATCH_STATE_APPLIED:
|
patching_v1.PATCH_STATE_APPLIED:
|
||||||
self.info_log(strategy_step,
|
self.info_log(strategy_step,
|
||||||
"Patch %s will be removed from subcloud" %
|
"Patch %s will be removed from subcloud" %
|
||||||
(patch_id))
|
(patch_id))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2021, 2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -24,7 +24,9 @@ class UpgradingDuplexState(BaseState):
|
||||||
|
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
super(UpgradingDuplexState, self).__init__(
|
super(UpgradingDuplexState, self).__init__(
|
||||||
next_state=consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_1, region_name=region_name)
|
next_state=consts.STRATEGY_STATE_UNLOCKING_CONTROLLER_1,
|
||||||
|
region_name=region_name
|
||||||
|
)
|
||||||
self.target_hostname = "controller-1"
|
self.target_hostname = "controller-1"
|
||||||
# max time to wait (in seconds) is: sleep_duration * max_queries
|
# max time to wait (in seconds) is: sleep_duration * max_queries
|
||||||
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
self.sleep_duration = DEFAULT_SLEEP_DURATION
|
||||||
|
@ -61,8 +63,12 @@ class UpgradingDuplexState(BaseState):
|
||||||
upgrades = self.get_sysinv_client(region).get_upgrades()
|
upgrades = self.get_sysinv_client(region).get_upgrades()
|
||||||
|
|
||||||
if len(upgrades) != 0:
|
if len(upgrades) != 0:
|
||||||
if (upgrades[0].state == consts.UPGRADE_STATE_DATA_MIGRATION_FAILED or
|
if (
|
||||||
upgrades[0].state == consts.UPGRADE_STATE_DATA_MIGRATION_COMPLETE):
|
upgrades[0].state ==
|
||||||
|
consts.UPGRADE_STATE_DATA_MIGRATION_FAILED or
|
||||||
|
upgrades[0].state ==
|
||||||
|
consts.UPGRADE_STATE_DATA_MIGRATION_COMPLETE
|
||||||
|
):
|
||||||
msg = "Upgrade state is %s now" % (upgrades[0].state)
|
msg = "Upgrade state is %s now" % (upgrades[0].state)
|
||||||
self.info_log(strategy_step, msg)
|
self.info_log(strategy_step, msg)
|
||||||
break
|
break
|
||||||
|
@ -79,10 +85,11 @@ class UpgradingDuplexState(BaseState):
|
||||||
continue
|
continue
|
||||||
api_counter += 1
|
api_counter += 1
|
||||||
if api_counter >= self.max_queries:
|
if api_counter >= self.max_queries:
|
||||||
raise Exception("Timeout waiting for update state to be updated to "
|
raise Exception(
|
||||||
"updated to 'data-migration-failed' or 'data-migration-complete'."
|
"Timeout waiting for update state to be updated to "
|
||||||
"Please check sysinv.log on the subcloud "
|
"'data-migration-failed' or 'data-migration-complete'. "
|
||||||
"for details.")
|
"Please check sysinv.log on the subcloud for details."
|
||||||
|
)
|
||||||
time.sleep(self.sleep_duration)
|
time.sleep(self.sleep_duration)
|
||||||
|
|
||||||
# If the upgrade state is 'data-migration-complete' we move to the
|
# If the upgrade state is 'data-migration-complete' we move to the
|
||||||
|
@ -95,7 +102,9 @@ class UpgradingDuplexState(BaseState):
|
||||||
|
|
||||||
# The list of upgrades will never contain more than one entry.
|
# The list of upgrades will never contain more than one entry.
|
||||||
if upgrades[0].state == consts.UPGRADE_STATE_DATA_MIGRATION_FAILED:
|
if upgrades[0].state == consts.UPGRADE_STATE_DATA_MIGRATION_FAILED:
|
||||||
raise Exception("Data migration failed on host %s" % self.target_hostname)
|
raise Exception(
|
||||||
|
"Data migration failed on host %s" % self.target_hostname
|
||||||
|
)
|
||||||
|
|
||||||
# If we reach at this point, the upgrade state is 'data-migration-complete'
|
# If we reach at this point, the upgrade state is 'data-migration-complete'
|
||||||
# and we can move to the next state.
|
# and we can move to the next state.
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import keyring
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import keyring
|
||||||
from oslo_serialization import base64
|
from oslo_serialization import base64
|
||||||
from tsconfig.tsconfig import SW_VERSION
|
from tsconfig.tsconfig import SW_VERSION
|
||||||
|
|
||||||
|
@ -88,7 +89,8 @@ class UpgradingSimplexState(BaseState):
|
||||||
subcloud data_install are obtained from:
|
subcloud data_install are obtained from:
|
||||||
|
|
||||||
dcmanager database:
|
dcmanager database:
|
||||||
subcloud.subcloud_install_initial::for values which are persisted at subcloud_add time
|
subcloud.subcloud_install_initial::for values which are persisted at
|
||||||
|
subcloud_add time
|
||||||
|
|
||||||
INSTALL: (needed for upgrade install)
|
INSTALL: (needed for upgrade install)
|
||||||
bootstrap_interface
|
bootstrap_interface
|
||||||
|
@ -103,7 +105,8 @@ class UpgradingSimplexState(BaseState):
|
||||||
# Set this options for https with self-signed certificate
|
# Set this options for https with self-signed certificate
|
||||||
# no_check_certificate
|
# no_check_certificate
|
||||||
|
|
||||||
# Override default filesystem device: also from host-show, but is static.
|
# Override default filesystem device: also from host-show, but is
|
||||||
|
static.
|
||||||
# rootfs_device: "/dev/disk/by-path/pci-0000:00:1f.2-ata-1.0"
|
# rootfs_device: "/dev/disk/by-path/pci-0000:00:1f.2-ata-1.0"
|
||||||
# boot_device: "/dev/disk/by-path/pci-0000:00:1f.2-ata-1.0"
|
# boot_device: "/dev/disk/by-path/pci-0000:00:1f.2-ata-1.0"
|
||||||
|
|
||||||
|
@ -111,22 +114,24 @@ class UpgradingSimplexState(BaseState):
|
||||||
# rd.net.timeout.ipv6dad: 300
|
# rd.net.timeout.ipv6dad: 300
|
||||||
|
|
||||||
BOOTSTRAP: (also needed for bootstrap)
|
BOOTSTRAP: (also needed for bootstrap)
|
||||||
# If the subcloud's bootstrap IP interface and the system controller are not on the
|
# If the subcloud's bootstrap IP interface and the system controller
|
||||||
# same network then the customer must configure a default route or static route
|
# are not on the same network then the customer must configure a
|
||||||
# so that the Central Cloud can login bootstrap the newly installed subcloud.
|
# default route or static route so that the Central Cloud can login
|
||||||
# If nexthop_gateway is specified and the network_address is not specified then a
|
# bootstrap the newly installed subcloud. If nexthop_gateway is
|
||||||
# default route will be configured. Otherwise, if a network_address is specified
|
# specified and the network_address is not specified then a default
|
||||||
then
|
# route will be configured. Otherwise, if a network_address is
|
||||||
# a static route will be configured.
|
# specified then a static route will be configured.
|
||||||
nexthop_gateway: default_route_address
|
nexthop_gateway: default_route_address
|
||||||
network_address: static_route_address
|
network_address: static_route_address
|
||||||
network_mask: static_route_mask
|
network_mask: static_route_mask
|
||||||
|
|
||||||
subcloud.data_upgrade - persist for upgrade duration
|
subcloud.data_upgrade - persist for upgrade duration
|
||||||
for values from subcloud online sysinv host-show (persist since upgrade-start)
|
for values from subcloud online sysinv host-show
|
||||||
|
(persist since upgrade-start)
|
||||||
bmc_address # sysinv_v1 host-show
|
bmc_address # sysinv_v1 host-show
|
||||||
bmc_username # sysinv_v1 host-show
|
bmc_username # sysinv_v1 host-show
|
||||||
for values from barbican_client (as barbican user), or from upgrade-start:
|
for values from barbican_client (as barbican user),
|
||||||
|
or from upgrade-start:
|
||||||
bmc_password --- obtain from barbican_client as barbican user
|
bmc_password --- obtain from barbican_client as barbican user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -239,7 +244,7 @@ class UpgradingSimplexState(BaseState):
|
||||||
return upgrade_data_install
|
return upgrade_data_install
|
||||||
|
|
||||||
def _get_subcloud_upgrade_data(
|
def _get_subcloud_upgrade_data(
|
||||||
self, strategy_step, subcloud_sysinv_client, subcloud_barbican_client):
|
self, strategy_step, subcloud_sysinv_client, subcloud_barbican_client):
|
||||||
"""Get the subcloud data required for upgrades.
|
"""Get the subcloud data required for upgrades.
|
||||||
|
|
||||||
In case the subcloud is no longer reachable, get upgrade_data from
|
In case the subcloud is no longer reachable, get upgrade_data from
|
||||||
|
@ -323,8 +328,9 @@ class UpgradingSimplexState(BaseState):
|
||||||
|
|
||||||
def perform_subcloud_install(self, strategy_step, install_values):
|
def perform_subcloud_install(self, strategy_step, install_values):
|
||||||
|
|
||||||
log_file = os.path.join(consts.DC_ANSIBLE_LOG_DIR, strategy_step.subcloud.name) + \
|
log_file = os.path.join(
|
||||||
'_playbook_output.log'
|
consts.DC_ANSIBLE_LOG_DIR,
|
||||||
|
strategy_step.subcloud.name) + '_playbook_output.log'
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
deploy_status=consts.DEPLOY_STATE_PRE_INSTALL)
|
deploy_status=consts.DEPLOY_STATE_PRE_INSTALL)
|
||||||
|
@ -375,7 +381,8 @@ class UpgradingSimplexState(BaseState):
|
||||||
# Detailed error message for subcloud error description field.
|
# Detailed error message for subcloud error description field.
|
||||||
# Exception message for strategy_step detail.
|
# Exception message for strategy_step detail.
|
||||||
msg = utils.find_ansible_error_msg(
|
msg = utils.find_ansible_error_msg(
|
||||||
strategy_step.subcloud.name, log_file, consts.DEPLOY_STATE_INSTALLING)
|
strategy_step.subcloud.name, log_file,
|
||||||
|
consts.DEPLOY_STATE_INSTALLING)
|
||||||
db_api.subcloud_update(
|
db_api.subcloud_update(
|
||||||
self.context, strategy_step.subcloud_id,
|
self.context, strategy_step.subcloud_id,
|
||||||
deploy_status=consts.DEPLOY_STATE_INSTALL_FAILED,
|
deploy_status=consts.DEPLOY_STATE_INSTALL_FAILED,
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from tsconfig.tsconfig import SW_VERSION
|
from tsconfig.tsconfig import SW_VERSION
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
|
@ -137,7 +137,9 @@ class SwUpdateManager(manager.Manager):
|
||||||
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_UPGRADE:
|
elif strategy_type == consts.SW_UPDATE_TYPE_UPGRADE:
|
||||||
# force option only has an effect in offline case for upgrade
|
# force option only has an effect in offline case for upgrade
|
||||||
if force and (availability_status != dccommon_consts.AVAILABILITY_ONLINE):
|
if force and (
|
||||||
|
availability_status != dccommon_consts.AVAILABILITY_ONLINE
|
||||||
|
):
|
||||||
if cfg.CONF.use_usm:
|
if cfg.CONF.use_usm:
|
||||||
return (subcloud_status.endpoint_type ==
|
return (subcloud_status.endpoint_type ==
|
||||||
dccommon_consts.ENDPOINT_TYPE_SOFTWARE and
|
dccommon_consts.ENDPOINT_TYPE_SOFTWARE and
|
||||||
|
@ -352,14 +354,16 @@ class SwUpdateManager(manager.Manager):
|
||||||
else:
|
else:
|
||||||
subcloud_status = db_api.subcloud_status_get(
|
subcloud_status = db_api.subcloud_status_get(
|
||||||
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_LOAD)
|
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_LOAD)
|
||||||
if subcloud_status.sync_status == dccommon_consts.SYNC_STATUS_IN_SYNC:
|
if subcloud_status.sync_status == \
|
||||||
|
dccommon_consts.SYNC_STATUS_IN_SYNC:
|
||||||
raise exceptions.BadRequest(
|
raise exceptions.BadRequest(
|
||||||
resource='strategy',
|
resource='strategy',
|
||||||
msg='Subcloud %s does not require upgrade' % cloud_name)
|
msg='Subcloud %s does not require upgrade' % cloud_name)
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_FIRMWARE:
|
elif strategy_type == consts.SW_UPDATE_TYPE_FIRMWARE:
|
||||||
subcloud_status = db_api.subcloud_status_get(
|
subcloud_status = db_api.subcloud_status_get(
|
||||||
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_FIRMWARE)
|
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_FIRMWARE)
|
||||||
if subcloud_status.sync_status == dccommon_consts.SYNC_STATUS_IN_SYNC:
|
if subcloud_status.sync_status == \
|
||||||
|
dccommon_consts.SYNC_STATUS_IN_SYNC:
|
||||||
raise exceptions.BadRequest(
|
raise exceptions.BadRequest(
|
||||||
resource='strategy',
|
resource='strategy',
|
||||||
msg='Subcloud %s does not require firmware update'
|
msg='Subcloud %s does not require firmware update'
|
||||||
|
@ -372,7 +376,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
subcloud_status = db_api.subcloud_status_get(
|
subcloud_status = db_api.subcloud_status_get(
|
||||||
context, subcloud.id,
|
context, subcloud.id,
|
||||||
dccommon_consts.ENDPOINT_TYPE_KUBERNETES)
|
dccommon_consts.ENDPOINT_TYPE_KUBERNETES)
|
||||||
if subcloud_status.sync_status == dccommon_consts.SYNC_STATUS_IN_SYNC:
|
if subcloud_status.sync_status == \
|
||||||
|
dccommon_consts.SYNC_STATUS_IN_SYNC:
|
||||||
raise exceptions.BadRequest(
|
raise exceptions.BadRequest(
|
||||||
resource='strategy',
|
resource='strategy',
|
||||||
msg='Subcloud %s does not require kubernetes update'
|
msg='Subcloud %s does not require kubernetes update'
|
||||||
|
@ -385,7 +390,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
subcloud_status = db_api.subcloud_status_get(
|
subcloud_status = db_api.subcloud_status_get(
|
||||||
context, subcloud.id,
|
context, subcloud.id,
|
||||||
dccommon_consts.ENDPOINT_TYPE_KUBE_ROOTCA)
|
dccommon_consts.ENDPOINT_TYPE_KUBE_ROOTCA)
|
||||||
if subcloud_status.sync_status == dccommon_consts.SYNC_STATUS_IN_SYNC:
|
if subcloud_status.sync_status == \
|
||||||
|
dccommon_consts.SYNC_STATUS_IN_SYNC:
|
||||||
raise exceptions.BadRequest(
|
raise exceptions.BadRequest(
|
||||||
resource='strategy',
|
resource='strategy',
|
||||||
msg='Subcloud %s does not require kube rootca update'
|
msg='Subcloud %s does not require kube rootca update'
|
||||||
|
@ -394,7 +400,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
# Make sure subcloud requires patching
|
# Make sure subcloud requires patching
|
||||||
subcloud_status = db_api.subcloud_status_get(
|
subcloud_status = db_api.subcloud_status_get(
|
||||||
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_PATCHING)
|
context, subcloud.id, dccommon_consts.ENDPOINT_TYPE_PATCHING)
|
||||||
if subcloud_status.sync_status == dccommon_consts.SYNC_STATUS_IN_SYNC:
|
if subcloud_status.sync_status == \
|
||||||
|
dccommon_consts.SYNC_STATUS_IN_SYNC:
|
||||||
raise exceptions.BadRequest(
|
raise exceptions.BadRequest(
|
||||||
resource='strategy',
|
resource='strategy',
|
||||||
msg='Subcloud %s does not require patching' % cloud_name)
|
msg='Subcloud %s does not require patching' % cloud_name)
|
||||||
|
@ -469,7 +476,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if strategy_type == consts.SW_UPDATE_TYPE_UPGRADE:
|
if strategy_type == consts.SW_UPDATE_TYPE_UPGRADE:
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status != \
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
if not force:
|
if not force:
|
||||||
continue
|
continue
|
||||||
elif cfg.CONF.use_usm:
|
elif cfg.CONF.use_usm:
|
||||||
|
@ -490,7 +498,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
msg='Upgrade sync status is unknown for one or more '
|
msg='Upgrade sync status is unknown for one or more '
|
||||||
'subclouds')
|
'subclouds')
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_PATCH:
|
elif strategy_type == consts.SW_UPDATE_TYPE_PATCH:
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status != \
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
continue
|
continue
|
||||||
elif (subcloud_status.endpoint_type ==
|
elif (subcloud_status.endpoint_type ==
|
||||||
dccommon_consts.ENDPOINT_TYPE_PATCHING and
|
dccommon_consts.ENDPOINT_TYPE_PATCHING and
|
||||||
|
@ -501,7 +510,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
msg='Patching sync status is unknown for one or more '
|
msg='Patching sync status is unknown for one or more '
|
||||||
'subclouds')
|
'subclouds')
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_FIRMWARE:
|
elif strategy_type == consts.SW_UPDATE_TYPE_FIRMWARE:
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status != \
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
continue
|
continue
|
||||||
elif (subcloud_status.endpoint_type ==
|
elif (subcloud_status.endpoint_type ==
|
||||||
dccommon_consts.ENDPOINT_TYPE_FIRMWARE and
|
dccommon_consts.ENDPOINT_TYPE_FIRMWARE and
|
||||||
|
@ -512,7 +522,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
msg='Firmware sync status is unknown for one or more '
|
msg='Firmware sync status is unknown for one or more '
|
||||||
'subclouds')
|
'subclouds')
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_KUBERNETES:
|
elif strategy_type == consts.SW_UPDATE_TYPE_KUBERNETES:
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status != \
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
continue
|
continue
|
||||||
elif (subcloud_status.endpoint_type ==
|
elif (subcloud_status.endpoint_type ==
|
||||||
dccommon_consts.ENDPOINT_TYPE_KUBERNETES and
|
dccommon_consts.ENDPOINT_TYPE_KUBERNETES and
|
||||||
|
@ -523,7 +534,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
msg='Kubernetes sync status is unknown for one or more '
|
msg='Kubernetes sync status is unknown for one or more '
|
||||||
'subclouds')
|
'subclouds')
|
||||||
elif strategy_type == consts.SW_UPDATE_TYPE_KUBE_ROOTCA_UPDATE:
|
elif strategy_type == consts.SW_UPDATE_TYPE_KUBE_ROOTCA_UPDATE:
|
||||||
if subcloud.availability_status != dccommon_consts.AVAILABILITY_ONLINE:
|
if subcloud.availability_status != \
|
||||||
|
dccommon_consts.AVAILABILITY_ONLINE:
|
||||||
continue
|
continue
|
||||||
elif (subcloud_status.endpoint_type ==
|
elif (subcloud_status.endpoint_type ==
|
||||||
dccommon_consts.ENDPOINT_TYPE_KUBE_ROOTCA and
|
dccommon_consts.ENDPOINT_TYPE_KUBE_ROOTCA and
|
||||||
|
@ -552,7 +564,8 @@ class SwUpdateManager(manager.Manager):
|
||||||
max_parallel_subclouds = 1
|
max_parallel_subclouds = 1
|
||||||
|
|
||||||
if max_parallel_subclouds is None:
|
if max_parallel_subclouds is None:
|
||||||
max_parallel_subclouds = consts.DEFAULT_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS
|
max_parallel_subclouds = (
|
||||||
|
consts.DEFAULT_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS)
|
||||||
|
|
||||||
strategy_step_created = False
|
strategy_step_created = False
|
||||||
# Create the strategy
|
# Create the strategy
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
# Copyright 2017 Ericsson AB.
|
# Copyright 2017 Ericsson AB.
|
||||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
# Copyright (c) 2017-2022, 2024 Wind River Systems, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# you may not use this file except in compliance with the License.
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# You may obtain a copy of the License at
|
# a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# implied.
|
# License for the specific language governing permissions and limitations
|
||||||
# See the License for the specific language governing permissions and
|
# under the License.
|
||||||
# limitations under the License.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
from dccommon.drivers.openstack import vim
|
from dccommon.drivers.openstack import vim
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.orchestrator.orch_thread import OrchThread
|
from dcmanager.orchestrator.orch_thread import OrchThread
|
||||||
|
@ -88,7 +89,8 @@ class SwUpgradeOrchThread(OrchThread):
|
||||||
consts.STRATEGY_STATE_FINISHING_PATCH_STRATEGY:
|
consts.STRATEGY_STATE_FINISHING_PATCH_STRATEGY:
|
||||||
FinishingPatchStrategyState,
|
FinishingPatchStrategyState,
|
||||||
consts.STRATEGY_STATE_STARTING_UPGRADE: StartingUpgradeState,
|
consts.STRATEGY_STATE_STARTING_UPGRADE: StartingUpgradeState,
|
||||||
consts.STRATEGY_STATE_TRANSFERRING_CA_CERTIFICATE: TransferCACertificateState,
|
consts.STRATEGY_STATE_TRANSFERRING_CA_CERTIFICATE:
|
||||||
|
TransferCACertificateState,
|
||||||
consts.STRATEGY_STATE_LOCKING_CONTROLLER_0: LockSimplexState,
|
consts.STRATEGY_STATE_LOCKING_CONTROLLER_0: LockSimplexState,
|
||||||
consts.STRATEGY_STATE_LOCKING_CONTROLLER_1: LockDuplexState,
|
consts.STRATEGY_STATE_LOCKING_CONTROLLER_1: LockDuplexState,
|
||||||
consts.STRATEGY_STATE_UPGRADING_SIMPLEX: UpgradingSimplexState,
|
consts.STRATEGY_STATE_UPGRADING_SIMPLEX: UpgradingSimplexState,
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# All Rights Reserved.
|
||||||
# not use this file except in compliance with the License. You may obtain
|
#
|
||||||
# a copy of the License at
|
# 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
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -83,12 +85,11 @@ class SubcloudStateClient(RPCClient):
|
||||||
update_state_only=update_state_only,
|
update_state_only=update_state_only,
|
||||||
audit_fail_count=audit_fail_count))
|
audit_fail_count=audit_fail_count))
|
||||||
|
|
||||||
def update_subcloud_endpoint_status(self, ctxt, subcloud_name=None,
|
def update_subcloud_endpoint_status(
|
||||||
subcloud_region=None,
|
self, ctxt, subcloud_name=None, subcloud_region=None, endpoint_type=None,
|
||||||
endpoint_type=None,
|
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC, ignore_endpoints=None,
|
||||||
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
alarmable=True
|
||||||
ignore_endpoints=None,
|
):
|
||||||
alarmable=True):
|
|
||||||
# Note: This is an asynchronous operation.
|
# Note: This is an asynchronous operation.
|
||||||
# See below for synchronous method call
|
# See below for synchronous method call
|
||||||
return self.cast(ctxt, self.make_msg('update_subcloud_endpoint_status',
|
return self.cast(ctxt, self.make_msg('update_subcloud_endpoint_status',
|
||||||
|
@ -99,12 +100,11 @@ class SubcloudStateClient(RPCClient):
|
||||||
ignore_endpoints=ignore_endpoints,
|
ignore_endpoints=ignore_endpoints,
|
||||||
alarmable=alarmable))
|
alarmable=alarmable))
|
||||||
|
|
||||||
def update_subcloud_endpoint_status_sync(self, ctxt, subcloud_name=None,
|
def update_subcloud_endpoint_status_sync(
|
||||||
subcloud_region=None,
|
self, ctxt, subcloud_name=None, subcloud_region=None, endpoint_type=None,
|
||||||
endpoint_type=None,
|
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC, ignore_endpoints=None,
|
||||||
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
alarmable=True
|
||||||
ignore_endpoints=None,
|
):
|
||||||
alarmable=True):
|
|
||||||
# Note: synchronous
|
# Note: synchronous
|
||||||
return self.call(ctxt, self.make_msg('update_subcloud_endpoint_status',
|
return self.call(ctxt, self.make_msg('update_subcloud_endpoint_status',
|
||||||
subcloud_name=subcloud_name,
|
subcloud_name=subcloud_name,
|
||||||
|
@ -144,16 +144,20 @@ class ManagerClient(RPCClient):
|
||||||
return self.call(ctxt, self.make_msg('delete_subcloud',
|
return self.call(ctxt, self.make_msg('delete_subcloud',
|
||||||
subcloud_id=subcloud_id))
|
subcloud_id=subcloud_id))
|
||||||
|
|
||||||
def rename_subcloud(self, ctxt, subcloud_id, curr_subcloud_name, new_subcloud_name=None):
|
def rename_subcloud(
|
||||||
|
self, ctxt, subcloud_id, curr_subcloud_name, new_subcloud_name=None
|
||||||
|
):
|
||||||
return self.call(ctxt, self.make_msg('rename_subcloud',
|
return self.call(ctxt, self.make_msg('rename_subcloud',
|
||||||
subcloud_id=subcloud_id,
|
subcloud_id=subcloud_id,
|
||||||
curr_subcloud_name=curr_subcloud_name,
|
curr_subcloud_name=curr_subcloud_name,
|
||||||
new_subcloud_name=new_subcloud_name))
|
new_subcloud_name=new_subcloud_name))
|
||||||
|
|
||||||
def update_subcloud(self, ctxt, subcloud_id, management_state=None,
|
def update_subcloud(
|
||||||
description=None, location=None, group_id=None,
|
self, ctxt, subcloud_id, management_state=None, description=None,
|
||||||
data_install=None, force=None,
|
location=None, group_id=None, data_install=None, force=None,
|
||||||
deploy_status=None, peer_group_id=None, bootstrap_values=None, bootstrap_address=None):
|
deploy_status=None, peer_group_id=None, bootstrap_values=None,
|
||||||
|
bootstrap_address=None
|
||||||
|
):
|
||||||
return self.call(ctxt, self.make_msg('update_subcloud',
|
return self.call(ctxt, self.make_msg('update_subcloud',
|
||||||
subcloud_id=subcloud_id,
|
subcloud_id=subcloud_id,
|
||||||
management_state=management_state,
|
management_state=management_state,
|
||||||
|
@ -242,11 +246,12 @@ class ManagerClient(RPCClient):
|
||||||
|
|
||||||
def subcloud_deploy_resume(self, ctxt, subcloud_id, subcloud_name,
|
def subcloud_deploy_resume(self, ctxt, subcloud_id, subcloud_name,
|
||||||
payload, deploy_states_to_run):
|
payload, deploy_states_to_run):
|
||||||
return self.cast(ctxt, self.make_msg('subcloud_deploy_resume',
|
return self.cast(ctxt, self.make_msg(
|
||||||
subcloud_id=subcloud_id,
|
'subcloud_deploy_resume',
|
||||||
subcloud_name=subcloud_name,
|
subcloud_id=subcloud_id,
|
||||||
payload=payload,
|
subcloud_name=subcloud_name,
|
||||||
deploy_states_to_run=deploy_states_to_run))
|
payload=payload,
|
||||||
|
deploy_states_to_run=deploy_states_to_run))
|
||||||
|
|
||||||
def get_subcloud_name_by_region_name(self, ctxt, subcloud_region):
|
def get_subcloud_name_by_region_name(self, ctxt, subcloud_region):
|
||||||
return self.call(ctxt, self.make_msg('get_subcloud_name_by_region_name',
|
return self.call(ctxt, self.make_msg('get_subcloud_name_by_region_name',
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# The right to copy, distribute, modify, or otherwise make use
|
# The right to copy, distribute, modify, or otherwise make use
|
||||||
# of this software may be licensed only pursuant to the terms
|
# of this software may be licensed only pursuant to the terms
|
||||||
|
@ -112,12 +112,11 @@ class DCManagerStateService(service.Service):
|
||||||
super(DCManagerStateService, self).stop()
|
super(DCManagerStateService, self).stop()
|
||||||
|
|
||||||
@request_context
|
@request_context
|
||||||
def update_subcloud_endpoint_status(self, context, subcloud_name=None,
|
def update_subcloud_endpoint_status(
|
||||||
subcloud_region=None,
|
self, context, subcloud_name=None, subcloud_region=None, endpoint_type=None,
|
||||||
endpoint_type=None,
|
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC, alarmable=True,
|
||||||
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
ignore_endpoints=None
|
||||||
alarmable=True,
|
):
|
||||||
ignore_endpoints=None):
|
|
||||||
# Updates subcloud endpoint sync status
|
# Updates subcloud endpoint sync status
|
||||||
LOG.info("Handling update_subcloud_endpoint_status request for "
|
LOG.info("Handling update_subcloud_endpoint_status request for "
|
||||||
"subcloud: (%s) endpoint: (%s) status:(%s) "
|
"subcloud: (%s) endpoint: (%s) status:(%s) "
|
||||||
|
|
|
@ -10,32 +10,30 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# The right to copy, distribute, modify, or otherwise make use
|
# The right to copy, distribute, modify, or otherwise make use
|
||||||
# of this software may be licensed only pursuant to the terms
|
# of this software may be licensed only pursuant to the terms
|
||||||
# of an applicable Wind River license agreement.
|
# of an applicable Wind River license agreement.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from fm_api import constants as fm_const
|
||||||
|
from fm_api import fm_api
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
from dcorch.rpc import client as dcorch_rpc_client
|
|
||||||
|
|
||||||
from dcmanager.audit import rpcapi as dcmanager_audit_rpc_client
|
from dcmanager.audit import rpcapi as dcmanager_audit_rpc_client
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.common import context
|
from dcmanager.common import context
|
||||||
from dcmanager.common import exceptions
|
from dcmanager.common import exceptions
|
||||||
from dcmanager.common import manager
|
from dcmanager.common import manager
|
||||||
from dcmanager.common import utils
|
from dcmanager.common import utils
|
||||||
from dcmanager.rpc import client as rpc_client
|
|
||||||
|
|
||||||
from dcmanager.db import api as db_api
|
from dcmanager.db import api as db_api
|
||||||
|
from dcmanager.rpc import client as rpc_client
|
||||||
from fm_api import constants as fm_const
|
from dcorch.rpc import client as dcorch_rpc_client
|
||||||
from fm_api import fm_api
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
ALARM_OUT_OF_SYNC = fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC
|
||||||
|
|
||||||
|
|
||||||
def sync_update_subcloud_endpoint_status(func):
|
def sync_update_subcloud_endpoint_status(func):
|
||||||
|
@ -133,27 +131,31 @@ class SubcloudStateManager(manager.Manager):
|
||||||
|
|
||||||
# Trigger subcloud audits for the subcloud after
|
# Trigger subcloud audits for the subcloud after
|
||||||
# its identity endpoint turns to other status from unknown
|
# its identity endpoint turns to other status from unknown
|
||||||
|
is_sync_unknown = sync_status != dccommon_consts.SYNC_STATUS_UNKNOWN
|
||||||
|
is_identity_unknown = (
|
||||||
|
original_identity_status == dccommon_consts.SYNC_STATUS_UNKNOWN
|
||||||
|
)
|
||||||
if endpoint_type == dccommon_consts.ENDPOINT_TYPE_IDENTITY \
|
if endpoint_type == dccommon_consts.ENDPOINT_TYPE_IDENTITY \
|
||||||
and sync_status != dccommon_consts.SYNC_STATUS_UNKNOWN \
|
and is_sync_unknown and is_identity_unknown:
|
||||||
and original_identity_status == dccommon_consts.SYNC_STATUS_UNKNOWN:
|
|
||||||
if not subcloud.first_identity_sync_complete:
|
if not subcloud.first_identity_sync_complete:
|
||||||
db_api.subcloud_update(context, subcloud_id,
|
db_api.subcloud_update(context, subcloud_id,
|
||||||
first_identity_sync_complete=True)
|
first_identity_sync_complete=True)
|
||||||
LOG.debug('Request for audits for %s after updating '
|
LOG.debug('Request for audits for %s after updating '
|
||||||
'identity out of unknown' % subcloud.name)
|
'identity out of unknown' % subcloud.name)
|
||||||
self.audit_rpc_client.trigger_subcloud_audits(context, subcloud_id)
|
self.audit_rpc_client.trigger_subcloud_audits(
|
||||||
|
context, subcloud_id)
|
||||||
|
|
||||||
entity_instance_id = "subcloud=%s.resource=%s" % \
|
entity_instance_id = "subcloud=%s.resource=%s" % \
|
||||||
(subcloud.name, endpoint_type)
|
(subcloud.name, endpoint_type)
|
||||||
fault = self.fm_api.get_fault(
|
fault = self.fm_api.get_fault(
|
||||||
fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC,
|
ALARM_OUT_OF_SYNC,
|
||||||
entity_instance_id)
|
entity_instance_id)
|
||||||
|
|
||||||
if (sync_status != dccommon_consts.SYNC_STATUS_OUT_OF_SYNC) \
|
if (sync_status != dccommon_consts.SYNC_STATUS_OUT_OF_SYNC) \
|
||||||
and fault:
|
and fault:
|
||||||
try:
|
try:
|
||||||
self.fm_api.clear_fault(
|
self.fm_api.clear_fault(
|
||||||
fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC, # noqa
|
ALARM_OUT_OF_SYNC,
|
||||||
entity_instance_id)
|
entity_instance_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
|
@ -162,8 +164,9 @@ class SubcloudStateManager(manager.Manager):
|
||||||
(sync_status == dccommon_consts.SYNC_STATUS_OUT_OF_SYNC):
|
(sync_status == dccommon_consts.SYNC_STATUS_OUT_OF_SYNC):
|
||||||
entity_type_id = fm_const.FM_ENTITY_TYPE_SUBCLOUD
|
entity_type_id = fm_const.FM_ENTITY_TYPE_SUBCLOUD
|
||||||
try:
|
try:
|
||||||
|
|
||||||
fault = fm_api.Fault(
|
fault = fm_api.Fault(
|
||||||
alarm_id=fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC, # noqa
|
alarm_id=ALARM_OUT_OF_SYNC,
|
||||||
alarm_state=fm_const.FM_ALARM_STATE_SET,
|
alarm_state=fm_const.FM_ALARM_STATE_SET,
|
||||||
entity_type_id=entity_type_id,
|
entity_type_id=entity_type_id,
|
||||||
entity_instance_id=entity_instance_id,
|
entity_instance_id=entity_instance_id,
|
||||||
|
@ -208,7 +211,7 @@ class SubcloudStateManager(manager.Manager):
|
||||||
(subcloud.name, endpoint)
|
(subcloud.name, endpoint)
|
||||||
|
|
||||||
fault = self.fm_api.get_fault(
|
fault = self.fm_api.get_fault(
|
||||||
fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC,
|
ALARM_OUT_OF_SYNC,
|
||||||
entity_instance_id)
|
entity_instance_id)
|
||||||
|
|
||||||
# TODO(yuxing): batch clear all the out-of-sync alarms of a
|
# TODO(yuxing): batch clear all the out-of-sync alarms of a
|
||||||
|
@ -219,7 +222,7 @@ class SubcloudStateManager(manager.Manager):
|
||||||
and fault:
|
and fault:
|
||||||
try:
|
try:
|
||||||
self.fm_api.clear_fault(
|
self.fm_api.clear_fault(
|
||||||
fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC, # noqa
|
ALARM_OUT_OF_SYNC,
|
||||||
entity_instance_id)
|
entity_instance_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
|
@ -229,7 +232,7 @@ class SubcloudStateManager(manager.Manager):
|
||||||
entity_type_id = fm_const.FM_ENTITY_TYPE_SUBCLOUD
|
entity_type_id = fm_const.FM_ENTITY_TYPE_SUBCLOUD
|
||||||
try:
|
try:
|
||||||
fault = fm_api.Fault(
|
fault = fm_api.Fault(
|
||||||
alarm_id=fm_const.FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC, # noqa
|
alarm_id=ALARM_OUT_OF_SYNC,
|
||||||
alarm_state=fm_const.FM_ALARM_STATE_SET,
|
alarm_state=fm_const.FM_ALARM_STATE_SET,
|
||||||
entity_type_id=entity_type_id,
|
entity_type_id=entity_type_id,
|
||||||
entity_instance_id=entity_instance_id,
|
entity_instance_id=entity_instance_id,
|
||||||
|
@ -250,9 +253,11 @@ class SubcloudStateManager(manager.Manager):
|
||||||
|
|
||||||
if endpoint_to_update_list:
|
if endpoint_to_update_list:
|
||||||
try:
|
try:
|
||||||
db_api.subcloud_status_update_endpoints(context, subcloud_id,
|
db_api.subcloud_status_update_endpoints(
|
||||||
endpoint_to_update_list,
|
context,
|
||||||
sync_status)
|
subcloud_id,
|
||||||
|
endpoint_to_update_list,
|
||||||
|
sync_status)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
|
|
||||||
|
@ -441,7 +446,9 @@ class SubcloudStateManager(manager.Manager):
|
||||||
try:
|
try:
|
||||||
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Failed to get subcloud by region name %s" % subcloud_region)
|
LOG.exception(
|
||||||
|
"Failed to get subcloud by region name %s" % subcloud_region
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if update_state_only:
|
if update_state_only:
|
||||||
|
@ -529,7 +536,9 @@ class SubcloudStateManager(manager.Manager):
|
||||||
try:
|
try:
|
||||||
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception("Failed to get subcloud by region name: %s" % subcloud_region)
|
LOG.exception(
|
||||||
|
"Failed to get subcloud by region name: %s" % subcloud_region
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 2015 Ericsson AB
|
# Copyright (c) 2015 Ericsson AB
|
||||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -16,25 +16,23 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import sqlalchemy
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_db import options
|
from oslo_db import options
|
||||||
|
from oslotest import base
|
||||||
|
import sqlalchemy
|
||||||
|
from sqlalchemy.engine import Engine
|
||||||
|
from sqlalchemy import event
|
||||||
|
|
||||||
from dcmanager.common import consts
|
from dcmanager.common import consts
|
||||||
from dcmanager.db import api as api
|
from dcmanager.db import api
|
||||||
from dcmanager.db.sqlalchemy import api as db_api
|
from dcmanager.db.sqlalchemy import api as db_api
|
||||||
|
|
||||||
from dcmanager.tests import utils
|
from dcmanager.tests import utils
|
||||||
from oslotest import base
|
|
||||||
|
|
||||||
|
|
||||||
get_engine = api.get_engine
|
get_engine = api.get_engine
|
||||||
|
|
||||||
# Enable foreign key support in sqlite - see:
|
# Enable foreign key support in sqlite - see:
|
||||||
# http://docs.sqlalchemy.org/en/latest/dialects/sqlite.html
|
# http://docs.sqlalchemy.org/en/latest/dialects/sqlite.html
|
||||||
from sqlalchemy.engine import Engine
|
|
||||||
from sqlalchemy import event
|
|
||||||
|
|
||||||
SUBCLOUD_1 = {'name': 'subcloud1',
|
SUBCLOUD_1 = {'name': 'subcloud1',
|
||||||
'region_name': '2ec93dfb654846909efe61d1b39dd2ce',
|
'region_name': '2ec93dfb654846909efe61d1b39dd2ce',
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import mock
|
|
||||||
from six.moves import http_client
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from six.moves import http_client
|
||||||
|
|
||||||
from dcmanager.db.sqlalchemy import api as db_api
|
from dcmanager.db.sqlalchemy import api as db_api
|
||||||
from dcmanager.rpc import client as rpc_client
|
from dcmanager.rpc import client as rpc_client
|
||||||
|
|
||||||
|
@ -308,7 +310,9 @@ class TestPeerGroupAssociationUpdate(testroot.DCManagerApiTest,
|
||||||
@mock.patch.object(psd_common, 'OpenStackDriver')
|
@mock.patch.object(psd_common, 'OpenStackDriver')
|
||||||
@mock.patch.object(peer_group_association, 'SysinvClient')
|
@mock.patch.object(peer_group_association, 'SysinvClient')
|
||||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||||
def test_sync_association(self, mock_client, mock_sysinv_client, mock_keystone_client):
|
def test_sync_association(
|
||||||
|
self, mock_client, mock_sysinv_client, mock_keystone_client
|
||||||
|
):
|
||||||
mock_client().sync_subcloud_peer_group.return_value = True
|
mock_client().sync_subcloud_peer_group.return_value = True
|
||||||
mock_keystone_client().keystone_client = FakeKeystoneClient()
|
mock_keystone_client().keystone_client = FakeKeystoneClient()
|
||||||
mock_sysinv_client.return_value = FakeSysinvClient()
|
mock_sysinv_client.return_value = FakeSysinvClient()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -7,10 +7,10 @@
|
||||||
import base64
|
import base64
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import mock
|
|
||||||
import os
|
import os
|
||||||
from os import path as os_path
|
from os import path as os_path
|
||||||
|
|
||||||
|
import mock
|
||||||
import six
|
import six
|
||||||
from tsconfig.tsconfig import SW_VERSION
|
from tsconfig.tsconfig import SW_VERSION
|
||||||
import webtest
|
import webtest
|
||||||
|
@ -172,7 +172,8 @@ class TestSubcloudDeployBootstrap(testroot.DCManagerApiTest):
|
||||||
@mock.patch.object(dutils, 'load_yaml_file')
|
@mock.patch.object(dutils, 'load_yaml_file')
|
||||||
@mock.patch.object(os_path, 'exists')
|
@mock.patch.object(os_path, 'exists')
|
||||||
def test_subcloud_bootstrap_no_bootstrap_values_on_request(
|
def test_subcloud_bootstrap_no_bootstrap_values_on_request(
|
||||||
self, mock_path_exists, mock_load_yaml_file):
|
self, mock_path_exists, mock_load_yaml_file
|
||||||
|
):
|
||||||
mock_path_exists.side_effect = [False, False, False, False, True]
|
mock_path_exists.side_effect = [False, False, False, False, True]
|
||||||
fake_bootstrap_values = copy.copy(
|
fake_bootstrap_values = copy.copy(
|
||||||
fake_subcloud.FAKE_BOOTSTRAP_FILE_DATA)
|
fake_subcloud.FAKE_BOOTSTRAP_FILE_DATA)
|
||||||
|
@ -219,7 +220,7 @@ class TestSubcloudDeployBootstrap(testroot.DCManagerApiTest):
|
||||||
name="existing_subcloud",
|
name="existing_subcloud",
|
||||||
deploy_status=consts.DEPLOY_STATE_DONE,
|
deploy_status=consts.DEPLOY_STATE_DONE,
|
||||||
**conflicting_subnet
|
**conflicting_subnet
|
||||||
)
|
)
|
||||||
|
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(
|
subcloud = fake_subcloud.create_fake_subcloud(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
|
@ -264,13 +265,15 @@ class TestSubcloudDeployConfig(testroot.DCManagerApiTest):
|
||||||
self, mock_load_yaml, mock_path_exists
|
self, mock_load_yaml, mock_path_exists
|
||||||
):
|
):
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx, data_install='')
|
subcloud = fake_subcloud.create_fake_subcloud(self.ctx, data_install='')
|
||||||
fake_password = (base64.b64encode('testpass'.encode("utf-8"))).decode('ascii')
|
fake_password = \
|
||||||
|
(base64.b64encode('testpass'.encode("utf-8"))).decode('ascii')
|
||||||
data = {'sysadmin_password': fake_password}
|
data = {'sysadmin_password': fake_password}
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_config.return_value = True
|
self.mock_rpc_client().subcloud_deploy_config.return_value = True
|
||||||
self.mock_get_request_data.return_value = data
|
self.mock_get_request_data.return_value = data
|
||||||
overrides_file = psd_common.get_config_file_path(subcloud.name)
|
overrides_file = psd_common.get_config_file_path(subcloud.name)
|
||||||
mock_path_exists.side_effect = lambda x: True if x == overrides_file else False
|
mock_path_exists.side_effect = \
|
||||||
|
lambda x: True if x == overrides_file else False
|
||||||
mock_load_yaml.return_value = {
|
mock_load_yaml.return_value = {
|
||||||
consts.BOOTSTRAP_ADDRESS:
|
consts.BOOTSTRAP_ADDRESS:
|
||||||
fake_subcloud.FAKE_BOOTSTRAP_VALUE[consts.BOOTSTRAP_ADDRESS]}
|
fake_subcloud.FAKE_BOOTSTRAP_VALUE[consts.BOOTSTRAP_ADDRESS]}
|
||||||
|
@ -289,7 +292,8 @@ class TestSubcloudDeployConfig(testroot.DCManagerApiTest):
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(
|
subcloud = fake_subcloud.create_fake_subcloud(
|
||||||
self.ctx, data_install=json.dumps(data_install)
|
self.ctx, data_install=json.dumps(data_install)
|
||||||
)
|
)
|
||||||
fake_password = (base64.b64encode('testpass'.encode("utf-8"))).decode('ascii')
|
fake_password = \
|
||||||
|
(base64.b64encode('testpass'.encode("utf-8"))).decode('ascii')
|
||||||
data = {'sysadmin_password': fake_password}
|
data = {'sysadmin_password': fake_password}
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_config.return_value = True
|
self.mock_rpc_client().subcloud_deploy_config.return_value = True
|
||||||
|
@ -391,7 +395,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
mock_initial_deployment.return_value = True
|
mock_initial_deployment.return_value = True
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
|
|
||||||
response = self.app.patch_json(
|
response = self.app.patch_json(
|
||||||
FAKE_URL + '/' + str(subcloud.id) + '/install',
|
FAKE_URL + '/' + str(subcloud.id) + '/install',
|
||||||
|
@ -427,10 +432,12 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
mock_initial_deployment.return_value = True
|
mock_initial_deployment.return_value = True
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
|
|
||||||
with mock.patch('builtins.open',
|
with mock.patch('builtins.open', mock.mock_open(
|
||||||
mock.mock_open(read_data=fake_subcloud.FAKE_UPGRADES_METADATA)):
|
read_data=fake_subcloud.FAKE_UPGRADES_METADATA
|
||||||
|
)):
|
||||||
response = self.app.patch_json(
|
response = self.app.patch_json(
|
||||||
FAKE_URL + '/' + str(subcloud.id) + '/install',
|
FAKE_URL + '/' + str(subcloud.id) + '/install',
|
||||||
headers=FAKE_HEADERS, params=install_payload)
|
headers=FAKE_HEADERS, params=install_payload)
|
||||||
|
@ -441,7 +448,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
|
|
||||||
@mock.patch.object(psd_common, 'is_initial_deployment')
|
@mock.patch.object(psd_common, 'is_initial_deployment')
|
||||||
def test_install_subcloud_not_initial_deployment(
|
def test_install_subcloud_not_initial_deployment(
|
||||||
self, mock_initial_deployment):
|
self, mock_initial_deployment
|
||||||
|
):
|
||||||
|
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(
|
subcloud = fake_subcloud.create_fake_subcloud(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
|
@ -463,7 +471,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
self.mock_get_subcloud_db_install_values.return_value = install_data
|
self.mock_get_subcloud_db_install_values.return_value = install_data
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
mock_initial_deployment.return_value = False
|
mock_initial_deployment.return_value = False
|
||||||
|
|
||||||
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
|
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
|
||||||
|
@ -489,7 +498,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
|
|
||||||
@mock.patch.object(psd_common, 'is_initial_deployment')
|
@mock.patch.object(psd_common, 'is_initial_deployment')
|
||||||
def test_install_subcloud_no_install_values_on_request_or_db(
|
def test_install_subcloud_no_install_values_on_request_or_db(
|
||||||
self, mock_initial_deployment):
|
self, mock_initial_deployment
|
||||||
|
):
|
||||||
|
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(
|
subcloud = fake_subcloud.create_fake_subcloud(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
|
@ -513,7 +523,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
|
|
||||||
@mock.patch.object(psd_common, 'is_initial_deployment')
|
@mock.patch.object(psd_common, 'is_initial_deployment')
|
||||||
def test_install_subcloud_no_install_values_on_request(
|
def test_install_subcloud_no_install_values_on_request(
|
||||||
self, mock_initial_deployment):
|
self, mock_initial_deployment
|
||||||
|
):
|
||||||
|
|
||||||
subcloud = fake_subcloud.create_fake_subcloud(
|
subcloud = fake_subcloud.create_fake_subcloud(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
|
@ -533,7 +544,8 @@ class TestSubcloudDeployInstall(testroot.DCManagerApiTest):
|
||||||
self.mock_get_subcloud_db_install_values.return_value = install_data
|
self.mock_get_subcloud_db_install_values.return_value = install_data
|
||||||
|
|
||||||
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
self.mock_rpc_client().subcloud_deploy_install.return_value = True
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
mock_initial_deployment.return_value = True
|
mock_initial_deployment.return_value = True
|
||||||
|
|
||||||
response = self.app.patch_json(
|
response = self.app.patch_json(
|
||||||
|
@ -688,8 +700,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
@mock.patch.object(os_path, 'isdir')
|
@mock.patch.object(os_path, 'isdir')
|
||||||
@mock.patch.object(os, 'listdir')
|
@mock.patch.object(os, 'listdir')
|
||||||
def test_resume_subcloud(
|
def test_resume_subcloud(
|
||||||
self, mock_os_listdir, mock_os_isdir, mock_initial_deployment,
|
self, mock_os_listdir, mock_os_isdir, mock_initial_deployment, mock_load_yaml
|
||||||
mock_load_yaml):
|
):
|
||||||
mock_os_isdir.return_value = True
|
mock_os_isdir.return_value = True
|
||||||
mock_os_listdir.return_value = ['deploy_chart_fake.tgz',
|
mock_os_listdir.return_value = ['deploy_chart_fake.tgz',
|
||||||
'deploy_overrides_fake.yaml',
|
'deploy_overrides_fake.yaml',
|
||||||
|
@ -705,7 +717,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
data_install=json.dumps(data_install)
|
data_install=json.dumps(data_install)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
||||||
mock_initial_deployment.return_value = True
|
mock_initial_deployment.return_value = True
|
||||||
mock_load_yaml.return_value = {
|
mock_load_yaml.return_value = {
|
||||||
|
@ -722,7 +735,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
install_request = {'install_values': data_install,
|
install_request = {'install_values': data_install,
|
||||||
'sysadmin_password': fake_sysadmin_password,
|
'sysadmin_password': fake_sysadmin_password,
|
||||||
'bmc_password': fake_bmc_password}
|
'bmc_password': fake_bmc_password}
|
||||||
bootstrap_request = {'bootstrap_values': fake_subcloud.FAKE_BOOTSTRAP_FILE_DATA}
|
bootstrap_request = \
|
||||||
|
{'bootstrap_values': fake_subcloud.FAKE_BOOTSTRAP_FILE_DATA}
|
||||||
config_request = {'deploy_config': 'deploy config values',
|
config_request = {'deploy_config': 'deploy config values',
|
||||||
'sysadmin_password': fake_sysadmin_password}
|
'sysadmin_password': fake_sysadmin_password}
|
||||||
resume_request = {**install_request,
|
resume_request = {**install_request,
|
||||||
|
@ -758,7 +772,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
deploy_status=consts.DEPLOY_STATE_CREATED,
|
deploy_status=consts.DEPLOY_STATE_CREATED,
|
||||||
software_version=SW_VERSION)
|
software_version=SW_VERSION)
|
||||||
|
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
||||||
mock_initial_deployment.return_value = False
|
mock_initial_deployment.return_value = False
|
||||||
|
|
||||||
|
@ -780,7 +795,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
deploy_status=consts.DEPLOY_STATE_CREATED,
|
deploy_status=consts.DEPLOY_STATE_CREATED,
|
||||||
software_version=SW_VERSION)
|
software_version=SW_VERSION)
|
||||||
|
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
||||||
invalid_resume_states = [consts.DEPLOY_STATE_INSTALLING,
|
invalid_resume_states = [consts.DEPLOY_STATE_INSTALLING,
|
||||||
consts.DEPLOY_STATE_BOOTSTRAPPING,
|
consts.DEPLOY_STATE_BOOTSTRAPPING,
|
||||||
|
@ -826,7 +842,8 @@ class TestSubcloudDeployResume(testroot.DCManagerApiTest):
|
||||||
mock_os_listdir.return_value = ['deploy_chart_fake.tgz',
|
mock_os_listdir.return_value = ['deploy_chart_fake.tgz',
|
||||||
'deploy_overrides_fake.yaml',
|
'deploy_overrides_fake.yaml',
|
||||||
'deploy_playbook_fake.yaml']
|
'deploy_playbook_fake.yaml']
|
||||||
self.mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
|
self.mock_get_vault_load_files.return_value = \
|
||||||
|
('iso_file_path', 'sig_file_path')
|
||||||
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
self.mock_rpc_client().subcloud_deploy_resume.return_value = True
|
||||||
mock_initial_deployment.return_value = True
|
mock_initial_deployment.return_value = True
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
# Copyright (c) 2020-2024 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -13,12 +13,14 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from os import path as os_path
|
from os import path as os_path
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import six
|
import six
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
|
from tsconfig.tsconfig import SW_VERSION
|
||||||
import webtest
|
import webtest
|
||||||
|
|
||||||
from dccommon import consts as dccommon_consts
|
from dccommon import consts as dccommon_consts
|
||||||
|
@ -30,14 +32,16 @@ from dcmanager.tests.unit.api import test_root_controller as testroot
|
||||||
from dcmanager.tests.unit.common import fake_subcloud
|
from dcmanager.tests.unit.common import fake_subcloud
|
||||||
from dcmanager.tests import utils
|
from dcmanager.tests import utils
|
||||||
|
|
||||||
from tsconfig.tsconfig import SW_VERSION
|
|
||||||
|
|
||||||
FAKE_SOFTWARE_VERSION = '22.12'
|
FAKE_SOFTWARE_VERSION = '22.12'
|
||||||
FAKE_TENANT = utils.UUID1
|
FAKE_TENANT = utils.UUID1
|
||||||
FAKE_ID = '1'
|
FAKE_ID = "1"
|
||||||
FAKE_URL = '/v1.0/subcloud-deploy'
|
FAKE_URL = "/v1.0/subcloud-deploy"
|
||||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
FAKE_HEADERS = {
|
||||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
"X-Tenant-Id": FAKE_TENANT,
|
||||||
|
"X_ROLE": "admin,member,reader",
|
||||||
|
"X-Identity-Status": "Confirmed",
|
||||||
|
"X-Project-Name": "admin",
|
||||||
|
}
|
||||||
|
|
||||||
FAKE_DEPLOY_PLAYBOOK_PREFIX = consts.DEPLOY_PLAYBOOK + '_'
|
FAKE_DEPLOY_PLAYBOOK_PREFIX = consts.DEPLOY_PLAYBOOK + '_'
|
||||||
FAKE_DEPLOY_OVERRIDES_PREFIX = consts.DEPLOY_OVERRIDES + '_'
|
FAKE_DEPLOY_OVERRIDES_PREFIX = consts.DEPLOY_OVERRIDES + '_'
|
||||||
|
@ -52,7 +56,8 @@ FAKE_DEPLOY_FILES = {
|
||||||
FAKE_DEPLOY_CHART_PREFIX: FAKE_DEPLOY_CHART_FILE,
|
FAKE_DEPLOY_CHART_PREFIX: FAKE_DEPLOY_CHART_FILE,
|
||||||
}
|
}
|
||||||
FAKE_DEPLOY_DELETE_FILES = {
|
FAKE_DEPLOY_DELETE_FILES = {
|
||||||
FAKE_DEPLOY_PLAYBOOK_PREFIX: '/opt/platform/deploy/22.12/deployment-manager.yaml',
|
FAKE_DEPLOY_PLAYBOOK_PREFIX:
|
||||||
|
'/opt/platform/deploy/22.12/deployment-manager.yaml',
|
||||||
FAKE_DEPLOY_OVERRIDES_PREFIX:
|
FAKE_DEPLOY_OVERRIDES_PREFIX:
|
||||||
'/opt/platform/deploy/22.12/deployment-manager-overrides-subcloud.yaml',
|
'/opt/platform/deploy/22.12/deployment-manager-overrides-subcloud.yaml',
|
||||||
FAKE_DEPLOY_CHART_PREFIX: '/opt/platform/deploy/22.12/deployment-manager.tgz',
|
FAKE_DEPLOY_CHART_PREFIX: '/opt/platform/deploy/22.12/deployment-manager.tgz',
|
||||||
|
@ -73,154 +78,144 @@ class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
||||||
super(TestSubcloudDeploy, self).setUp()
|
super(TestSubcloudDeploy, self).setUp()
|
||||||
self.ctx = utils.dummy_context()
|
self.ctx = utils.dummy_context()
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy(self, mock_upload_files):
|
def test_post_subcloud_deploy(self, mock_upload_files):
|
||||||
params = [('release', FAKE_SOFTWARE_VERSION)]
|
params = [("release", FAKE_SOFTWARE_VERSION)]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, webtest.Upload(fake_name, fake_content)))
|
fields.append((opt, webtest.Upload(fake_name, fake_content)))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
params += fields
|
params += fields
|
||||||
|
|
||||||
with mock.patch('builtins.open',
|
with mock.patch('builtins.open',
|
||||||
mock.mock_open(read_data=fake_subcloud.FAKE_UPGRADES_METADATA)):
|
mock.mock_open(
|
||||||
|
read_data=fake_subcloud.FAKE_UPGRADES_METADATA
|
||||||
|
)):
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(FAKE_URL,
|
||||||
headers=FAKE_HEADERS,
|
headers=FAKE_HEADERS,
|
||||||
params=params)
|
params=params)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
self.assertEqual(FAKE_SOFTWARE_VERSION, response.json['software_version'])
|
self.assertEqual(FAKE_SOFTWARE_VERSION, response.json["software_version"])
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_without_release(self, mock_upload_files):
|
def test_post_subcloud_deploy_without_release(self, mock_upload_files):
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(FAKE_URL, headers=FAKE_HEADERS, upload_files=fields)
|
||||||
headers=FAKE_HEADERS,
|
|
||||||
upload_files=fields)
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
# Verify the active release will be returned if release doesn't present
|
# Verify the active release will be returned if release doesn't present
|
||||||
self.assertEqual(SW_VERSION, response.json['software_version'])
|
self.assertEqual(SW_VERSION, response.json["software_version"])
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_missing_chart(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_chart(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES, consts.DEPLOY_PRESTAGE]
|
opts = [
|
||||||
|
consts.DEPLOY_PLAYBOOK,
|
||||||
|
consts.DEPLOY_OVERRIDES,
|
||||||
|
consts.DEPLOY_PRESTAGE,
|
||||||
|
]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(
|
||||||
headers=FAKE_HEADERS,
|
FAKE_URL, headers=FAKE_HEADERS, upload_files=fields, expect_errors=True
|
||||||
upload_files=fields,
|
)
|
||||||
expect_errors=True)
|
|
||||||
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_missing_chart_prestages(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_chart_prestages(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES]
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(
|
||||||
headers=FAKE_HEADERS,
|
FAKE_URL, headers=FAKE_HEADERS, upload_files=fields, expect_errors=True
|
||||||
upload_files=fields,
|
)
|
||||||
expect_errors=True)
|
|
||||||
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
def test_post_subcloud_deploy_missing_playbook_overrides(
|
||||||
def test_post_subcloud_deploy_missing_playbook_overrides(self, mock_upload_files):
|
self, mock_upload_files
|
||||||
|
):
|
||||||
opts = [consts.DEPLOY_CHART, consts.DEPLOY_PRESTAGE]
|
opts = [consts.DEPLOY_CHART, consts.DEPLOY_PRESTAGE]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(
|
||||||
headers=FAKE_HEADERS,
|
FAKE_URL, headers=FAKE_HEADERS, upload_files=fields, expect_errors=True
|
||||||
upload_files=fields,
|
)
|
||||||
expect_errors=True)
|
|
||||||
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_missing_prestage(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_prestage(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES, consts.DEPLOY_CHART]
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES, consts.DEPLOY_CHART]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(FAKE_URL, headers=FAKE_HEADERS, upload_files=fields)
|
||||||
headers=FAKE_HEADERS,
|
|
||||||
upload_files=fields)
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_all_input(self, mock_upload_files):
|
def test_post_subcloud_deploy_all_input(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES,
|
opts = [
|
||||||
consts.DEPLOY_CHART, consts.DEPLOY_PRESTAGE]
|
consts.DEPLOY_PLAYBOOK,
|
||||||
|
consts.DEPLOY_OVERRIDES,
|
||||||
|
consts.DEPLOY_CHART,
|
||||||
|
consts.DEPLOY_PRESTAGE,
|
||||||
|
]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(FAKE_URL, headers=FAKE_HEADERS, upload_files=fields)
|
||||||
headers=FAKE_HEADERS,
|
|
||||||
upload_files=fields)
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_prestage(self, mock_upload_files):
|
def test_post_subcloud_deploy_prestage(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PRESTAGE]
|
opts = [consts.DEPLOY_PRESTAGE]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
fake_name = opt + "_fake"
|
fake_name = opt + "_fake"
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, fake_name, fake_content))
|
fields.append((opt, fake_name, fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(FAKE_URL, headers=FAKE_HEADERS, upload_files=fields)
|
||||||
headers=FAKE_HEADERS,
|
|
||||||
upload_files=fields)
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController, "_upload_files")
|
||||||
'_upload_files')
|
|
||||||
def test_post_subcloud_deploy_missing_file_name(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_file_name(self, mock_upload_files):
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for opt in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
fake_content = "fake content".encode('utf-8')
|
fake_content = "fake content".encode("utf-8")
|
||||||
fields.append((opt, "", fake_content))
|
fields.append((opt, "", fake_content))
|
||||||
mock_upload_files.return_value = True
|
mock_upload_files.return_value = True
|
||||||
response = self.app.post(FAKE_URL,
|
response = self.app.post(
|
||||||
headers=FAKE_HEADERS,
|
FAKE_URL, headers=FAKE_HEADERS, upload_files=fields, expect_errors=True
|
||||||
upload_files=fields,
|
)
|
||||||
expect_errors=True)
|
|
||||||
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
@mock.patch.object(dutils, 'get_filename_by_prefix')
|
@mock.patch.object(dutils, "get_filename_by_prefix")
|
||||||
def test_get_subcloud_deploy_with_release(self, mock_get_filename_by_prefix):
|
def test_get_subcloud_deploy_with_release(self, mock_get_filename_by_prefix):
|
||||||
|
|
||||||
def get_filename_by_prefix_side_effect(dir_path, prefix):
|
def get_filename_by_prefix_side_effect(dir_path, prefix):
|
||||||
filename = FAKE_DEPLOY_FILES.get(prefix)
|
filename = FAKE_DEPLOY_FILES.get(prefix)
|
||||||
if filename:
|
if filename:
|
||||||
|
@ -234,24 +229,34 @@ class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
||||||
url = FAKE_URL + '/' + FAKE_SOFTWARE_VERSION
|
url = FAKE_URL + '/' + FAKE_SOFTWARE_VERSION
|
||||||
|
|
||||||
with mock.patch('builtins.open',
|
with mock.patch('builtins.open',
|
||||||
mock.mock_open(read_data=fake_subcloud.FAKE_UPGRADES_METADATA)):
|
mock.mock_open(
|
||||||
|
read_data=fake_subcloud.FAKE_UPGRADES_METADATA
|
||||||
|
)):
|
||||||
response = self.app.get(url, headers=FAKE_HEADERS)
|
response = self.app.get(url, headers=FAKE_HEADERS)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
self.assertEqual(FAKE_SOFTWARE_VERSION,
|
self.assertEqual(
|
||||||
response.json['subcloud_deploy']['software_version'])
|
FAKE_SOFTWARE_VERSION,
|
||||||
self.assertEqual(FAKE_DEPLOY_PLAYBOOK_FILE,
|
response.json["subcloud_deploy"]["software_version"],
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_PLAYBOOK])
|
)
|
||||||
self.assertEqual(FAKE_DEPLOY_OVERRIDES_FILE,
|
self.assertEqual(
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_OVERRIDES])
|
FAKE_DEPLOY_PLAYBOOK_FILE,
|
||||||
self.assertEqual(FAKE_DEPLOY_CHART_FILE,
|
response.json["subcloud_deploy"][consts.DEPLOY_PLAYBOOK],
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_CHART])
|
)
|
||||||
self.assertEqual(None,
|
self.assertEqual(
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_PRESTAGE])
|
FAKE_DEPLOY_OVERRIDES_FILE,
|
||||||
|
response.json["subcloud_deploy"][consts.DEPLOY_OVERRIDES],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
FAKE_DEPLOY_CHART_FILE,
|
||||||
|
response.json["subcloud_deploy"][consts.DEPLOY_CHART],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
None, response.json["subcloud_deploy"][consts.DEPLOY_PRESTAGE]
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(dutils, 'get_filename_by_prefix')
|
@mock.patch.object(dutils, "get_filename_by_prefix")
|
||||||
def test_get_subcloud_deploy_without_release(self, mock_get_filename_by_prefix):
|
def test_get_subcloud_deploy_without_release(self, mock_get_filename_by_prefix):
|
||||||
|
|
||||||
def get_filename_by_prefix_side_effect(dir_path, prefix):
|
def get_filename_by_prefix_side_effect(dir_path, prefix):
|
||||||
filename = FAKE_DEPLOY_FILES.get(prefix)
|
filename = FAKE_DEPLOY_FILES.get(prefix)
|
||||||
if filename:
|
if filename:
|
||||||
|
@ -260,33 +265,47 @@ class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
os.path.isdir = mock.Mock(return_value=True)
|
os.path.isdir = mock.Mock(return_value=True)
|
||||||
mock_get_filename_by_prefix.side_effect = \
|
mock_get_filename_by_prefix.side_effect = get_filename_by_prefix_side_effect
|
||||||
get_filename_by_prefix_side_effect
|
|
||||||
response = self.app.get(FAKE_URL, headers=FAKE_HEADERS)
|
response = self.app.get(FAKE_URL, headers=FAKE_HEADERS)
|
||||||
self.assertEqual(response.status_code, http_client.OK)
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
self.assertEqual(SW_VERSION,
|
self.assertEqual(
|
||||||
response.json['subcloud_deploy']['software_version'])
|
SW_VERSION, response.json["subcloud_deploy"]["software_version"]
|
||||||
self.assertEqual(FAKE_DEPLOY_PLAYBOOK_FILE,
|
)
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_PLAYBOOK])
|
self.assertEqual(
|
||||||
self.assertEqual(FAKE_DEPLOY_OVERRIDES_FILE,
|
FAKE_DEPLOY_PLAYBOOK_FILE,
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_OVERRIDES])
|
response.json["subcloud_deploy"][consts.DEPLOY_PLAYBOOK],
|
||||||
self.assertEqual(FAKE_DEPLOY_CHART_FILE,
|
)
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_CHART])
|
self.assertEqual(
|
||||||
self.assertEqual(None,
|
FAKE_DEPLOY_OVERRIDES_FILE,
|
||||||
response.json['subcloud_deploy'][consts.DEPLOY_PRESTAGE])
|
response.json["subcloud_deploy"][consts.DEPLOY_OVERRIDES],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
FAKE_DEPLOY_CHART_FILE,
|
||||||
|
response.json["subcloud_deploy"][consts.DEPLOY_CHART],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
None, response.json["subcloud_deploy"][consts.DEPLOY_PRESTAGE]
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_config_file_path(self):
|
def test_get_config_file_path(self):
|
||||||
bootstrap_file = psd_common.get_config_file_path("subcloud1")
|
bootstrap_file = psd_common.get_config_file_path("subcloud1")
|
||||||
install_values = psd_common.get_config_file_path("subcloud1",
|
install_values = psd_common.get_config_file_path(
|
||||||
consts.INSTALL_VALUES)
|
"subcloud1", consts.INSTALL_VALUES
|
||||||
deploy_config = psd_common.get_config_file_path("subcloud1",
|
)
|
||||||
consts.DEPLOY_CONFIG)
|
deploy_config = psd_common.get_config_file_path(
|
||||||
self.assertEqual(bootstrap_file,
|
"subcloud1", consts.DEPLOY_CONFIG
|
||||||
f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1.yml')
|
)
|
||||||
self.assertEqual(install_values,
|
self.assertEqual(
|
||||||
f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1/install_values.yml')
|
bootstrap_file, f"{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1.yml"
|
||||||
self.assertEqual(deploy_config,
|
)
|
||||||
f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_deploy_config.yml')
|
self.assertEqual(
|
||||||
|
install_values,
|
||||||
|
f"{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1/install_values.yml",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
deploy_config,
|
||||||
|
f"{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_deploy_config.yml",
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(os_path, 'isdir')
|
@mock.patch.object(os_path, 'isdir')
|
||||||
@mock.patch.object(dutils, 'get_sw_version')
|
@mock.patch.object(dutils, 'get_sw_version')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2023 Wind River Systems, Inc.
|
# Copyright (c) 2023-2024 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -45,46 +45,41 @@ class SubcloudPeerGroupAPIMixin(APIMixin):
|
||||||
def _get_test_subcloud_peer_group_request(self, **kw):
|
def _get_test_subcloud_peer_group_request(self, **kw):
|
||||||
# id should not be part of the structure
|
# id should not be part of the structure
|
||||||
group = {
|
group = {
|
||||||
'peer-group-name': kw.get('peer_group_name', SAMPLE_SUBCLOUD_PEER_GROUP_NAME),
|
'peer-group-name': kw.get(
|
||||||
|
'peer_group_name', SAMPLE_SUBCLOUD_PEER_GROUP_NAME
|
||||||
|
),
|
||||||
'system-leader-id': kw.get(
|
'system-leader-id': kw.get(
|
||||||
'system_leader_id',
|
'system_leader_id', '62c9592d-f799-4db9-8d40-6786a74d6021'
|
||||||
'62c9592d-f799-4db9-8d40-6786a74d6021'),
|
),
|
||||||
'system-leader-name': kw.get(
|
'system-leader-name': kw.get(
|
||||||
'system_leader_name',
|
'system_leader_name', 'dc-test'
|
||||||
'dc-test'),
|
),
|
||||||
'group-priority': kw.get(
|
'group-priority': kw.get('group_priority', '0'),
|
||||||
'group_priority',
|
'group-state': kw.get('group_state', 'enabled'),
|
||||||
'0'),
|
|
||||||
'group-state': kw.get(
|
|
||||||
'group_state',
|
|
||||||
'enabled'),
|
|
||||||
'max-subcloud-rehoming': kw.get(
|
'max-subcloud-rehoming': kw.get(
|
||||||
'max_subcloud_rehoming',
|
'max_subcloud_rehoming',
|
||||||
SAMPLE_SUBCLOUD_PEER_GROUP_MAX_SUBCLOUDS_REHOMING)
|
SAMPLE_SUBCLOUD_PEER_GROUP_MAX_SUBCLOUDS_REHOMING
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return group
|
return group
|
||||||
|
|
||||||
def _get_test_subcloud_peer_group_dict(self, **kw):
|
def _get_test_subcloud_peer_group_dict(self, **kw):
|
||||||
# id should not be part of the structure
|
# id should not be part of the structure
|
||||||
group = {
|
group = {
|
||||||
'peer_group_name': kw.get('peer_group_name', SAMPLE_SUBCLOUD_PEER_GROUP_NAME),
|
'peer_group_name': kw.get(
|
||||||
|
'peer_group_name', SAMPLE_SUBCLOUD_PEER_GROUP_NAME
|
||||||
|
),
|
||||||
'system_leader_id': kw.get(
|
'system_leader_id': kw.get(
|
||||||
'system_leader_id',
|
'system_leader_id', '62c9592d-f799-4db9-8d40-6786a74d6021'
|
||||||
'62c9592d-f799-4db9-8d40-6786a74d6021'),
|
),
|
||||||
'system_leader_name': kw.get(
|
'system_leader_name': kw.get('system_leader_name', 'dc-test'),
|
||||||
'system_leader_name',
|
'group_priority': kw.get('group_priority', '0'),
|
||||||
'dc-test'),
|
'group_state': kw.get('group_state', 'enabled'),
|
||||||
'group_priority': kw.get(
|
|
||||||
'group_priority',
|
|
||||||
'0'),
|
|
||||||
'group_state': kw.get(
|
|
||||||
'group_state',
|
|
||||||
'enabled'),
|
|
||||||
'max_subcloud_rehoming': kw.get(
|
'max_subcloud_rehoming': kw.get(
|
||||||
'max_subcloud_rehoming',
|
'max_subcloud_rehoming',
|
||||||
SAMPLE_SUBCLOUD_PEER_GROUP_MAX_SUBCLOUDS_REHOMING),
|
SAMPLE_SUBCLOUD_PEER_GROUP_MAX_SUBCLOUDS_REHOMING
|
||||||
|
),
|
||||||
'migration_status': None
|
'migration_status': None
|
||||||
|
|
||||||
}
|
}
|
||||||
return group
|
return group
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue