libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anthonys...@apache.org
Subject [02/51] [abbrv] libcloud git commit: Merge branch 'trunk' into github-728
Date Mon, 09 Jan 2017 04:52:22 GMT
http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/backup/test_dimensiondata.py
----------------------------------------------------------------------
diff --cc libcloud/test/backup/test_dimensiondata.py
index 285c777,b2f599c..5cbbdf5
--- a/libcloud/test/backup/test_dimensiondata.py
+++ b/libcloud/test/backup/test_dimensiondata.py
@@@ -1,431 -1,502 +1,502 @@@
 -# 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.
 -
 -try:
 -    from lxml import etree as ET
 -except ImportError:
 -    from xml.etree import ElementTree as ET
 -
 -import sys
 -from libcloud.utils.py3 import httplib
 -
 -from libcloud.common.dimensiondata import DimensionDataAPIException
 -from libcloud.common.types import InvalidCredsError
 -from libcloud.backup.base import BackupTargetJob
 -from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData
 -from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN
 -
 -from libcloud.test import MockHttp, unittest
 -from libcloud.test.backup import TestCaseMixin
 -from libcloud.test.file_fixtures import BackupFileFixtures
 -
 -from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 -
 -
 -class DimensionDataTests(unittest.TestCase, TestCaseMixin):
 -
 -    def setUp(self):
 -        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
 -        DimensionDataMockHttp.type = None
 -        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
 -
 -    def test_invalid_region(self):
 -        with self.assertRaises(ValueError):
 -            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
 -
 -    def test_invalid_creds(self):
 -        DimensionDataMockHttp.type = 'UNAUTHORIZED'
 -        with self.assertRaises(InvalidCredsError):
 -            self.driver.list_targets()
 -
 -    def test_list_targets(self):
 -        targets = self.driver.list_targets()
 -        self.assertEqual(len(targets), 2)
 -        self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10')
 -        self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 -        self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise')
 -
 -    def test_create_target(self):
 -        target = self.driver.create_target(
 -            'name',
 -            'e75ead52-692f-4314-8725-c8a4f4d13a87',
 -            extra={'servicePlan': 'Enterprise'})
 -        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
 -        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 -        self.assertEqual(target.extra['servicePlan'], 'Enterprise')
 -
 -    def test_create_target_DEFAULT(self):
 -        DimensionDataMockHttp.type = 'DEFAULT'
 -        target = self.driver.create_target(
 -            'name',
 -            'e75ead52-692f-4314-8725-c8a4f4d13a87')
 -        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
 -        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 -
 -    def test_create_target_EXISTS(self):
 -        DimensionDataMockHttp.type = 'EXISTS'
 -        with self.assertRaises(DimensionDataAPIException) as context:
 -            self.driver.create_target(
 -                'name',
 -                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 -                extra={'servicePlan': 'Enterprise'})
 -        self.assertEqual(context.exception.code, 'ERROR')
 -        self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).')
 -
 -    def test_update_target(self):
 -        target = self.driver.list_targets()[0]
 -        extra = {'servicePlan': 'Essentials'}
 -        new_target = self.driver.update_target(target, extra=extra)
 -        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
 -
 -    def test_update_target_DEFAULT(self):
 -        DimensionDataMockHttp.type = 'DEFAULT'
 -        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
 -        self.driver.update_target(target)
 -
 -    def test_update_target_STR(self):
 -        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
 -        extra = {'servicePlan': 'Essentials'}
 -        new_target = self.driver.update_target(target, extra=extra)
 -        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
 -
 -    def test_delete_target(self):
 -        target = self.driver.list_targets()[0]
 -        self.assertTrue(self.driver.delete_target(target))
 -
 -    def test_ex_add_client_to_target(self):
 -        target = self.driver.list_targets()[0]
 -        client = self.driver.ex_list_available_client_types(target)[0]
 -        storage_policy = self.driver.ex_list_available_storage_policies(target)[0]
 -        schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0]
 -        self.assertTrue(
 -            self.driver.ex_add_client_to_target(target, client, storage_policy,
 -                                                schedule_policy, 'ON_FAILURE', 'nobody@example.com')
 -        )
 -
 -    def test_ex_add_client_to_target_STR(self):
 -        self.assertTrue(
 -            self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy',
 -                                                '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com')
 -        )
 -
 -    def test_ex_get_backup_details_for_target(self):
 -        target = self.driver.list_targets()[0]
 -        response = self.driver.ex_get_backup_details_for_target(target)
 -        self.assertEqual(response.service_plan, 'Enterprise')
 -        client = response.clients[0]
 -        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
 -        self.assertEqual(client.type.type, 'FA.Linux')
 -        self.assertEqual(client.running_job.progress, 5)
 -        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
 -        self.assertEqual(len(client.alert.notify_list), 2)
 -        self.assertTrue(isinstance(client.alert.notify_list, list))
 -
 -    def test_ex_get_backup_details_for_target_NOBACKUP(self):
 -        target = self.driver.list_targets()[0].address
 -        DimensionDataMockHttp.type = 'NOBACKUP'
 -        response = self.driver.ex_get_backup_details_for_target(target)
 -        self.assertTrue(response is None)
 -
 -    def test_ex_cancel_target_job(self):
 -        target = self.driver.list_targets()[0]
 -        response = self.driver.ex_get_backup_details_for_target(target)
 -        client = response.clients[0]
 -        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
 -        success = client.running_job.cancel()
 -        self.assertTrue(success)
 -
 -    def test_ex_cancel_target_job_with_extras(self):
 -        success = self.driver.cancel_target_job(
 -            None,
 -            ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
 -            ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
 -        )
 -        self.assertTrue(success)
 -
 -    def test_ex_cancel_target_job_FAIL(self):
 -        DimensionDataMockHttp.type = 'FAIL'
 -        with self.assertRaises(DimensionDataAPIException) as context:
 -            self.driver.cancel_target_job(
 -                None,
 -                ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
 -                ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
 -            )
 -        self.assertEqual(context.exception.code, 'ERROR')
 -
 -    """Test a backup info for a target that does not have a client"""
 -    def test_ex_get_backup_details_for_target_NO_CLIENT(self):
 -        DimensionDataMockHttp.type = 'NOCLIENT'
 -        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
 -        self.assertEqual(response.service_plan, 'Essentials')
 -        self.assertEqual(len(response.clients), 0)
 -
 -    """Test a backup details that has a client, but no alerting or running jobs"""
 -    def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self):
 -        DimensionDataMockHttp.type = 'NOJOB'
 -        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87')
 -        self.assertEqual(response.service_plan, 'Enterprise')
 -        self.assertTrue(isinstance(response.clients, list))
 -        self.assertEqual(len(response.clients), 1)
 -        client = response.clients[0]
 -        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
 -        self.assertEqual(client.type.type, 'FA.Linux')
 -        self.assertIsNone(client.running_job)
 -        self.assertIsNone(client.alert)
 -
 -    """Test getting backup info for a server that doesn't exist"""
 -    def test_ex_get_backup_details_for_target_DISABLED(self):
 -        DimensionDataMockHttp.type = 'DISABLED'
 -        with self.assertRaises(DimensionDataAPIException) as context:
 -            self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
 -        self.assertEqual(context.exception.code, 'ERROR')
 -        self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup')
 -
 -    def test_ex_list_available_client_types(self):
 -        target = self.driver.list_targets()[0]
 -        answer = self.driver.ex_list_available_client_types(target)
 -        self.assertEqual(len(answer), 1)
 -        self.assertEqual(answer[0].type, 'FA.Linux')
 -        self.assertEqual(answer[0].is_file_system, True)
 -        self.assertEqual(answer[0].description, 'Linux File system')
 -
 -    def test_ex_list_available_storage_policies(self):
 -        target = self.driver.list_targets()[0]
 -        answer = self.driver.ex_list_available_storage_policies(target)
 -        self.assertEqual(len(answer), 1)
 -        self.assertEqual(answer[0].name,
 -                         '30 Day Storage Policy + Secondary Copy')
 -        self.assertEqual(answer[0].retention_period, 30)
 -        self.assertEqual(answer[0].secondary_location, 'Primary')
 -
 -    def test_ex_list_available_schedule_policies(self):
 -        target = self.driver.list_targets()[0]
 -        answer = self.driver.ex_list_available_schedule_policies(target)
 -        self.assertEqual(len(answer), 1)
 -        self.assertEqual(answer[0].name, '12AM - 6AM')
 -        self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM')
 -
 -    def test_ex_remove_client_from_target(self):
 -        target = self.driver.list_targets()[0]
 -        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
 -        self.assertTrue(self.driver.ex_remove_client_from_target(target, client))
 -
 -    def test_ex_remove_client_from_target_STR(self):
 -        self.assertTrue(
 -            self.driver.ex_remove_client_from_target(
 -                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 -                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 -            )
 -        )
 -
 -    def test_ex_remove_client_from_target_FAIL(self):
 -        DimensionDataMockHttp.type = 'FAIL'
 -        with self.assertRaises(DimensionDataAPIException) as context:
 -            self.driver.ex_remove_client_from_target(
 -                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 -                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 -            )
 -        self.assertEqual(context.exception.code, 'ERROR')
 -        self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg)
 -
 -    def test_priv_target_to_target_address(self):
 -        target = self.driver.list_targets()[0]
 -        self.assertEqual(
 -            self.driver._target_to_target_address(target),
 -            'e75ead52-692f-4314-8725-c8a4f4d13a87'
 -        )
 -
 -    def test_priv_target_to_target_address_STR(self):
 -        self.assertEqual(
 -            self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'),
 -            'e75ead52-692f-4314-8725-c8a4f4d13a87'
 -        )
 -
 -    def test_priv_target_to_target_address_TYPEERROR(self):
 -        with self.assertRaises(TypeError):
 -            self.driver._target_to_target_address([1, 2, 3])
 -
 -    def test_priv_client_to_client_id(self):
 -        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
 -        self.assertEqual(
 -            self.driver._client_to_client_id(client),
 -            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 -        )
 -
 -    def test_priv_client_to_client_id_STR(self):
 -        self.assertEqual(
 -            self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'),
 -            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 -        )
 -
 -    def test_priv_client_to_client_id_TYPEERROR(self):
 -        with self.assertRaises(TypeError):
 -            self.driver._client_to_client_id([1, 2, 3])
 -
 -
 -class InvalidRequestError(Exception):
 -    def __init__(self, tag):
 -        super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
 -
 -
 -class DimensionDataMockHttp(MockHttp):
 -
 -    fixtures = BackupFileFixtures('dimensiondata')
 -
 -    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
 -        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
 -
 -    def _oec_0_9_myaccount(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_FAIL(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers):
 -        body = self.fixtures.load('oec_0_9_myaccount.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            'server_server.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            '_backup_client_type.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy(
 -            self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            '_backup_client_storagePolicy.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy(
 -            self, method, url, body, headers):
 -        body = self.fixtures.load(
 -            '_backup_client_schedulePolicy.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client(
 -            self, method, url, body, headers):
 -        if method == 'POST':
 -            body = self.fixtures.load(
 -                '_backup_client_SUCCESS_PUT.xml')
 -            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -        else:
 -            raise ValueError("Unknown Method {0}".format(method))
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT(
 -            self, method, url, body, headers):
 -        # only gets here are implemented
 -        # If we get any other method something has gone wrong
 -        assert(method == 'GET')
 -        body = self.fixtures.load(
 -            '_backup_INFO_NOCLIENT.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED(
 -            self, method, url, body, headers):
 -        # only gets here are implemented
 -        # If we get any other method something has gone wrong
 -        assert(method == 'GET')
 -        body = self.fixtures.load(
 -            '_backup_INFO_DISABLED.xml')
 -        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB(
 -            self, method, url, body, headers):
 -        # only gets here are implemented
 -        # If we get any other method something has gone wrong
 -        assert(method == 'GET')
 -        body = self.fixtures.load(
 -            '_backup_INFO_NOJOB.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT(
 -            self, method, url, body, headers):
 -        if method != 'POST':
 -            raise InvalidRequestError('Only POST is accepted for this test')
 -        request = ET.fromstring(body)
 -        service_plan = request.get('servicePlan')
 -        if service_plan != DEFAULT_BACKUP_PLAN:
 -            raise InvalidRequestError('The default plan %s should have been passed in.  Not %s' % (DEFAULT_BACKUP_PLAN, service_plan))
 -        body = self.fixtures.load(
 -            '_backup_ENABLE.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup(
 -            self, method, url, body, headers):
 -        if method == 'POST':
 -            body = self.fixtures.load(
 -                '_backup_ENABLE.xml')
 -            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -        elif method == 'GET':
 -            if url.endswith('disable'):
 -                body = self.fixtures.load(
 -                    '_backup_DISABLE.xml')
 -                return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -            body = self.fixtures.load(
 -                '_backup_INFO.xml')
 -            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -        else:
 -            raise ValueError("Unknown Method {0}".format(method))
 -
 -    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
 -            self, method, url, body, headers):
 -        assert(method == 'GET')
 -        body = self.fixtures.load('server_server_NOBACKUP.xml')
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS(
 -            self, method, url, body, headers):
 -        # only POSTs are implemented
 -        # If we get any other method something has gone wrong
 -        assert(method == 'POST')
 -        body = self.fixtures.load(
 -            '_backup_EXISTS.xml')
 -        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify(
 -            self, method, url, body, headers):
 -        request = ET.fromstring(body)
 -        service_plan = request.get('servicePlan')
 -        if service_plan != 'Essentials':
 -            raise InvalidRequestError("Expected Essentials backup plan in request")
 -        body = self.fixtures.load('_backup_modify.xml')
 -
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT(
 -            self, method, url, body, headers):
 -        request = ET.fromstring(body)
 -        service_plan = request.get('servicePlan')
 -        if service_plan != DEFAULT_BACKUP_PLAN:
 -            raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN)
 -        body = self.fixtures.load('_backup_modify.xml')
 -
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8(
 -            self, method, url, body, headers):
 -        if url.endswith('disable'):
 -            body = self.fixtures.load(
 -                ('_remove_backup_client.xml')
 -            )
 -        elif url.endswith('cancelJob'):
 -            body = self.fixtures.load(
 -                (''
 -                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml')
 -            )
 -        else:
 -            raise ValueError("Unknown URL: %s" % url)
 -        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 -
 -    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL(
 -            self, method, url, body, headers):
 -        if url.endswith('disable'):
 -            body = self.fixtures.load(
 -                ('_remove_backup_client_FAIL.xml')
 -            )
 -        elif url.endswith('cancelJob'):
 -            body = self.fixtures.load(
 -                (''
 -                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml')
 -            )
 -        else:
 -            raise ValueError("Unknown URL: %s" % url)
 -        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 -
 -
 -if __name__ == '__main__':
 -    sys.exit(unittest.main())
 +# 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.
 +
 +try:
 +    from lxml import etree as ET
 +except ImportError:
 +    from xml.etree import ElementTree as ET
 +
 +import sys
 +from libcloud.utils.py3 import httplib
 +
 +from libcloud.common.dimensiondata import DimensionDataAPIException
 +from libcloud.common.types import InvalidCredsError
++from libcloud.backup.base import BackupTargetJob
 +from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData
 +from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN
 +
 +from libcloud.test import MockHttp, unittest
 +from libcloud.test.backup import TestCaseMixin
 +from libcloud.test.file_fixtures import BackupFileFixtures
 +
 +from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 +
 +
 +class DimensionDataTests(unittest.TestCase, TestCaseMixin):
 +
 +    def setUp(self):
 +        DimensionData.connectionCls.conn_class = DimensionDataMockHttp
 +        DimensionDataMockHttp.type = None
 +        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
 +
 +    def test_invalid_region(self):
 +        with self.assertRaises(ValueError):
 +            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
 +
 +    def test_invalid_creds(self):
 +        DimensionDataMockHttp.type = 'UNAUTHORIZED'
 +        with self.assertRaises(InvalidCredsError):
 +            self.driver.list_targets()
 +
 +    def test_list_targets(self):
 +        targets = self.driver.list_targets()
 +        self.assertEqual(len(targets), 2)
 +        self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10')
 +        self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 +        self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise')
 +
 +    def test_create_target(self):
 +        target = self.driver.create_target(
 +            'name',
 +            'e75ead52-692f-4314-8725-c8a4f4d13a87',
 +            extra={'servicePlan': 'Enterprise'})
 +        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
 +        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 +        self.assertEqual(target.extra['servicePlan'], 'Enterprise')
 +
 +    def test_create_target_DEFAULT(self):
 +        DimensionDataMockHttp.type = 'DEFAULT'
 +        target = self.driver.create_target(
 +            'name',
 +            'e75ead52-692f-4314-8725-c8a4f4d13a87')
 +        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
 +        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
 +
 +    def test_create_target_EXISTS(self):
 +        DimensionDataMockHttp.type = 'EXISTS'
 +        with self.assertRaises(DimensionDataAPIException) as context:
 +            self.driver.create_target(
 +                'name',
 +                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 +                extra={'servicePlan': 'Enterprise'})
 +        self.assertEqual(context.exception.code, 'ERROR')
 +        self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).')
 +
 +    def test_update_target(self):
 +        target = self.driver.list_targets()[0]
 +        extra = {'servicePlan': 'Essentials'}
 +        new_target = self.driver.update_target(target, extra=extra)
 +        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
 +
 +    def test_update_target_DEFAULT(self):
 +        DimensionDataMockHttp.type = 'DEFAULT'
 +        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
 +        self.driver.update_target(target)
 +
 +    def test_update_target_STR(self):
 +        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
 +        extra = {'servicePlan': 'Essentials'}
 +        new_target = self.driver.update_target(target, extra=extra)
 +        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
 +
 +    def test_delete_target(self):
 +        target = self.driver.list_targets()[0]
 +        self.assertTrue(self.driver.delete_target(target))
 +
 +    def test_ex_add_client_to_target(self):
 +        target = self.driver.list_targets()[0]
 +        client = self.driver.ex_list_available_client_types(target)[0]
 +        storage_policy = self.driver.ex_list_available_storage_policies(target)[0]
 +        schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0]
 +        self.assertTrue(
 +            self.driver.ex_add_client_to_target(target, client, storage_policy,
 +                                                schedule_policy, 'ON_FAILURE', 'nobody@example.com')
 +        )
 +
 +    def test_ex_add_client_to_target_STR(self):
 +        self.assertTrue(
 +            self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy',
 +                                                '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com')
 +        )
 +
 +    def test_ex_get_backup_details_for_target(self):
 +        target = self.driver.list_targets()[0]
 +        response = self.driver.ex_get_backup_details_for_target(target)
 +        self.assertEqual(response.service_plan, 'Enterprise')
 +        client = response.clients[0]
 +        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
 +        self.assertEqual(client.type.type, 'FA.Linux')
-         self.assertEqual(client.running_job.percentage, 5)
++        self.assertEqual(client.running_job.progress, 5)
++        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
 +        self.assertEqual(len(client.alert.notify_list), 2)
 +        self.assertTrue(isinstance(client.alert.notify_list, list))
 +
++    def test_ex_get_backup_details_for_target_NOBACKUP(self):
++        target = self.driver.list_targets()[0].address
++        DimensionDataMockHttp.type = 'NOBACKUP'
++        response = self.driver.ex_get_backup_details_for_target(target)
++        self.assertTrue(response is None)
++
++    def test_ex_cancel_target_job(self):
++        target = self.driver.list_targets()[0]
++        response = self.driver.ex_get_backup_details_for_target(target)
++        client = response.clients[0]
++        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
++        success = client.running_job.cancel()
++        self.assertTrue(success)
++
++    def test_ex_cancel_target_job_with_extras(self):
++        success = self.driver.cancel_target_job(
++            None,
++            ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
++            ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
++        )
++        self.assertTrue(success)
++
++    def test_ex_cancel_target_job_FAIL(self):
++        DimensionDataMockHttp.type = 'FAIL'
++        with self.assertRaises(DimensionDataAPIException) as context:
++            self.driver.cancel_target_job(
++                None,
++                ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
++                ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
++            )
++        self.assertEqual(context.exception.code, 'ERROR')
++
 +    """Test a backup info for a target that does not have a client"""
 +    def test_ex_get_backup_details_for_target_NO_CLIENT(self):
 +        DimensionDataMockHttp.type = 'NOCLIENT'
 +        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
 +        self.assertEqual(response.service_plan, 'Essentials')
 +        self.assertEqual(len(response.clients), 0)
 +
 +    """Test a backup details that has a client, but no alerting or running jobs"""
 +    def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self):
 +        DimensionDataMockHttp.type = 'NOJOB'
 +        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87')
 +        self.assertEqual(response.service_plan, 'Enterprise')
 +        self.assertTrue(isinstance(response.clients, list))
 +        self.assertEqual(len(response.clients), 1)
 +        client = response.clients[0]
 +        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
 +        self.assertEqual(client.type.type, 'FA.Linux')
 +        self.assertIsNone(client.running_job)
 +        self.assertIsNone(client.alert)
 +
 +    """Test getting backup info for a server that doesn't exist"""
 +    def test_ex_get_backup_details_for_target_DISABLED(self):
 +        DimensionDataMockHttp.type = 'DISABLED'
 +        with self.assertRaises(DimensionDataAPIException) as context:
 +            self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
 +        self.assertEqual(context.exception.code, 'ERROR')
 +        self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup')
 +
 +    def test_ex_list_available_client_types(self):
 +        target = self.driver.list_targets()[0]
 +        answer = self.driver.ex_list_available_client_types(target)
 +        self.assertEqual(len(answer), 1)
 +        self.assertEqual(answer[0].type, 'FA.Linux')
 +        self.assertEqual(answer[0].is_file_system, True)
 +        self.assertEqual(answer[0].description, 'Linux File system')
 +
 +    def test_ex_list_available_storage_policies(self):
 +        target = self.driver.list_targets()[0]
 +        answer = self.driver.ex_list_available_storage_policies(target)
 +        self.assertEqual(len(answer), 1)
 +        self.assertEqual(answer[0].name,
 +                         '30 Day Storage Policy + Secondary Copy')
 +        self.assertEqual(answer[0].retention_period, 30)
 +        self.assertEqual(answer[0].secondary_location, 'Primary')
 +
 +    def test_ex_list_available_schedule_policies(self):
 +        target = self.driver.list_targets()[0]
 +        answer = self.driver.ex_list_available_schedule_policies(target)
 +        self.assertEqual(len(answer), 1)
 +        self.assertEqual(answer[0].name, '12AM - 6AM')
 +        self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM')
 +
 +    def test_ex_remove_client_from_target(self):
 +        target = self.driver.list_targets()[0]
 +        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
 +        self.assertTrue(self.driver.ex_remove_client_from_target(target, client))
 +
 +    def test_ex_remove_client_from_target_STR(self):
 +        self.assertTrue(
 +            self.driver.ex_remove_client_from_target(
 +                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 +                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 +            )
 +        )
 +
-     def test_ex_remove_client_from_target_BUSY(self):
-         DimensionDataMockHttp.type = 'BUSY'
++    def test_ex_remove_client_from_target_FAIL(self):
++        DimensionDataMockHttp.type = 'FAIL'
 +        with self.assertRaises(DimensionDataAPIException) as context:
 +            self.driver.ex_remove_client_from_target(
 +                'e75ead52-692f-4314-8725-c8a4f4d13a87',
 +                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 +            )
 +        self.assertEqual(context.exception.code, 'ERROR')
 +        self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg)
 +
 +    def test_priv_target_to_target_address(self):
 +        target = self.driver.list_targets()[0]
 +        self.assertEqual(
 +            self.driver._target_to_target_address(target),
 +            'e75ead52-692f-4314-8725-c8a4f4d13a87'
 +        )
 +
 +    def test_priv_target_to_target_address_STR(self):
 +        self.assertEqual(
 +            self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'),
 +            'e75ead52-692f-4314-8725-c8a4f4d13a87'
 +        )
 +
 +    def test_priv_target_to_target_address_TYPEERROR(self):
 +        with self.assertRaises(TypeError):
 +            self.driver._target_to_target_address([1, 2, 3])
 +
 +    def test_priv_client_to_client_id(self):
 +        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
 +        self.assertEqual(
 +            self.driver._client_to_client_id(client),
 +            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 +        )
 +
 +    def test_priv_client_to_client_id_STR(self):
 +        self.assertEqual(
 +            self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'),
 +            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
 +        )
 +
 +    def test_priv_client_to_client_id_TYPEERROR(self):
 +        with self.assertRaises(TypeError):
 +            self.driver._client_to_client_id([1, 2, 3])
 +
 +
 +class InvalidRequestError(Exception):
 +    def __init__(self, tag):
 +        super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
 +
 +
 +class DimensionDataMockHttp(MockHttp):
 +
 +    fixtures = BackupFileFixtures('dimensiondata')
 +
 +    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
 +        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
 +
 +    def _oec_0_9_myaccount(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
-     def _oec_0_9_myaccount_BUSY(self, method, url, body, headers):
++    def _oec_0_9_myaccount_FAIL(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers):
 +        body = self.fixtures.load('oec_0_9_myaccount.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
-     def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
++        body = self.fixtures.load(
++            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
++        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
++
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
++        body = self.fixtures.load(
++            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
++        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
++
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
++        body = self.fixtures.load(
++            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
++        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
++
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
++            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
-     def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
++            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
-     def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml')
++            'server_server.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type.xml')
++            '_backup_client_type.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy(
 +            self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy.xml')
++            '_backup_client_storagePolicy.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy(
 +            self, method, url, body, headers):
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy.xml')
++            '_backup_client_schedulePolicy.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client(
 +            self, method, url, body, headers):
 +        if method == 'POST':
 +            body = self.fixtures.load(
-                 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_SUCCESS_PUT.xml')
++                '_backup_client_SUCCESS_PUT.xml')
 +            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +        else:
 +            raise ValueError("Unknown Method {0}".format(method))
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT(
 +            self, method, url, body, headers):
 +        # only gets here are implemented
 +        # If we get any other method something has gone wrong
 +        assert(method == 'GET')
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_INFO_NOCLIENT.xml')
++            '_backup_INFO_NOCLIENT.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED(
 +            self, method, url, body, headers):
 +        # only gets here are implemented
 +        # If we get any other method something has gone wrong
 +        assert(method == 'GET')
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_INFO_DISABLED.xml')
++            '_backup_INFO_DISABLED.xml')
 +        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB(
 +            self, method, url, body, headers):
 +        # only gets here are implemented
 +        # If we get any other method something has gone wrong
 +        assert(method == 'GET')
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_INFO_NOJOB.xml')
++            '_backup_INFO_NOJOB.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT(
 +            self, method, url, body, headers):
 +        if method != 'POST':
 +            raise InvalidRequestError('Only POST is accepted for this test')
 +        request = ET.fromstring(body)
 +        service_plan = request.get('servicePlan')
 +        if service_plan != DEFAULT_BACKUP_PLAN:
 +            raise InvalidRequestError('The default plan %s should have been passed in.  Not %s' % (DEFAULT_BACKUP_PLAN, service_plan))
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_ENABLE.xml')
++            '_backup_ENABLE.xml')
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup(
 +            self, method, url, body, headers):
 +        if method == 'POST':
 +            body = self.fixtures.load(
-                 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_ENABLE.xml')
++                '_backup_ENABLE.xml')
 +            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +        elif method == 'GET':
 +            if url.endswith('disable'):
 +                body = self.fixtures.load(
-                     'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLE.xml')
++                    '_backup_DISABLE.xml')
 +                return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +            body = self.fixtures.load(
-                 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_INFO.xml')
++                '_backup_INFO.xml')
 +            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +        else:
 +            raise ValueError("Unknown Method {0}".format(method))
 +
++    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
++            self, method, url, body, headers):
++        assert(method == 'GET')
++        body = self.fixtures.load('server_server_NOBACKUP.xml')
++        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
++
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS(
 +            self, method, url, body, headers):
 +        # only POSTs are implemented
 +        # If we get any other method something has gone wrong
 +        assert(method == 'POST')
 +        body = self.fixtures.load(
-             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS.xml')
++            '_backup_EXISTS.xml')
 +        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify(
 +            self, method, url, body, headers):
 +        request = ET.fromstring(body)
 +        service_plan = request.get('servicePlan')
 +        if service_plan != 'Essentials':
 +            raise InvalidRequestError("Expected Essentials backup plan in request")
-         body = self.fixtures.load('oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify.xml')
++        body = self.fixtures.load('_backup_modify.xml')
 +
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT(
 +            self, method, url, body, headers):
 +        request = ET.fromstring(body)
 +        service_plan = request.get('servicePlan')
 +        if service_plan != DEFAULT_BACKUP_PLAN:
 +            raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN)
-         body = self.fixtures.load('oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify.xml')
++        body = self.fixtures.load('_backup_modify.xml')
 +
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
 +    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8(
 +            self, method, url, body, headers):
-         body = self.fixtures.load(
-             ('_remove_backup_client.xml')
-         )
++        if url.endswith('disable'):
++            body = self.fixtures.load(
++                ('_remove_backup_client.xml')
++            )
++        elif url.endswith('cancelJob'):
++            body = self.fixtures.load(
++                (''
++                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml')
++            )
++        else:
++            raise ValueError("Unknown URL: %s" % url)
 +        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 +
-     def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_BUSY(
++    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL(
 +            self, method, url, body, headers):
-         body = self.fixtures.load(
-             ('_remove_backup_client_BUSY.xml')
-         )
++        if url.endswith('disable'):
++            body = self.fixtures.load(
++                ('_remove_backup_client_FAIL.xml')
++            )
++        elif url.endswith('cancelJob'):
++            body = self.fixtures.load(
++                (''
++                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml')
++            )
++        else:
++            raise ValueError("Unknown URL: %s" % url)
 +        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 +
 +
 +if __name__ == '__main__':
 +    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/common/test_nfsn.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/common/test_openstack_identity.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_ecs.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --cc libcloud/test/compute/test_gce.py
index 90699ef,9ec97e0..bdcd30c
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@@ -15,22 -15,20 +15,20 @@@
  """
  Tests for Google Compute Engine Driver
  """
+ import datetime
+ import mock
  import sys
  import unittest
- import datetime
  
  from libcloud.utils.py3 import httplib
- from libcloud.compute.drivers.gce import (GCENodeDriver, API_VERSION,
-                                           timestamp_to_datetime,
-                                           GCEAddress, GCEBackendService,
-                                           GCEFirewall, GCEForwardingRule,
-                                           GCEHealthCheck, GCENetwork,
-                                           GCENodeImage, GCERoute,
-                                           GCETargetHttpProxy, GCEUrlMap,
-                                           GCEZone)
+ from libcloud.compute.drivers.gce import (
+     GCENodeDriver, API_VERSION, timestamp_to_datetime, GCEAddress, GCEBackend,
+     GCEBackendService, GCEFirewall, GCEForwardingRule, GCEHealthCheck,
+     GCENetwork, GCENodeImage, GCERoute, GCERegion, GCETargetHttpProxy,
+     GCEUrlMap, GCEZone, GCESubnetwork)
  from libcloud.common.google import (GoogleBaseAuthConnection,
                                      ResourceNotFoundError, ResourceExistsError,
 -                                    InvalidRequestError, GoogleBaseError)
 +                                    GoogleBaseError)
  from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase
  from libcloud.compute.base import Node, StorageVolume
  

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --cc libcloud/test/compute/test_openstack.py
index 2474b49,c6cc76b..2d63f6b
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@@ -1471,9 -1530,23 +1523,22 @@@ class OpenStack_1_1_Tests(unittest.Test
                                               force=True)
          self.assertEqual(ret.id, '3fbbcccf-d058-4502-8844-6feeffdf4cb5')
  
+     def test_ex_create_snapshot_does_not_post_optional_parameters_if_none(self):
+         volume = self.driver.list_volumes()[0]
+         with patch.object(self.driver, '_to_snapshot'):
+             with patch.object(self.driver.connection, 'request') as mock_request:
+                 self.driver.create_volume_snapshot(volume,
+                                                    name=None,
+                                                    ex_description=None,
+                                                    ex_force=True)
+ 
+         name, args, kwargs = mock_request.mock_calls[0]
+         self.assertFalse("display_name" in kwargs["data"]["snapshot"])
+         self.assertFalse("display_description" in kwargs["data"]["snapshot"])
+ 
      def test_destroy_volume_snapshot(self):
          if self.driver_type.type == 'rackspace':
 -            self.conn_classes[0].type = 'RACKSPACE'
 -            self.conn_classes[1].type = 'RACKSPACE'
 +            self.conn_class.type = 'RACKSPACE'
  
          snapshot = self.driver.ex_list_snapshots()[0]
          ret = self.driver.destroy_volume_snapshot(snapshot)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_ovh.py
----------------------------------------------------------------------
diff --cc libcloud/test/compute/test_ovh.py
index 0000000,f434f7a..77394e5
mode 000000,100644..100644
--- a/libcloud/test/compute/test_ovh.py
+++ b/libcloud/test/compute/test_ovh.py
@@@ -1,0 -1,243 +1,242 @@@
+ # 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.
+ import sys
+ import unittest
+ from mock import patch
+ 
+ from libcloud.utils.py3 import httplib
+ 
+ from libcloud.compute.drivers.ovh import OvhNodeDriver
+ 
+ from libcloud.test.common.test_ovh import BaseOvhMockHttp
+ from libcloud.test.secrets import OVH_PARAMS
+ from libcloud.test.file_fixtures import ComputeFileFixtures
+ 
+ 
+ class OvhMockHttp(BaseOvhMockHttp):
+     """Fixtures needed for tests related to rating model"""
+     fixtures = ComputeFileFixtures('ovh')
+ 
+     def _json_1_0_auth_time_get(self, method, url, body, headers):
+         body = self.fixtures.load('auth_time_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_region_get(self, method, url, body, headers):
+         body = self.fixtures.load('region_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_flavor_get(self, method, url, body, headers):
+         body = self.fixtures.load('flavor_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_flavor_region_SBG1_get(self, method, url, body, headers):
+         body = self.fixtures.load('flavor_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_flavor_foo_id_get(self, method, url, body, headers):
+         body = self.fixtures.load('flavor_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_image_get(self, method, url, body, headers):
+         body = self.fixtures.load('image_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_image_foo_id_get(self, method, url, body, headers):
+         body = self.fixtures.load('image_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_sshkey_region_SBG1_get(self, method, url, body, headers):
+         body = self.fixtures.load('ssh_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_sshkey_post(self, method, url, body, headers):
+         body = self.fixtures.load('ssh_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_ssh_mykey_get(self, method, url, body, headers):
+         body = self.fixtures.load('ssh_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_instance_get(self, method, url, body, headers):
+         body = self.fixtures.load('instance_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_instance_foo_get(self, method, url, body, headers):
+         body = self.fixtures.load('instance_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_instance_foo_delete(self, method, url, body, headers):
+         return (httplib.OK, '', {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_instance_post(self, method, url, body, headers):
+         body = self.fixtures.load('instance_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_get(self, method, url, body, headers):
+         body = self.fixtures.load('volume_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_post(self, method, url, body, headers):
+         body = self.fixtures.load('volume_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_foo_get(self, method, url, body, headers):
+         body = self.fixtures.load('volume_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_foo_delete(self, method, url, body, headers):
+         return (httplib.OK, '', {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_foo_attach_post(self, method, url, body, headers):
+         body = self.fixtures.load('volume_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_foo_detach_post(self, method, url, body, headers):
+         body = self.fixtures.load('volume_get_detail.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_snapshot_region_SBG_1_get(self, method, url, body, headers):
+         body = self.fixtures.load('volume_snapshot_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_snapshot_get(self, method, url, body, headers):
+         body = self.fixtures.load('volume_snapshot_get.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_snapshot_foo_get(self, method, url, body, headers):
+         body = self.fixtures.load('volume_snapshot_get_details.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_snapshot_foo_snap_delete(self, method, url, body, headers):
+         return (httplib.OK, None, {}, httplib.responses[httplib.OK])
+ 
+     def _json_1_0_cloud_project_project_id_volume_foo_snapshot__post(self, method, url, body, headers):
+         body = self.fixtures.load('volume_snapshot_get_details.json')
+         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ 
+ 
+ @patch('libcloud.common.ovh.OvhConnection._timedelta', 42)
+ class OvhTests(unittest.TestCase):
+     def setUp(self):
 -        OvhNodeDriver.connectionCls.conn_classes = (
 -            OvhMockHttp, OvhMockHttp)
++        OvhNodeDriver.connectionCls.conn_class = OvhMockHttp
+         OvhMockHttp.type = None
+         self.driver = OvhNodeDriver(*OVH_PARAMS)
+ 
+     def test_list_locations(self):
+         images = self.driver.list_locations()
+         self.assertTrue(len(images) > 0)
+ 
+     def test_list_images(self):
+         images = self.driver.list_images()
+         self.assertTrue(len(images) > 0)
+ 
+     def test_get_image(self):
+         image = self.driver.get_image('foo-id')
+         self.assertEqual(image.id, 'foo-id')
+ 
+     def test_list_sizes(self):
+         sizes = self.driver.list_sizes()
+         self.assertTrue(len(sizes) > 0)
+ 
+     def test_get_size(self):
+         size = self.driver.ex_get_size('foo-id')
+         self.assertEqual(size.id, 'foo-id')
+ 
+     def test_list_key_pairs(self):
+         keys = self.driver.list_sizes()
+         self.assertTrue(len(keys) > 0)
+ 
+     def test_get_key_pair(self):
+         location = self.driver.list_locations()[0]
+         key = self.driver.get_key_pair('mykey', location)
+         self.assertEqual(key.name, 'mykey')
+ 
+     def test_import_key_pair_from_string(self):
+         location = self.driver.list_locations()[0]
+         key = self.driver.import_key_pair_from_string('mykey', 'material',
+                                                       location)
+         self.assertEqual(key.name, 'mykey')
+ 
+     def test_list_nodes(self):
+         nodes = self.driver.list_nodes()
+         self.assertTrue(len(nodes) > 0)
+ 
+     def test_get_node(self):
+         node = self.driver.ex_get_node('foo')
+         self.assertEqual(node.name, 'test_vm')
+ 
+     def test_create_node(self):
+         location = self.driver.list_locations()[0]
+         image = self.driver.list_sizes(location)[0]
+         size = self.driver.list_sizes(location)[0]
+         node = self.driver.create_node(name='test_vm', image=image, size=size,
+                                        location=location)
+         self.assertEqual(node.name, 'test_vm')
+ 
+     def test_destroy_node(self):
+         node = self.driver.list_nodes()[0]
+         self.driver.destroy_node(node)
+ 
+     def test_list_volumes(self):
+         volumes = self.driver.list_volumes()
+         self.assertTrue(len(volumes) > 0)
+ 
+     def test_get_volume(self):
+         volume = self.driver.ex_get_volume('foo')
+         self.assertEqual(volume.name, 'testvol')
+ 
+     def test_create_volume(self):
+         location = self.driver.list_locations()[0]
+         volume = self.driver.create_volume(size=10, name='testvol',
+                                            location=location)
+         self.assertEqual(volume.name, 'testvol')
+ 
+     def test_destroy_volume(self):
+         volume = self.driver.list_volumes()[0]
+         self.driver.destroy_volume(volume)
+ 
+     def test_attach_volume(self):
+         node = self.driver.list_nodes()[0]
+         volume = self.driver.ex_get_volume('foo')
+         response = self.driver.attach_volume(node=node, volume=volume)
+         self.assertTrue(response)
+ 
+     def test_detach_volume(self):
+         node = self.driver.list_nodes()[0]
+         volume = self.driver.ex_get_volume('foo')
+         response = self.driver.detach_volume(ex_node=node, volume=volume)
+         self.assertTrue(response)
+ 
+     def test_ex_list_snapshots(self):
+         self.driver.ex_list_snapshots()
+ 
+     def test_ex_get_volume_snapshot(self):
+         self.driver.ex_get_volume_snapshot('foo')
+ 
+     def test_list_volume_snapshots(self):
+         volume = self.driver.ex_get_volume('foo')
+         self.driver.list_volume_snapshots(volume)
+ 
+     def test_create_volume_snapshot(self):
+         volume = self.driver.ex_get_volume('foo')
+         self.driver.create_volume_snapshot(volume)
+ 
+     def test_destroy_volume_snapshot(self):
+         snapshot = self.driver.ex_get_volume_snapshot('foo')
+         result = self.driver.destroy_volume_snapshot(snapshot)
+         self.assertTrue(result)
+ 
+ if __name__ == '__main__':
+     sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_rackspace.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_vcloud.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/compute/test_vultr.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/container/test_docker.py
----------------------------------------------------------------------
diff --cc libcloud/test/container/test_docker.py
index ba2f29a,32c7127..95011e9
--- a/libcloud/test/container/test_docker.py
+++ b/libcloud/test/container/test_docker.py
@@@ -30,72 -30,91 +30,91 @@@ from libcloud.test import MockHtt
  class DockerContainerDriverTestCase(unittest.TestCase):
  
      def setUp(self):
-         DockerContainerDriver.connectionCls.conn_class = DockerMockHttp
-         DockerMockHttp.type = None
-         DockerMockHttp.use_param = 'a'
-         self.driver = DockerContainerDriver(*CONTAINER_PARAMS_DOCKER)
+         # Create a test driver for each version
+         versions = ('linux_124', 'mac_124')
+         self.drivers = []
+         for version in versions:
 -            DockerContainerDriver.connectionCls.conn_classes = (
 -                DockerMockHttp, DockerMockHttp)
++            DockerContainerDriver.connectionCls.conn_class = \
++                DockerMockHttp
+             DockerMockHttp.type = None
+             DockerMockHttp.use_param = 'a'
+             driver = DockerContainerDriver(*CONTAINER_PARAMS_DOCKER)
+             driver.version = version
+             self.drivers.append(driver)
  
      def test_list_images(self):
-         images = self.driver.list_images()
-         self.assertEqual(len(images), 4)
-         self.assertIsInstance(images[0], ContainerImage)
-         self.assertEqual(images[0].id,
-                          'cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0')
-         self.assertEqual(images[0].name, 'mongo:latest')
+         for driver in self.drivers:
+             images = driver.list_images()
+             self.assertEqual(len(images), 4)
+             self.assertIsInstance(images[0], ContainerImage)
+             self.assertEqual(images[0].id,
+                              'cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0')
+             self.assertEqual(images[0].name, 'mongo:latest')
  
      def test_install_image(self):
-         image = self.driver.install_image('ubuntu:12.04')
-         self.assertTrue(image is not None)
-         self.assertEqual(image.id, 'cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0')
+         for driver in self.drivers:
+             image = driver.install_image('ubuntu:12.04')
+             self.assertTrue(image is not None)
+             self.assertEqual(image.id, '992069aee4016783df6345315302fa59681aae51a8eeb2f889dea59290f21787')
  
      def test_list_containers(self):
-         containers = self.driver.list_containers(all=True)
-         self.assertEqual(len(containers), 6)
-         self.assertEqual(containers[0].id,
-                          '160936dc54fe8c332095676d9379003534b8cddd7565fa63018996e06dae1b6b')
-         self.assertEqual(containers[0].name, 'hubot')
-         self.assertEqual(containers[0].image.name, 'stackstorm/hubot')
+         for driver in self.drivers:
+             containers = driver.list_containers(all=True)
+             self.assertEqual(len(containers), 6)
+             self.assertEqual(containers[0].id,
+                              '160936dc54fe8c332095676d9379003534b8cddd7565fa63018996e06dae1b6b')
+             self.assertEqual(containers[0].name, 'hubot')
+             self.assertEqual(containers[0].image.name, 'stackstorm/hubot')
  
      def test_deploy_container(self):
-         image = self.driver.list_images()[0]
-         container = self.driver.deploy_container(image=image, name='test')
-         self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         self.assertEqual(container.name, 'gigantic_goldberg')
+         for driver in self.drivers:
+             image = driver.list_images()[0]
+             container = driver.deploy_container(image=image, name='test')
+             self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             self.assertEqual(container.name, 'gigantic_goldberg')
  
      def test_get_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         self.assertEqual(container.name, 'gigantic_goldberg')
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             self.assertEqual(container.name, 'gigantic_goldberg')
  
      def test_start_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         container.start()
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             container.start()
  
      def test_stop_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         container.stop()
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             container.stop()
  
      def test_restart_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         container.restart()
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             container.restart()
  
      def test_delete_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         container.destroy()
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             container.destroy()
  
      def test_ex_rename_container(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         self.driver.ex_rename_container(container, 'bob')
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             driver.ex_rename_container(container, 'bob')
  
      def test_ex_get_logs(self):
-         container = self.driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
-         logs = self.driver.ex_get_logs(container)
-         self.assertTrue(logs is not None)
+         for driver in self.drivers:
+             container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303')
+             logs = driver.ex_get_logs(container)
+             self.assertTrue(logs is not None)
  
      def test_ex_search_images(self):
-         images = self.driver.ex_search_images('mysql')
-         self.assertEqual(len(images), 25)
-         self.assertEqual(images[0].name, 'mysql')
+         for driver in self.drivers:
+             images = driver.ex_search_images('mysql')
+             self.assertEqual(len(images), 25)
+             self.assertEqual(images[0].name, 'mysql')
  
  
  class DockerMockHttp(MockHttp):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/dns/test_auroradns.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/dns/test_rackspace.py
----------------------------------------------------------------------
diff --cc libcloud/test/dns/test_rackspace.py
index 6140987,0679f05..ba5159d
--- a/libcloud/test/dns/test_rackspace.py
+++ b/libcloud/test/dns/test_rackspace.py
@@@ -47,13 -46,17 +46,16 @@@ RDNS_LB = LoadBalancer('370b0ff8-3f57-4
  
  
  class RackspaceUSTests(unittest.TestCase):
-     klass = RackspaceUSDNSDriver
+     klass = RackspaceDNSDriver
      endpoint_url = 'https://dns.api.rackspacecloud.com/v1.0/11111'
+     region = 'us'
  
      def setUp(self):
 -        self.klass.connectionCls.conn_classes = (
 -            None, RackspaceMockHttp)
 +        self.klass.connectionCls.conn_class = RackspaceMockHttp
          RackspaceMockHttp.type = None
-         self.driver = self.klass(*DNS_PARAMS_RACKSPACE)
+ 
+         driver_kwargs = {'region': self.region}
+         self.driver = self.klass(*DNS_PARAMS_RACKSPACE, **driver_kwargs)
          self.driver.connection.poll_interval = 0.0
          # normally authentication happens lazily, but we force it here
          self.driver.connection._populate_hosts_and_request_paths()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/loadbalancer/test_dimensiondata.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/loadbalancer/test_elb.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04fa0666/libcloud/test/loadbalancer/test_rackspace.py
----------------------------------------------------------------------
diff --cc libcloud/test/loadbalancer/test_rackspace.py
index 1eefeb8,15ba54c..112d825
--- a/libcloud/test/loadbalancer/test_rackspace.py
+++ b/libcloud/test/loadbalancer/test_rackspace.py
@@@ -917,9 -918,10 +916,9 @@@ class RackspaceLBTests(unittest.TestCas
  class RackspaceUKLBTests(RackspaceLBTests):
  
      def setUp(self):
 -        RackspaceLBDriver.connectionCls.conn_classes = (None,
 -                                                        RackspaceLBMockHttp)
 +        RackspaceLBDriver.connectionCls.conn_class = RackspaceLBMockHttp
          RackspaceLBMockHttp.type = None
-         self.driver = RackspaceUKLBDriver('user', 'key')
+         self.driver = RackspaceLBDriver('user', 'key', region='lon')
          # normally authentication happens lazily, but we force it here
          self.driver.connection._populate_hosts_and_request_paths()
  


Mime
View raw message