Port V1 Tempest test from designate's contrib folder

These are a close to a straight port as was possible, no cleanup was
performed where it wasn't absolutly necessary.

In addition, we add flags to enable V1, V2, Admin API tests, and a
V1 servers API flag, as these tests have proved particularly
susceptible to race conditions.

Change-Id: Idc31c00c95fde96087f4f222ae9c17e554e6b1fc
diff --git a/designate_tempest_plugin/clients.py b/designate_tempest_plugin/clients.py
index 9e64b15..6ad397f 100644
--- a/designate_tempest_plugin/clients.py
+++ b/designate_tempest_plugin/clients.py
@@ -14,6 +14,12 @@
 from tempest import clients
 from tempest import config
 
+from designate_tempest_plugin.services.dns.v1.json.domains_client import \
+    DomainsClient
+from designate_tempest_plugin.services.dns.v1.json.records_client import \
+    RecordsClient
+from designate_tempest_plugin.services.dns.v1.json.servers_client import \
+    ServersClient
 from designate_tempest_plugin.services.dns.v2.json.zones_client import \
     ZonesClient
 from designate_tempest_plugin.services.dns.v2.json.zone_imports_client import \
@@ -34,9 +40,27 @@
 CONF = config.CONF
 
 
-class Manager(clients.Manager):
+class ManagerV1(clients.Manager):
     def __init__(self, credentials=None, service=None):
-        super(Manager, self).__init__(credentials, service)
+        super(ManagerV1, self).__init__(credentials, service)
+
+        params = {
+            'service': CONF.dns.catalog_type,
+            'region': CONF.identity.region,
+            'endpoint_type': CONF.dns.endpoint_type,
+            'build_interval': CONF.dns.build_interval,
+            'build_timeout': CONF.dns.build_timeout
+        }
+        params.update(self.default_params)
+
+        self.domains_client = DomainsClient(self.auth_provider, **params)
+        self.records_client = RecordsClient(self.auth_provider, **params)
+        self.servers_client = ServersClient(self.auth_provider, **params)
+
+
+class ManagerV2(clients.Manager):
+    def __init__(self, credentials=None, service=None):
+        super(ManagerV2, self).__init__(credentials, service)
 
         params = {
             'service': CONF.dns.catalog_type,
diff --git a/designate_tempest_plugin/config.py b/designate_tempest_plugin/config.py
index 4094149..1dffcf0 100644
--- a/designate_tempest_plugin/config.py
+++ b/designate_tempest_plugin/config.py
@@ -13,6 +13,15 @@
 # under the License.
 from oslo_config import cfg
 
+service_available_group = cfg.OptGroup(name="service_available",
+                                       title="Available OpenStack Services")
+
+ServiceAvailableGroup = [
+    cfg.BoolOpt("designate",
+                default=True,
+                help="Whether or not designate is expected to be available."),
+]
+
 dns_group = cfg.OptGroup(name='dns',
                          title='DNS service options')
 
@@ -32,3 +41,21 @@
                default=60,
                help="Timeout in seconds to wait for an resource to build."),
 ]
+
+dns_feature_group = cfg.OptGroup(name='dns_feature_enabled',
+                                 title='Enabled Designate Features')
+
+DnsFeatureGroup = [
+    cfg.BoolOpt('api_v1',
+                default=True,
+                help="Is the v1 dns API enabled."),
+    cfg.BoolOpt('api_v2',
+                default=True,
+                help="Is the v2 dns API enabled."),
+    cfg.BoolOpt('api_admin',
+                default=True,
+                help="Is the admin dns API enabled."),
+    cfg.BoolOpt('api_v1_servers',
+                default=False,
+                help="Is the v1 dns servers API enabled."),
+]
diff --git a/designate_tempest_plugin/plugin.py b/designate_tempest_plugin/plugin.py
index 20f19c1..0a093ef 100644
--- a/designate_tempest_plugin/plugin.py
+++ b/designate_tempest_plugin/plugin.py
@@ -51,8 +51,12 @@
         conf (ConfigOpts): The conf object that can be used to register
         additional options on.
         """
+        config.register_opt_group(conf, project_config.service_available_group,
+                                  project_config.ServiceAvailableGroup)
         config.register_opt_group(conf, project_config.dns_group,
                                   project_config.DnsGroup)
+        config.register_opt_group(conf, project_config.dns_feature_group,
+                                  project_config.DnsFeatureGroup)
 
     def get_opt_lists(self):
         """
@@ -62,5 +66,11 @@
                             and options in that group.
         Return type: list
         """
-        return [(project_config.dns_group.name,
-                 project_config.DnsGroup)]
+        return [
+            (project_config.service_available_group.name,
+             project_config.ServiceAvailableGroup),
+            (project_config.dns_group.name,
+             project_config.DnsGroup),
+            (project_config.dns_feature_group.name,
+             project_config.DnsFeatureGroup),
+        ]
diff --git a/designate_tempest_plugin/schemas/__init__.py b/designate_tempest_plugin/schemas/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/designate_tempest_plugin/schemas/__init__.py
diff --git a/designate_tempest_plugin/schemas/v1/__init__.py b/designate_tempest_plugin/schemas/v1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/designate_tempest_plugin/schemas/v1/__init__.py
diff --git a/designate_tempest_plugin/schemas/v1/domains_schema.py b/designate_tempest_plugin/schemas/v1/domains_schema.py
new file mode 100644
index 0000000..50247e8
--- /dev/null
+++ b/designate_tempest_plugin/schemas/v1/domains_schema.py
@@ -0,0 +1,123 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+#
+#    Licensed 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.
+
+list_domains = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "domains": {
+                "type": "array",
+                "items": {
+                    "type": "object",
+                    "properties": {
+                        "created_at": {"type": "string"},
+                        "description": {
+                            "anyOf": [{'type': 'string'}, {"type": "null"}]},
+                        "email": {"type": "string"},
+                        "id": {"type": "string"},
+                        "name": {"type": "string"},
+                        "serial": {"type": "number"},
+                        "ttl": {"type": "number"},
+                        "updated_at": {
+                            "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                    },
+                    'required': ['id', 'name', 'email', 'ttl']
+                }
+            }
+        },
+        'required': ['domains']
+    }
+}
+
+create_domain = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "domain": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "description": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]},
+                    "email": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "serial": {"type": "number"},
+                    "ttl": {"type": "number"},
+                    "updated_at": {"type": "null"}
+                },
+                "required": ['id', 'name', 'email', 'ttl']
+            }
+        }
+    },
+    "required": ['domain']
+}
+
+update_domain = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "domain": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "description": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]},
+                    "email": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "serial": {"type": "number"},
+                    "ttl": {"type": "number"},
+                    "updated_at": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                },
+                "required": ['id', 'name', 'email', 'ttl']
+            }
+        }
+    },
+    "required": ['domain']
+}
+
+get_domain = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "domain": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "description": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]},
+                    "email": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "serial": {"type": "number"},
+                    "ttl": {"type": "number"},
+                    "updated_at": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                },
+                "required": ['id', 'name', 'email', 'ttl']
+            }
+        }
+    },
+    "required": ['domain']
+}
+
+delete_domain = {
+    'status_code': [200],
+}
diff --git a/designate_tempest_plugin/schemas/v1/records_schema.py b/designate_tempest_plugin/schemas/v1/records_schema.py
new file mode 100644
index 0000000..ef81d5d
--- /dev/null
+++ b/designate_tempest_plugin/schemas/v1/records_schema.py
@@ -0,0 +1,126 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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.
+list_records = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "records": {
+                "type": "array",
+                "items": {
+                    "type": "object",
+                    "properties": {
+                        "created_at": {"type": "string"},
+                        "data": {"type": "string"},
+                        "description": {"type": "null"},
+                        "domain_id": {"type": "string"},
+                        "id": {"type": "string"},
+                        "name": {"type": "string"},
+                        "priority": {"type": "null"},
+                        "ttl": {"type": "null"},
+                        "type": {"type": "string"},
+                        "updated_at": {
+                            "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                    },
+                    'required': ['id', 'name', 'type', 'data']
+                }
+            }
+        },
+        'required': ['records']
+    }
+}
+
+create_record = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "record": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "data": {"type": "string"},
+                    "description": {"type": "null"},
+                    "domain_id": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "priority": {"type": "null"},
+                    "ttl": {"type": "null"},
+                    "type": {"type": "string"},
+                    "updated_at": {"type": "null"}
+                },
+                "required": ['id', 'name', 'type', 'domain_id']
+            }
+        }
+    },
+    "required": ['record']
+}
+
+update_record = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "record": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "data": {"type": "string"},
+                    "description": {"type": "null"},
+                    "domain_id": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "priority": {"type": "null"},
+                    "ttl": {"type": "null"},
+                    "type": {"type": "string"},
+                    "updated_at": {"type": "string"}
+                },
+                "required": ['id', 'name', 'type', 'domain_id']
+            }
+        }
+    },
+    "required": ['record']
+}
+
+get_record = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "record": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "data": {"type": "string"},
+                    "description": {"type": "null"},
+                    "domain_id": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "priority": {"type": "null"},
+                    "ttl": {"type": "null"},
+                    "type": {"type": "string"},
+                    "updated_at": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                },
+                "required": ['id', 'name', 'type', 'domain_id']
+            }
+        }
+    },
+    "required": ['record']
+}
+
+delete_record = {
+    'status_code': [200],
+}
diff --git a/designate_tempest_plugin/schemas/v1/servers_schema.py b/designate_tempest_plugin/schemas/v1/servers_schema.py
new file mode 100644
index 0000000..934917d
--- /dev/null
+++ b/designate_tempest_plugin/schemas/v1/servers_schema.py
@@ -0,0 +1,103 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+#
+#    Licensed 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.
+
+
+list_servers = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "servers": {
+                "type": "array",
+                "items": {
+                    "type": "object",
+                    "properties": {
+                        "created_at": {"type": "string"},
+                        "id": {"type": "string"},
+                        "name": {"type": "string"},
+                        "updated_at": {
+                            "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                    },
+                    'required': ['id', 'name']
+                }
+            }
+        },
+        'required': ['servers']
+    }
+}
+
+create_server = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "server": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "updated_at": {"type": "null"}
+                },
+                "required": ['id', 'name']
+            }
+        }
+    },
+    "required": ['server']
+}
+
+update_server = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "server": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "updated_at": {"type": "string"}
+                },
+                "required": ['id', 'name']
+            }
+        }
+    },
+    "required": ['server']
+}
+
+get_server = {
+    "status_code": [200],
+    "response_body": {
+        "type": "object",
+        "properties": {
+            "server": {
+                "type": "object",
+                "properties": {
+                    "created_at": {"type": "string"},
+                    "id": {"type": "string"},
+                    "name": {"type": "string"},
+                    "updated_at": {
+                        "anyOf": [{'type': 'string'}, {"type": "null"}]}
+                },
+                "required": ['id', 'name']
+            }
+        }
+    },
+    "required": ['server']
+}
+
+delete_server = {
+    'status_code': [200],
+}
diff --git a/designate_tempest_plugin/services/dns/admin/json/base.py b/designate_tempest_plugin/services/dns/admin/json/base.py
index 2714625..b9cfa1e 100644
--- a/designate_tempest_plugin/services/dns/admin/json/base.py
+++ b/designate_tempest_plugin/services/dns/admin/json/base.py
@@ -19,3 +19,10 @@
 class DnsClientAdminBase(base.DnsClientBase):
     """Base Admin API Tempest REST client for Designate API"""
     uri_prefix = 'admin'
+
+    CREATE_STATUS_CODES = [201, 202]
+    SHOW_STATUS_CODES = [200]
+    LIST_STATUS_CODES = [200]
+    PUT_STATUS_CODES = [200, 202]
+    UPDATE_STATUS_CODES = [200, 202]
+    DELETE_STATUS_CODES = [202, 204]
diff --git a/designate_tempest_plugin/services/dns/json/base.py b/designate_tempest_plugin/services/dns/json/base.py
index ef7260b..f9b1de7 100644
--- a/designate_tempest_plugin/services/dns/json/base.py
+++ b/designate_tempest_plugin/services/dns/json/base.py
@@ -49,6 +49,13 @@
 
     uri_prefix = ''
 
+    CREATE_STATUS_CODES = []
+    SHOW_STATUS_CODES = []
+    LIST_STATUS_CODES = []
+    PUT_STATUS_CODES = []
+    UPDATE_STATUS_CODES = []
+    DELETE_STATUS_CODES = []
+
     def serialize(self, object_dict):
         return json.dumps(object_dict)
 
@@ -114,7 +121,7 @@
 
         resp, body = self.post(uri, body=body, headers=headers,
                                extra_headers=extra_headers)
-        self.expected_success([201, 202], resp.status)
+        self.expected_success(self.CREATE_STATUS_CODES, resp.status)
 
         return resp, self.deserialize(resp, body)
 
@@ -130,7 +137,7 @@
 
         resp, body = self.get(uri, headers=headers)
 
-        self.expected_success(200, resp.status)
+        self.expected_success(self.SHOW_STATUS_CODES, resp.status)
 
         return resp, self.deserialize(resp, body)
 
@@ -145,7 +152,7 @@
 
         resp, body = self.get(uri)
 
-        self.expected_success(200, resp.status)
+        self.expected_success(self.LIST_STATUS_CODES, resp.status)
 
         return resp, self.deserialize(resp, body)
 
@@ -163,7 +170,7 @@
         uri = self.get_uri(resource, uuid=uuid, params=params)
         resp, body = self.put(uri, body=body)
 
-        self.expected_success([200, 202], resp.status)
+        self.expected_success(self.PUT_STATUS_CODES, resp.status)
 
         return resp, self.deserialize(resp, body)
 
@@ -182,7 +189,7 @@
 
         resp, body = self.patch(uri, body=body)
 
-        self.expected_success([200, 202], resp.status)
+        self.expected_success(self.UPDATE_STATUS_CODES, resp.status)
 
         return resp, self.deserialize(resp, body)
 
@@ -197,7 +204,7 @@
         uri = self.get_uri(resource, uuid=uuid, params=params)
 
         resp, body = self.delete(uri)
-        self.expected_success([202, 204], resp.status)
+        self.expected_success(self.DELETE_STATUS_CODES, resp.status)
         if resp.status == 202:
             body = self.deserialize(resp, body)
 
diff --git a/designate_tempest_plugin/services/dns/v1/__init__.py b/designate_tempest_plugin/services/dns/v1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/__init__.py
diff --git a/designate_tempest_plugin/services/dns/v1/json/__init__.py b/designate_tempest_plugin/services/dns/v1/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/json/__init__.py
diff --git a/designate_tempest_plugin/services/dns/v1/json/base.py b/designate_tempest_plugin/services/dns/v1/json/base.py
new file mode 100644
index 0000000..2b1c4f3
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/json/base.py
@@ -0,0 +1,28 @@
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+# Licensed 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 designate_tempest_plugin.services.dns.json import base
+
+handle_errors = base.handle_errors
+
+
+class DnsClientV1Base(base.DnsClientBase):
+    """Base API V1 Tempest REST client for Designate API"""
+    uri_prefix = 'v1'
+
+    CREATE_STATUS_CODES = [200]
+    SHOW_STATUS_CODES = [200]
+    LIST_STATUS_CODES = [200]
+    PUT_STATUS_CODES = [200]
+    UPDATE_STATUS_CODES = []
+    DELETE_STATUS_CODES = [200]
diff --git a/designate_tempest_plugin/services/dns/v1/json/domains_client.py b/designate_tempest_plugin/services/dns/v1/json/domains_client.py
new file mode 100644
index 0000000..2b76d503
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/json/domains_client.py
@@ -0,0 +1,95 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# All Rights Reserved.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 tempest import config
+
+from designate_tempest_plugin.schemas.v1 import domains_schema as schema
+from designate_tempest_plugin.services.dns.v1.json import base
+
+CONF = config.CONF
+
+
+class DomainsClient(base.DnsClientV1Base):
+    @base.handle_errors
+    def list_domains(self, params=None):
+        """List all domains."""
+        resp, body = self._list_request('domains', params=params)
+
+        self.validate_response(schema.list_domains, resp, body)
+
+        return resp, body['domains']
+
+    @base.handle_errors
+    def get_domain(self, uuid, params=None):
+        """Gets a specific zone.
+        :param uuid: Unique identifier of the domain in UUID format.
+        :param params: A Python dict that represents the query paramaters to
+                       include in the request URI.
+        :return: Serialized domain as a dictionary.
+        :return: A tuple with the server response and the deserialized domain.
+        """
+        resp, body = self._show_request('domains', uuid, params=params)
+
+        self.validate_response(schema.get_domain, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def delete_domain(self, uuid, params=None):
+        """Delete the given domain."""
+        resp, body = self._delete_request('domains', uuid, params=params)
+
+        self.validate_response(schema.delete_domain, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def create_domain(self, name, email, params=None, **kwargs):
+        """Creates a domain."""
+        post_body = {
+            "name": name,
+            "email": email
+        }
+
+        for option in ['ttl', 'description']:
+            post_param = option
+            value = kwargs.get(option)
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._create_request('domains', post_body, params=params)
+
+        self.validate_response(schema.create_domain, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def update_domain(self, uuid, params=None, **kwargs):
+        """Updates a domain."""
+        post_body = {}
+
+        for option in ['email', 'name', 'ttl', 'description']:
+            post_param = option
+            value = kwargs.get(option)
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._put_request('domains', uuid, post_body,
+                                       params=params)
+
+        self.validate_response(schema.update_domain, resp, body)
+
+        return resp, body
diff --git a/designate_tempest_plugin/services/dns/v1/json/records_client.py b/designate_tempest_plugin/services/dns/v1/json/records_client.py
new file mode 100644
index 0000000..432016e
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/json/records_client.py
@@ -0,0 +1,102 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# All Rights Reserved.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 tempest import config
+
+from designate_tempest_plugin.schemas.v1 import records_schema as schema
+from designate_tempest_plugin.services.dns.v1.json import base
+
+CONF = config.CONF
+
+
+class RecordsClient(base.DnsClientV1Base):
+    @base.handle_errors
+    def list_records(self, domain_uuid, params=None):
+        """List all records."""
+        base_uri = 'domains/%s/records' % (domain_uuid)
+
+        resp, body = self._list_request(base_uri, params=params)
+
+        self.validate_response(schema.list_records, resp, body)
+
+        return resp, body['records']
+
+    @base.handle_errors
+    def get_record(self, domain_uuid, uuid, params=None):
+        """Get the details of a record."""
+        base_uri = 'domains/%s/records' % (domain_uuid)
+
+        resp, body = self._show_request(base_uri, uuid, params=params)
+
+        self.validate_response(schema.get_record, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def delete_record(self, domain_uuid, uuid, params=None):
+        """Delete the given record."""
+        base_uri = 'domains/%s/records' % (domain_uuid)
+
+        resp, body = self._delete_request(base_uri, uuid, params=params)
+
+        self.validate_response(schema.delete_record, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def create_record(self, domain_uuid, name, type, data, params=None,
+                      **kwargs):
+        """Creates a record."""
+        base_uri = 'domains/%s/records' % (domain_uuid)
+
+        post_body = {
+            "name": name,
+            "type": type,
+            "data": data
+        }
+
+        for option in ['ttl', 'priority', 'description']:
+            post_param = option
+            value = kwargs.get(option)
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._create_request(base_uri, post_body, params=params)
+
+        self.validate_response(schema.create_record, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def update_record(self, domain_uuid, uuid, params=None, **kwargs):
+        """Updates a record."""
+        base_uri = 'domains/%s/records' % (domain_uuid)
+
+        post_body = {}
+
+        for option in ['name', 'type', 'data', 'ttl', 'priority',
+                       'description']:
+            post_param = option
+            value = kwargs.get(option)
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._put_request(base_uri, uuid, post_body,
+                                       params=params)
+
+        self.validate_response(schema.update_record, resp, body)
+
+        return resp, body
diff --git a/designate_tempest_plugin/services/dns/v1/json/servers_client.py b/designate_tempest_plugin/services/dns/v1/json/servers_client.py
new file mode 100644
index 0000000..9268602
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v1/json/servers_client.py
@@ -0,0 +1,88 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# All Rights Reserved.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 tempest import config
+
+from designate_tempest_plugin.schemas.v1 import servers_schema as schema
+from designate_tempest_plugin.services.dns.v1.json import base
+
+CONF = config.CONF
+
+
+class ServersClient(base.DnsClientV1Base):
+    @base.handle_errors
+    def list_servers(self, params=None):
+        """List all servers."""
+        resp, body = self._list_request('servers', params=params)
+
+        self.validate_response(schema.list_servers, resp, body)
+
+        return resp, body['servers']
+
+    @base.handle_errors
+    def get_server(self, uuid, params=None):
+        """Get the details of a server."""
+        resp, body = self._show_request('servers', uuid, params=params)
+
+        self.validate_response(schema.get_server, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def delete_server(self, uuid, params=None):
+        """Delete the given server."""
+        resp, body = self._delete_request('servers', uuid, params=params)
+
+        self.validate_response(schema.delete_server, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def create_server(self, name, params=None, **kwargs):
+        """Creates a server."""
+        post_body = {
+            "name": name,
+        }
+
+        for option in ['name']:
+            value = kwargs.get(option)
+            post_param = option
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._create_request('servers', post_body, params=params)
+
+        self.validate_response(schema.create_server, resp, body)
+
+        return resp, body
+
+    @base.handle_errors
+    def update_server(self, uuid, params=None, **kwargs):
+        """Updates a server."""
+        post_body = {}
+
+        for option in ['name']:
+            post_param = option
+            value = kwargs.get(option)
+            if value is not None:
+                post_body[post_param] = value
+
+        resp, body = self._put_request('servers', uuid, post_body,
+                                       params=params)
+
+        self.validate_response(schema.update_server, resp, body)
+
+        return resp, body
diff --git a/designate_tempest_plugin/services/dns/v2/json/base.py b/designate_tempest_plugin/services/dns/v2/json/base.py
index a679fd6..ad3e4d6 100644
--- a/designate_tempest_plugin/services/dns/v2/json/base.py
+++ b/designate_tempest_plugin/services/dns/v2/json/base.py
@@ -19,3 +19,10 @@
 class DnsClientV2Base(base.DnsClientBase):
     """Base API V2 Tempest REST client for Designate API"""
     uri_prefix = 'v2'
+
+    CREATE_STATUS_CODES = [201, 202]
+    SHOW_STATUS_CODES = [200]
+    LIST_STATUS_CODES = [200]
+    PUT_STATUS_CODES = [200, 202]
+    UPDATE_STATUS_CODES = [200, 202]
+    DELETE_STATUS_CODES = [202, 204]
diff --git a/designate_tempest_plugin/tests/api/admin/test_quotas.py b/designate_tempest_plugin/tests/api/admin/test_quotas.py
index e2d89af..ba77711 100644
--- a/designate_tempest_plugin/tests/api/admin/test_quotas.py
+++ b/designate_tempest_plugin/tests/api/admin/test_quotas.py
@@ -20,7 +20,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseQuotasTest(base.BaseDnsTest):
+class BaseQuotasTest(base.BaseDnsAdminTest):
     # see: https://bugs.launchpad.net/designate/+bug/1573141
     excluded_keys = ['api_expected_size']
 
diff --git a/designate_tempest_plugin/tests/api/v1/__init__.py b/designate_tempest_plugin/tests/api/v1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/designate_tempest_plugin/tests/api/v1/__init__.py
diff --git a/designate_tempest_plugin/tests/api/v1/test_domains.py b/designate_tempest_plugin/tests/api/v1/test_domains.py
new file mode 100644
index 0000000..132df39
--- /dev/null
+++ b/designate_tempest_plugin/tests/api/v1/test_domains.py
@@ -0,0 +1,82 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# All Rights Reserved.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 six
+from tempest.common.utils import data_utils
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+
+from designate_tempest_plugin.tests import base
+
+
+class DnsDomainsTest(base.BaseDnsV1Test):
+    @classmethod
+    def setup_clients(cls):
+        super(DnsDomainsTest, cls).setup_clients()
+
+        cls.client = cls.os.domains_client
+
+    @classmethod
+    def setUpClass(cls):
+        super(DnsDomainsTest, cls).setUpClass()
+        cls.setup_domains = list()
+        for i in range(2):
+            name = data_utils.rand_name('domain') + '.com.'
+            email = data_utils.rand_name('dns') + '@testmail.com'
+            _, domain = cls.client.create_domain(name, email)
+            cls.setup_domains.append(domain)
+
+    @classmethod
+    def tearDownClass(cls):
+        for domain in cls.setup_domains:
+            cls.client.delete_domain(domain['id'])
+        super(DnsDomainsTest, cls).tearDownClass()
+
+    def _delete_domain(self, domain_id):
+        self.client.delete_domain(domain_id)
+        self.assertRaises(lib_exc.NotFound,
+                          self.client.get_domain, domain_id)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('a78a4a6a-77a6-4dab-a61a-17df9731bca8')
+    def test_list_domains(self):
+        # Get a list of domains
+        _, domains = self.client.list_domains()
+        # Verify domains created in setup class are in the list
+        for domain in self.setup_domains:
+            self.assertIn(domain['id'],
+                          six.moves.map(lambda x: x['id'], domains))
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('29f76dd4-2456-4e42-b0ca-bbffcc6bbf59')
+    def test_create_update_get_domain(self):
+        # Create Domain
+        d_name = data_utils.rand_name('domain') + '.com.'
+        d_email = data_utils.rand_name('dns') + '@testmail.com'
+        _, domain = self.client.create_domain(name=d_name, email=d_email)
+        self.addCleanup(self._delete_domain, domain['id'])
+        self.assertEqual(d_name, domain['name'])
+        self.assertEqual(d_email, domain['email'])
+        # Update Domain with  ttl
+        d_ttl = 3600
+        _, update_domain = self.client.update_domain(domain['id'],
+                                                   ttl=d_ttl)
+        self.assertEqual(d_ttl, update_domain['ttl'])
+        # Get the details of Domain
+        _, get_domain = self.client.get_domain(domain['id'])
+        self.assertEqual(update_domain['name'], get_domain['name'])
+        self.assertEqual(update_domain['email'], get_domain['email'])
+        self.assertEqual(update_domain['ttl'], get_domain['ttl'])
diff --git a/designate_tempest_plugin/tests/api/v1/test_records.py b/designate_tempest_plugin/tests/api/v1/test_records.py
new file mode 100644
index 0000000..21bffa4
--- /dev/null
+++ b/designate_tempest_plugin/tests/api/v1/test_records.py
@@ -0,0 +1,111 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P
+# All Rights Reserved.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 six
+from tempest.common.utils import data_utils
+from tempest import test
+
+from designate_tempest_plugin.tests import base
+
+
+class RecordsTest(base.BaseDnsV1Test):
+    @classmethod
+    def setup_clients(cls):
+        super(RecordsTest, cls).setup_clients()
+
+        cls.client = cls.os.records_client
+
+    @classmethod
+    def setUpClass(cls):
+        super(RecordsTest, cls).setUpClass()
+
+        # Creates domains and Records for testcase
+        cls.setup_records = list()
+        name = data_utils.rand_name('domain') + '.com.'
+        email = data_utils.rand_name('dns') + '@testmail.com'
+        _, cls.domain = cls.os.domains_client.create_domain(name, email)
+        # Creates a record with type as A
+        r_name = 'www.' + name
+        data1 = "192.0.2.3"
+        _, record = cls.client.create_record(
+            cls.domain['id'], name=r_name, data=data1,
+            type='A')
+        cls.setup_records.append(record)
+        # Creates a record with type AAAA
+        data2 = "2001:db8:0:1234:0:5678:9:12"
+        _, record = cls.client.create_record(
+            cls.domain['id'], name=r_name,
+            data=data2, type='AAAA')
+        cls.setup_records.append(record)
+
+    @classmethod
+    def tearDownClass(cls):
+        for record in cls.setup_records:
+            cls.client.delete_record(cls.domain['id'], record['id'])
+        cls.os.domains_client.delete_domain(cls.domain['id'])
+
+    def _delete_record(self, domain_id, record_id):
+        self.client.delete_record(domain_id, record_id)
+        # TODO(kiall): Records in v1 should 404 immediatly after deletion.
+        # self.assertRaises(lib_exc.NotFound,
+        #                   self.client.get_record, domain_id, record_id)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('4c7bee47-68a4-4668-81f9-fa973ddfa1f1')
+    def test_list_records_for_domain(self):
+        # Get a list of records for a domain
+        _, records = self.client.list_records(self.domain['id'])
+        # Verify records created in setup class are in the list
+        for record in self.setup_records:
+            self.assertIn(record['id'],
+                          six.moves.map(lambda x: x['id'], records))
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('1714fe3a-8a29-420e-a7dc-8209c7c174de')
+    def test_create_update_get_delete_record(self):
+        # Create Domain
+        name = data_utils.rand_name('domain') + '.com.'
+        email = data_utils.rand_name('dns') + '@testmail.com'
+        _, domain = self.os.domains_client.create_domain(name, email)
+        self.addCleanup(self.os.domains_client.delete_domain, domain['id'])
+        # Create Record
+        r_name = 'www.' + name
+        r_data = "192.0.2.4"
+        _, record = self.client.create_record(domain['id'],
+                                              name=r_name, data=r_data,
+                                              type='A')
+        self.addCleanup(self._delete_record, domain['id'], record['id'])
+        self.assertIsNotNone(record['id'])
+        self.assertEqual(domain['id'], record['domain_id'])
+        self.assertEqual(r_name, record['name'])
+        self.assertEqual(r_data, record['data'])
+        self.assertEqual('A', record['type'])
+        # Update Record with data and ttl
+        r_data1 = "192.0.2.5"
+        r_ttl = 3600
+        _, update_record = self.client.update_record(domain['id'],
+                                                     record['id'],
+                                                     name=r_name, type='A',
+                                                     data=r_data1, ttl=r_ttl)
+        self.assertEqual(r_data1, update_record['data'])
+        self.assertEqual(r_ttl, update_record['ttl'])
+        # GET record
+        _, get_record = self.client.get_record(domain['id'], record['id'])
+        self.assertEqual(update_record['data'], get_record['data'])
+        self.assertEqual(update_record['name'], get_record['name'])
+        self.assertEqual(update_record['type'], get_record['type'])
+        self.assertEqual(update_record['ttl'], get_record['ttl'])
+        self.assertEqual(update_record['domain_id'], get_record['domain_id'])
diff --git a/designate_tempest_plugin/tests/api/v1/test_servers.py b/designate_tempest_plugin/tests/api/v1/test_servers.py
new file mode 100644
index 0000000..a2ac54c
--- /dev/null
+++ b/designate_tempest_plugin/tests/api/v1/test_servers.py
@@ -0,0 +1,97 @@
+# Copyright 2014 Hewlett-Packard Development Company, L.P.
+# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
+#
+#    Licensed 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 six
+from tempest.common.utils import data_utils
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+from tempest import config
+
+from designate_tempest_plugin.tests import base
+
+
+CONF = config.CONF
+
+
+class ServersAdminTest(base.BaseDnsV1Test):
+    """
+    Tests Servers API Create, Get, List and Delete
+    that require admin privileges
+    """
+    credentials = ['admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ServersAdminTest, cls).setup_clients()
+
+        cls.client = cls.os_adm.servers_client
+
+    @classmethod
+    def skip_checks(cls):
+        super(ServersAdminTest, cls).skip_checks()
+
+        if not CONF.dns_feature_enabled.api_v1_servers:
+            skip_msg = ("%s skipped as designate V1 servers API is not "
+                        "available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersAdminTest, cls).setUpClass()
+
+        cls.setup_servers = list()
+        for i in range(2):
+            name = data_utils.rand_name('dns-server') + '.com.'
+            _, server = cls.client.create_server(name)
+            cls.setup_servers.append(server)
+
+    @classmethod
+    def tearDownClass(cls):
+        for server in cls.setup_servers:
+            cls.client.delete_server(server['id'])
+        super(ServersAdminTest, cls).tearDownClass()
+
+    def _delete_server(self, server_id):
+        self.client.delete_server(server_id)
+        self.assertRaises(lib_exc.NotFound,
+                          self.client.get_server, server_id)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('0296fb0c-f400-4b52-9be4-a24f37646e3f')
+    def test_list_servers(self):
+        # Get a list of servers
+        _, servers = self.client.list_servers()
+        # Verify servers created in setup class are in the list
+        for server in self.setup_servers:
+            self.assertIn(server['id'],
+                          six.moves.map(lambda x: x['id'], servers))
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('7d18fdfc-3959-4c3f-9855-0bf2f8c9ade2')
+    def test_create_update_get_delete_server(self):
+        # Create Dns Server
+        s_name1 = data_utils.rand_name('dns-server') + '.com.'
+        _, server = self.client.create_server(s_name1)
+        self.addCleanup(self._delete_server, server['id'])
+        self.assertEqual(s_name1, server['name'])
+        self.assertIsNotNone(server['id'])
+        # Update Dns Server
+        s_name2 = data_utils.rand_name('update-dns-server') + '.com.'
+        _, update_server = self.client.update_server(server['id'],
+                                                     name=s_name2)
+        self.assertEqual(s_name2, update_server['name'])
+        # Get the details of Server
+        _, get_server = self.client.get_server(server['id'])
+        self.assertEqual(update_server['name'], get_server['name'])
diff --git a/designate_tempest_plugin/tests/api/v2/test_blacklists.py b/designate_tempest_plugin/tests/api/v2/test_blacklists.py
index 791a22c..81178cf 100644
--- a/designate_tempest_plugin/tests/api/v2/test_blacklists.py
+++ b/designate_tempest_plugin/tests/api/v2/test_blacklists.py
@@ -22,7 +22,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseBlacklistsTest(base.BaseDnsTest):
+class BaseBlacklistsTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'links']
 
 
diff --git a/designate_tempest_plugin/tests/api/v2/test_pool.py b/designate_tempest_plugin/tests/api/v2/test_pool.py
index 47e3324..a5c6e66 100644
--- a/designate_tempest_plugin/tests/api/v2/test_pool.py
+++ b/designate_tempest_plugin/tests/api/v2/test_pool.py
@@ -23,7 +23,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BasePoolTest(base.BaseDnsTest):
+class BasePoolTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'links', 'ns_records']
 
     def _assertExpectedNSRecords(self, expected, actual, expected_key):
diff --git a/designate_tempest_plugin/tests/api/v2/test_recordset.py b/designate_tempest_plugin/tests/api/v2/test_recordset.py
index 1c9d87d..4e0f0fb 100644
--- a/designate_tempest_plugin/tests/api/v2/test_recordset.py
+++ b/designate_tempest_plugin/tests/api/v2/test_recordset.py
@@ -21,7 +21,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseRecordsetsTest(base.BaseDnsTest):
+class BaseRecordsetsTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'version', 'links',
                      'type']
 
diff --git a/designate_tempest_plugin/tests/api/v2/test_tld.py b/designate_tempest_plugin/tests/api/v2/test_tld.py
index 46e5b48..bdec93e 100644
--- a/designate_tempest_plugin/tests/api/v2/test_tld.py
+++ b/designate_tempest_plugin/tests/api/v2/test_tld.py
@@ -21,7 +21,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseTldTest(base.BaseDnsTest):
+class BaseTldTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'links']
 
 
diff --git a/designate_tempest_plugin/tests/api/v2/test_zones.py b/designate_tempest_plugin/tests/api/v2/test_zones.py
index f97e256..62f188e 100644
--- a/designate_tempest_plugin/tests/api/v2/test_zones.py
+++ b/designate_tempest_plugin/tests/api/v2/test_zones.py
@@ -22,7 +22,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseZonesTest(base.BaseDnsTest):
+class BaseZonesTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'version', 'links',
                     'status', 'action']
 
diff --git a/designate_tempest_plugin/tests/api/v2/test_zones_exports.py b/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
index d11bb64..c9350e6 100644
--- a/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
+++ b/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
@@ -21,7 +21,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseZoneExportsTest(base.BaseDnsTest):
+class BaseZoneExportsTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'version', 'links',
                      'status', 'location']
 
diff --git a/designate_tempest_plugin/tests/api/v2/test_zones_imports.py b/designate_tempest_plugin/tests/api/v2/test_zones_imports.py
index c2b5585..ff2d5ef 100644
--- a/designate_tempest_plugin/tests/api/v2/test_zones_imports.py
+++ b/designate_tempest_plugin/tests/api/v2/test_zones_imports.py
@@ -21,7 +21,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseZonesImportTest(base.BaseDnsTest):
+class BaseZonesImportTest(base.BaseDnsV2Test):
     excluded_keys = ['created_at', 'updated_at', 'version', 'links',
                      'status', 'message']
 
diff --git a/designate_tempest_plugin/tests/base.py b/designate_tempest_plugin/tests/base.py
index 6519a4f..9f24d62 100644
--- a/designate_tempest_plugin/tests/base.py
+++ b/designate_tempest_plugin/tests/base.py
@@ -13,16 +13,17 @@
 # under the License.
 import six
 from tempest import test
+from tempest import config
 
 from designate_tempest_plugin import clients
 
 
+CONF = config.CONF
+
+
 class BaseDnsTest(test.BaseTestCase):
     """Base class for DNS tests."""
 
-    # Use the Designate Client Manager
-    client_manager = clients.Manager
-
     # NOTE(andreaf) credentials holds a list of the credentials to be allocated
     # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
     # a list of roles - the first element of the list being a label, and the
@@ -33,8 +34,64 @@
     # credentials in the tests that require them.
     credentials = ['primary']
 
+    @classmethod
+    def skip_checks(cls):
+        super(BaseDnsTest, cls).skip_checks()
+
+        if not CONF.service_available.designate:
+            skip_msg = ("%s skipped as designate is not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
+
     def assertExpected(self, expected, actual, excluded_keys):
         for key, value in six.iteritems(expected):
             if key not in excluded_keys:
                 self.assertIn(key, actual)
                 self.assertEqual(value, actual[key], key)
+
+
+class BaseDnsV1Test(BaseDnsTest):
+    """Base class for DNS V1 API tests."""
+
+    # Use the Designate V1 Client Manager
+    client_manager = clients.ManagerV1
+
+    @classmethod
+    def skip_checks(cls):
+        super(BaseDnsV1Test, cls).skip_checks()
+
+        if not CONF.dns_feature_enabled.api_v1:
+            skip_msg = ("%s skipped as designate v1 API is not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+
+class BaseDnsV2Test(BaseDnsTest):
+    """Base class for DNS V2 API tests."""
+
+    # Use the Designate V2 Client Manager
+    client_manager = clients.ManagerV2
+
+    @classmethod
+    def skip_checks(cls):
+        super(BaseDnsV2Test, cls).skip_checks()
+
+        if not CONF.dns_feature_enabled.api_v2:
+            skip_msg = ("%s skipped as designate v2 API is not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+
+class BaseDnsAdminTest(BaseDnsTest):
+    """Base class for DNS Admin API tests."""
+
+    # Use the Designate V2 Client Manager
+    client_manager = clients.ManagerV2
+
+    @classmethod
+    def skip_checks(cls):
+        super(BaseDnsAdminTest, cls).skip_checks()
+        if not CONF.dns_feature_enabled.api_admin:
+            skip_msg = ("%s skipped as designate admin API is not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
diff --git a/designate_tempest_plugin/tests/scenario/v2/test_zones.py b/designate_tempest_plugin/tests/scenario/v2/test_zones.py
index ea807d8..afd5b40 100644
--- a/designate_tempest_plugin/tests/scenario/v2/test_zones.py
+++ b/designate_tempest_plugin/tests/scenario/v2/test_zones.py
@@ -21,7 +21,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class ZonesTest(base.BaseDnsTest):
+class ZonesTest(base.BaseDnsV2Test):
     @classmethod
     def setup_clients(cls):
         super(ZonesTest, cls).setup_clients()