442 lines
18 KiB
Python
442 lines
18 KiB
Python
# 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_system_peer(self, system_peer_uuid):
|
|
"""Get system peer."""
|
|
if system_peer_uuid is None:
|
|
raise ValueError("system_peer_uuid is required.")
|
|
url = f"{self.endpoint}/system-peers/{system_peer_uuid}"
|
|
|
|
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 \
|
|
'System Peer not found' in response.text:
|
|
raise exceptions.SystemPeerNotFound(
|
|
system_peer=system_peer_uuid)
|
|
message = "Get SystemPeer: system_peer_uuid %s failed with RC: %d" \
|
|
% (system_peer_uuid, response.status_code)
|
|
LOG.error(message)
|
|
raise Exception(message)
|
|
|
|
def get_subcloud(self, subcloud_ref, is_region_name=False):
|
|
"""Get subcloud."""
|
|
if subcloud_ref is None:
|
|
raise ValueError("subcloud_ref is required.")
|
|
url = f"{self.endpoint}/subclouds/{subcloud_ref}/detail"
|
|
|
|
headers = {"X-Auth-Token": self.token}
|
|
if is_region_name:
|
|
headers["User-Agent"] = consts.DCMANAGER_V1_HTTP_AGENT
|
|
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 = f"{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 = f"{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 = f"{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 get_peer_group_association_with_peer_id_and_pg_id(self, peer_id,
|
|
pg_id):
|
|
"""Get peer group association with peer id and PG id."""
|
|
for association in self.get_peer_group_association_list():
|
|
if peer_id == association.get('system-peer-id') and \
|
|
pg_id == association.get('peer-group-id'):
|
|
return association
|
|
raise exceptions.PeerGroupAssociationNotFound(
|
|
association_id=None)
|
|
|
|
def get_peer_group_association_list(self):
|
|
"""Get peer group association list."""
|
|
url = f"{self.endpoint}/peer-group-associations"
|
|
|
|
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('peer_group_associations', [])
|
|
else:
|
|
message = "Get Peer Group Association list failed with RC: %d" % \
|
|
response.status_code
|
|
LOG.error(message)
|
|
raise Exception(message)
|
|
|
|
def add_subcloud_peer_group(self, **kwargs):
|
|
"""Add a subcloud peer group."""
|
|
url = f"{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 = f"{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 add_peer_group_association(self, **kwargs):
|
|
"""Add a peer group association."""
|
|
url = f"{self.endpoint}/peer-group-associations"
|
|
|
|
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 Peer Group Association: %s, failed with RC: %d" % \
|
|
(kwargs, response.status_code)
|
|
LOG.error(message)
|
|
raise Exception(message)
|
|
|
|
def update_peer_group_association_sync_status(self, association_id,
|
|
sync_status):
|
|
"""Update the peer group association sync_status."""
|
|
if association_id is None:
|
|
raise ValueError("association_id is required.")
|
|
url = f"{self.endpoint}/peer-group-associations/{association_id}"
|
|
update_kwargs = {"sync_status": sync_status}
|
|
|
|
headers = {"X-Auth-Token": self.token,
|
|
"Content-Type": "application/json"}
|
|
response = requests.patch(url, json=update_kwargs, headers=headers,
|
|
timeout=self.timeout)
|
|
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
if response.status_code == 404 and \
|
|
'Peer Group Association not found' in response.text:
|
|
raise exceptions.PeerGroupAssociationNotFound(
|
|
association_id=association_id)
|
|
message = "Update Peer Group Association: association_id %s, " \
|
|
"sync_status %s, failed with RC: %d" % (
|
|
association_id, sync_status, 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 audit_subcloud_peer_group(self, peer_group_ref, **kwargs):
|
|
"""Audit 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}/audit"
|
|
|
|
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 = "Audit 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, is_region_name=False):
|
|
"""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}
|
|
# Add header to flag the request is from another DC,
|
|
# server will treat subcloud_ref as a region_name
|
|
if is_region_name:
|
|
headers["User-Agent"] = consts.DCMANAGER_V1_HTTP_AGENT
|
|
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_peer_group_association(self, association_id):
|
|
"""Delete the peer group association."""
|
|
if association_id is None:
|
|
raise ValueError("association_id is required.")
|
|
url = f"{self.endpoint}/peer-group-associations/{association_id}"
|
|
|
|
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 \
|
|
'Peer Group Association not found' in response.text:
|
|
raise exceptions.PeerGroupAssociationNotFound(
|
|
association_id=association_id)
|
|
message = "Delete Peer Group Association: association_id %s " \
|
|
"failed with RC: %d" % (association_id, 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)
|
|
elif response.status_code == 400 and \
|
|
'a peer group which is associated with a system peer' in \
|
|
response.text:
|
|
raise exceptions.SubcloudPeerGroupDeleteFailedAssociated(
|
|
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)
|