Add dcmanager client driver support

Add dcmanager client driver to access the peer site dcmanager API

Test Plan:
1. PASS - Verify get subcloud and subcloud list,
          get subcloud peer group and list
2. PASS - Verify add subcloud and add subcloud peer group
3. PASS - Verify delete subcloud and delete subcloud peer group

Call example:
p_ks_client = PeerSiteDriver(
        auth_url=peer.manager_endpoint,
        username=peer.manager_username,
        password=base64.b64decode(
            peer.manager_password.encode("utf-8")).decode("utf-8"),
        site_uuid=peer.peer_uuid)
dc_endpoint = p_ks_client.session.get_endpoint(
        service_type='dcmanager',
        region_name=dccommon_consts.SYSTEM_CONTROLLER_NAME,
        interface=dccommon_consts.KS_ENDPOINT_PUBLIC)
dc_client = DcmanagerClient(dccommon_consts.SYSTEM_CONTROLLER_NAME,
                            p_ks_client.session,
                            endpoint=dc_endpoint)
dc_client.get_subcloud('subcloud1')

Story: 2010852
Task: 48679
Change-Id: I7cdd773ee1238c1e61b5e5d8753ffea9416fcd91
Signed-off-by: Zhang Rong(Jon) <rong.zhang@windriver.com>
This commit is contained in:
Zhang Rong(Jon) 2023-08-22 17:44:36 +08:00
parent 35d473c04d
commit fe1045afce
5 changed files with 890 additions and 0 deletions

View File

@ -16,8 +16,13 @@ SECONDS_IN_HOUR = 3600
KS_ENDPOINT_ADMIN = "admin"
KS_ENDPOINT_INTERNAL = "internal"
KS_ENDPOINT_PUBLIC = "public"
KS_ENDPOINT_DEFAULT = KS_ENDPOINT_ADMIN
KS_ENDPOINT_USER_DOMAIN_DEFAULT = "Default"
KS_ENDPOINT_PROJECT_DEFAULT = "admin"
KS_ENDPOINT_PROJECT_DOMAIN_DEFAULT = "Default"
ENDPOINT_TYPE_IDENTITY_OS = "identity_openstack"
# openstack endpoint types

View File

@ -0,0 +1,294 @@
# Copyright (c) 2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from oslo_log import log
import requests
from requests_toolbelt import MultipartEncoder
from dccommon import consts
from dccommon.drivers import base
from dccommon import exceptions
LOG = log.getLogger(__name__)
DCMANAGER_CLIENT_REST_DEFAULT_TIMEOUT = 600
class DcmanagerClient(base.DriverBase):
"""Dcmanager V1 driver."""
def __init__(self, region, session,
timeout=DCMANAGER_CLIENT_REST_DEFAULT_TIMEOUT,
endpoint_type=consts.KS_ENDPOINT_PUBLIC,
endpoint=None):
if endpoint is None:
endpoint = session.get_endpoint(
service_type='dcmanager',
region_name=region,
interface=endpoint_type)
self.endpoint = endpoint
self.token = session.get_token()
self.timeout = timeout
def get_subcloud(self, subcloud_ref):
"""Get subcloud."""
if subcloud_ref is None:
raise ValueError("subcloud_ref is required.")
url = f"{self.endpoint}/subclouds/{subcloud_ref}"
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud not found' in response.text:
raise exceptions.SubcloudNotFound(subcloud_ref=subcloud_ref)
message = "Get Subcloud: subcloud_ref %s failed with RC: %d" % \
(subcloud_ref, response.status_code)
LOG.error(message)
raise Exception(message)
def get_subcloud_list(self):
"""Get subcloud list."""
url = self.endpoint + '/subclouds'
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
data = response.json()
return data.get('subclouds', [])
else:
message = "Get Subcloud list failed with RC: %d" % \
response.status_code
LOG.error(message)
raise Exception(message)
def get_subcloud_group_list(self):
"""Get subcloud group list."""
url = self.endpoint + '/subcloud-groups'
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
data = response.json()
return data.get('subcloud_groups', [])
else:
message = "Get Subcloud Group list: failed with RC: %d" % \
response.status_code
LOG.error(message)
raise Exception(message)
def get_subcloud_peer_group_list(self):
"""Get subcloud peer group list."""
url = self.endpoint + '/subcloud-peer-groups'
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
data = response.json()
return data.get('subcloud_peer_groups', [])
else:
message = "Get Subcloud Peer Group list: failed with RC: %d" % \
response.status_code
LOG.error(message)
raise Exception(message)
def get_subcloud_peer_group(self, peer_group_ref):
"""Get subcloud peer group."""
if peer_group_ref is None:
raise ValueError("peer_group_ref is required.")
url = f"{self.endpoint}/subcloud-peer-groups/{peer_group_ref}"
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud Peer Group not found' in response.text:
raise exceptions.SubcloudPeerGroupNotFound(
peer_group_ref=peer_group_ref)
message = "Get Subcloud Peer Group: peer_group_ref %s " \
"failed with RC: %d" % (peer_group_ref, response.status_code)
LOG.error(message)
raise Exception(message)
def get_subcloud_list_by_peer_group(self, peer_group_ref):
"""Get subclouds in the specified subcloud peer group."""
if peer_group_ref is None:
raise ValueError("peer_group_ref is required.")
url = f"{self.endpoint}/subcloud-peer-groups/{peer_group_ref}/" \
"subclouds"
headers = {"X-Auth-Token": self.token}
response = requests.get(url, headers=headers, timeout=self.timeout)
if response.status_code == 200:
data = response.json()
return data.get('subclouds', [])
else:
if response.status_code == 404 and \
'Subcloud Peer Group not found' in response.text:
raise exceptions.SubcloudPeerGroupNotFound(
peer_group_ref=peer_group_ref)
message = "Get Subcloud list by Peer Group: peer_group_ref %s " \
"failed with RC: %d" % (peer_group_ref, response.status_code)
LOG.error(message)
raise Exception(message)
def add_subcloud_peer_group(self, **kwargs):
"""Add a subcloud peer group."""
url = self.endpoint + '/subcloud-peer-groups'
headers = {"X-Auth-Token": self.token,
"Content-Type": "application/json"}
response = requests.post(url, json=kwargs, headers=headers,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
message = "Add Subcloud Peer Group: %s, failed with RC: %d" % \
(kwargs, response.status_code)
LOG.error(message)
raise Exception(message)
def add_subcloud_with_secondary_status(self, files, data):
"""Add a subcloud with secondary status."""
url = self.endpoint + '/subclouds'
# If not explicitly specified, set 'secondary' to true by default.
# This action adds a secondary subcloud with rehoming data in the
# peer site without creating an actual subcloud.
if 'secondary' in data and data['secondary'] != "true":
raise ValueError("secondary in data must true.")
data['secondary'] = "true"
fields = dict()
if files is not None:
# If files are specified, add them to the fields.
for k, v in files.items():
fields.update({k: (v, open(v, 'rb'),)})
fields.update(data)
enc = MultipartEncoder(fields=fields)
headers = {"X-Auth-Token": self.token,
"Content-Type": enc.content_type}
response = requests.post(url, headers=headers, data=enc,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
message = "Add Subcloud with secondary status: files: %s, " \
"data: %s, failed with RC: %d" % (files, data,
response.status_code)
LOG.error(message)
raise Exception(message)
def update_subcloud_peer_group(self, peer_group_ref, **kwargs):
"""Update the subcloud peer group."""
if peer_group_ref is None:
raise ValueError("peer_group_ref is required.")
url = f"{self.endpoint}/subcloud-peer-groups/{peer_group_ref}"
headers = {"X-Auth-Token": self.token,
"Content-Type": "application/json"}
response = requests.patch(url, json=kwargs, headers=headers,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud Peer Group not found' in response.text:
raise exceptions.SubcloudPeerGroupNotFound(
peer_group_ref=peer_group_ref)
message = "Update Subcloud Peer Group: peer_group_ref %s, %s, " \
"failed with RC: %d" % (peer_group_ref, kwargs,
response.status_code)
LOG.error(message)
raise Exception(message)
def update_subcloud(self, subcloud_ref, files, data):
"""Update the subcloud."""
if subcloud_ref is None:
raise ValueError("subcloud_ref is required.")
url = f"{self.endpoint}/subclouds/{subcloud_ref}"
fields = dict()
if files is not None:
# If files are specified, add them to the fields.
for k, v in files.items():
fields.update({k: (v, open(v, 'rb'),)})
fields.update(data)
enc = MultipartEncoder(fields=fields)
headers = {"X-Auth-Token": self.token,
"Content-Type": enc.content_type}
response = requests.patch(url, headers=headers, data=enc,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud not found' in response.text:
raise exceptions.SubcloudNotFound(subcloud_ref=subcloud_ref)
message = "Update Subcloud: subcloud_ref: %s files: %s, " \
"data: %s, failed with RC: %d" % (subcloud_ref, files, data,
response.status_code)
LOG.error(message)
raise Exception(message)
def delete_subcloud_peer_group(self, peer_group_ref):
"""Delete the subcloud peer group."""
if peer_group_ref is None:
raise ValueError("peer_group_ref is required.")
url = f"{self.endpoint}/subcloud-peer-groups/{peer_group_ref}"
headers = {"X-Auth-Token": self.token}
response = requests.delete(url, headers=headers,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud Peer Group not found' in response.text:
raise exceptions.SubcloudPeerGroupNotFound(
peer_group_ref=peer_group_ref)
message = "Delete Subcloud Peer Group: peer_group_ref %s " \
"failed with RC: %d" % (peer_group_ref, response.status_code)
LOG.error(message)
raise Exception(message)
def delete_subcloud(self, subcloud_ref):
"""Delete the subcloud."""
if subcloud_ref is None:
raise ValueError("subcloud_ref is required.")
url = f"{self.endpoint}/subclouds/{subcloud_ref}"
headers = {"X-Auth-Token": self.token}
response = requests.delete(url, headers=headers,
timeout=self.timeout)
if response.status_code == 200:
return response.json()
else:
if response.status_code == 404 and \
'Subcloud not found' in response.text:
raise exceptions.SubcloudNotFound(subcloud_ref=subcloud_ref)
message = "Delete Subcloud: subcloud_ref %s failed with RC: %d" % \
(subcloud_ref, response.status_code)
LOG.error(message)
raise Exception(message)

View File

@ -0,0 +1,198 @@
# Copyright (c) 2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
"""
Peer Site OpenStack Driver
"""
import collections
import threading
from keystoneauth1 import loading
from keystoneauth1 import session
from keystoneclient.v3 import client as ks_client
from oslo_concurrency import lockutils
from oslo_log import log
from dccommon import consts
from dccommon.drivers import base
from dccommon import exceptions
from dccommon.utils import is_token_expiring_soon
LOG = log.getLogger(__name__)
LOCK_NAME = 'dc-openstackdriver-peer'
KEYSTONE_CLIENT_NAME = 'keystone'
AUTH_PLUGIN_PASSWORD = 'password'
HTTP_CONNECT_TIMEOUT = 10
class PeerSiteDriver(object):
os_clients_dict = collections.defaultdict(dict)
_identity_tokens = {}
def __init__(self, site_uuid, auth_url, username, password,
region_name=consts.CLOUD_0,
endpoint_type=consts.KS_ENDPOINT_PUBLIC):
if not (site_uuid and auth_url and username and password):
raise exceptions.InvalidInputError
self.site_uuid = site_uuid
self.auth_url = auth_url
self.username = username
self.password = password
self.region_name = region_name
self.endpoint_type = endpoint_type
# Check if objects are cached and try to use those
self.keystone_client = self.get_cached_keystone_client(site_uuid)
if self.keystone_client is None:
LOG.debug("No cached keystone client found. Creating new keystone "
"client for peer site %s", site_uuid)
try:
# Create the keystone client for this site with the provided
# username and password and auth_url.
self.keystone_client = PeerKeystoneClient(
auth_url, username, password,
region_name=region_name,
auth_type=endpoint_type)
except Exception as exception:
LOG.error('peer site %s keystone_client error: %s' %
(site_uuid, str(exception)))
raise exception
# Cache the client object
PeerSiteDriver.update_site_clients(site_uuid,
KEYSTONE_CLIENT_NAME,
self.keystone_client)
@lockutils.synchronized(LOCK_NAME)
def get_cached_keystone_client(self, site_uuid):
if ((site_uuid in PeerSiteDriver.os_clients_dict) and
self._is_token_valid(site_uuid)):
return (PeerSiteDriver.os_clients_dict[site_uuid][
KEYSTONE_CLIENT_NAME])
@classmethod
@lockutils.synchronized(LOCK_NAME)
def update_site_clients(cls, site_uuid, client_name, client_object):
cls.os_clients_dict[site_uuid][client_name] = client_object
@classmethod
@lockutils.synchronized(LOCK_NAME)
def delete_site_clients(cls, site_uuid, clear_token=False):
LOG.warn("delete_site_clients=%s, clear_token=%s" %
(site_uuid, clear_token))
if site_uuid in cls.os_clients_dict:
del cls.os_clients_dict[site_uuid]
if clear_token:
cls._identity_tokens[site_uuid] = None
def _is_token_valid(self, site_uuid):
try:
keystone = PeerSiteDriver.os_clients_dict[site_uuid][
KEYSTONE_CLIENT_NAME].keystone_client
if (not PeerSiteDriver._identity_tokens
or site_uuid not in PeerSiteDriver._identity_tokens
or not PeerSiteDriver._identity_tokens[site_uuid]):
PeerSiteDriver._identity_tokens[site_uuid] = \
keystone.tokens.validate(keystone.session.get_token(),
include_catalog=False)
LOG.info("Token for peer site %s expires_at=%s" %
(site_uuid,
PeerSiteDriver._identity_tokens[site_uuid]
['expires_at']))
except Exception as exception:
LOG.warn('_is_token_valid handle: site: %s error: %s' %
(site_uuid, str(exception)))
# Reset the cached dictionary
PeerSiteDriver.os_clients_dict[site_uuid] = \
collections.defaultdict(dict)
PeerSiteDriver._identity_tokens[site_uuid] = None
return False
token_expiring_soon = is_token_expiring_soon(
token=self._identity_tokens[site_uuid])
# If token is expiring soon, reset cached dictionaries and return False.
# Else return true.
if token_expiring_soon:
LOG.info("The cached keystone token for peer site %s "
"will expire soon %s" %
(site_uuid,
PeerSiteDriver._identity_tokens[site_uuid]
['expires_at']))
# Reset the cached dictionary
PeerSiteDriver.os_clients_dict[site_uuid] = \
collections.defaultdict(dict)
PeerSiteDriver._identity_tokens[site_uuid] = None
return False
else:
return True
class PeerKeystoneClient(base.DriverBase):
"""Peer Site Keystone V3 driver."""
plugin_loader = None
plugin_lock = threading.Lock()
def __init__(self, auth_url, username, password,
region_name=consts.CLOUD_0,
project_name=consts.KS_ENDPOINT_PROJECT_DEFAULT,
project_domain_name=consts.KS_ENDPOINT_PROJECT_DOMAIN_DEFAULT,
user_domain_name=consts.KS_ENDPOINT_USER_DOMAIN_DEFAULT,
auth_type=consts.KS_ENDPOINT_PUBLIC):
if not (auth_url and username and password):
raise exceptions.InvalidInputError
self.auth_url = auth_url
self.username = username
self.password = password
self.auth_type = auth_type
self.region_name = region_name
self.project_name = project_name
self.project_domain_name = project_domain_name
self.user_domain_name = user_domain_name
self.session = PeerKeystoneClient.get_admin_session(
self.auth_url,
self.username,
self.user_domain_name,
self.password,
self.project_name,
self.project_domain_name)
self.keystone_client = self._create_keystone_client()
@classmethod
def get_admin_session(cls, auth_url, user_name, user_domain_name,
user_password, user_project, user_project_domain,
timeout=None):
with PeerKeystoneClient.plugin_lock:
if PeerKeystoneClient.plugin_loader is None:
PeerKeystoneClient.plugin_loader = loading.get_plugin_loader(
AUTH_PLUGIN_PASSWORD)
user_auth = PeerKeystoneClient.plugin_loader.load_from_options(
auth_url=auth_url,
username=user_name,
user_domain_name=user_domain_name,
password=user_password,
project_name=user_project,
project_domain_name=user_project_domain,
)
timeout = (HTTP_CONNECT_TIMEOUT if timeout is None else timeout)
return session.Session(
auth=user_auth, additional_headers=consts.USER_HEADER,
timeout=timeout)
def _create_keystone_client(self):
client_kwargs = {
'session': self.session,
'region_name': self.region_name,
'interface': self.auth_type
}
return ks_client.Client(**client_kwargs)

View File

@ -127,3 +127,11 @@ class SubcloudShutdownError(PlaybookExecutionFailed):
class ApiException(DCCommonException):
message = _("%(endpoint)s failed with status code: %(rc)d")
class SubcloudNotFound(NotFound):
message = _("Subcloud %(subcloud_ref)s not found")
class SubcloudPeerGroupNotFound(NotFound):
message = _("Subcloud Peer Group %(peer_group_ref)s not found")

View File

@ -0,0 +1,385 @@
# Copyright (c) 2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import mock
import os
import uuid
import yaml
from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack import dcmanager_v1
from dccommon import exceptions as dccommon_exceptions
from dccommon.tests import base
FAKE_ID = '1'
SUBCLOUD_NAME = 'Subcloud1'
SUBCLOUD_BOOTSTRAP_ADDRESS = '192.168.0.10'
SUBCLOUD_BOOTSTRAP_VALUE_PATH = '/tmp/test_subcloud_bootstrap_value.yaml'
SUBCLOUD_GROUP_NAME = 'SubcloudGroup1'
SYSTEM_PEER_UUID = str(uuid.uuid4())
SYSTEM_PEER_NAME = 'SystemPeer1'
SUBCLOUD_PEER_GROUP_ID = 1
SUBCLOUD_PEER_GROUP_NAME = 'SubcloudPeerGroup1'
FAKE_ENDPOINT = 'http://128.128.1.1:8119/v1.0'
FAKE_TOKEN = 'token'
FAKE_TIMEOUT = 600
FAKE_SUBCLOUD_DATA = {"id": FAKE_ID,
"name": SUBCLOUD_NAME,
"description": "subcloud1 description",
"location": "subcloud1 location",
"software-version": "22.12",
"management-state": "managed",
"deploy-status": "complete",
"management-subnet": "192.168.101.0/24",
"management-start-ip": "192.168.101.2",
"management-end-ip": "192.168.101.50",
"management-gateway-ip": "192.168.101.1",
"systemcontroller-gateway-ip": "192.168.204.101",
"group-id": 1,
"peer-group-id": SUBCLOUD_PEER_GROUP_ID,
"rehome-data": "null",
"availability-status": "disabled"}
FAKE_SUBCLOUD_PEER_GROUP_DATA = {
"id": SUBCLOUD_PEER_GROUP_ID,
"peer-group-name": SUBCLOUD_PEER_GROUP_NAME,
"system-leader-id": SYSTEM_PEER_UUID,
"system-leader-name": SYSTEM_PEER_NAME,
"max-subcloud-rehoming": 1,
"group-state": "enabled",
"group-priority": 1
}
class TestDcmanagerClient(base.DCCommonTestCase):
def setUp(self):
super(TestDcmanagerClient, self).setUp()
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = FAKE_SUBCLOUD_DATA
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_subcloud = client.get_subcloud(SUBCLOUD_NAME)
self.assertEqual(SUBCLOUD_NAME, actual_subcloud.get('name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_not_found(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 404
mock_response.text = "Subcloud not found"
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
self.assertRaises(dccommon_exceptions.SubcloudNotFound,
client.get_subcloud, SUBCLOUD_NAME)
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_list(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"subclouds": [FAKE_SUBCLOUD_DATA]}
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_subclouds = client.get_subcloud_list()
self.assertEqual(1, len(actual_subclouds))
self.assertEqual(SUBCLOUD_NAME, actual_subclouds[0].get('name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_group_list(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"subcloud_groups": [{"name": SUBCLOUD_GROUP_NAME}]}
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_subcloud_groups = client.get_subcloud_group_list()
self.assertEqual(1, len(actual_subcloud_groups))
self.assertEqual(SUBCLOUD_GROUP_NAME,
actual_subcloud_groups[0].get('name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_peer_group_list(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"subcloud_peer_groups": [FAKE_SUBCLOUD_PEER_GROUP_DATA]}
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_peer_group = client.get_subcloud_peer_group_list()
self.assertEqual(1, len(actual_peer_group))
self.assertEqual(SUBCLOUD_PEER_GROUP_NAME,
actual_peer_group[0].get('peer-group-name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_peer_group(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = FAKE_SUBCLOUD_PEER_GROUP_DATA
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_peer_group = client.get_subcloud_peer_group(
SUBCLOUD_PEER_GROUP_NAME)
self.assertEqual(SUBCLOUD_PEER_GROUP_NAME,
actual_peer_group.get('peer-group-name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_peer_group_not_found(
self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 404
mock_response.text = "Subcloud Peer Group not found"
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
self.assertRaises(dccommon_exceptions.SubcloudPeerGroupNotFound,
client.get_subcloud_peer_group,
SUBCLOUD_PEER_GROUP_NAME)
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_list_by_peer_group(self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"subclouds": [FAKE_SUBCLOUD_DATA]}
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_subclouds = client.get_subcloud_list_by_peer_group(
SUBCLOUD_PEER_GROUP_NAME)
self.assertEqual(1, len(actual_subclouds))
self.assertEqual(SUBCLOUD_NAME, actual_subclouds[0].get('name'))
@mock.patch('requests.get')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_get_subcloud_list_by_peer_group_not_found(
self, mock_client_init, mock_get):
mock_response = mock.MagicMock()
mock_response.status_code = 404
mock_response.text = "Subcloud Peer Group not found"
mock_get.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
self.assertRaises(dccommon_exceptions.SubcloudPeerGroupNotFound,
client.get_subcloud_list_by_peer_group,
SUBCLOUD_PEER_GROUP_NAME)
@mock.patch('requests.post')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_add_subcloud_peer_group(self, mock_client_init, mock_post):
peer_group_kwargs = {
'peer-group-name': SUBCLOUD_PEER_GROUP_NAME
}
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = FAKE_SUBCLOUD_PEER_GROUP_DATA
mock_post.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
actual_peer_group = client.add_subcloud_peer_group(
**peer_group_kwargs)
self.assertEqual(SUBCLOUD_PEER_GROUP_NAME,
actual_peer_group.get('peer-group-name'))
@mock.patch('requests.post')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_add_subcloud_with_secondary_status(self, mock_client_init,
mock_post):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = FAKE_SUBCLOUD_DATA
mock_post.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
# create the cache file for subcloud create
yaml_data = yaml.dump(FAKE_SUBCLOUD_DATA)
with open(SUBCLOUD_BOOTSTRAP_VALUE_PATH, 'w') as file:
file.write(yaml_data)
subcloud_kwargs = {
"data": {
"bootstrap-address": SUBCLOUD_BOOTSTRAP_ADDRESS
},
"files": {
"bootstrap_values": SUBCLOUD_BOOTSTRAP_VALUE_PATH
}
}
actual_subcloud = client.add_subcloud_with_secondary_status(
**subcloud_kwargs)
self.assertEqual(SUBCLOUD_NAME, actual_subcloud.get('name'))
# purge the cache file
os.remove(SUBCLOUD_BOOTSTRAP_VALUE_PATH)
@mock.patch('requests.delete')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_delete_subcloud_peer_group(self, mock_client_init, mock_delete):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = ''
mock_delete.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
result = client.delete_subcloud_peer_group(SUBCLOUD_PEER_GROUP_NAME)
mock_delete.assert_called_once_with(
FAKE_ENDPOINT + '/subcloud-peer-groups/' +
SUBCLOUD_PEER_GROUP_NAME,
headers={"X-Auth-Token": FAKE_TOKEN},
timeout=FAKE_TIMEOUT
)
self.assertEqual(result, '')
@mock.patch('requests.delete')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_delete_subcloud_peer_group_not_found(self, mock_client_init,
mock_delete):
mock_response = mock.MagicMock()
mock_response.status_code = 404
mock_response.text = "Subcloud Peer Group not found"
mock_delete.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
self.assertRaises(dccommon_exceptions.SubcloudPeerGroupNotFound,
client.delete_subcloud_peer_group,
SUBCLOUD_PEER_GROUP_NAME)
@mock.patch('requests.delete')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_delete_subcloud(self, mock_client_init, mock_delete):
mock_response = mock.MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = ''
mock_delete.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
result = client.delete_subcloud(SUBCLOUD_NAME)
mock_delete.assert_called_once_with(
FAKE_ENDPOINT + '/subclouds/' + SUBCLOUD_NAME,
headers={"X-Auth-Token": FAKE_TOKEN},
timeout=FAKE_TIMEOUT
)
self.assertEqual(result, '')
@mock.patch('requests.delete')
@mock.patch.object(dcmanager_v1.DcmanagerClient, '__init__')
def test_delete_subcloud_not_found(self, mock_client_init,
mock_delete):
mock_response = mock.MagicMock()
mock_response.status_code = 404
mock_response.text = "Subcloud not found"
mock_delete.return_value = mock_response
mock_client_init.return_value = None
client = dcmanager_v1.DcmanagerClient(
dccommon_consts.SYSTEM_CONTROLLER_NAME, None)
client.endpoint = FAKE_ENDPOINT
client.token = FAKE_TOKEN
client.timeout = FAKE_TIMEOUT
self.assertRaises(dccommon_exceptions.SubcloudNotFound,
client.delete_subcloud,
SUBCLOUD_NAME)