Keystone token and resource caching

Add the following misc. changes to dcorch and dcmanager components:
- Cache the master resource in dcorch audit
- Consolidate the openstack drivers to common module, combine the
  dcmanager and dcorch sysinv client. (Note: the sdk driver that
  used by nova, neutron and cinder will be cleaned as part of
  story 2006588).
- Update the common sdk driver:
  . in order to avoid creating new keystone client multiple times
  . to add a option for caching region clients, in addition to the
    keystone client
  . finally, to randomize the token early renewal duration
- Change subcloud audit manager, patch audit manager,
  and sw update manager to:
  utilize the sdk driver which caches the keystone client and token

Test cases:
1. Manage/unmanage subclouds
2. Platform resources sync and audit
3. Verify the keystone token is cached until the token is
   expired
4. Add/delete subclouds
5. Managed subcloud goes offline/online (power off/on)
6. Managed subcloud goes offline/online (delete/add a static route)
7. Apply a patch to all subclouds via patch Orchestration

Story: 2007267
Task: 38865

Change-Id: I75e0cf66a797a65faf75e7c64dafb07f54c2df06
Signed-off-by: Tao Liu <tao.liu@windriver.com>
This commit is contained in:
Tao Liu 2020-03-12 09:46:29 -04:00
parent 1e588cbefa
commit 7f3827f24d
62 changed files with 1147 additions and 646 deletions

View File

@ -1,4 +1,5 @@
# distributedcloud # distributedcloud
distributedcloud-dccommon
distributedcloud-dcmanager distributedcloud-dcmanager
distributedcloud-dcorch distributedcloud-dcorch
distributedcloud-dcdbsync distributedcloud-dcdbsync

View File

@ -6,6 +6,7 @@ test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1}
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1}
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60}
PYTHON=$(echo ${PYTHON:-python} | sed 's/--source distributedcloud//g') PYTHON=$(echo ${PYTHON:-python} | sed 's/--source distributedcloud//g')
${PYTHON} -m subunit.run discover -s dccommon $LISTOPT $IDOPTION
${PYTHON} -m subunit.run discover -s dcmanager $LISTOPT $IDOPTION ${PYTHON} -m subunit.run discover -s dcmanager $LISTOPT $IDOPTION
${PYTHON} -m subunit.run discover -s dcorch $LISTOPT $IDOPTION ${PYTHON} -m subunit.run discover -s dcorch $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE test_id_option=--load-list $IDFILE

View File

@ -70,6 +70,13 @@ BuildRequires: python-babel
%description %description
Distributed Cloud provides configuration and management of distributed clouds Distributed Cloud provides configuration and management of distributed clouds
# DC Common
%package dccommon
Summary: DC common module
%description dccommon
Distributed Cloud Common Module
# DC Manager # DC Manager
%package dcmanager %package dcmanager
Summary: DC Manager Summary: DC Manager
@ -163,6 +170,12 @@ install -p -D -m 640 %{_builddir}/%{pypi_name}-%{version}%{_sysconfdir}/dcdbsync
# install ansible overrides dir # install ansible overrides dir
install -d -m 600 ${RPM_BUILD_ROOT}/opt/dc/ansible install -d -m 600 ${RPM_BUILD_ROOT}/opt/dc/ansible
%files dccommon
%license LICENSE
%{python2_sitelib}/dccommon*
%{python2_sitelib}/distributedcloud-*.egg-info
%exclude %{python2_sitelib}/dccommon/tests
%files dcmanager %files dcmanager
%license LICENSE %license LICENSE
%{python2_sitelib}/dcmanager* %{python2_sitelib}/dcmanager*

View File

@ -0,0 +1,176 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import pbr.version
__version__ = pbr.version.VersionInfo('distributedcloud').version_string()

View File

@ -0,0 +1,38 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
SECONDS_IN_HOUR = 3600
KS_ENDPOINT_ADMIN = "admin"
KS_ENDPOINT_INTERNAL = "internal"
KS_ENDPOINT_DEFAULT = KS_ENDPOINT_INTERNAL
ENDPOINT_TYPE_IDENTITY_OS = "identity_openstack"
# openstack endpoint types
ENDPOINT_TYPES_LIST_OS = [ENDPOINT_TYPE_IDENTITY_OS]
# distributed Cloud constants
CLOUD_0 = "RegionOne"
VIRTUAL_MASTER_CLOUD = "SystemController"
SW_UPDATE_DEFAULT_TITLE = "all clouds default"
USER_HEADER_VALUE = "distcloud"
USER_HEADER = {'User-Header': USER_HEADER_VALUE}

View File

@ -9,7 +9,13 @@
# 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.
#
# Copyright (c) 2017-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
""" """
Base class for all drivers. Base class for all drivers.
""" """

View File

@ -10,16 +10,22 @@
# 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) 2018 Wind River Systems, Inc.
# #
# Copyright (c) 2018-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from oslo_log import log from oslo_log import log
import fmclient import fmclient
from dcorch.common import exceptions from dccommon import consts as dccommon_consts
from dcorch.drivers import base from dccommon.drivers import base
from dccommon import exceptions
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
API_VERSION = '1' API_VERSION = '1'
@ -28,7 +34,8 @@ API_VERSION = '1'
class FmClient(base.DriverBase): class FmClient(base.DriverBase):
"""Fault Management driver.""" """Fault Management driver."""
def __init__(self, region, session, endpoint_type): def __init__(self, region, session,
endpoint_type=dccommon_consts.KS_ENDPOINT_DEFAULT):
self.region_name = region self.region_name = region
try: try:
self.fm = fmclient.Client(API_VERSION, self.fm = fmclient.Client(API_VERSION,

View File

@ -12,14 +12,20 @@
# 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-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from keystoneauth1 import exceptions as keystone_exceptions from keystoneauth1 import exceptions as keystone_exceptions
from keystoneclient.v3.contrib import endpoint_filter from keystoneclient.v3.contrib import endpoint_filter
from oslo_utils import importutils from oslo_utils import importutils
from dcorch.common.endpoint_cache import EndpointCache from dccommon.drivers import base
from dcorch.common import exceptions from dccommon.endpoint_cache import EndpointCache
from dcorch.drivers import base from dccommon import exceptions
# Ensure keystonemiddleware options are imported # Ensure keystonemiddleware options are imported
importutils.import_module('keystonemiddleware.auth_token') importutils.import_module('keystonemiddleware.auth_token')

View File

@ -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) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -23,7 +23,7 @@ from oslo_log import log
import requests import requests
from requests_toolbelt import MultipartEncoder from requests_toolbelt import MultipartEncoder
from dcmanager.drivers import base from dccommon.drivers import base
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -0,0 +1,222 @@
# Copyright 2017-2020 Wind River Inc
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
OpenStack Driver
"""
import collections
import random
from oslo_concurrency import lockutils
from oslo_log import log
from oslo_utils import timeutils
from dccommon import consts
from dccommon.drivers.openstack.fm import FmClient
from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dccommon import exceptions
# Gap, in seconds, to determine whether the given token is about to expire
# These values are used to randomize the token early renewal duration and
# to distribute the new keystone creation to different audit cycles
STALE_TOKEN_DURATION_MIN = 40
STALE_TOKEN_DURATION_MAX = 120
STALE_TOKEN_DURATION_STEP = 20
KEYSTONE_CLIENT_NAME = 'keystone'
SYSINV_CLIENT_NAME = 'sysinv'
FM_CLIENT_NAME = 'fm'
LOG = log.getLogger(__name__)
LOCK_NAME = 'dc-openstackdriver-platform'
SUPPORTED_REGION_CLIENTS = [
SYSINV_CLIENT_NAME,
FM_CLIENT_NAME
]
# region client type and class mappings
region_client_class_map = {
SYSINV_CLIENT_NAME: SysinvClient,
FM_CLIENT_NAME: FmClient,
}
class OpenStackDriver(object):
os_clients_dict = collections.defaultdict(dict)
_identity_tokens = {}
def __init__(self, region_name=consts.CLOUD_0, thread_name='dcorch',
auth_url=None, region_clients=SUPPORTED_REGION_CLIENTS):
# Check if objects are cached and try to use those
self.region_name = region_name
self.keystone_client = None
self.sysinv_client = None
self.fm_client = None
if region_clients:
# check if the requested clients are in the supported client list
result = all(c in SUPPORTED_REGION_CLIENTS for c in region_clients)
if not result:
message = ("Requested clients are not supported: %s" %
' '.join(region_clients))
LOG.error(message)
raise exceptions.InvalidInputError
self.get_cached_keystone_client(region_name)
if self.keystone_client is None:
LOG.info("get new keystone client for subcloud %s", region_name)
try:
self.keystone_client = KeystoneClient(region_name, auth_url)
OpenStackDriver.update_region_clients(region_name,
KEYSTONE_CLIENT_NAME,
self.keystone_client)
except Exception as exception:
LOG.error('keystone_client region %s error: %s' %
(region_name, exception.message))
raise exception
if region_clients:
self.get_cached_region_clients_for_thread(region_name,
thread_name,
region_clients)
for client_name in region_clients:
client_obj_name = client_name + '_client'
if getattr(self, client_obj_name) is None:
# Create new client object and cache it
try:
client_object = region_client_class_map[client_name](
region_name, self.keystone_client.session)
setattr(self, client_obj_name, client_object)
OpenStackDriver.update_region_clients(region_name,
client_name,
client_object,
thread_name)
except Exception as exception:
LOG.error('Region %s client %s thread %s error: %s' %
(region_name, client_name, thread_name,
exception.message))
raise exception
@lockutils.synchronized(LOCK_NAME)
def get_cached_keystone_client(self, region_name):
if ((region_name in OpenStackDriver.os_clients_dict) and
(KEYSTONE_CLIENT_NAME in
OpenStackDriver.os_clients_dict[region_name]) and
self._is_token_valid(region_name)):
self.keystone_client = (OpenStackDriver.os_clients_dict
[region_name][KEYSTONE_CLIENT_NAME])
@lockutils.synchronized(LOCK_NAME)
def get_cached_region_clients_for_thread(self, region_name, thread_name,
clients):
if ((region_name in OpenStackDriver.os_clients_dict) and
(thread_name in OpenStackDriver.os_clients_dict[
region_name])):
for client in clients:
if client in (OpenStackDriver.os_clients_dict[region_name]
[thread_name]):
LOG.debug('Using cached OS %s client objects %s %s' %
(client, region_name, thread_name))
client_obj = (OpenStackDriver.os_clients_dict[region_name]
[thread_name][client])
setattr(self, client + '_client', client_obj)
else:
OpenStackDriver.os_clients_dict[region_name][thread_name] = {}
@classmethod
@lockutils.synchronized(LOCK_NAME)
def update_region_clients(cls, region_name, client_name, client_object,
thread_name=None):
if thread_name is not None:
cls.os_clients_dict[region_name][thread_name][client_name] = \
client_object
else:
cls.os_clients_dict[region_name][client_name] = client_object
@classmethod
@lockutils.synchronized(LOCK_NAME)
def delete_region_clients(cls, region_name, clear_token=False):
LOG.warn("delete_region_clients=%s, clear_token=%s" %
(region_name, clear_token))
if region_name in cls.os_clients_dict:
del cls.os_clients_dict[region_name]
if clear_token:
cls._identity_tokens[region_name] = None
@classmethod
@lockutils.synchronized(LOCK_NAME)
def delete_region_clients_for_thread(cls, region_name, thread_name):
LOG.debug("delete_region_clients=%s, thread_name=%s" %
(region_name, thread_name))
if (region_name in cls.os_clients_dict and
thread_name in cls.os_clients_dict[region_name]):
del cls.os_clients_dict[region_name][thread_name]
def _is_token_valid(self, region_name):
try:
keystone = \
OpenStackDriver.os_clients_dict[region_name]['keystone'].\
keystone_client
if (not OpenStackDriver._identity_tokens
or region_name not in OpenStackDriver._identity_tokens
or not OpenStackDriver._identity_tokens[region_name]):
OpenStackDriver._identity_tokens[region_name] = \
keystone.tokens.validate(keystone.session.get_token(),
include_catalog=False)
LOG.info("Token for subcloud %s expires_at=%s" %
(region_name,
OpenStackDriver._identity_tokens[region_name]
['expires_at']))
else:
token = keystone.tokens.validate(
OpenStackDriver._identity_tokens[region_name],
include_catalog=False)
if token != OpenStackDriver._identity_tokens[region_name]:
LOG.debug("%s: updating token %s to %s" %
(region_name,
OpenStackDriver._identity_tokens[region_name],
token))
OpenStackDriver._identity_tokens[region_name] = token
except Exception as exception:
LOG.info('_is_token_valid handle: %s', exception.message)
# Reset the cached dictionary
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
OpenStackDriver._identity_tokens[region_name] = None
return False
expiry_time = timeutils.normalize_time(timeutils.parse_isotime(
self._identity_tokens[region_name]['expires_at']))
duration = random.randrange(STALE_TOKEN_DURATION_MIN,
STALE_TOKEN_DURATION_MAX,
STALE_TOKEN_DURATION_STEP)
if timeutils.is_soon(expiry_time, duration):
LOG.info("The cached keystone token for subcloud %s "
"will expire soon %s" %
(region_name,
OpenStackDriver._identity_tokens[region_name]
['expires_at']))
# Reset the cached dictionary
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
OpenStackDriver._identity_tokens[region_name] = None
return False
else:
return True

View File

@ -1,3 +1,5 @@
# Copyright 2016 Ericsson AB
# 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
@ -9,10 +11,16 @@
# 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.
#
# Copyright (c) 2017-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import hashlib import hashlib
from cgtsclient import client as cgts_client
from cgtsclient.exc import HTTPConflict from cgtsclient.exc import HTTPConflict
from cgtsclient.exc import HTTPNotFound from cgtsclient.exc import HTTPNotFound
from cgtsclient.v1.icommunity import CREATION_ATTRIBUTES \ from cgtsclient.v1.icommunity import CREATION_ATTRIBUTES \
@ -20,14 +28,14 @@ from cgtsclient.v1.icommunity import CREATION_ATTRIBUTES \
from cgtsclient.v1.itrapdest import CREATION_ATTRIBUTES \ from cgtsclient.v1.itrapdest import CREATION_ATTRIBUTES \
as SNMP_TRAPDEST_CREATION_ATTRIBUTES as SNMP_TRAPDEST_CREATION_ATTRIBUTES
from oslo_log import log from oslo_log import log
from sysinv.common import constants as sysinv_constants from sysinv.common import constants as sysinv_constants
from dcorch.common import consts from dccommon.drivers import base
from dcorch.common import exceptions from dccommon import exceptions
from dcorch.drivers import base
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
API_VERSION = '1' API_VERSION = '1'
@ -49,43 +57,141 @@ def make_sysinv_patch(update_dict):
class SysinvClient(base.DriverBase): class SysinvClient(base.DriverBase):
"""Sysinv V1 driver.""" """Sysinv V1 driver."""
def __init__(self, region_name, session): def __init__(self, region, session):
self._expired = False
self.api_version = API_VERSION
self.region_name = region_name
self.session = session
self.client = self.update_client(
self.api_version, self.region_name, self.session)
def update_client(self, api_version, region_name, session):
try: try:
endpoint = self.session.get_endpoint( # TOX cannot import cgts_client and all the dependencies therefore
service_type=consts.ENDPOINT_TYPE_PLATFORM, # the client is being lazy loaded since TOX doesn't actually
interface=consts.KS_ENDPOINT_INTERNAL, # require the cgtsclient module.
region_name=region_name) from cgtsclient import client
# The sysinv client doesn't support a session, so we need to
# get an endpoint and token.
endpoint = session.get_endpoint(service_type='platform',
region_name=region,
interface='internal')
token = session.get_token() token = session.get_token()
client = cgts_client.Client(
api_version, self.sysinv_client = client.Client(API_VERSION,
username=session.auth._username, endpoint=endpoint,
password=session.auth._password, token=token)
tenant_name=session.auth._project_name, self.region_name = region
auth_url=session.auth.auth_url,
endpoint=endpoint,
token=token)
except exceptions.ServiceUnavailable: except exceptions.ServiceUnavailable:
raise raise
self._expired = False def get_controller_hosts(self):
"""Get a list of controller hosts."""
return self.sysinv_client.ihost.list_personality(
sysinv_constants.CONTROLLER)
return client def get_management_interface(self, hostname):
"""Get the management interface for a host."""
interfaces = self.sysinv_client.iinterface.list(hostname)
for interface in interfaces:
interface_networks = self.sysinv_client.interface_network.\
list_by_interface(interface.uuid)
for if_net in interface_networks:
if if_net.network_type == sysinv_constants.NETWORK_TYPE_MGMT:
return interface
# This can happen if the host is still being installed and has not
# yet created its management interface.
LOG.warning("Management interface on host %s not found" % hostname)
return None
def get_management_address_pool(self):
"""Get the management address pool for a host."""
networks = self.sysinv_client.network.list()
for network in networks:
if network.type == sysinv_constants.NETWORK_TYPE_MGMT:
address_pool_uuid = network.pool_uuid
break
else:
LOG.error("Management address pool not found")
raise exceptions.InternalError()
return self.sysinv_client.address_pool.get(address_pool_uuid)
def get_oam_addresses(self):
"""Get the oam address pool for a host."""
iextoam_object = self.sysinv_client.iextoam.list()
if iextoam_object is not None and len(iextoam_object) != 0:
return iextoam_object[0]
else:
LOG.error("OAM address not found")
raise exceptions.OAMAddressesNotFound()
def create_route(self, interface_uuid, network, prefix, gateway, metric):
"""Create a static route on an interface."""
LOG.info("Creating route: interface: %s dest: %s/%s "
"gateway: %s metric %s" % (interface_uuid, network,
prefix, gateway, metric))
self.sysinv_client.route.create(interface_uuid=interface_uuid,
network=network,
prefix=prefix,
gateway=gateway,
metric=metric)
def delete_route(self, interface_uuid, network, prefix, gateway, metric):
"""Delete a static route."""
# Get the routes for this interface
routes = self.sysinv_client.route.list_by_interface(interface_uuid)
for route in routes:
if (route.network == network and route.prefix == prefix and
route.gateway == gateway and route.metric == metric):
LOG.info("Deleting route: interface: %s dest: %s/%s "
"gateway: %s metric %s" % (interface_uuid, network,
prefix, gateway, metric))
self.sysinv_client.route.delete(route.uuid)
return
LOG.warning("Route not found: interface: %s dest: %s/%s gateway: %s "
"metric %s" % (interface_uuid, network, prefix, gateway,
metric))
def get_service_groups(self):
"""Get a list of service groups."""
return self.sysinv_client.sm_servicegroup.list()
def get_loads(self):
"""Get a list of loads."""
return self.sysinv_client.load.list()
def get_applications(self):
"""Get a list of containerized applications"""
# Get a list of containerized applications the system knows of
return self.sysinv_client.app.list()
def get_system(self):
"""Get the system."""
systems = self.sysinv_client.isystem.list()
return systems[0]
def get_service_parameters(self, name, value):
"""Get service parameters for a given name."""
opts = []
opt = dict()
opt['field'] = name
opt['value'] = value
opt['op'] = 'eq'
opt['type'] = ''
opts.append(opt)
parameters = self.sysinv_client.service_parameter.list(q=opts)
return parameters
def get_registry_image_tags(self, image_name):
"""Get the image tags for an image from the local registry"""
image_tags = self.sysinv_client.registry_image.tags(image_name)
return image_tags
def get_dns(self): def get_dns(self):
"""Get the dns nameservers for this region """Get the dns nameservers for this region
:return: dns :return: dns
""" """
idnss = self.client.idns.list() idnss = self.sysinv_client.idns.list()
if not idnss: if not idnss:
LOG.info("dns is None for region: %s" % self.region_name) LOG.info("dns is None for region: %s" % self.region_name)
return None return None
@ -115,14 +221,14 @@ class SysinvClient(base.DriverBase):
'action': 'apply'}) 'action': 'apply'})
LOG.info("region={} dns update uuid={} patch={}".format( LOG.info("region={} dns update uuid={} patch={}".format(
self.region_name, idns.uuid, patch)) self.region_name, idns.uuid, patch))
idns = self.client.idns.update(idns.uuid, patch) idns = self.sysinv_client.idns.update(idns.uuid, patch)
else: else:
LOG.info("update_dns no changes, skip dns region={} " LOG.info("update_dns no changes, skip dns region={} "
"update uuid={} nameservers={}".format( "update uuid={} nameservers={}".format(
self.region_name, idns.uuid, nameservers)) self.region_name, idns.uuid, nameservers))
except Exception as e: except Exception as e:
LOG.error("update_dns exception={}".format(e)) LOG.error("update_dns exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return idns return idns
@ -131,7 +237,7 @@ class SysinvClient(base.DriverBase):
:return: itrapdests list of itrapdest :return: itrapdests list of itrapdest
""" """
itrapdests = self.client.itrapdest.list() itrapdests = self.sysinv_client.itrapdest.list()
return itrapdests return itrapdests
def snmp_trapdest_create(self, trapdest_dict): def snmp_trapdest_create(self, trapdest_dict):
@ -153,7 +259,8 @@ class SysinvClient(base.DriverBase):
"trapdest_create_dict={}".format( "trapdest_create_dict={}".format(
self.region_name, trapdest_create_dict)) self.region_name, trapdest_create_dict))
try: try:
itrapdest = self.client.itrapdest.create(**trapdest_create_dict) itrapdest = self.sysinv_client.itrapdest.create(
**trapdest_create_dict)
except HTTPConflict: except HTTPConflict:
LOG.info("snmp_trapdest_create exists region={}" LOG.info("snmp_trapdest_create exists region={}"
"trapdest_dict={}".format( "trapdest_dict={}".format(
@ -169,7 +276,7 @@ class SysinvClient(base.DriverBase):
break break
except Exception as e: except Exception as e:
LOG.error("snmp_trapdest_create exception={}".format(e)) LOG.error("snmp_trapdest_create exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return itrapdest return itrapdest
@ -181,7 +288,7 @@ class SysinvClient(base.DriverBase):
try: try:
LOG.info("snmp_trapdest_delete region {} ip_address: {}".format( LOG.info("snmp_trapdest_delete region {} ip_address: {}".format(
self.region_name, trapdest_ip_address)) self.region_name, trapdest_ip_address))
self.client.itrapdest.delete(trapdest_ip_address) self.sysinv_client.itrapdest.delete(trapdest_ip_address)
except HTTPNotFound: except HTTPNotFound:
LOG.info("snmp_trapdest_delete NotFound {} for region: {}".format( LOG.info("snmp_trapdest_delete NotFound {} for region: {}".format(
trapdest_ip_address, self.region_name)) trapdest_ip_address, self.region_name))
@ -189,14 +296,14 @@ class SysinvClient(base.DriverBase):
ip_address=trapdest_ip_address) ip_address=trapdest_ip_address)
except Exception as e: except Exception as e:
LOG.error("snmp_trapdest_delete exception={}".format(e)) LOG.error("snmp_trapdest_delete exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
def snmp_community_list(self): def snmp_community_list(self):
"""Get the community list for this region """Get the community list for this region
:return: icommunitys list of icommunity :return: icommunitys list of icommunity
""" """
icommunitys = self.client.icommunity.list() icommunitys = self.sysinv_client.icommunity.list()
return icommunitys return icommunitys
def snmp_community_create(self, community_dict): def snmp_community_create(self, community_dict):
@ -217,7 +324,8 @@ class SysinvClient(base.DriverBase):
"community_create_dict={}".format( "community_create_dict={}".format(
self.region_name, community_create_dict)) self.region_name, community_create_dict))
try: try:
icommunity = self.client.icommunity.create(**community_create_dict) icommunity = self.sysinv_client.icommunity.create(
**community_create_dict)
except HTTPConflict: except HTTPConflict:
LOG.info("snmp_community_create exists region={}" LOG.info("snmp_community_create exists region={}"
"community_dict={}".format( "community_dict={}".format(
@ -233,7 +341,7 @@ class SysinvClient(base.DriverBase):
break break
except Exception as e: except Exception as e:
LOG.error("snmp_community_create exception={}".format(e)) LOG.error("snmp_community_create exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return icommunity return icommunity
@ -245,7 +353,7 @@ class SysinvClient(base.DriverBase):
try: try:
LOG.info("snmp_community_delete region {} community: {}".format( LOG.info("snmp_community_delete region {} community: {}".format(
self.region_name, community)) self.region_name, community))
self.client.icommunity.delete(community) self.sysinv_client.icommunity.delete(community)
except HTTPNotFound: except HTTPNotFound:
LOG.info("snmp_community_delete NotFound {} for region: {}".format( LOG.info("snmp_community_delete NotFound {} for region: {}".format(
community, self.region_name)) community, self.region_name))
@ -253,7 +361,7 @@ class SysinvClient(base.DriverBase):
community=community) community=community)
except Exception as e: except Exception as e:
LOG.error("snmp_community_delete exception={}".format(e)) LOG.error("snmp_community_delete exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
def get_certificates(self): def get_certificates(self):
"""Get the certificates for this region """Get the certificates for this region
@ -262,11 +370,11 @@ class SysinvClient(base.DriverBase):
""" """
try: try:
certificates = self.client.certificate.list() certificates = self.sysinv_client.certificate.list()
except Exception as e: except Exception as e:
LOG.error("get_certificates region={} " LOG.error("get_certificates region={} "
"exception={}".format(self.region_name, e)) "exception={}".format(self.region_name, e))
raise exceptions.SyncRequestFailedRetry() raise e
if not certificates: if not certificates:
LOG.info("No certificates in region: {}".format( LOG.info("No certificates in region: {}".format(
@ -347,10 +455,10 @@ class SysinvClient(base.DriverBase):
(signature.startswith(sysinv_constants.CERT_MODE_SSL) or (signature.startswith(sysinv_constants.CERT_MODE_SSL) or
(signature.startswith(sysinv_constants.CERT_MODE_TPM)))): (signature.startswith(sysinv_constants.CERT_MODE_TPM)))):
# ensure https is enabled # ensure https is enabled
isystem = self.client.isystem.list()[0] isystem = self.sysinv_client.isystem.list()[0]
https_enabled = isystem.capabilities.get('https_enabled', False) https_enabled = isystem.capabilities.get('https_enabled', False)
if not https_enabled: if not https_enabled:
isystem = self.client.isystem.update( isystem = self.sysinv_client.isystem.update(
isystem.uuid, isystem.uuid,
[{"path": "/https_enabled", [{"path": "/https_enabled",
"value": "true", "value": "true",
@ -359,14 +467,14 @@ class SysinvClient(base.DriverBase):
self.region_name, isystem.uuid)) self.region_name, isystem.uuid))
try: try:
icertificate = self.client.certificate.certificate_install( icertificate = self.sysinv_client.certificate.certificate_install(
certificate, data) certificate, data)
LOG.info("update_certificate region={} signature={}".format( LOG.info("update_certificate region={} signature={}".format(
self.region_name, self.region_name,
signature)) signature))
except Exception as e: except Exception as e:
LOG.error("update_certificate exception={}".format(e)) LOG.error("update_certificate exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return icertificate return icertificate
@ -378,7 +486,8 @@ class SysinvClient(base.DriverBase):
try: try:
LOG.info(" delete_certificate region {} certificate: {}".format( LOG.info(" delete_certificate region {} certificate: {}".format(
self.region_name, certificate.signature)) self.region_name, certificate.signature))
self.client.certificate.certificate_uninstall(certificate.uuid) self.sysinv_client.certificate.certificate_uninstall(
certificate.uuid)
except HTTPNotFound: except HTTPNotFound:
LOG.info("delete_certificate NotFound {} for region: {}".format( LOG.info("delete_certificate NotFound {} for region: {}".format(
certificate.signature, self.region_name)) certificate.signature, self.region_name))
@ -390,7 +499,7 @@ class SysinvClient(base.DriverBase):
:return: iuser :return: iuser
""" """
iusers = self.client.iuser.list() iusers = self.sysinv_client.iuser.list()
if not iusers: if not iusers:
LOG.info("user is None for region: %s" % self.region_name) LOG.info("user is None for region: %s" % self.region_name)
return None return None
@ -423,14 +532,14 @@ class SysinvClient(base.DriverBase):
}) })
LOG.info("region={} user update uuid={} patch={}".format( LOG.info("region={} user update uuid={} patch={}".format(
self.region_name, iuser.uuid, patch)) self.region_name, iuser.uuid, patch))
iuser = self.client.iuser.update(iuser.uuid, patch) iuser = self.sysinv_client.iuser.update(iuser.uuid, patch)
else: else:
LOG.info("update_user no changes, skip user region={} " LOG.info("update_user no changes, skip user region={} "
"update uuid={} passwd_hash={}".format( "update uuid={} passwd_hash={}".format(
self.region_name, iuser.uuid, passwd_hash)) self.region_name, iuser.uuid, passwd_hash))
except Exception as e: except Exception as e:
LOG.error("update_user exception={}".format(e)) LOG.error("update_user exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return iuser return iuser
@ -448,10 +557,10 @@ class SysinvClient(base.DriverBase):
LOG.info("post_fernet_repo driver region={} " LOG.info("post_fernet_repo driver region={} "
"fernet_repo_list={}".format(self.region_name, key_list)) "fernet_repo_list={}".format(self.region_name, key_list))
try: try:
self.client.fernet.create(key_list) self.sysinv_client.fernet.create(key_list)
except Exception as e: except Exception as e:
LOG.error("post_fernet_repo exception={}".format(e)) LOG.error("post_fernet_repo exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
def put_fernet_repo(self, key_list): def put_fernet_repo(self, key_list):
"""Update the fernet keys for this region """Update the fernet keys for this region
@ -462,10 +571,10 @@ class SysinvClient(base.DriverBase):
LOG.info("put_fernet_repo driver region={} " LOG.info("put_fernet_repo driver region={} "
"fernet_repo_list={}".format(self.region_name, key_list)) "fernet_repo_list={}".format(self.region_name, key_list))
try: try:
self.client.fernet.put(key_list) self.sysinv_client.fernet.put(key_list)
except Exception as e: except Exception as e:
LOG.error("put_fernet_repo exception={}".format(e)) LOG.error("put_fernet_repo exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
def get_fernet_keys(self): def get_fernet_keys(self):
"""Retrieve the fernet keys for this region """Retrieve the fernet keys for this region
@ -474,9 +583,9 @@ class SysinvClient(base.DriverBase):
""" """
try: try:
keys = self.client.fernet.list() keys = self.sysinv_client.fernet.list()
except Exception as e: except Exception as e:
LOG.error("get_fernet_keys exception={}".format(e)) LOG.error("get_fernet_keys exception={}".format(e))
raise exceptions.SyncRequestFailedRetry() raise e
return keys return keys

View File

@ -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) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -23,9 +23,10 @@ from oslo_log import log
from nfv_client.openstack import sw_update from nfv_client.openstack import sw_update
from dcmanager.common import consts from dccommon import consts
from dcmanager.common import exceptions from dccommon.drivers import base
from dcmanager.drivers import base from dccommon import exceptions
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -12,6 +12,13 @@
# 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.
#
# Copyright (c) 2018-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import collections import collections
import threading import threading
@ -24,7 +31,7 @@ from keystoneclient.v3 import client as keystone_client
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 dcorch.common import consts from dccommon import consts
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -0,0 +1,105 @@
# Copyright 2015 Huawei Technologies Co., Ltd.
# Copyright 2015 Ericsson AB.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
"""
DC Orchestrator base exception handling.
"""
import six
from oslo_utils import encodeutils
from oslo_utils import excutils
from dcorch.common.i18n import _
class DCCommonException(Exception):
"""Base Commond Driver Exception.
To correctly use this class, inherit from it and define
a 'message' property. That message will get printf'd
with the keyword arguments provided to the constructor.
"""
message = _("An unknown exception occurred.")
def __init__(self, **kwargs):
try:
super(DCCommonException, self).__init__(self.message % kwargs)
self.msg = self.message % kwargs
except Exception:
with excutils.save_and_reraise_exception() as ctxt:
if not self.use_fatal_exceptions():
ctxt.reraise = False
# at least get the core message out if something happened
super(DCCommonException, self).__init__(self.message)
if six.PY2:
def __unicode__(self):
return encodeutils.exception_to_unicode(self.msg)
def use_fatal_exceptions(self):
return False
class NotFound(DCCommonException):
pass
class Conflict(DCCommonException):
pass
class ServiceUnavailable(DCCommonException):
message = _("The service is unavailable")
class InvalidInputError(DCCommonException):
message = _("An invalid value was provided")
class InternalError(DCCommonException):
message = _("Error when performing operation")
class OAMAddressesNotFound(NotFound):
message = _("OAM Addresses Not Found")
class TrapDestAlreadyExists(Conflict):
message = _("TrapDest in region=%(region_name)s ip_address=%(ip_address)s "
"community=%(community)s already exists")
class TrapDestNotFound(NotFound):
message = _("Trapdest in region=%(region_name)s with ip_address "
"%(ip_address)s not found")
class CommunityAlreadyExists(Conflict):
message = _("Community %(community)s in region=%(region_name)s "
"already exists")
class CommunityNotFound(NotFound):
message = _("Community %(community)s not found in region=%(region_name)s")
class CertificateNotFound(NotFound):
message = _("Certificate in region=%(region_name)s with signature "
"%(signature)s not found")

View File

@ -0,0 +1,32 @@
# Copyright (c) 2015 Ericsson AB
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dccommon.tests import utils
from oslotest import base
class DCCommonTestCase(base.BaseTestCase):
"""Test case base class for all unit tests."""
def setUp(self):
super(DCCommonTestCase, self).setUp()
self.ctx = utils.dummy_context()

View File

@ -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 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -19,10 +19,9 @@
import mock import mock
from dcmanager.tests import base from dccommon.drivers.openstack import keystone_v3
from dcmanager.tests import utils from dccommon.tests import base
from dccommon.tests import utils
from dcorch.drivers.openstack import keystone_v3
FAKE_SERVICE = [ FAKE_SERVICE = [
'endpoint_volume', 'endpoint_volume',
@ -50,7 +49,7 @@ class FakeEndpoint(object):
self.region = region self.region = region
class TestKeystoneClient(base.DCManagerTestCase): class TestKeystoneClient(base.DCCommonTestCase):
def setUp(self): def setUp(self):
super(TestKeystoneClient, self).setUp() super(TestKeystoneClient, self).setUp()
self.ctx = utils.dummy_context() self.ctx = utils.dummy_context()

View File

@ -0,0 +1,45 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import mock
from dccommon.drivers.openstack import sdk_platform as sdk
from dccommon import exceptions
from dccommon.tests import base
class TestOpenStackDriver(base.DCCommonTestCase):
@mock.patch.object(sdk, 'KeystoneClient')
@mock.patch.object(sdk.OpenStackDriver, '_is_token_valid')
def test_init(self, mock_keystone_client, mock_is_token_valid):
region_name = 'subcloud1'
os_client = sdk.OpenStackDriver(region_name, region_clients=None)
self.assertIsNotNone(os_client)
new_keystone_client = os_client.keystone_client
self.assertIsNotNone(new_keystone_client)
mock_is_token_valid(region_name).return_value = True
cached_keystone_client = sdk.OpenStackDriver(
region_name, region_clients=None).keystone_client
self.assertEqual(new_keystone_client, cached_keystone_client)
self.assertRaises(exceptions.InvalidInputError,
sdk.OpenStackDriver,
region_name, region_clients=['fake_client'])

View File

@ -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 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -19,10 +19,11 @@
import mock import mock
from dccommon.drivers.openstack import sysinv_v1
from dccommon.tests import base
from dccommon.tests import utils
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.drivers.openstack import sysinv_v1 from dcmanager.tests import utils as dcmanager_utils
from dcmanager.tests import base
from dcmanager.tests import utils
from ddt import ddt from ddt import ddt
from ddt import file_data from ddt import file_data
@ -61,7 +62,7 @@ class FakeRoute(object):
@ddt @ddt
class TestSysinvClient(base.DCManagerTestCase): class TestSysinvClient(base.DCCommonTestCase):
def setUp(self): def setUp(self):
super(TestSysinvClient, self).setUp() super(TestSysinvClient, self).setUp()
self.ctx = utils.dummy_context() self.ctx = utils.dummy_context()
@ -110,7 +111,7 @@ class TestSysinvClient(base.DCManagerTestCase):
management_pool = sysinv_client.get_management_address_pool() management_pool = sysinv_client.get_management_address_pool()
self.assertEqual(pool, management_pool) self.assertEqual(pool, management_pool)
@file_data(utils.get_data_filepath('sysinv', 'routes')) @file_data(dcmanager_utils.get_data_filepath('sysinv', 'routes'))
@mock.patch.object(sysinv_v1.SysinvClient, '__init__') @mock.patch.object(sysinv_v1.SysinvClient, '__init__')
def test_create_route(self, value, mock_sysinvclient_init): def test_create_route(self, value, mock_sysinvclient_init):
fake_route = utils.create_route_dict(value) fake_route = utils.create_route_dict(value)
@ -129,7 +130,7 @@ class TestSysinvClient(base.DCManagerTestCase):
network=fake_route['network'], prefix=fake_route['prefix'], network=fake_route['network'], prefix=fake_route['prefix'],
gateway=fake_route['gateway'], metric=fake_route['metric']) gateway=fake_route['gateway'], metric=fake_route['metric'])
@file_data(utils.get_data_filepath('sysinv', 'routes')) @file_data(dcmanager_utils.get_data_filepath('sysinv', 'routes'))
@mock.patch.object(sysinv_v1.SysinvClient, '__init__') @mock.patch.object(sysinv_v1.SysinvClient, '__init__')
def test_delete_route(self, value, mock_sysinvclient_init): def test_delete_route(self, value, mock_sysinvclient_init):
# fake_route = utils.create_route_dict(value) # fake_route = utils.create_route_dict(value)

View File

@ -13,7 +13,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 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -22,13 +22,16 @@
from mock import patch from mock import patch
from dcmanager.tests import base from oslo_config import cfg
from dcmanager.tests import utils
from dccommon import endpoint_cache
from dccommon.tests import base
from dccommon.tests import utils
from dcmanager.tests import utils as dcmanager_utils
from ddt import ddt from ddt import ddt
from ddt import file_data from ddt import file_data
from dcorch.common import endpoint_cache
FAKE_REGION = 'fake_region' FAKE_REGION = 'fake_region'
FAKE_SERVICE = 'fake_service' FAKE_SERVICE = 'fake_service'
@ -45,11 +48,15 @@ FAKE_NEUTRON_URL_1 = 'fake_url_neutron_1'
@ddt @ddt
class EndpointCacheTest(base.DCManagerTestCase): class EndpointCacheTest(base.DCCommonTestCase):
def setUp(self): def setUp(self):
super(EndpointCacheTest, self).setUp() super(EndpointCacheTest, self).setUp()
auth_uri_opts = [
cfg.StrOpt('auth_uri',
default="fake_auth_uri")]
cfg.CONF.register_opts(auth_uri_opts, 'cache')
@file_data(utils.get_data_filepath('keystone', 'endpoint')) @file_data(dcmanager_utils.get_data_filepath('keystone', 'endpoint'))
@patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client') @patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client')
@patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone') @patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone')
def test_get_endpoint(self, value, mock_method, mock_init): def test_get_endpoint(self, value, mock_method, mock_init):
@ -62,7 +69,7 @@ class EndpointCacheTest(base.DCManagerTestCase):
endpoint_dict['service_id']), endpoint_dict['service_id']),
endpoint_dict['url']) endpoint_dict['url'])
@file_data(utils.get_data_filepath('keystone', 'endpoint')) @file_data(dcmanager_utils.get_data_filepath('keystone', 'endpoint'))
@patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client') @patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client')
@patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone') @patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone')
def test_get_endpoint_not_found(self, value, mock_method, mock_init): def test_get_endpoint_not_found(self, value, mock_method, mock_init):
@ -76,7 +83,7 @@ class EndpointCacheTest(base.DCManagerTestCase):
self.assertEqual(cache.get_endpoint(endpoint_dict['region_id'], self.assertEqual(cache.get_endpoint(endpoint_dict['region_id'],
'another_fake_service'), '') 'another_fake_service'), '')
@file_data(utils.get_data_filepath('keystone', 'endpoint')) @file_data(dcmanager_utils.get_data_filepath('keystone', 'endpoint'))
@patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client') @patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client')
@patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone') @patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone')
def test_get_endpoint_retry(self, value, mock_method, mock_init): def test_get_endpoint_retry(self, value, mock_method, mock_init):
@ -89,7 +96,7 @@ class EndpointCacheTest(base.DCManagerTestCase):
endpoint_dict['service_id']), endpoint_dict['service_id']),
'another_fake_url') 'another_fake_url')
@file_data(utils.get_data_filepath('keystone', 'endpoint')) @file_data(dcmanager_utils.get_data_filepath('keystone', 'endpoint'))
@patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client') @patch.object(endpoint_cache.EndpointCache, '_initialize_keystone_client')
@patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone') @patch.object(endpoint_cache.EndpointCache, '_get_endpoint_from_keystone')
def test_update_endpoint(self, value, mock_method, mock_init): def test_update_endpoint(self, value, mock_method, mock_init):

View File

@ -0,0 +1,59 @@
# Copyright (c) 2015 Ericsson AB
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from oslo_context import context
def create_route_dict(data_list):
return {'created-at': data_list[0],
'updated-at': data_list[1],
'deleted-at': data_list[2],
'id': data_list[3],
'uuid': data_list[4],
'family': data_list[5],
'network': data_list[6],
'prefix': data_list[7],
'gateway': data_list[8],
'metric': data_list[9],
'interface-id': data_list[10]}
def create_endpoint_dict(data_list):
return {'id': data_list[0],
'legacy_endpoint_id': data_list[1],
'interface': data_list[2],
'service_id': data_list[3],
'url': data_list[4],
'extra': data_list[5],
'enabled': data_list[6],
'region_id': data_list[7]}
def dummy_context(user='test_username', tenant='test_project_id',
region_name=None):
return context.RequestContext.from_dict({
'auth_token': 'abcd1234',
'user': user,
'project': tenant,
'is_admin': True,
'region_name': region_name
})

View File

@ -36,7 +36,10 @@ from controllerconfig.common.exceptions import ValidateFail
from controllerconfig.utils import validate_address_str from controllerconfig.utils import validate_address_str
from controllerconfig.utils import validate_network_str from controllerconfig.utils import validate_network_str
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dccommon import exceptions as dccommon_exceptions
from keystoneauth1 import exceptions as keystone_exceptions from keystoneauth1 import exceptions as keystone_exceptions
from dcmanager.api.controllers import restcomm from dcmanager.api.controllers import restcomm
@ -46,7 +49,7 @@ from dcmanager.common.i18n import _
from dcmanager.common import install_consts from dcmanager.common import install_consts
from dcmanager.common import utils from dcmanager.common import utils
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
from dcmanager.rpc import client as rpc_client from dcmanager.rpc import client as rpc_client
CONF = cfg.CONF CONF = cfg.CONF
@ -356,7 +359,7 @@ class SubcloudsController(object):
message = ("Identity endpoint for subcloud: %s not found. %s" % message = ("Identity endpoint for subcloud: %s not found. %s" %
(subcloud_name, e)) (subcloud_name, e))
LOG.error(message) LOG.error(message)
except exceptions.OAMAddressesNotFound: except dccommon_exceptions.OAMAddressesNotFound:
message = ("OAM addresses for subcloud: %s not found." % message = ("OAM addresses for subcloud: %s not found." %
(subcloud_name)) (subcloud_name))
LOG.error(message) LOG.error(message)

View File

@ -27,6 +27,7 @@ import pecan
from pecan import expose from pecan import expose
from pecan import request from pecan import request
from dccommon import consts as dccommon_consts
from dcmanager.api.controllers import restcomm from dcmanager.api.controllers import restcomm
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.common import exceptions from dcmanager.common import exceptions
@ -128,7 +129,7 @@ class SwUpdateOptionsController(object):
if subcloud_ref == consts.DEFAULT_REGION_NAME: if subcloud_ref == consts.DEFAULT_REGION_NAME:
# update default options # update default options
subcloud_name = consts.SW_UPDATE_DEFAULT_TITLE subcloud_name = dccommon_consts.SW_UPDATE_DEFAULT_TITLE
if db_api.sw_update_opts_default_get(context): if db_api.sw_update_opts_default_get(context):
# entry already in db, update it. # entry already in db, update it.

View File

@ -87,8 +87,6 @@ STRATEGY_STATE_COMPLETE = "complete"
STRATEGY_STATE_ABORTED = "aborted" STRATEGY_STATE_ABORTED = "aborted"
STRATEGY_STATE_FAILED = "failed" STRATEGY_STATE_FAILED = "failed"
SW_UPDATE_DEFAULT_TITLE = "all clouds default"
# Subcloud deploy status states # Subcloud deploy status states
DEPLOY_STATE_NONE = 'not-deployed' DEPLOY_STATE_NONE = 'not-deployed'
DEPLOY_STATE_PRE_INSTALL = 'pre-install' DEPLOY_STATE_PRE_INSTALL = 'pre-install'

View File

@ -136,10 +136,6 @@ class InternalError(DCManagerException):
message = _("Error when performing operation") message = _("Error when performing operation")
class OAMAddressesNotFound(NotFound):
message = _("OAM Addresses Not Found")
class InvalidInputError(DCManagerException): class InvalidInputError(DCManagerException):
message = _("An invalid value was provided") message = _("An invalid value was provided")

View File

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# Copyright (c) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -31,10 +31,10 @@ 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 dcmanager.common import consts from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack import vim
from dcmanager.common import exceptions from dcmanager.common import exceptions
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack import vim
from dcorch.common import consts as dcorch_consts from dcorch.common import consts as dcorch_consts
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -103,7 +103,7 @@ def get_sw_update_opts(context,
subcloud_id=subcloud_id) 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, consts.SW_UPDATE_DEFAULT_TITLE) sw_update_opts_ref, dccommon_consts.SW_UPDATE_DEFAULT_TITLE)
def ensure_lock_path(): def ensure_lock_path():

View File

@ -13,14 +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.
# #
# Copyright (c) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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 dcmanager.drivers.openstack import vim from dccommon.drivers.openstack import vim
import sqlalchemy import sqlalchemy

View File

@ -1,163 +0,0 @@
# Copyright 2016 Ericsson AB
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from oslo_log import log
from sysinv.common import constants as sysinv_constants
# from dcmanager.common import consts
from dcmanager.common import exceptions
from dcmanager.drivers import base
LOG = log.getLogger(__name__)
API_VERSION = '1'
class SysinvClient(base.DriverBase):
"""Sysinv V1 driver."""
def __init__(self, region, session):
try:
# TOX cannot import cgts_client and all the dependencies therefore
# the client is being lazy loaded since TOX doesn't actually
# require the cgtsclient module.
from cgtsclient import client
# The sysinv client doesn't support a session, so we need to
# get an endpoint and token.
endpoint = session.get_endpoint(service_type='platform',
region_name=region,
interface='internal')
token = session.get_token()
self.sysinv_client = client.Client(API_VERSION,
endpoint=endpoint,
token=token)
except exceptions.ServiceUnavailable:
raise
def get_controller_hosts(self):
"""Get a list of controller hosts."""
return self.sysinv_client.ihost.list_personality(
sysinv_constants.CONTROLLER)
def get_management_interface(self, hostname):
"""Get the management interface for a host."""
interfaces = self.sysinv_client.iinterface.list(hostname)
for interface in interfaces:
interface_networks = self.sysinv_client.interface_network.\
list_by_interface(interface.uuid)
for if_net in interface_networks:
if if_net.network_type == sysinv_constants.NETWORK_TYPE_MGMT:
return interface
# This can happen if the host is still being installed and has not
# yet created its management interface.
LOG.warning("Management interface on host %s not found" % hostname)
return None
def get_management_address_pool(self):
"""Get the management address pool for a host."""
networks = self.sysinv_client.network.list()
for network in networks:
if network.type == sysinv_constants.NETWORK_TYPE_MGMT:
address_pool_uuid = network.pool_uuid
break
else:
LOG.error("Management address pool not found")
raise exceptions.InternalError()
return self.sysinv_client.address_pool.get(address_pool_uuid)
def get_oam_addresses(self):
"""Get the oam address pool for a host."""
iextoam_object = self.sysinv_client.iextoam.list()
if iextoam_object is not None and len(iextoam_object) != 0:
return iextoam_object[0]
else:
LOG.error("OAM address not found")
raise exceptions.OAMAddressesNotFound()
def create_route(self, interface_uuid, network, prefix, gateway, metric):
"""Create a static route on an interface."""
LOG.info("Creating route: interface: %s dest: %s/%s "
"gateway: %s metric %s" % (interface_uuid, network,
prefix, gateway, metric))
self.sysinv_client.route.create(interface_uuid=interface_uuid,
network=network,
prefix=prefix,
gateway=gateway,
metric=metric)
def delete_route(self, interface_uuid, network, prefix, gateway, metric):
"""Delete a static route."""
# Get the routes for this interface
routes = self.sysinv_client.route.list_by_interface(interface_uuid)
for route in routes:
if (route.network == network and route.prefix == prefix and
route.gateway == gateway and route.metric == metric):
LOG.info("Deleting route: interface: %s dest: %s/%s "
"gateway: %s metric %s" % (interface_uuid, network,
prefix, gateway, metric))
self.sysinv_client.route.delete(route.uuid)
return
LOG.warning("Route not found: interface: %s dest: %s/%s gateway: %s "
"metric %s" % (interface_uuid, network, prefix, gateway,
metric))
def get_service_groups(self):
"""Get a list of service groups."""
return self.sysinv_client.sm_servicegroup.list()
def get_loads(self):
"""Get a list of loads."""
return self.sysinv_client.load.list()
def get_applications(self):
"""Get a list of containerized applications"""
# Get a list of containerized applications the system knows of
return self.sysinv_client.app.list()
def get_system(self):
"""Get the system."""
systems = self.sysinv_client.isystem.list()
return systems[0]
def get_service_parameters(self, name, value):
"""Get service parameters for a given name."""
opts = []
opt = dict()
opt['field'] = name
opt['value'] = value
opt['op'] = 'eq'
opt['type'] = ''
opts.append(opt)
parameters = self.sysinv_client.service_parameter.list(q=opts)
return parameters
def get_registry_image_tags(self, image_name):
"""Get the image tags for an image from the local registry"""
image_tags = self.sysinv_client.registry_image.tags(image_name)
return image_tags

View File

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# Copyright (c) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -24,8 +24,12 @@ from keystoneauth1 import exceptions as keystone_exceptions
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 dccommon.drivers.openstack import patching_v1
from dccommon.drivers.openstack.patching_v1 import PatchingClient
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dcorch.common import consts as dcorch_consts from dcorch.common import consts as dcorch_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.common import context from dcmanager.common import context
@ -33,10 +37,6 @@ from dcmanager.common.i18n import _
from dcmanager.common import manager from dcmanager.common import manager
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack import patching_v1
from dcmanager.drivers.openstack.patching_v1 import PatchingClient
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -105,7 +105,9 @@ class PatchAuditManager(manager.Manager):
LOG.info('Triggered patch audit.') LOG.info('Triggered patch audit.')
try: try:
ks_client = KeystoneClient() m_os_ks_client = OpenStackDriver(
region_name=consts.DEFAULT_REGION_NAME,
region_clients=None).keystone_client
except Exception: except Exception:
LOG.warn('Failure initializing KeystoneClient, exiting audit.') LOG.warn('Failure initializing KeystoneClient, exiting audit.')
return return
@ -113,7 +115,7 @@ class PatchAuditManager(manager.Manager):
# First query RegionOne to determine what patches should be applied # First query RegionOne to determine what patches should be applied
# to the system. # to the system.
patching_client = PatchingClient( patching_client = PatchingClient(
consts.DEFAULT_REGION_NAME, ks_client.session) consts.DEFAULT_REGION_NAME, m_os_ks_client.session)
regionone_patches = patching_client.query() regionone_patches = patching_client.query()
LOG.debug("regionone_patches: %s" % regionone_patches) LOG.debug("regionone_patches: %s" % regionone_patches)
@ -142,7 +144,8 @@ class PatchAuditManager(manager.Manager):
continue continue
try: try:
sc_ks_client = KeystoneClient(subcloud.name) sc_os_client = OpenStackDriver(region_name=subcloud.name,
region_clients=None)
except (keystone_exceptions.EndpointNotFound, except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure, keystone_exceptions.ConnectFailure,
keystone_exceptions.ConnectTimeout, keystone_exceptions.ConnectTimeout,
@ -154,16 +157,16 @@ class PatchAuditManager(manager.Manager):
continue continue
try: try:
patching_client = PatchingClient(subcloud.name, patching_client = PatchingClient(
sc_ks_client.session) subcloud.name, sc_os_client.keystone_client.session)
except keystone_exceptions.EndpointNotFound: except keystone_exceptions.EndpointNotFound:
LOG.warn("Patching endpoint for online subcloud %s not found." LOG.warn("Patching endpoint for online subcloud %s not found."
% subcloud.name) % subcloud.name)
continue continue
try: try:
sysinv_client = SysinvClient(subcloud.name, sysinv_client = SysinvClient(
sc_ks_client.session) subcloud.name, sc_os_client.keystone_client.session)
except keystone_exceptions.EndpointNotFound: except keystone_exceptions.EndpointNotFound:
LOG.warn("Sysinv endpoint for online subcloud %s not found." LOG.warn("Sysinv endpoint for online subcloud %s not found."
% subcloud.name) % subcloud.name)

View File

@ -28,8 +28,9 @@ from fm_api import constants as fm_const
from fm_api import fm_api from fm_api import fm_api
from sysinv.common import constants as sysinv_constants from sysinv.common import constants as sysinv_constants
from dcorch.common import consts as dcorch_consts from dccommon import consts as dccommon_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dcorch.rpc import client as dcorch_rpc_client from dcorch.rpc import client as dcorch_rpc_client
from dcmanager.common import consts from dcmanager.common import consts
@ -38,7 +39,6 @@ from dcmanager.common import exceptions
from dcmanager.common.i18n import _ from dcmanager.common.i18n import _
from dcmanager.common import manager from dcmanager.common import manager
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
from dcmanager.manager import scheduler from dcmanager.manager import scheduler
CONF = cfg.CONF CONF = cfg.CONF
@ -47,7 +47,7 @@ LOG = logging.getLogger(__name__)
# We will update the state of each subcloud in the dcorch about once per hour. # We will update the state of each subcloud in the dcorch about once per hour.
# Calculate how many iterations that will be. # Calculate how many iterations that will be.
SUBCLOUD_STATE_UPDATE_ITERATIONS = \ SUBCLOUD_STATE_UPDATE_ITERATIONS = \
dcorch_consts.SECONDS_IN_HOUR / CONF.scheduler.subcloud_audit_interval dccommon_consts.SECONDS_IN_HOUR / CONF.scheduler.subcloud_audit_interval
class SubcloudAuditManager(manager.Manager): class SubcloudAuditManager(manager.Manager):
@ -94,9 +94,10 @@ class SubcloudAuditManager(manager.Manager):
update_subcloud_state = False update_subcloud_state = False
# Determine whether OpenStack is installed in central cloud # Determine whether OpenStack is installed in central cloud
ks_client = KeystoneClient() os_client = OpenStackDriver(region_name=consts.DEFAULT_REGION_NAME,
region_clients=None)
sysinv_client = SysinvClient(consts.DEFAULT_REGION_NAME, sysinv_client = SysinvClient(consts.DEFAULT_REGION_NAME,
ks_client.session) os_client.keystone_client.session)
# This could be optimized in the future by attempting to get just the # This could be optimized in the future by attempting to get just the
# one application. However, sysinv currently treats this as a failure # one application. However, sysinv currently treats this as a failure
# if the application is not installed and generates warning logs, so it # if the application is not installed and generates warning logs, so it
@ -163,9 +164,10 @@ class SubcloudAuditManager(manager.Manager):
avail_to_set = consts.AVAILABILITY_OFFLINE avail_to_set = consts.AVAILABILITY_OFFLINE
try: try:
ks_client = KeystoneClient(subcloud_name) os_client = OpenStackDriver(region_name=subcloud_name,
region_clients=None)
sysinv_client = SysinvClient(subcloud_name, sysinv_client = SysinvClient(subcloud_name,
ks_client.session) os_client.keystone_client.session)
except (keystone_exceptions.EndpointNotFound, except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure, keystone_exceptions.ConnectFailure,
keystone_exceptions.ConnectTimeout, keystone_exceptions.ConnectTimeout,
@ -383,7 +385,7 @@ class SubcloudAuditManager(manager.Manager):
remove_subcloud_sync_endpoint_type remove_subcloud_sync_endpoint_type
if dcm_update_func and dco_update_func: if dcm_update_func and dco_update_func:
endpoint_type_list = dcorch_consts.ENDPOINT_TYPES_LIST_OS endpoint_type_list = dccommon_consts.ENDPOINT_TYPES_LIST_OS
try: try:
# Notify dcorch to add/remove sync endpoint type list # Notify dcorch to add/remove sync endpoint type list
dco_update_func(self.context, subcloud_name, dco_update_func(self.context, subcloud_name,

View File

@ -30,11 +30,11 @@ from six.moves.urllib import error as urllib_error
from six.moves.urllib import parse from six.moves.urllib import parse
from six.moves.urllib import request from six.moves.urllib import request
from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.common import exceptions from dcmanager.common import exceptions
from dcmanager.common import install_consts from dcmanager.common import install_consts
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from oslo_log import log as logging from oslo_log import log as logging

View File

@ -35,8 +35,10 @@ from oslo_messaging import RemoteError
from tsconfig.tsconfig import CONFIG_PATH from tsconfig.tsconfig import CONFIG_PATH
from tsconfig.tsconfig import SW_VERSION from tsconfig.tsconfig import SW_VERSION
from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dcorch.common import consts as dcorch_consts from dcorch.common import consts as dcorch_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcorch.rpc import client as dcorch_rpc_client from dcorch.rpc import client as dcorch_rpc_client
from dcmanager.common import consts from dcmanager.common import consts
@ -46,7 +48,6 @@ from dcmanager.common.i18n import _
from dcmanager.common import manager from dcmanager.common import manager
from dcmanager.common import utils from dcmanager.common import utils
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
from dcmanager.manager.subcloud_install import SubcloudInstall from dcmanager.manager.subcloud_install import SubcloudInstall
from fm_api import constants as fm_const from fm_api import constants as fm_const

View File

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# Copyright (c) 2017 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -28,8 +28,12 @@ import time
from keystoneauth1 import exceptions as keystone_exceptions from keystoneauth1 import exceptions as keystone_exceptions
from oslo_log import log as logging from oslo_log import log as logging
from dccommon.drivers.openstack import patching_v1
from dccommon.drivers.openstack.patching_v1 import PatchingClient
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dccommon.drivers.openstack import vim
from dcorch.common import consts as dcorch_consts from dcorch.common import consts as dcorch_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.common import context from dcmanager.common import context
@ -38,10 +42,6 @@ from dcmanager.common.i18n import _
from dcmanager.common import manager from dcmanager.common import manager
from dcmanager.common import utils from dcmanager.common import utils
from dcmanager.db import api as db_api from dcmanager.db import api as db_api
from dcmanager.drivers.openstack import patching_v1
from dcmanager.drivers.openstack.patching_v1 import PatchingClient
from dcmanager.drivers.openstack.sysinv_v1 import SysinvClient
from dcmanager.drivers.openstack import vim
from dcmanager.manager.patch_audit_manager import PatchAuditManager from dcmanager.manager.patch_audit_manager import PatchAuditManager
from dcmanager.manager import scheduler from dcmanager.manager import scheduler
@ -329,10 +329,13 @@ class PatchOrchThread(threading.Thread):
LOG.info("PatchOrchThread Stopped") LOG.info("PatchOrchThread Stopped")
@staticmethod @staticmethod
def get_ks_client(region_name=None): def get_ks_client(region_name=consts.DEFAULT_REGION_NAME):
"""This will get a new keystone client (and new token)""" """This will get a cached keystone client (and token)"""
try: try:
return KeystoneClient(region_name) os_client = OpenStackDriver(
region_name=region_name,
region_clients=None)
return os_client.keystone_client
except Exception: except Exception:
LOG.warn('Failure initializing KeystoneClient') LOG.warn('Failure initializing KeystoneClient')
raise raise

View File

@ -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 Wind River Systems, Inc. # Copyright (c) 2017-2020 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
@ -188,10 +188,10 @@ class TestAuditManager(base.DCManagerTestCase):
dcorch_messaging.setup("fake://", optional=True) dcorch_messaging.setup("fake://", optional=True)
@mock.patch.object(patch_audit_manager, 'PatchingClient') @mock.patch.object(patch_audit_manager, 'PatchingClient')
@mock.patch.object(patch_audit_manager, 'KeystoneClient') @mock.patch.object(patch_audit_manager, 'OpenStackDriver')
@mock.patch.object(patch_audit_manager, 'context') @mock.patch.object(patch_audit_manager, 'context')
def test_init(self, mock_context, def test_init(self, mock_context,
mock_keystone_client, mock_openstack_driver,
mock_patching_client): mock_patching_client):
mock_context.get_admin_context.return_value = self.ctxt mock_context.get_admin_context.return_value = self.ctxt
@ -205,11 +205,11 @@ class TestAuditManager(base.DCManagerTestCase):
@mock.patch.object(patch_audit_manager, 'SysinvClient') @mock.patch.object(patch_audit_manager, 'SysinvClient')
@mock.patch.object(patch_audit_manager, 'db_api') @mock.patch.object(patch_audit_manager, 'db_api')
@mock.patch.object(patch_audit_manager, 'PatchingClient') @mock.patch.object(patch_audit_manager, 'PatchingClient')
@mock.patch.object(patch_audit_manager, 'KeystoneClient') @mock.patch.object(patch_audit_manager, 'OpenStackDriver')
@mock.patch.object(patch_audit_manager, 'context') @mock.patch.object(patch_audit_manager, 'context')
def test_periodic_patch_audit_in_sync( def test_periodic_patch_audit_in_sync(
self, mock_context, self, mock_context,
mock_keystone_client, mock_openstack_driver,
mock_patching_client, mock_patching_client,
mock_db_api, mock_db_api,
mock_sysinv_client): mock_sysinv_client):
@ -243,11 +243,11 @@ class TestAuditManager(base.DCManagerTestCase):
@mock.patch.object(patch_audit_manager, 'SysinvClient') @mock.patch.object(patch_audit_manager, 'SysinvClient')
@mock.patch.object(patch_audit_manager, 'db_api') @mock.patch.object(patch_audit_manager, 'db_api')
@mock.patch.object(patch_audit_manager, 'PatchingClient') @mock.patch.object(patch_audit_manager, 'PatchingClient')
@mock.patch.object(patch_audit_manager, 'KeystoneClient') @mock.patch.object(patch_audit_manager, 'OpenStackDriver')
@mock.patch.object(patch_audit_manager, 'context') @mock.patch.object(patch_audit_manager, 'context')
def test_periodic_patch_audit_out_of_sync( def test_periodic_patch_audit_out_of_sync(
self, mock_context, self, mock_context,
mock_keystone_client, mock_openstack_driver,
mock_patching_client, mock_patching_client,
mock_db_api, mock_db_api,
mock_sysinv_client): mock_sysinv_client):
@ -295,11 +295,11 @@ class TestAuditManager(base.DCManagerTestCase):
@mock.patch.object(patch_audit_manager, 'db_api') @mock.patch.object(patch_audit_manager, 'db_api')
@mock.patch.object(patch_audit_manager, 'PatchingClient') @mock.patch.object(patch_audit_manager, 'PatchingClient')
@mock.patch.object(patch_audit_manager, 'KeystoneClient') @mock.patch.object(patch_audit_manager, 'OpenStackDriver')
@mock.patch.object(patch_audit_manager, 'context') @mock.patch.object(patch_audit_manager, 'context')
def test_periodic_patch_audit_ignore_unmanaged_or_offline( def test_periodic_patch_audit_ignore_unmanaged_or_offline(
self, mock_context, self, mock_context,
mock_keystone_client, mock_openstack_driver,
mock_patching_client, mock_patching_client,
mock_db_api): mock_db_api):
mock_context.get_admin_context.return_value = self.ctxt mock_context.get_admin_context.return_value = self.ctxt
@ -321,11 +321,11 @@ class TestAuditManager(base.DCManagerTestCase):
@mock.patch.object(patch_audit_manager, 'SysinvClient') @mock.patch.object(patch_audit_manager, 'SysinvClient')
@mock.patch.object(patch_audit_manager, 'db_api') @mock.patch.object(patch_audit_manager, 'db_api')
@mock.patch.object(patch_audit_manager, 'PatchingClient') @mock.patch.object(patch_audit_manager, 'PatchingClient')
@mock.patch.object(patch_audit_manager, 'KeystoneClient') @mock.patch.object(patch_audit_manager, 'OpenStackDriver')
@mock.patch.object(patch_audit_manager, 'context') @mock.patch.object(patch_audit_manager, 'context')
def test_periodic_patch_audit_extra_patches( def test_periodic_patch_audit_extra_patches(
self, mock_context, self, mock_context,
mock_keystone_client, mock_openstack_driver,
mock_patching_client, mock_patching_client,
mock_db_api, mock_db_api,
mock_sysinv_client): mock_sysinv_client):

View File

@ -23,11 +23,11 @@ import mock
import sys import sys
sys.modules['fm_core'] = mock.Mock() sys.modules['fm_core'] = mock.Mock()
from dccommon import consts as dccommon_consts
from dcmanager.common import consts from dcmanager.common import consts
from dcmanager.db.sqlalchemy import api as db_api from dcmanager.db.sqlalchemy import api as db_api
from dcmanager.manager import subcloud_audit_manager from dcmanager.manager import subcloud_audit_manager
from dcmanager.manager import subcloud_manager from dcmanager.manager import subcloud_manager
from dcorch.common import consts as dcorch_consts
from dcmanager.tests import base from dcmanager.tests import base
@ -198,8 +198,8 @@ class TestAuditManager(base.DCManagerTestCase):
self.addCleanup(p.stop) self.addCleanup(p.stop)
# Mock the KeystoneClient # Mock the KeystoneClient
p = mock.patch.object(subcloud_audit_manager, 'KeystoneClient') p = mock.patch.object(subcloud_audit_manager, 'OpenStackDriver')
self.mock_keystone_client = p.start() self.mock_openstack_driver = p.start()
self.addCleanup(p.stop) self.addCleanup(p.stop)
# Mock the context # Mock the context
@ -401,7 +401,7 @@ class TestAuditManager(base.DCManagerTestCase):
# Verify the openstack endpoints were added # Verify the openstack endpoints were added
self.fake_dcorch_api.add_subcloud_sync_endpoint_type.\ self.fake_dcorch_api.add_subcloud_sync_endpoint_type.\
assert_called_with(mock.ANY, 'subcloud1', assert_called_with(mock.ANY, 'subcloud1',
dcorch_consts.ENDPOINT_TYPES_LIST_OS) dccommon_consts.ENDPOINT_TYPES_LIST_OS)
# Verify the subcloud openstack_installed was updated # Verify the subcloud openstack_installed was updated
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, 'subcloud1') updated_subcloud = db_api.subcloud_get_by_name(self.ctx, 'subcloud1')

View File

@ -132,28 +132,3 @@ def create_subcloud_dict(data_list):
'external_oam_gateway_address': data_list[20], 'external_oam_gateway_address': data_list[20],
'external_oam_floating_address': data_list[21], 'external_oam_floating_address': data_list[21],
'sysadmin_password': data_list[22]} 'sysadmin_password': data_list[22]}
def create_route_dict(data_list):
return {'created-at': data_list[0],
'updated-at': data_list[1],
'deleted-at': data_list[2],
'id': data_list[3],
'uuid': data_list[4],
'family': data_list[5],
'network': data_list[6],
'prefix': data_list[7],
'gateway': data_list[8],
'metric': data_list[9],
'interface-id': data_list[10]}
def create_endpoint_dict(data_list):
return {'id': data_list[0],
'legacy_endpoint_id': data_list[1],
'interface': data_list[2],
'service_id': data_list[3],
'url': data_list[4],
'extra': data_list[5],
'enabled': data_list[6],
'region_id': data_list[7]}

View File

@ -20,16 +20,16 @@ from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_service.wsgi import Request from oslo_service.wsgi import Request
from dccommon import consts as dccommon_consts
from dcorch.api.proxy.apps.proxy import Proxy from dcorch.api.proxy.apps.proxy import Proxy
from dcorch.api.proxy.common.service import Middleware from dcorch.api.proxy.common.service import Middleware
from dcorch.api.proxy.common import utils from dcorch.api.proxy.common import utils
from dcorch.common import consts
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
filter_opts = [ filter_opts = [
cfg.StrOpt('user_header', cfg.StrOpt('user_header',
default=consts.TOPIC_ORCH_ENGINE, default=dccommon_consts.USER_HEADER_VALUE,
help='An application specific header'), help='An application specific header'),
] ]

View File

@ -22,8 +22,9 @@ from six.moves.urllib.parse import urlparse
from keystoneauth1 import exceptions as keystone_exceptions from keystoneauth1 import exceptions as keystone_exceptions
from oslo_log import log as logging from oslo_log import log as logging
from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack import sdk_platform as sdk
from dcorch.common import consts from dcorch.common import consts
from dcorch.drivers.openstack import sdk_platform as sdk
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -138,7 +139,7 @@ def set_request_forward_environ(req, remote_host, remote_port):
def _get_fernet_keys(): def _get_fernet_keys():
"""Get fernet keys from sysinv.""" """Get fernet keys from sysinv."""
os_client = sdk.OpenStackDriver(region_name=consts.CLOUD_0, os_client = sdk.OpenStackDriver(region_name=dccommon_consts.CLOUD_0,
thread_name='proxy') thread_name='proxy')
try: try:
key_list = os_client.sysinv_client.get_fernet_keys() key_list = os_client.sysinv_client.get_fernet_keys()
@ -146,12 +147,12 @@ def _get_fernet_keys():
except (keystone_exceptions.connection.ConnectTimeout, except (keystone_exceptions.connection.ConnectTimeout,
keystone_exceptions.ConnectFailure) as e: keystone_exceptions.ConnectFailure) as e:
LOG.info("get_fernet_keys: cloud {} is not reachable [{}]" LOG.info("get_fernet_keys: cloud {} is not reachable [{}]"
.format(consts.CLOUD_0, str(e))) .format(dccommon_consts.CLOUD_0, str(e)))
sdk.OpenStackDriver.delete_region_clients(consts.CLOUD_0) sdk.OpenStackDriver.delete_region_clients(dccommon_consts.CLOUD_0)
return None return None
except (AttributeError, TypeError) as e: except (AttributeError, TypeError) as e:
LOG.info("get_fernet_keys error {}".format(e)) LOG.info("get_fernet_keys error {}".format(e))
sdk.OpenStackDriver.delete_region_clients(consts.CLOUD_0, sdk.OpenStackDriver.delete_region_clients(dccommon_consts.CLOUD_0,
clear_token=True) clear_token=True)
return None return None
except Exception as e: except Exception as e:

View File

@ -63,14 +63,8 @@ RPC_API_VERSION = "1.0"
TOPIC_ORCH_ENGINE = "dcorch-engine" TOPIC_ORCH_ENGINE = "dcorch-engine"
# Distributed Cloud constants
CLOUD_0 = "RegionOne"
VIRTUAL_MASTER_CLOUD = "SystemController"
ALARMS_DISABLED = "disabled" ALARMS_DISABLED = "disabled"
USER_HEADER = {'User-Header': TOPIC_ORCH_ENGINE}
# SyncRequest States # SyncRequest States
ORCH_REQUEST_NONE = None ORCH_REQUEST_NONE = None
ORCH_REQUEST_QUEUED = "queued" # in database, not in thread ORCH_REQUEST_QUEUED = "queued" # in database, not in thread
@ -134,14 +128,11 @@ ENDPOINT_TYPE_PATCHING = "patching"
ENDPOINT_TYPE_IDENTITY = "identity" ENDPOINT_TYPE_IDENTITY = "identity"
ENDPOINT_TYPE_FM = "faultmanagement" ENDPOINT_TYPE_FM = "faultmanagement"
ENDPOINT_TYPE_NFV = "nfv" ENDPOINT_TYPE_NFV = "nfv"
ENDPOINT_TYPE_IDENTITY_OS = "identity_openstack"
# platform endpoint types # platform endpoint types
ENDPOINT_TYPES_LIST = [ENDPOINT_TYPE_PLATFORM, ENDPOINT_TYPES_LIST = [ENDPOINT_TYPE_PLATFORM,
ENDPOINT_TYPE_PATCHING, ENDPOINT_TYPE_PATCHING,
ENDPOINT_TYPE_IDENTITY] ENDPOINT_TYPE_IDENTITY]
# openstack endpoint types
ENDPOINT_TYPES_LIST_OS = [ENDPOINT_TYPE_IDENTITY_OS]
ENDPOINT_QUOTA_MAPPING = { ENDPOINT_QUOTA_MAPPING = {
ENDPOINT_TYPE_COMPUTE: NOVA_QUOTA_FIELDS, ENDPOINT_TYPE_COMPUTE: NOVA_QUOTA_FIELDS,
@ -149,10 +140,6 @@ ENDPOINT_QUOTA_MAPPING = {
ENDPOINT_TYPE_VOLUME: CINDER_QUOTA_FIELDS, ENDPOINT_TYPE_VOLUME: CINDER_QUOTA_FIELDS,
} }
KS_ENDPOINT_ADMIN = "admin"
KS_ENDPOINT_INTERNAL = "internal"
KS_ENDPOINT_DEFAULT = KS_ENDPOINT_INTERNAL
# DB sync agent endpoint # DB sync agent endpoint
DBS_ENDPOINT_INTERNAL = "internal" DBS_ENDPOINT_INTERNAL = "internal"
DBS_ENDPOINT_DEFAULT = DBS_ENDPOINT_INTERNAL DBS_ENDPOINT_DEFAULT = DBS_ENDPOINT_INTERNAL
@ -186,8 +173,6 @@ ALARM_OK_STATUS = "OK"
ALARM_DEGRADED_STATUS = "degraded" ALARM_DEGRADED_STATUS = "degraded"
ALARM_CRITICAL_STATUS = "critical" ALARM_CRITICAL_STATUS = "critical"
SECONDS_IN_HOUR = 3600
# Subcloud initial sync state # Subcloud initial sync state
INITIAL_SYNC_STATE_NONE = "none" INITIAL_SYNC_STATE_NONE = "none"
INITIAL_SYNC_STATE_REQUESTED = "requested" INITIAL_SYNC_STATE_REQUESTED = "requested"

View File

@ -207,27 +207,3 @@ class OrchRequestAlreadyExists(Conflict):
class ObjectActionError(OrchestratorException): class ObjectActionError(OrchestratorException):
msg_fmt = _('Object action %(action)s failed because: %(reason)s') msg_fmt = _('Object action %(action)s failed because: %(reason)s')
class TrapDestAlreadyExists(Conflict):
message = _("TrapDest in region=%(region_name)s ip_address=%(ip_address)s "
"community=%(community)s already exists")
class TrapDestNotFound(NotFound):
message = _("Trapdest in region=%(region_name)s with ip_address "
"%(ip_address)s not found")
class CommunityAlreadyExists(Conflict):
message = _("Community %(community)s in region=%(region_name)s "
"already exists")
class CommunityNotFound(NotFound):
message = _("Community %(community)s not found in region=%(region_name)s")
class CertificateNotFound(NotFound):
message = _("Certificate in region=%(region_name)s with signature "
"%(signature)s not found")

View File

@ -24,9 +24,10 @@ from oslo_utils import timeutils
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.drivers.openstack.fm import FmClient from dccommon import consts as dccommon_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient from dccommon.drivers.openstack.fm import FmClient
from dcorch.drivers.openstack.sysinv_v1 import SysinvClient from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
# Gap, in seconds, to determine whether the given token is about to expire # Gap, in seconds, to determine whether the given token is about to expire
STALE_TOKEN_DURATION = 60 STALE_TOKEN_DURATION = 60
@ -40,7 +41,7 @@ class OpenStackDriver(object):
_identity_tokens = {} _identity_tokens = {}
@lockutils.synchronized('dcorch-openstackdriver') @lockutils.synchronized('dcorch-openstackdriver')
def __init__(self, region_name=consts.VIRTUAL_MASTER_CLOUD, def __init__(self, region_name=dccommon_consts.VIRTUAL_MASTER_CLOUD,
auth_url=None): auth_url=None):
# Check if objects are cached and try to use those # Check if objects are cached and try to use those
self.region_name = region_name self.region_name = region_name
@ -84,7 +85,7 @@ class OpenStackDriver(object):
self.fm_client = FmClient( self.fm_client = FmClient(
region_name, region_name,
self.keystone_client.session, self.keystone_client.session,
endpoint_type=consts.KS_ENDPOINT_DEFAULT) endpoint_type=dccommon_consts.KS_ENDPOINT_DEFAULT)
OpenStackDriver.os_clients_dict[region_name][ OpenStackDriver.os_clients_dict[region_name][
'fm'] = self.fm_client 'fm'] = self.fm_client
except Exception as exception: except Exception as exception:
@ -239,8 +240,8 @@ class OpenStackDriver(object):
region_lists = \ region_lists = \
KeystoneClient().endpoint_cache.get_all_regions() KeystoneClient().endpoint_cache.get_all_regions()
# nova, cinder, and neutron have no endpoints in consts.CLOUD_0 # nova, cinder, and neutron have no endpoints in consts.CLOUD_0
if consts.CLOUD_0 in region_lists: if dccommon_consts.CLOUD_0 in region_lists:
region_lists.remove(consts.CLOUD_0) region_lists.remove(dccommon_consts.CLOUD_0)
return region_lists return region_lists
except Exception as exception: except Exception as exception:
LOG.error('Error Occurred: %s', exception.message) LOG.error('Error Occurred: %s', exception.message)

View File

@ -1,181 +0,0 @@
# Copyright 2017-2018 Wind River Inc
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
OpenStack Driver
"""
import collections
from oslo_concurrency import lockutils
from oslo_log import log
from oslo_utils import timeutils
from dcorch.common import consts
from dcorch.drivers.openstack.fm import FmClient
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcorch.drivers.openstack.sysinv_v1 import SysinvClient
# Gap, in seconds, to determine whether the given token is about to expire
STALE_TOKEN_DURATION = 60
LOG = log.getLogger(__name__)
LOCK_NAME = 'dcorch-openstackdriver-platform'
class OpenStackDriver(object):
os_clients_dict = collections.defaultdict(dict)
_identity_tokens = {}
@lockutils.synchronized(LOCK_NAME)
def __init__(self, region_name=consts.CLOUD_0, thread_name='dcorch',
auth_url=None):
# Check if objects are cached and try to use those
self.region_name = region_name
self.sysinv_client = None
self.fm_client = None
if ((region_name in OpenStackDriver.os_clients_dict) and
('keystone' in self.os_clients_dict[region_name]) and
self._is_token_valid(region_name)):
self.keystone_client = \
self.os_clients_dict[region_name]['keystone']
else:
LOG.info("get new keystone client for subcloud %s", region_name)
try:
self.keystone_client = KeystoneClient(region_name, auth_url)
OpenStackDriver.os_clients_dict[region_name]['keystone'] =\
self.keystone_client
except Exception as exception:
LOG.error('keystone_client region %s error: %s' %
(region_name, exception.message))
if ((region_name in OpenStackDriver.os_clients_dict) and
(thread_name in OpenStackDriver.os_clients_dict[region_name])):
if ('sysinv' in OpenStackDriver.os_clients_dict[region_name]
[thread_name]):
LOG.debug('Using cached OS sysinv client objects %s %s' %
(region_name, thread_name))
self.sysinv_client = OpenStackDriver.os_clients_dict[
region_name][thread_name]['sysinv']
if ('fm' in OpenStackDriver.os_clients_dict[region_name]
[thread_name]):
LOG.debug('Using cached OS fm client objects %s %s' %
(region_name, thread_name))
self.fm_client = OpenStackDriver.os_clients_dict[
region_name][thread_name]['fm']
else:
OpenStackDriver.os_clients_dict[region_name][thread_name] = {}
if self.sysinv_client is None:
# Create new sysinv client object and cache it
try:
self.sysinv_client = SysinvClient(region_name,
self.keystone_client.session)
(OpenStackDriver.os_clients_dict[region_name][thread_name]
['sysinv']) = self.sysinv_client
except Exception as exception:
LOG.error('sysinv_client region %s thread %s error: %s' %
(region_name, thread_name, exception.message))
if self.fm_client is None:
# Create new fm client object and cache it
try:
self.fm_client = FmClient(
region_name,
self.keystone_client.session,
endpoint_type=consts.KS_ENDPOINT_DEFAULT)
(OpenStackDriver.os_clients_dict[region_name][thread_name]
['fm']) = self.fm_client
except Exception as exception:
LOG.error('fm_client region %s thread %s error: %s' %
(region_name, thread_name, exception.message))
@classmethod
@lockutils.synchronized(LOCK_NAME)
def delete_region_clients(cls, region_name, clear_token=False):
LOG.warn("delete_region_clients=%s, clear_token=%s" %
(region_name, clear_token))
if region_name in cls.os_clients_dict:
del cls.os_clients_dict[region_name]
if clear_token:
cls._identity_tokens[region_name] = None
@classmethod
@lockutils.synchronized(LOCK_NAME)
def delete_region_clients_for_thread(cls, region_name, thread_name):
LOG.debug("delete_region_clients=%s, thread_name=%s" %
(region_name, thread_name))
if (region_name in cls.os_clients_dict and
thread_name in cls.os_clients_dict[region_name]):
del cls.os_clients_dict[region_name][thread_name]
def _is_token_valid(self, region_name):
try:
keystone = \
OpenStackDriver.os_clients_dict[region_name]['keystone'].\
keystone_client
if (not OpenStackDriver._identity_tokens
or region_name not in OpenStackDriver._identity_tokens
or not OpenStackDriver._identity_tokens[region_name]):
OpenStackDriver._identity_tokens[region_name] = \
keystone.tokens.validate(keystone.session.get_token())
LOG.info("Get new token for subcloud %s expires_at=%s" %
(region_name,
OpenStackDriver._identity_tokens[region_name]
['expires_at']))
# Reset the cached dictionary
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
return False
token = \
keystone.tokens.validate(OpenStackDriver._identity_tokens
[region_name])
if token != OpenStackDriver._identity_tokens[region_name]:
LOG.info("updating token %s to %s" %
(OpenStackDriver._identity_tokens[region_name],
token))
OpenStackDriver._identity_tokens[region_name] = token
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
return False
except Exception as exception:
LOG.info('_is_token_valid handle: %s', exception.message)
# Reset the cached dictionary
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
OpenStackDriver._identity_tokens[region_name] = None
return False
expiry_time = timeutils.normalize_time(timeutils.parse_isotime(
self._identity_tokens[region_name]['expires_at']))
if timeutils.is_soon(expiry_time, STALE_TOKEN_DURATION):
LOG.info("The cached keystone token for subcloud %s "
"will expire soon %s" %
(region_name,
OpenStackDriver._identity_tokens[region_name]
['expires_at']))
# Reset the cached dictionary
OpenStackDriver.os_clients_dict[region_name] = \
collections.defaultdict(dict)
OpenStackDriver._identity_tokens[region_name] = None
return False
else:
return True

View File

@ -14,6 +14,8 @@
# limitations under the License. # limitations under the License.
import datetime import datetime
from dccommon import consts as dccommon_consts
from dccommon import exceptions as dccommon_exceptions
from dcmanager.common import consts as dcm_consts from dcmanager.common import consts as dcm_consts
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import context from dcorch.common import context
@ -22,10 +24,10 @@ from dcorch.common.i18n import _
from dcorch.common import manager from dcorch.common import manager
from dcorch.db import api as db_api from dcorch.db import api as db_api
from dcorch.drivers.openstack.fm import FmClient from dccommon.drivers.openstack.fm import FmClient
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dcorch.drivers.openstack import sdk_platform as sdk from dccommon.drivers.openstack import sdk_platform as sdk
from dcorch.drivers.openstack.sysinv_v1 import SysinvClient from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
@ -63,7 +65,7 @@ class AlarmAggregateManager(manager.Manager):
ks_client = KeystoneClient(subcloud_name) ks_client = KeystoneClient(subcloud_name)
sysinv_client = SysinvClient(subcloud_name, ks_client.session) sysinv_client = SysinvClient(subcloud_name, ks_client.session)
fm_client = FmClient(subcloud_name, ks_client.session, fm_client = FmClient(subcloud_name, ks_client.session,
consts.KS_ENDPOINT_DEFAULT) dccommon_consts.KS_ENDPOINT_DEFAULT)
sysinv_client.snmp_trapdest_create(payload) sysinv_client.snmp_trapdest_create(payload)
self.update_alarm_summary(self.context, subcloud_name, self.update_alarm_summary(self.context, subcloud_name,
fm_client=fm_client) fm_client=fm_client)
@ -76,7 +78,7 @@ class AlarmAggregateManager(manager.Manager):
LOG.info("snmp_trapdest_create AttributeError region_name=%s" % LOG.info("snmp_trapdest_create AttributeError region_name=%s" %
subcloud_name) subcloud_name)
pass pass
except exceptions.TrapDestAlreadyExists: except dccommon_exceptions.TrapDestAlreadyExists:
LOG.info("snmp_trapdest_create TrapDestAlreadyExists " LOG.info("snmp_trapdest_create TrapDestAlreadyExists "
"region_name=%s payload %s" % (subcloud_name, payload)) "region_name=%s payload %s" % (subcloud_name, payload))
pass pass

View File

@ -20,14 +20,16 @@ from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack.keystone_v3 import KeystoneClient
from dccommon.drivers.openstack.sysinv_v1 import SysinvClient
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import context from dcorch.common import context
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.common.i18n import _ from dcorch.common.i18n import _
from dcorch.common import manager from dcorch.common import manager
from dcorch.common import utils from dcorch.common import utils
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcorch.drivers.openstack.sysinv_v1 import SysinvClient
FERNET_REPO_MASTER_ID = "keys" FERNET_REPO_MASTER_ID = "keys"
KEY_ROTATE_CMD = "/usr/bin/keystone-fernet-keys-rotate-active" KEY_ROTATE_CMD = "/usr/bin/keystone-fernet-keys-rotate-active"
@ -67,7 +69,8 @@ class FernetKeyManager(manager.Manager):
def _schedule_work(self, operation_type, subcloud=None): def _schedule_work(self, operation_type, subcloud=None):
keys = self._get_master_keys() keys = self._get_master_keys()
if not keys: if not keys:
LOG.info(_("No fernet keys returned from %s") % consts.CLOUD_0) LOG.info(_("No fernet keys returned from %s") %
dccommon_consts.CLOUD_0)
return return
try: try:
resource_info = FernetKeyManager.to_resource_info(keys) resource_info = FernetKeyManager.to_resource_info(keys)
@ -91,14 +94,14 @@ class FernetKeyManager(manager.Manager):
try: try:
# No cached client is required as it is called during the initial # No cached client is required as it is called during the initial
# sync and after weekly key rotation # sync and after weekly key rotation
ks_client = KeystoneClient(consts.CLOUD_0) ks_client = KeystoneClient(dccommon_consts.CLOUD_0)
sysinv_client = SysinvClient(consts.CLOUD_0, sysinv_client = SysinvClient(dccommon_consts.CLOUD_0,
ks_client.session) ks_client.session)
keys = sysinv_client.get_fernet_keys() keys = sysinv_client.get_fernet_keys()
except (exceptions.ConnectionRefused, exceptions.NotAuthorized, except (exceptions.ConnectionRefused, exceptions.NotAuthorized,
exceptions.TimeOut): exceptions.TimeOut):
LOG.info(_("Retrieving the fernet keys from %s timeout") % LOG.info(_("Retrieving the fernet keys from %s timeout") %
consts.CLOUD_0) dccommon_consts.CLOUD_0)
except Exception as e: except Exception as e:
LOG.info(_("Fail to retrieve the master fernet keys: %s") % LOG.info(_("Fail to retrieve the master fernet keys: %s") %
e.message) e.message)
@ -122,7 +125,8 @@ class FernetKeyManager(manager.Manager):
def distribute_keys(self, ctxt, subcloud_name): def distribute_keys(self, ctxt, subcloud_name):
keys = self._get_master_keys() keys = self._get_master_keys()
if not keys: if not keys:
LOG.info(_("No fernet keys returned from %s") % consts.CLOUD_0) LOG.info(_("No fernet keys returned from %s") %
dccommon_consts.CLOUD_0)
return return
resource_info = FernetKeyManager.to_resource_info(keys) resource_info = FernetKeyManager.to_resource_info(keys)
key_list = FernetKeyManager.from_resource_info(resource_info) key_list = FernetKeyManager.from_resource_info(resource_info)

View File

@ -23,9 +23,10 @@ import time
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 dccommon import consts as dccommon_consts
from dccommon import endpoint_cache
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import context from dcorch.common import context
from dcorch.common import endpoint_cache
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.common.i18n import _ from dcorch.common.i18n import _
from dcorch.common import manager from dcorch.common import manager
@ -114,7 +115,7 @@ class QuotaManager(manager.Manager):
def get_projects_users_with_modified_quotas(self): def get_projects_users_with_modified_quotas(self):
# get the list of project/user tuples that have modified quotas # get the list of project/user tuples that have modified quotas
project_user_list = set([]) project_user_list = set([])
os_client = sdk.OpenStackDriver(consts.VIRTUAL_MASTER_CLOUD) os_client = sdk.OpenStackDriver(dccommon_consts.VIRTUAL_MASTER_CLOUD)
try: try:
quotas = os_client.nova_client.nova_client.quotas.list() quotas = os_client.nova_client.nova_client.quotas.list()
project_user_quotas = quotas['project_user_quotas'] project_user_quotas = quotas['project_user_quotas']
@ -306,7 +307,7 @@ class QuotaManager(manager.Manager):
# are managed by dcorch so delete them from all regions except # are managed by dcorch so delete them from all regions except
# the master one. # the master one.
for region in regions_usage_dict_copy: for region in regions_usage_dict_copy:
if region == consts.VIRTUAL_MASTER_CLOUD: if region == dccommon_consts.VIRTUAL_MASTER_CLOUD:
continue continue
for quota in consts.QUOTAS_FOR_MANAGED_RESOURCES: for quota in consts.QUOTAS_FOR_MANAGED_RESOURCES:
regions_usage_dict_copy[region].pop(quota, None) regions_usage_dict_copy[region].pop(quota, None)
@ -357,7 +358,7 @@ class QuotaManager(manager.Manager):
# Remove the master region from the list. Its quotas should already # Remove the master region from the list. Its quotas should already
# be up to date for managed resources. # be up to date for managed resources.
region_lists.remove(consts.VIRTUAL_MASTER_CLOUD) region_lists.remove(dccommon_consts.VIRTUAL_MASTER_CLOUD)
# (NOTE: knasim-wrs): The Master Cloud's Project ID and User ID # (NOTE: knasim-wrs): The Master Cloud's Project ID and User ID
# dont mean anything for the subcloud, so we need to first resolve # dont mean anything for the subcloud, so we need to first resolve
@ -407,8 +408,9 @@ class QuotaManager(manager.Manager):
def get_overall_tenant_quota_limits(self, project_id, user_id): def get_overall_tenant_quota_limits(self, project_id, user_id):
# Return quota limits in the master cloud. These are the overall # Return quota limits in the master cloud. These are the overall
# quota limits for the whole cloud. # quota limits for the whole cloud.
return self.get_tenant_quota_limits_region(project_id, user_id, return self.get_tenant_quota_limits_region(
consts.VIRTUAL_MASTER_CLOUD) project_id, user_id,
dccommon_consts.VIRTUAL_MASTER_CLOUD)
def get_tenant_quota_usage_per_region(self, project_id, user_id): def get_tenant_quota_usage_per_region(self, project_id, user_id):
# Return quota usage dict with keys as region name & values as usages. # Return quota usage dict with keys as region name & values as usages.

View File

@ -21,6 +21,7 @@ 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 dccommon import consts as dccommon_consts
from dcmanager.common import consts as dcm_consts from dcmanager.common import consts as dcm_consts
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import context from dcorch.common import context
@ -134,10 +135,10 @@ class EngineService(service.Service):
self.periodic_sync_audit, self.periodic_sync_audit,
initial_delay=self.periodic_interval / 2) initial_delay=self.periodic_interval / 2)
self.TG.add_timer(CONF.fernet.key_rotation_interval * self.TG.add_timer(CONF.fernet.key_rotation_interval *
consts.SECONDS_IN_HOUR, dccommon_consts.SECONDS_IN_HOUR,
self.periodic_key_rotation, self.periodic_key_rotation,
initial_delay=(CONF.fernet.key_rotation_interval initial_delay=(CONF.fernet.key_rotation_interval
* consts.SECONDS_IN_HOUR)) * dccommon_consts.SECONDS_IN_HOUR))
def service_registry_report(self): def service_registry_report(self):
ctx = context.get_admin_context() ctx = context.get_admin_context()

View File

@ -15,6 +15,7 @@
import threading import threading
from dccommon import consts as dccommon_consts
from dcmanager.common import consts as dcm_consts from dcmanager.common import consts as dcm_consts
from dcorch.common import consts as dco_consts from dcorch.common import consts as dco_consts
from dcorch.engine.sync_services.identity import IdentitySyncThread from dcorch.engine.sync_services.identity import IdentitySyncThread
@ -28,7 +29,7 @@ LOG = logging.getLogger(__name__)
syncthread_subclass_map = { syncthread_subclass_map = {
dco_consts.ENDPOINT_TYPE_PLATFORM: SysinvSyncThread, dco_consts.ENDPOINT_TYPE_PLATFORM: SysinvSyncThread,
dco_consts.ENDPOINT_TYPE_IDENTITY: IdentitySyncThread, dco_consts.ENDPOINT_TYPE_IDENTITY: IdentitySyncThread,
dco_consts.ENDPOINT_TYPE_IDENTITY_OS: IdentitySyncThread dccommon_consts.ENDPOINT_TYPE_IDENTITY_OS: IdentitySyncThread
} }

View File

@ -21,6 +21,7 @@ from novaclient import utils as novaclient_utils
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from dccommon import consts as dccommon_consts
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.common import utils from dcorch.common import utils
@ -60,7 +61,7 @@ class ComputeSyncThread(SyncThread):
if (not self.sc_nova_client and self.sc_admin_session): if (not self.sc_nova_client and self.sc_admin_session):
self.sc_nova_client = novaclient.Client( self.sc_nova_client = novaclient.Client(
'2.38', session=self.sc_admin_session, '2.38', session=self.sc_admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=self.subcloud_engine.subcloud.region_name) region_name=self.subcloud_engine.subcloud.region_name)
def initialize(self): def initialize(self):
@ -72,8 +73,8 @@ class ComputeSyncThread(SyncThread):
# todo: update version to 2.53 once on pike # todo: update version to 2.53 once on pike
self.m_nova_client = novaclient.Client( self.m_nova_client = novaclient.Client(
'2.38', session=self.admin_session, '2.38', session=self.admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=consts.VIRTUAL_MASTER_CLOUD) region_name=dccommon_consts.VIRTUAL_MASTER_CLOUD)
self.initialize_sc_clients() self.initialize_sc_clients()
LOG.info("session and clients initialized", extra=self.log_extra) LOG.info("session and clients initialized", extra=self.log_extra)

View File

@ -17,6 +17,7 @@
import base64 import base64
from collections import namedtuple from collections import namedtuple
from dccommon import consts as dccommon_consts
from dcdbsync.dbsyncclient import client as dbsyncclient from dcdbsync.dbsyncclient import client as dbsyncclient
from dcdbsync.dbsyncclient import exceptions as dbsync_exceptions from dcdbsync.dbsyncclient import exceptions as dbsync_exceptions
from dcorch.common import consts from dcorch.common import consts
@ -94,7 +95,7 @@ class IdentitySyncThread(SyncThread):
if (not self.sc_ks_client and self.sc_admin_session): if (not self.sc_ks_client and self.sc_admin_session):
self.sc_ks_client = keystoneclient.Client( self.sc_ks_client = keystoneclient.Client(
session=self.sc_admin_session, session=self.sc_admin_session,
endpoint_type=consts.KS_ENDPOINT_ADMIN, endpoint_type=dccommon_consts.KS_ENDPOINT_ADMIN,
region_name=self.subcloud_engine.subcloud.region_name) region_name=self.subcloud_engine.subcloud.region_name)
# create a dbsync client for the subcloud # create a dbsync client for the subcloud
if (not self.sc_dbs_client and self.sc_admin_session): if (not self.sc_dbs_client and self.sc_admin_session):
@ -231,7 +232,7 @@ class IdentitySyncThread(SyncThread):
if not m_users: if not m_users:
LOG.error("No users returned from {}". LOG.error("No users returned from {}".
format(consts.VIRTUAL_MASTER_CLOUD)) format(dccommon_consts.VIRTUAL_MASTER_CLOUD))
raise exceptions.SyncRequestFailed raise exceptions.SyncRequestFailed
# get users from the subcloud # get users from the subcloud
@ -251,7 +252,7 @@ class IdentitySyncThread(SyncThread):
if not m_projects: if not m_projects:
LOG.error("No projects returned from {}". LOG.error("No projects returned from {}".
format(consts.VIRTUAL_MASTER_CLOUD)) format(dccommon_consts.VIRTUAL_MASTER_CLOUD))
raise exceptions.SyncRequestFailed raise exceptions.SyncRequestFailed
# get projects from the subcloud # get projects from the subcloud
@ -1485,7 +1486,8 @@ class IdentitySyncThread(SyncThread):
self.m_ks_client) self.m_ks_client)
except dbsync_exceptions.Unauthorized as e: except dbsync_exceptions.Unauthorized as e:
LOG.info("Get resource [{}] request failed for {}: {}." LOG.info("Get resource [{}] request failed for {}: {}."
.format(resource_type, consts.VIRTUAL_MASTER_CLOUD, .format(resource_type,
dccommon_consts.VIRTUAL_MASTER_CLOUD,
str(e)), extra=self.log_extra) str(e)), extra=self.log_extra)
# In case of token expires, re-authenticate and retry once # In case of token expires, re-authenticate and retry once
self.reinitialize_m_clients() self.reinitialize_m_clients()

View File

@ -20,6 +20,7 @@ from neutronclient.neutron import client as neutronclient
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from dccommon import consts as dccommon_consts
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.drivers.openstack import sdk from dcorch.drivers.openstack import sdk
@ -61,7 +62,7 @@ class NetworkSyncThread(SyncThread):
if (not self.sc_neutron_client and self.sc_admin_session): if (not self.sc_neutron_client and self.sc_admin_session):
self.sc_neutron_client = neutronclient.Client( self.sc_neutron_client = neutronclient.Client(
"2.0", session=self.sc_admin_session, "2.0", session=self.sc_admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=self.subcloud_engine.subcloud.region_name) region_name=self.subcloud_engine.subcloud.region_name)
def initialize(self): def initialize(self):
@ -72,8 +73,8 @@ class NetworkSyncThread(SyncThread):
super(NetworkSyncThread, self).initialize() super(NetworkSyncThread, self).initialize()
self.m_neutron_client = neutronclient.Client( self.m_neutron_client = neutronclient.Client(
"2.0", session=self.admin_session, "2.0", session=self.admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=consts.VIRTUAL_MASTER_CLOUD) region_name=dccommon_consts.VIRTUAL_MASTER_CLOUD)
self.initialize_sc_clients() self.initialize_sc_clients()
LOG.info("session and clients initialized", extra=self.log_extra) LOG.info("session and clients initialized", extra=self.log_extra)

View File

@ -1,4 +1,4 @@
# Copyright 2017-2018 Wind River # Copyright 2017-2020 Wind River
# #
# 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.
@ -19,9 +19,12 @@ from requests_toolbelt import MultipartDecoder
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack import sdk_platform as sdk
from dccommon import exceptions as dccommon_exceptions
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.drivers.openstack import sdk_platform as sdk
from dcorch.engine.fernet_key_manager import FERNET_REPO_MASTER_ID from dcorch.engine.fernet_key_manager import FERNET_REPO_MASTER_ID
from dcorch.engine.fernet_key_manager import FernetKeyManager from dcorch.engine.fernet_key_manager import FernetKeyManager
from dcorch.engine.sync_thread import AUDIT_RESOURCE_EXTRA from dcorch.engine.sync_thread import AUDIT_RESOURCE_EXTRA
@ -210,7 +213,7 @@ class SysinvSyncThread(SyncThread):
try: try:
s_os_client.sysinv_client.snmp_trapdest_delete( s_os_client.sysinv_client.snmp_trapdest_delete(
subcloud_rsrc.subcloud_resource_id) subcloud_rsrc.subcloud_resource_id)
except exceptions.TrapDestNotFound: except dccommon_exceptions.TrapDestNotFound:
# SNMP trapdest already deleted in subcloud, carry on. # SNMP trapdest already deleted in subcloud, carry on.
LOG.info("SNMP trapdest not in subcloud, may be already deleted", LOG.info("SNMP trapdest not in subcloud, may be already deleted",
extra=self.log_extra) extra=self.log_extra)
@ -277,7 +280,7 @@ class SysinvSyncThread(SyncThread):
try: try:
s_os_client.sysinv_client.snmp_community_delete( s_os_client.sysinv_client.snmp_community_delete(
subcloud_rsrc.subcloud_resource_id) subcloud_rsrc.subcloud_resource_id)
except exceptions.CommunityNotFound: except dccommon_exceptions.CommunityNotFound:
# Community already deleted in subcloud, carry on. # Community already deleted in subcloud, carry on.
LOG.info("SNMP community not in subcloud, may be already deleted", LOG.info("SNMP community not in subcloud, may be already deleted",
extra=self.log_extra) extra=self.log_extra)
@ -397,11 +400,11 @@ class SysinvSyncThread(SyncThread):
cert_to_delete = certificate cert_to_delete = certificate
break break
if not cert_to_delete: if not cert_to_delete:
raise exceptions.CertificateNotFound( raise dccommon_exceptions.CertificateNotFound(
region_name=self.subcloud_engine.subcloud.region_name, region_name=self.subcloud_engine.subcloud.region_name,
signature=subcloud_rsrc.subcloud_resource_id) signature=subcloud_rsrc.subcloud_resource_id)
s_os_client.sysinv_client.delete_certificate(cert_to_delete) s_os_client.sysinv_client.delete_certificate(cert_to_delete)
except exceptions.CertificateNotFound: except dccommon_exceptions.CertificateNotFound:
# Certificate already deleted in subcloud, carry on. # Certificate already deleted in subcloud, carry on.
LOG.info("Certificate not in subcloud, may be already deleted", LOG.info("Certificate not in subcloud, may be already deleted",
extra=self.log_extra) extra=self.log_extra)
@ -564,8 +567,9 @@ class SysinvSyncThread(SyncThread):
# SysInv Audit Related # SysInv Audit Related
def get_master_resources(self, resource_type): def get_master_resources(self, resource_type):
try: try:
os_client = sdk.OpenStackDriver(region_name=consts.CLOUD_0, os_client = sdk.OpenStackDriver(
thread_name=self.audit_thread.name) region_name=dccommon_consts.CLOUD_0,
thread_name=self.audit_thread.name)
if resource_type == consts.RESOURCE_TYPE_SYSINV_DNS: if resource_type == consts.RESOURCE_TYPE_SYSINV_DNS:
return [self.get_dns_resource(os_client)] return [self.get_dns_resource(os_client)]
elif resource_type == consts.RESOURCE_TYPE_SYSINV_SNMP_COMM: elif resource_type == consts.RESOURCE_TYPE_SYSINV_SNMP_COMM:
@ -631,10 +635,11 @@ class SysinvSyncThread(SyncThread):
return None return None
def post_audit(self): def post_audit(self):
super(SysinvSyncThread, self).post_audit()
sdk.OpenStackDriver.delete_region_clients_for_thread( sdk.OpenStackDriver.delete_region_clients_for_thread(
self.region_name, self.audit_thread.name) self.region_name, self.audit_thread.name)
sdk.OpenStackDriver.delete_region_clients_for_thread( sdk.OpenStackDriver.delete_region_clients_for_thread(
consts.CLOUD_0, self.audit_thread.name) dccommon_consts.CLOUD_0, self.audit_thread.name)
def get_dns_resource(self, os_client): def get_dns_resource(self, os_client):
return os_client.sysinv_client.get_dns() return os_client.sysinv_client.get_dns()

View File

@ -19,6 +19,7 @@ from keystoneauth1 import exceptions as keystone_exceptions
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from dccommon import consts as dccommon_consts
from dcorch.common import consts from dcorch.common import consts
from dcorch.common import exceptions from dcorch.common import exceptions
from dcorch.engine import quota_manager from dcorch.engine import quota_manager
@ -55,7 +56,7 @@ class VolumeSyncThread(SyncThread):
if (not self.sc_cinder_client and self.sc_admin_session): if (not self.sc_cinder_client and self.sc_admin_session):
self.sc_cinder_client = cinderclient.Client( self.sc_cinder_client = cinderclient.Client(
"3.0", session=self.sc_admin_session, "3.0", session=self.sc_admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=self.subcloud_engine.subcloud.region_name) region_name=self.subcloud_engine.subcloud.region_name)
def initialize(self): def initialize(self):
@ -66,8 +67,8 @@ class VolumeSyncThread(SyncThread):
super(VolumeSyncThread, self).initialize() super(VolumeSyncThread, self).initialize()
self.m_cinder_client = cinderclient.Client( self.m_cinder_client = cinderclient.Client(
"3.0", session=self.admin_session, "3.0", session=self.admin_session,
endpoint_type=consts.KS_ENDPOINT_INTERNAL, endpoint_type=dccommon_consts.KS_ENDPOINT_INTERNAL,
region_name=consts.VIRTUAL_MASTER_CLOUD) region_name=dccommon_consts.VIRTUAL_MASTER_CLOUD)
self.initialize_sc_clients() self.initialize_sc_clients()
LOG.info("session and clients initialized", extra=self.log_extra) LOG.info("session and clients initialized", extra=self.log_extra)

View File

@ -1,4 +1,4 @@
# Copyright 2017 Wind River # Copyright 2017-2020 Wind River
# #
# 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.
@ -13,11 +13,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import collections
import threading import threading
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 dccommon import consts as dccommon_consts
from dcdbsync.dbsyncclient import client as dbsyncclient from dcdbsync.dbsyncclient import client as dbsyncclient
from dcmanager.common import consts as dcmanager_consts from dcmanager.common import consts as dcmanager_consts
from dcmanager.rpc import client as dcmanager_rpc_client from dcmanager.rpc import client as dcmanager_rpc_client
@ -54,11 +57,15 @@ STATE_COMPLETED = 'completed'
AUDIT_RESOURCE_MISSING = 'missing' AUDIT_RESOURCE_MISSING = 'missing'
AUDIT_RESOURCE_EXTRA = 'extra_resource' AUDIT_RESOURCE_EXTRA = 'extra_resource'
AUDIT_LOCK_NAME = 'dcorch-audit'
class SyncThread(object): class SyncThread(object):
"""Manages tasks related to resource management.""" """Manages tasks related to resource management."""
MAX_RETRY = 2 MAX_RETRY = 2
# used by the audit to cache the master resources
master_resources_dict = collections.defaultdict(dict)
def __init__(self, subcloud_engine, endpoint_type=None): def __init__(self, subcloud_engine, endpoint_type=None):
super(SyncThread, self).__init__() super(SyncThread, self).__init__()
@ -71,7 +78,7 @@ class SyncThread(object):
self.condition = threading.Condition() # used to wake up the thread self.condition = threading.Condition() # used to wake up the thread
self.ctxt = context.get_admin_context() self.ctxt = context.get_admin_context()
self.sync_handler_map = {} self.sync_handler_map = {}
self.master_region_name = consts.CLOUD_0 self.master_region_name = dccommon_consts.CLOUD_0
self.audit_resources = [] self.audit_resources = []
self.log_extra = { self.log_extra = {
@ -122,7 +129,7 @@ class SyncThread(object):
config = None config = None
if self.endpoint_type in consts.ENDPOINT_TYPES_LIST: if self.endpoint_type in consts.ENDPOINT_TYPES_LIST:
config = cfg.CONF.cache config = cfg.CONF.cache
elif self.endpoint_type in consts.ENDPOINT_TYPES_LIST_OS: elif self.endpoint_type in dccommon_consts.ENDPOINT_TYPES_LIST_OS:
config = cfg.CONF.openstack_cache config = cfg.CONF.openstack_cache
else: else:
raise exceptions.EndpointNotSupported( raise exceptions.EndpointNotSupported(
@ -136,16 +143,18 @@ class SyncThread(object):
project_domain_name=config.admin_project_domain_name, project_domain_name=config.admin_project_domain_name,
user_domain_name=config.admin_user_domain_name) user_domain_name=config.admin_user_domain_name)
self.admin_session = session.Session( self.admin_session = session.Session(
auth=auth, timeout=60, additional_headers=consts.USER_HEADER) auth=auth, timeout=60,
additional_headers=dccommon_consts.USER_HEADER)
# keystone client # keystone client
self.ks_client = keystoneclient.Client( self.ks_client = keystoneclient.Client(
session=self.admin_session, session=self.admin_session,
region_name=consts.CLOUD_0) region_name=dccommon_consts.CLOUD_0)
# dcdbsync client # dcdbsync client
self.dbs_client = dbsyncclient.Client( self.dbs_client = dbsyncclient.Client(
endpoint_type=consts.DBS_ENDPOINT_INTERNAL, endpoint_type=consts.DBS_ENDPOINT_INTERNAL,
session=self.admin_session, session=self.admin_session,
region_name=consts.CLOUD_0) region_name=dccommon_consts.CLOUD_0)
def initialize_sc_clients(self): def initialize_sc_clients(self):
# base implementation of initializing the subcloud specific # base implementation of initializing the subcloud specific
@ -158,7 +167,7 @@ class SyncThread(object):
name='keystone', type='identity') name='keystone', type='identity')
sc_auth_url = self.ks_client.endpoints.list( sc_auth_url = self.ks_client.endpoints.list(
service=identity_service[0].id, service=identity_service[0].id,
interface=consts.KS_ENDPOINT_ADMIN, interface=dccommon_consts.KS_ENDPOINT_ADMIN,
region=self.subcloud_engine.subcloud.region_name) region=self.subcloud_engine.subcloud.region_name)
try: try:
LOG.info("Found sc_auth_url: {}".format(sc_auth_url)) LOG.info("Found sc_auth_url: {}".format(sc_auth_url))
@ -175,7 +184,7 @@ class SyncThread(object):
config = None config = None
if self.endpoint_type in consts.ENDPOINT_TYPES_LIST: if self.endpoint_type in consts.ENDPOINT_TYPES_LIST:
config = cfg.CONF.cache config = cfg.CONF.cache
elif self.endpoint_type in consts.ENDPOINT_TYPES_LIST_OS: elif self.endpoint_type in dccommon_consts.ENDPOINT_TYPES_LIST_OS:
config = cfg.CONF.openstack_cache config = cfg.CONF.openstack_cache
sc_auth = loader.load_from_options( sc_auth = loader.load_from_options(
@ -188,7 +197,7 @@ class SyncThread(object):
self.sc_admin_session = session.Session( self.sc_admin_session = session.Session(
auth=sc_auth, timeout=60, auth=sc_auth, timeout=60,
additional_headers=consts.USER_HEADER) additional_headers=dccommon_consts.USER_HEADER)
def initial_sync(self): def initial_sync(self):
# Return True to indicate initial sync success # Return True to indicate initial sync success
@ -487,9 +496,12 @@ class SyncThread(object):
extra=self.log_extra) extra=self.log_extra)
self.post_audit() self.post_audit()
@lockutils.synchronized(AUDIT_LOCK_NAME)
def post_audit(self): def post_audit(self):
# The specific SyncThread subclasses may perform post audit actions # reset the cached master resources
return SyncThread.master_resources_dict = collections.defaultdict(dict)
# The specific SyncThread subclasses may perform additional post
# audit actions
def audit_find_missing(self, resource_type, m_resources, def audit_find_missing(self, resource_type, m_resources,
db_resources, sc_resources, db_resources, sc_resources,
@ -706,12 +718,19 @@ class SyncThread(object):
if sc_resources is None: if sc_resources is None:
return m_resources, db_resources, sc_resources return m_resources, db_resources, sc_resources
db_resources = self.get_db_master_resources(resource_type) db_resources = self.get_db_master_resources(resource_type)
# todo: master resources will be read by multiple threads m_resources = self.get_cached_master_resources(resource_type)
# depending on the number of subclouds. Could do some kind of
# caching for performance improvement.
m_resources = self.get_master_resources(resource_type)
return m_resources, db_resources, sc_resources return m_resources, db_resources, sc_resources
@lockutils.synchronized(AUDIT_LOCK_NAME)
def get_cached_master_resources(self, resource_type):
if resource_type in SyncThread.master_resources_dict:
m_resources = SyncThread.master_resources_dict[resource_type]
else:
m_resources = self.get_master_resources(resource_type)
if m_resources is not None:
SyncThread.master_resources_dict[resource_type] = m_resources
return m_resources
def get_subcloud_resources(self, resource_type): def get_subcloud_resources(self, resource_type):
return None return None

View File

@ -15,7 +15,7 @@
import collections import collections
import datetime import datetime
from dcorch.common import consts from dccommon import consts as dccommon_consts
from dcorch.common import context from dcorch.common import context
from dcorch.rpc import client as rpc_client from dcorch.rpc import client as rpc_client
from multiprocessing import Queue from multiprocessing import Queue
@ -57,7 +57,7 @@ class Controller(object):
self.system_trap_tstamps[system] = collections.deque() self.system_trap_tstamps[system] = collections.deque()
def handle_trap(self, system, msg): def handle_trap(self, system, msg):
if system == consts.CLOUD_0: if system == dccommon_consts.CLOUD_0:
return return
if not (system in self.system_last_updates): if not (system in self.system_last_updates):
self._add_system(system) self._add_system(system)

View File

@ -21,6 +21,7 @@ classifier =
[files] [files]
packages = packages =
dccommon
dcmanager dcmanager
dcorch dcorch
dcdbsync dcdbsync

View File

@ -181,7 +181,7 @@ deps = {[testenv:py27]deps}
-e{[dc]cgcs_patch_src_dir} -e{[dc]cgcs_patch_src_dir}
commands = commands =
pylint {posargs} dcmanager dcorch dcdbsync --rcfile=./pylint.rc pylint {posargs} dccommon dcmanager dcorch dcdbsync --rcfile=./pylint.rc
[testenv:linters] [testenv:linters]
basepython = python3 basepython = python3