690 lines
25 KiB
Python
690 lines
25 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership.
|
|
# The ASF licenses this file to You 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.
|
|
|
|
from libcloud.utils.py3 import ET
|
|
from libcloud.backup.base import BackupDriver, BackupTarget, BackupTargetJob
|
|
from libcloud.backup.types import BackupTargetType
|
|
from libcloud.backup.types import Provider
|
|
from libcloud.common.dimensiondata import dd_object_to_id
|
|
from libcloud.common.dimensiondata import DimensionDataConnection
|
|
from libcloud.common.dimensiondata import DimensionDataBackupClient
|
|
from libcloud.common.dimensiondata import DimensionDataBackupClientAlert
|
|
from libcloud.common.dimensiondata import DimensionDataBackupClientType
|
|
from libcloud.common.dimensiondata import DimensionDataBackupDetails
|
|
from libcloud.common.dimensiondata import DimensionDataBackupSchedulePolicy
|
|
from libcloud.common.dimensiondata import DimensionDataBackupStoragePolicy
|
|
from libcloud.common.dimensiondata import API_ENDPOINTS, DEFAULT_REGION
|
|
from libcloud.common.dimensiondata import TYPES_URN
|
|
from libcloud.common.dimensiondata import GENERAL_NS, BACKUP_NS
|
|
from libcloud.utils.xml import fixxpath, findtext, findall
|
|
|
|
# pylint: disable=no-member
|
|
|
|
DEFAULT_BACKUP_PLAN = 'Advanced'
|
|
|
|
|
|
class DimensionDataBackupDriver(BackupDriver):
|
|
"""
|
|
DimensionData backup driver.
|
|
"""
|
|
|
|
selected_region = None
|
|
connectionCls = DimensionDataConnection
|
|
name = 'Dimension Data Backup'
|
|
website = 'https://cloud.dimensiondata.com/'
|
|
type = Provider.DIMENSIONDATA
|
|
api_version = 1.0
|
|
|
|
network_domain_id = None
|
|
|
|
def __init__(self, key, secret=None, secure=True, host=None, port=None,
|
|
api_version=None, region=DEFAULT_REGION, **kwargs):
|
|
|
|
if region not in API_ENDPOINTS and host is None:
|
|
raise ValueError(
|
|
'Invalid region: %s, no host specified' % (region))
|
|
if region is not None:
|
|
self.selected_region = API_ENDPOINTS[region]
|
|
|
|
super(DimensionDataBackupDriver, self).__init__(
|
|
key=key, secret=secret,
|
|
secure=secure, host=host,
|
|
port=port,
|
|
api_version=api_version,
|
|
region=region,
|
|
**kwargs)
|
|
|
|
def _ex_connection_class_kwargs(self):
|
|
"""
|
|
Add the region to the kwargs before the connection is instantiated
|
|
"""
|
|
|
|
kwargs = super(DimensionDataBackupDriver,
|
|
self)._ex_connection_class_kwargs()
|
|
kwargs['region'] = self.selected_region
|
|
return kwargs
|
|
|
|
def get_supported_target_types(self):
|
|
"""
|
|
Get a list of backup target types this driver supports
|
|
|
|
:return: ``list`` of :class:``BackupTargetType``
|
|
"""
|
|
return [BackupTargetType.VIRTUAL]
|
|
|
|
def list_targets(self):
|
|
"""
|
|
List all backuptargets
|
|
|
|
:rtype: ``list`` of :class:`BackupTarget`
|
|
"""
|
|
targets = self._to_targets(
|
|
self.connection.request_with_orgId_api_2('server/server').object)
|
|
return targets
|
|
|
|
def create_target(self, name, address,
|
|
type=BackupTargetType.VIRTUAL, extra=None):
|
|
"""
|
|
Creates a new backup target
|
|
|
|
:param name: Name of the target (not used)
|
|
:type name: ``str``
|
|
|
|
:param address: The ID of the node in Dimension Data Cloud
|
|
:type address: ``str``
|
|
|
|
:param type: Backup target type, only Virtual supported
|
|
:type type: :class:`BackupTargetType`
|
|
|
|
:param extra: (optional) Extra attributes (driver specific).
|
|
:type extra: ``dict``
|
|
|
|
:rtype: Instance of :class:`BackupTarget`
|
|
"""
|
|
if extra is not None:
|
|
service_plan = extra.get('servicePlan', DEFAULT_BACKUP_PLAN)
|
|
else:
|
|
service_plan = DEFAULT_BACKUP_PLAN
|
|
extra = {'servicePlan': service_plan}
|
|
|
|
create_node = ET.Element('NewBackup',
|
|
{'xmlns': BACKUP_NS})
|
|
create_node.set('servicePlan', service_plan)
|
|
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup' % (address),
|
|
method='POST',
|
|
data=ET.tostring(create_node)).object
|
|
|
|
asset_id = None
|
|
for info in findall(response,
|
|
'additionalInformation',
|
|
GENERAL_NS):
|
|
if info.get('name') == 'assetId':
|
|
asset_id = findtext(info, 'value', GENERAL_NS)
|
|
|
|
return BackupTarget(
|
|
id=asset_id,
|
|
name=name,
|
|
address=address,
|
|
type=type,
|
|
extra=extra,
|
|
driver=self
|
|
)
|
|
|
|
def create_target_from_node(self, node, type=BackupTargetType.VIRTUAL,
|
|
extra=None):
|
|
"""
|
|
Creates a new backup target from an existing node
|
|
|
|
:param node: The Node to backup
|
|
:type node: ``Node``
|
|
|
|
:param type: Backup target type (Physical, Virtual, ...).
|
|
:type type: :class:`BackupTargetType`
|
|
|
|
:param extra: (optional) Extra attributes (driver specific).
|
|
:type extra: ``dict``
|
|
|
|
:rtype: Instance of :class:`BackupTarget`
|
|
"""
|
|
return self.create_target(name=node.name,
|
|
address=node.id,
|
|
type=BackupTargetType.VIRTUAL,
|
|
extra=extra)
|
|
|
|
def create_target_from_container(self, container,
|
|
type=BackupTargetType.OBJECT,
|
|
extra=None):
|
|
"""
|
|
Creates a new backup target from an existing storage container
|
|
|
|
:param node: The Container to backup
|
|
:type node: ``Container``
|
|
|
|
:param type: Backup target type (Physical, Virtual, ...).
|
|
:type type: :class:`BackupTargetType`
|
|
|
|
:param extra: (optional) Extra attributes (driver specific).
|
|
:type extra: ``dict``
|
|
|
|
:rtype: Instance of :class:`BackupTarget`
|
|
"""
|
|
return NotImplementedError(
|
|
'create_target_from_container not supported for this driver')
|
|
|
|
def update_target(self, target, name=None, address=None, extra=None):
|
|
"""
|
|
Update the properties of a backup target, only changing the serviceplan
|
|
is supported.
|
|
|
|
:param target: Backup target to update
|
|
:type target: Instance of :class:`BackupTarget` or ``str``
|
|
|
|
:param name: Name of the target
|
|
:type name: ``str``
|
|
|
|
:param address: Hostname, FQDN, IP, file path etc.
|
|
:type address: ``str``
|
|
|
|
:param extra: (optional) Extra attributes (driver specific).
|
|
:type extra: ``dict``
|
|
|
|
:rtype: Instance of :class:`BackupTarget`
|
|
"""
|
|
if extra is not None:
|
|
service_plan = extra.get('servicePlan', DEFAULT_BACKUP_PLAN)
|
|
else:
|
|
service_plan = DEFAULT_BACKUP_PLAN
|
|
request = ET.Element('ModifyBackup',
|
|
{'xmlns': BACKUP_NS})
|
|
request.set('servicePlan', service_plan)
|
|
server_id = self._target_to_target_address(target)
|
|
self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/modify' % (server_id),
|
|
method='POST',
|
|
data=ET.tostring(request)).object
|
|
if isinstance(target, BackupTarget):
|
|
target.extra = extra
|
|
else:
|
|
target = self.ex_get_target_by_id(server_id)
|
|
return target
|
|
|
|
def delete_target(self, target):
|
|
"""
|
|
Delete a backup target
|
|
|
|
:param target: Backup target to delete
|
|
:type target: Instance of :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup?disable' % (server_id),
|
|
method='GET').object
|
|
response_code = findtext(response, 'result', GENERAL_NS)
|
|
return response_code in ['IN_PROGRESS', 'SUCCESS']
|
|
|
|
def list_recovery_points(self, target, start_date=None, end_date=None):
|
|
"""
|
|
List the recovery points available for a target
|
|
|
|
:param target: Backup target to delete
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param start_date: The start date to show jobs between (optional)
|
|
:type start_date: :class:`datetime.datetime`
|
|
|
|
:param end_date: The end date to show jobs between (optional)
|
|
:type end_date: :class:`datetime.datetime``
|
|
|
|
:rtype: ``list`` of :class:`BackupTargetRecoveryPoint`
|
|
"""
|
|
raise NotImplementedError(
|
|
'list_recovery_points not implemented for this driver')
|
|
|
|
def recover_target(self, target, recovery_point, path=None):
|
|
"""
|
|
Recover a backup target to a recovery point
|
|
|
|
:param target: Backup target to delete
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param recovery_point: Backup target with the backup data
|
|
:type recovery_point: Instance of :class:`BackupTarget`
|
|
|
|
:param path: The part of the recovery point to recover (optional)
|
|
:type path: ``str``
|
|
|
|
:rtype: Instance of :class:`BackupTargetJob`
|
|
"""
|
|
raise NotImplementedError(
|
|
'recover_target not implemented for this driver')
|
|
|
|
def recover_target_out_of_place(self, target, recovery_point,
|
|
recovery_target, path=None):
|
|
"""
|
|
Recover a backup target to a recovery point out-of-place
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param recovery_point: Backup target with the backup data
|
|
:type recovery_point: Instance of :class:`BackupTarget`
|
|
|
|
:param recovery_target: Backup target with to recover the data to
|
|
:type recovery_target: Instance of :class:`BackupTarget`
|
|
|
|
:param path: The part of the recovery point to recover (optional)
|
|
:type path: ``str``
|
|
|
|
:rtype: Instance of :class:`BackupTargetJob`
|
|
"""
|
|
raise NotImplementedError(
|
|
'recover_target_out_of_place not implemented for this driver')
|
|
|
|
def get_target_job(self, target, id):
|
|
"""
|
|
Get a specific backup job by ID
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param id: Backup target with the backup data
|
|
:type id: Instance of :class:`BackupTarget`
|
|
|
|
:rtype: :class:`BackupTargetJob`
|
|
"""
|
|
jobs = self.list_target_jobs(target)
|
|
return list(filter(lambda x: x.id == id, jobs))[0]
|
|
|
|
def list_target_jobs(self, target):
|
|
"""
|
|
List the backup jobs on a target
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:rtype: ``list`` of :class:`BackupTargetJob`
|
|
"""
|
|
raise NotImplementedError(
|
|
'list_target_jobs not implemented for this driver')
|
|
|
|
def create_target_job(self, target, extra=None):
|
|
"""
|
|
Create a new backup job on a target
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param extra: (optional) Extra attributes (driver specific).
|
|
:type extra: ``dict``
|
|
|
|
:rtype: Instance of :class:`BackupTargetJob`
|
|
"""
|
|
raise NotImplementedError(
|
|
'create_target_job not implemented for this driver')
|
|
|
|
def resume_target_job(self, target, job):
|
|
"""
|
|
Resume a suspended backup job on a target
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param job: Backup target job to resume
|
|
:type job: Instance of :class:`BackupTargetJob`
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
raise NotImplementedError(
|
|
'resume_target_job not implemented for this driver')
|
|
|
|
def suspend_target_job(self, target, job):
|
|
"""
|
|
Suspend a running backup job on a target
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget`
|
|
|
|
:param job: Backup target job to suspend
|
|
:type job: Instance of :class:`BackupTargetJob`
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
raise NotImplementedError(
|
|
'suspend_target_job not implemented for this driver')
|
|
|
|
def cancel_target_job(self, job, ex_client=None, ex_target=None):
|
|
"""
|
|
Cancel a backup job on a target
|
|
|
|
:param job: Backup target job to cancel. If it is ``None``
|
|
ex_client and ex_target must be set
|
|
:type job: Instance of :class:`BackupTargetJob` or ``None``
|
|
|
|
:param ex_client: Client of the job to cancel.
|
|
Not necessary if job is specified.
|
|
DimensionData only has 1 job per client
|
|
:type ex_client: Instance of :class:`DimensionDataBackupClient`
|
|
or ``str``
|
|
|
|
:param ex_target: Target to cancel a job from.
|
|
Not necessary if job is specified.
|
|
:type ex_target: Instance of :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
if job is None:
|
|
if ex_client is None or ex_target is None:
|
|
raise ValueError("Either job or ex_client and "
|
|
"ex_target have to be set")
|
|
server_id = self._target_to_target_address(ex_target)
|
|
client_id = self._client_to_client_id(ex_client)
|
|
else:
|
|
server_id = job.target.address
|
|
client_id = job.extra['clientId']
|
|
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client/%s?cancelJob' % (server_id,
|
|
client_id),
|
|
method='GET').object
|
|
response_code = findtext(response, 'result', GENERAL_NS)
|
|
return response_code in ['IN_PROGRESS', 'SUCCESS']
|
|
|
|
def ex_get_target_by_id(self, id):
|
|
"""
|
|
Get a target by server id
|
|
|
|
:param id: The id of the target you want to get
|
|
:type id: ``str``
|
|
|
|
:rtype: :class:`BackupTarget`
|
|
"""
|
|
node = self.connection.request_with_orgId_api_2(
|
|
'server/server/%s' % id).object
|
|
return self._to_target(node)
|
|
|
|
def ex_add_client_to_target(self, target, client_type, storage_policy,
|
|
schedule_policy, trigger, email):
|
|
"""
|
|
Add a client to a target
|
|
|
|
:param target: Backup target with the backup data
|
|
:type target: Instance of :class:`BackupTarget` or ``str``
|
|
|
|
:param client: Client to add to the target
|
|
:type client: Instance of :class:`DimensionDataBackupClientType`
|
|
or ``str``
|
|
|
|
:param storage_policy: The storage policy for the client
|
|
:type storage_policy: Instance of
|
|
:class:`DimensionDataBackupStoragePolicy`
|
|
or ``str``
|
|
|
|
:param schedule_policy: The schedule policy for the client
|
|
:type schedule_policy: Instance of
|
|
:class:`DimensionDataBackupSchedulePolicy`
|
|
or ``str``
|
|
|
|
:param trigger: The notify trigger for the client
|
|
:type trigger: ``str``
|
|
|
|
:param email: The notify email for the client
|
|
:type email: ``str``
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
|
|
backup_elm = ET.Element('NewBackupClient',
|
|
{'xmlns': BACKUP_NS})
|
|
if isinstance(client_type, DimensionDataBackupClientType):
|
|
ET.SubElement(backup_elm, "type").text = client_type.type
|
|
else:
|
|
ET.SubElement(backup_elm, "type").text = client_type
|
|
|
|
if isinstance(storage_policy, DimensionDataBackupStoragePolicy):
|
|
ET.SubElement(backup_elm,
|
|
"storagePolicyName").text = storage_policy.name
|
|
else:
|
|
ET.SubElement(backup_elm,
|
|
"storagePolicyName").text = storage_policy
|
|
|
|
if isinstance(schedule_policy, DimensionDataBackupSchedulePolicy):
|
|
ET.SubElement(backup_elm,
|
|
"schedulePolicyName").text = schedule_policy.name
|
|
else:
|
|
ET.SubElement(backup_elm,
|
|
"schedulePolicyName").text = schedule_policy
|
|
|
|
alerting_elm = ET.SubElement(backup_elm, "alerting")
|
|
alerting_elm.set('trigger', trigger)
|
|
ET.SubElement(alerting_elm, "emailAddress").text = email
|
|
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client' % (server_id),
|
|
method='POST',
|
|
data=ET.tostring(backup_elm)).object
|
|
response_code = findtext(response, 'result', GENERAL_NS)
|
|
return response_code in ['IN_PROGRESS', 'SUCCESS']
|
|
|
|
def ex_remove_client_from_target(self, target, backup_client):
|
|
"""
|
|
Removes a client from a backup target
|
|
|
|
:param target: The backup target to remove the client from
|
|
:type target: :class:`BackupTarget` or ``str``
|
|
|
|
:param backup_client: The backup client to remove
|
|
:type backup_client: :class:`DimensionDataBackupClient` or ``str``
|
|
|
|
:rtype: ``bool``
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
client_id = self._client_to_client_id(backup_client)
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client/%s?disable' % (server_id, client_id),
|
|
method='GET').object
|
|
response_code = findtext(response, 'result', GENERAL_NS)
|
|
return response_code in ['IN_PROGRESS', 'SUCCESS']
|
|
|
|
def ex_get_backup_details_for_target(self, target):
|
|
"""
|
|
Returns a backup details object for a target
|
|
|
|
:param target: The backup target to get details for
|
|
:type target: :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: :class:`DimensionDataBackupDetails`
|
|
"""
|
|
if not isinstance(target, BackupTarget):
|
|
target = self.ex_get_target_by_id(target)
|
|
if target is None:
|
|
return
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup' % (target.address),
|
|
method='GET').object
|
|
return self._to_backup_details(response, target)
|
|
|
|
def ex_list_available_client_types(self, target):
|
|
"""
|
|
Returns a list of available backup client types
|
|
|
|
:param target: The backup target to list available types for
|
|
:type target: :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: ``list`` of :class:`DimensionDataBackupClientType`
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client/type' % (server_id),
|
|
method='GET').object
|
|
return self._to_client_types(response)
|
|
|
|
def ex_list_available_storage_policies(self, target):
|
|
"""
|
|
Returns a list of available backup storage policies
|
|
|
|
:param target: The backup target to list available policies for
|
|
:type target: :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: ``list`` of :class:`DimensionDataBackupStoragePolicy`
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client/storagePolicy' % (server_id),
|
|
method='GET').object
|
|
return self._to_storage_policies(response)
|
|
|
|
def ex_list_available_schedule_policies(self, target):
|
|
"""
|
|
Returns a list of available backup schedule policies
|
|
|
|
:param target: The backup target to list available policies for
|
|
:type target: :class:`BackupTarget` or ``str``
|
|
|
|
:rtype: ``list`` of :class:`DimensionDataBackupSchedulePolicy`
|
|
"""
|
|
server_id = self._target_to_target_address(target)
|
|
response = self.connection.request_with_orgId_api_1(
|
|
'server/%s/backup/client/schedulePolicy' % (server_id),
|
|
method='GET').object
|
|
return self._to_schedule_policies(response)
|
|
|
|
def _to_storage_policies(self, object):
|
|
elements = object.findall(fixxpath('storagePolicy', BACKUP_NS))
|
|
|
|
return [self._to_storage_policy(el) for el in elements]
|
|
|
|
def _to_storage_policy(self, element):
|
|
return DimensionDataBackupStoragePolicy(
|
|
retention_period=int(element.get('retentionPeriodInDays')),
|
|
name=element.get('name'),
|
|
secondary_location=element.get('secondaryLocation')
|
|
)
|
|
|
|
def _to_schedule_policies(self, object):
|
|
elements = object.findall(fixxpath('schedulePolicy', BACKUP_NS))
|
|
|
|
return [self._to_schedule_policy(el) for el in elements]
|
|
|
|
def _to_schedule_policy(self, element):
|
|
return DimensionDataBackupSchedulePolicy(
|
|
name=element.get('name'),
|
|
description=element.get('description')
|
|
)
|
|
|
|
def _to_client_types(self, object):
|
|
elements = object.findall(fixxpath('backupClientType', BACKUP_NS))
|
|
|
|
return [self._to_client_type(el) for el in elements]
|
|
|
|
def _to_client_type(self, element):
|
|
description = element.get('description')
|
|
if description is None:
|
|
description = findtext(element, 'description', BACKUP_NS)
|
|
return DimensionDataBackupClientType(
|
|
type=element.get('type'),
|
|
description=description,
|
|
is_file_system=bool(element.get('isFileSystem') == 'true')
|
|
)
|
|
|
|
def _to_backup_details(self, object, target):
|
|
return DimensionDataBackupDetails(
|
|
asset_id=object.get('assetId'),
|
|
service_plan=object.get('servicePlan'),
|
|
status=object.get('state'),
|
|
clients=self._to_clients(object, target)
|
|
)
|
|
|
|
def _to_clients(self, object, target):
|
|
elements = object.findall(fixxpath('backupClient', BACKUP_NS))
|
|
|
|
return [self._to_client(el, target) for el in elements]
|
|
|
|
def _to_client(self, element, target):
|
|
client_id = element.get('id')
|
|
return DimensionDataBackupClient(
|
|
id=client_id,
|
|
type=self._to_client_type(element),
|
|
status=element.get('status'),
|
|
schedule_policy=findtext(element, 'schedulePolicyName', BACKUP_NS),
|
|
storage_policy=findtext(element, 'storagePolicyName', BACKUP_NS),
|
|
download_url=findtext(element, 'downloadUrl', BACKUP_NS),
|
|
running_job=self._to_backup_job(element, target, client_id),
|
|
alert=self._to_alert(element)
|
|
)
|
|
|
|
def _to_alert(self, element):
|
|
alert = element.find(fixxpath('alerting', BACKUP_NS))
|
|
if alert is not None:
|
|
notify_list = [
|
|
email_addr.text for email_addr
|
|
in alert.findall(fixxpath('emailAddress', BACKUP_NS))
|
|
]
|
|
return DimensionDataBackupClientAlert(
|
|
trigger=element.get('trigger'),
|
|
notify_list=notify_list
|
|
)
|
|
return None
|
|
|
|
def _to_backup_job(self, element, target, client_id):
|
|
running_job = element.find(fixxpath('runningJob', BACKUP_NS))
|
|
if running_job is not None:
|
|
return BackupTargetJob(
|
|
id=running_job.get('id'),
|
|
status=running_job.get('status'),
|
|
progress=int(running_job.get('percentageComplete')),
|
|
driver=self.connection.driver,
|
|
target=target,
|
|
extra={'clientId': client_id}
|
|
)
|
|
return None
|
|
|
|
def _to_targets(self, object):
|
|
node_elements = object.findall(fixxpath('server', TYPES_URN))
|
|
|
|
return [self._to_target(el) for el in node_elements]
|
|
|
|
def _to_target(self, element):
|
|
backup = findall(element, 'backup', TYPES_URN)
|
|
if len(backup) == 0:
|
|
return
|
|
extra = {
|
|
'description': findtext(element, 'description', TYPES_URN),
|
|
'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN),
|
|
'datacenterId': element.get('datacenterId'),
|
|
'deployedTime': findtext(element, 'createTime', TYPES_URN),
|
|
'servicePlan': backup[0].get('servicePlan')
|
|
}
|
|
|
|
n = BackupTarget(id=backup[0].get('assetId'),
|
|
name=findtext(element, 'name', TYPES_URN),
|
|
address=element.get('id'),
|
|
driver=self.connection.driver,
|
|
type=BackupTargetType.VIRTUAL,
|
|
extra=extra)
|
|
return n
|
|
|
|
@staticmethod
|
|
def _client_to_client_id(backup_client):
|
|
return dd_object_to_id(backup_client, DimensionDataBackupClient)
|
|
|
|
@staticmethod
|
|
def _target_to_target_address(target):
|
|
return dd_object_to_id(target, BackupTarget, id_value='address')
|