distcloud/distributedcloud/dccommon/drivers/openstack/dcmanager_v1.py

445 lines
18 KiB
Python

# Copyright (c) 2023-2024 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,
"User-Agent": consts.DCMANAGER_V1_HTTP_AGENT}
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,
"User-Agent": consts.DCMANAGER_V1_HTTP_AGENT}
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)