def resource_setup(cls): super(RecordsetsTest, cls).resource_setup() zone_id = CONF.dns.zone_id if zone_id: LOG.info('Retrieve info from a zone') _, zone = cls.client.show_zone(zone_id) else: # Make sure we have an allowed TLD available tld_name = dns_data_utils.rand_zone_name(name="RecordsetsTest") cls.tld_name = f".{tld_name}" cls.class_tld = cls.admin_tld_client.create_tld( tld_name=tld_name[:-1]) LOG.info('Create a new zone') zone_name = dns_data_utils.rand_zone_name( name="recordsets_test_setup", suffix=cls.tld_name) zone = cls.client.create_zone(name=zone_name)[1] cls.addClassResourceCleanup( test_utils.call_and_ignore_notfound_exc, cls.client.delete_zone, zone['id']) LOG.info('Ensure we respond with ACTIVE') waiters.wait_for_zone_status(cls.client, zone['id'], 'ACTIVE') cls.zone = zone
def update_zone(self, uuid, email=None, ttl=None, description=None, wait_until=False, params=None): """Update a zone with the specified parameters. :param uuid: The unique identifier of the zone. :param email: The email for the zone. Default: Random Value :param ttl: The ttl for the zone. Default: Random Value :param description: A description of the zone. Default: Random Value :param wait_until: Block until the zone reaches the desiered status :param params: A Python dict that represents the query paramaters to include in the request URI. :return: A tuple with the server response and the updated zone. """ zone = { 'email': email or dns_data_utils.rand_email(), 'ttl': ttl or dns_data_utils.rand_ttl(), 'description': description or data_utils.rand_name('test-zone'), } resp, body = self._update_request('zones', uuid, zone, params=params) # Update Zone should Return a HTTP 202 self.expected_success(202, resp.status) if wait_until: waiters.wait_for_zone_status(self, body['id'], wait_until) return resp, body
def update_zone(self, uuid, email=None, ttl=None, description=None, wait_until=False, params=None): """Update a zone with the specified parameters. :param uuid: The unique identifier of the zone. :param email: The email for the zone. Default: Random Value :param ttl: The ttl for the zone. Default: Random Value :param description: A description of the zone. Default: Random Value :param wait_until: Block until the zone reaches the desiered status :param params: A Python dict that represents the query paramaters to include in the request URI. :return: A tuple with the server response and the updated zone. """ zone = { 'email': email or dns_data_utils.rand_email(), 'ttl': ttl or dns_data_utils.rand_ttl(), 'description': description or data_utils.rand_name('test-zone'), } resp, body = self._update_request('zones', uuid, zone, params=params) # Update Zone should Return a HTTP 202 self.expected_success(202, resp.status) if wait_until: waiters.wait_for_zone_status(self, body['id'], wait_until) return resp, body
def test_create_zone_import_and_wait_for_zone(self): name = dns_data_utils.rand_zone_name('testimport') zonefile = dns_data_utils.rand_zonefile_data(name=name) LOG.info('Import zone %r', name) _, zone_import = self.client.create_zone_import(zonefile) self.addCleanup(self.client.delete_zone_import, zone_import['id']) LOG.info('Wait for the zone import to COMPLETE') waiters.wait_for_zone_import_status(self.client, zone_import['id'], "COMPLETE") LOG.info('Check the zone import looks good') _, zone_import = self.client.show_zone_import(zone_import['id']) self.addCleanup(self.wait_zone_delete, self.zones_client, zone_import['zone_id']) self.assertEqual('COMPLETE', zone_import['status']) self.assertIsNotNone(zone_import['zone_id']) self.assertIsNotNone(zone_import['links'].get('zone')) LOG.info('Wait for the imported zone to go to ACTIVE') waiters.wait_for_zone_status(self.zones_client, zone_import['zone_id'], "ACTIVE") LOG.info('Check the imported zone looks good') _, zone = self.zones_client.show_zone(zone_import['zone_id']) self.assertEqual('NONE', zone['action']) self.assertEqual('ACTIVE', zone['status']) self.assertEqual(name, zone['name'])
def test_create_zone_import_and_wait_for_zone(self): name = dns_data_utils.rand_zone_name('testimport') zonefile = dns_data_utils.rand_zonefile_data(name=name) LOG.info('Import zone %r', name) _, zone_import = self.client.create_zone_import(zonefile) self.addCleanup(self.client.delete_zone_import, zone_import['id']) LOG.info('Wait for the zone import to COMPLETE') waiters.wait_for_zone_import_status(self.client, zone_import['id'], "COMPLETE") LOG.info('Check the zone import looks good') _, zone_import = self.client.show_zone_import(zone_import['id']) self.assertEqual('COMPLETE', zone_import['status']) self.assertIsNotNone(zone_import['zone_id']) self.assertIsNotNone(zone_import['links'].get('zone')) LOG.info('Wait for the imported zone to go to ACTIVE') waiters.wait_for_zone_status(self.zones_client, zone_import['zone_id'], "ACTIVE") LOG.info('Check the imported zone looks good') _, zone = self.zones_client.show_zone(zone_import['zone_id']) self.assertEqual('NONE', zone['action']) self.assertEqual('ACTIVE', zone['status']) self.assertEqual(name, zone['name'])
def test_create_and_delete_zone(self): LOG.info('Create a zone') zone_name = dns_data_utils.rand_zone_name( name="create_and_delete_zone", suffix=self.tld_name) zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, zone['id'], ignore_errors=lib_exc.NotFound) LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual(const.CREATE, zone['action']) self.assertEqual(const.PENDING, zone['status']) waiters.wait_for_zone_status(self.client, zone['id'], const.ACTIVE) LOG.info('Re-Fetch the zone') zone = self.client.show_zone(zone['id'])[1] LOG.info('Ensure we respond with NONE+ACTIVE') self.assertEqual(const.NONE, zone['action']) self.assertEqual(const.ACTIVE, zone['status']) LOG.info('Delete the zone') zone = self.client.delete_zone(zone['id'])[1] LOG.info('Ensure we respond with DELETE+PENDING') self.assertEqual(const.DELETE, zone['action']) self.assertEqual(const.PENDING, zone['status']) waiters.wait_for_zone_404(self.client, zone['id'])
def test_create_and_delete_zone(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id'], ignore_errors=lib_exc.NotFound) LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', zone['action']) self.assertEqual('PENDING', zone['status']) waiters.wait_for_zone_status( self.client, zone['id'], 'ACTIVE') LOG.info('Re-Fetch the zone') _, zone = self.client.show_zone(zone['id']) LOG.info('Ensure we respond with NONE+PENDING') self.assertEqual('NONE', zone['action']) self.assertEqual('ACTIVE', zone['status']) LOG.info('Delete the zone') _, zone = self.client.delete_zone(zone['id']) LOG.info('Ensure we respond with DELETE+PENDING') self.assertEqual('DELETE', zone['action']) self.assertEqual('PENDING', zone['status']) waiters.wait_for_zone_404(self.client, zone['id'])
def test_zone_create_propagates_to_nameservers(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id']) waiters.wait_for_zone_status(self.client, zone['id'], "ACTIVE") waiters.wait_for_query(self.query_client, zone['name'], "SOA")
def test_zone_create_propagates_to_nameservers(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id']) waiters.wait_for_zone_status(self.client, zone['id'], "ACTIVE") waiters.wait_for_query(self.query_client, zone['name'], "SOA")
def test_create_and_delete_zone(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id'], ignore_errors=lib_exc.NotFound) LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', zone['action']) self.assertEqual('PENDING', zone['status']) waiters.wait_for_zone_status(self.client, zone['id'], 'ACTIVE') LOG.info('Re-Fetch the zone') _, zone = self.client.show_zone(zone['id']) LOG.info('Ensure we respond with NONE+PENDING') self.assertEqual('NONE', zone['action']) self.assertEqual('ACTIVE', zone['status']) LOG.info('Delete the zone') _, zone = self.client.delete_zone(zone['id']) LOG.info('Ensure we respond with DELETE+PENDING') self.assertEqual('DELETE', zone['action']) self.assertEqual('PENDING', zone['status']) waiters.wait_for_zone_404(self.client, zone['id'])
def test_zone_create_propagates_to_nameservers(self): LOG.info('Create a zone') zone_name = dns_data_utils.rand_zone_name( name="zone_create_propagates", suffix=self.tld_name) zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, zone['id']) waiters.wait_for_zone_status(self.client, zone['id'], const.ACTIVE) waiters.wait_for_query(self.query_client, zone['name'], const.SOA)
def test_zone_delete_propagates_to_nameservers(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id'], ignore_errors=lib_exc.NotFound) waiters.wait_for_zone_status(self.client, zone['id'], "ACTIVE") waiters.wait_for_query(self.query_client, zone['name'], "SOA") LOG.info('Delete the zone') self.client.delete_zone(zone['id']) waiters.wait_for_zone_404(self.client, zone['id']) waiters.wait_for_query(self.query_client, zone['name'], "SOA", found=False)
def test_zone_delete_propagates_to_nameservers(self): LOG.info('Create a zone') _, zone = self.client.create_zone() self.addCleanup(self.client.delete_zone, zone['id'], ignore_errors=lib_exc.NotFound) waiters.wait_for_zone_status(self.client, zone['id'], "ACTIVE") waiters.wait_for_query(self.query_client, zone['name'], "SOA") LOG.info('Delete the zone') self.client.delete_zone(zone['id']) waiters.wait_for_zone_404(self.client, zone['id']) waiters.wait_for_query(self.query_client, zone['name'], "SOA", found=False)
def test_manually_trigger_update_secondary_zone_negative(self): # Create a PRIMARY zone LOG.info('Create a PRIMARY zone') zone_name = dns_data_utils.rand_zone_name( name="manually_trigger_update_primary", suffix=self.tld_name) pr_zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, pr_zone['id']) waiters.wait_for_zone_status(self.client, pr_zone['id'], 'ACTIVE') LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', pr_zone['action']) self.assertEqual('PENDING', pr_zone['status']) # Get the Name Servers created for a PRIMARY zone nameservers = [ dic['hostname'] for dic in self.client.show_zone_nameservers( pr_zone['id'])[1]['nameservers'] ] # Make sure that the nameservers are not available using DNS # query and if it does, skip the test. LOG.info('Check if NameServers are available, skip the test if not') for ns in nameservers: if self._query_nameserver(ns, 5, pr_zone['name'], zone_type='SOA') is True: raise self.skipException( "Nameserver:{} is available, but negative test scenario " "needs it to be unavailable, therefore test is " "skipped.".format(ns.strip('.'))) # Create a SECONDARY zone LOG.info('Create a SECONDARY zone') zone_name = dns_data_utils.rand_zone_name( name="manually_trigger_update_secondary", suffix=self.tld_name) sec_zone = self.client.create_zone(name=zone_name, zone_type=const.SECONDARY_ZONE_TYPE, primaries=nameservers)[1] self.addCleanup(self.wait_zone_delete, self.client, sec_zone['id']) LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', sec_zone['action']) self.assertEqual('PENDING', sec_zone['status']) # Manually trigger_update zone LOG.info('Manually Trigger an Update of a Secondary Zone when the ' 'nameservers not pingable. Expected: error status code 500') with self.assertRaisesDns(lib_exc.ServerFault, 'unknown', 500): self.client.trigger_manual_update(sec_zone['id'])
def resource_setup(cls): super(RecordsetsTest, cls).resource_setup() zone_id = CONF.dns.zone_id if zone_id: LOG.info('Retrieve info from a zone') _, zone = cls.client.show_zone(zone_id) else: LOG.info('Create a new zone') _, zone = cls.client.create_zone() cls.addClassResourceCleanup( test_utils.call_and_ignore_notfound_exc, cls.client.delete_zone, zone['id']) LOG.info('Ensure we respond with ACTIVE') waiters.wait_for_zone_status(cls.client, zone['id'], 'ACTIVE') cls.zone = zone
def resource_setup(cls): super(RecordsetsTest, cls).resource_setup() zone_id = CONF.dns.zone_id if zone_id: LOG.info('Retrieve info from a zone') _, zone = cls.client.show_zone(zone_id) else: LOG.info('Create a new zone') _, zone = cls.client.create_zone() cls.addClassResourceCleanup( test_utils.call_and_ignore_notfound_exc, cls.client.delete_zone, zone['id']) LOG.info('Ensure we respond with ACTIVE') waiters.wait_for_zone_status(cls.client, zone['id'], 'ACTIVE') cls.zone = zone
def test_zone_abandon(self): LOG.info('Create a PRIMARY zone') zone_name = dns_data_utils.rand_zone_name(name="zone_abandon", suffix=self.tld_name) pr_zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, pr_zone['id']) waiters.wait_for_zone_status(self.client, pr_zone['id'], 'ACTIVE') LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', pr_zone['action']) self.assertEqual('PENDING', pr_zone['status']) LOG.info('Fetch the zone') self.client.show_zone(pr_zone['id']) LOG.info('Check that the zone was created on Nameserver/BIND') waiters.wait_for_query(self.query_client, pr_zone['name'], "SOA") # Test RBAC expected_allowed = ['os_admin'] if CONF.dns_feature_enabled.enforce_new_defaults: expected_allowed.append('os_system_admin') self.check_CUD_RBAC_enforcement( 'ZonesClient', 'abandon_zone', expected_allowed, False, pr_zone['id'], headers={'x-auth-sudo-project-id': pr_zone['project_id']}) # Test abandoning the zone LOG.info('Abandon a zone') self.admin_client.abandon_zone( pr_zone['id'], headers={'x-auth-sudo-project-id': pr_zone['project_id']}) LOG.info('Wait for the zone to become 404/NotFound in Designate') waiters.wait_for_zone_404(self.client, pr_zone['id']) LOG.info('Check that the zone is still exists in Nameserver/BIND') waiters.wait_for_query(self.query_client, pr_zone['name'], "SOA")
def test_zone_delete_propagates_to_nameservers(self): LOG.info('Create a zone') zone_name = dns_data_utils.rand_zone_name( name="zone_delete_propagates", suffix=self.tld_name) zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, zone['id'], ignore_errors=lib_exc.NotFound) waiters.wait_for_zone_status(self.client, zone['id'], const.ACTIVE) waiters.wait_for_query(self.query_client, zone['name'], const.SOA) LOG.info('Delete the zone') self.client.delete_zone(zone['id']) waiters.wait_for_zone_404(self.client, zone['id']) waiters.wait_for_query(self.query_client, zone['name'], const.SOA, found=False)
def test_zone_abandon_forbidden(self): LOG.info('Create a PRIMARY zone and add to the cleanup') zone_name = dns_data_utils.rand_zone_name( name="zone_abandon_forbidden", suffix=self.tld_name) pr_zone = self.client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.client, pr_zone['id']) waiters.wait_for_zone_status(self.client, pr_zone['id'], 'ACTIVE') LOG.info('Ensure we respond with CREATE+PENDING') self.assertEqual('CREATE', pr_zone['action']) self.assertEqual('PENDING', pr_zone['status']) LOG.info('Fetch the zone') self.client.show_zone(pr_zone['id']) LOG.info('Check that the zone was created on Nameserver/BIND') waiters.wait_for_query(self.query_client, pr_zone['name'], "SOA") LOG.info('Abandon a zone as primary client, Expected: should ' 'fail with: 403 forbidden') self.assertRaises(lib_exc.Forbidden, self.client.abandon_zone, zone_id=pr_zone['id'])
def _create_client_recordset(self, clients_list): """Create a zone and asoociated recordset using given credentials :param clients_list: supported credentials are: 'primary' and 'alt'. :return: dictionary of created recordsets. """ recordsets_created = {} for client in clients_list: if client == 'primary': # Create a zone and wait till it's ACTIVE zone_name = dns_data_utils.rand_zone_name(name="primary", suffix=self.tld_name) zone = self.zone_client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id']) waiters.wait_for_zone_status(self.zone_client, zone['id'], const.ACTIVE) # Create a recordset and wait till it's ACTIVE recordset_data = dns_data_utils.rand_recordset_data( record_type='A', zone_name=zone['name']) resp, body = self.client.create_recordset( zone['id'], recordset_data) self.addCleanup(self.wait_recordset_delete, self.client, self.zone['id'], body['id']) self.assertEqual(const.PENDING, body['status'], 'Failed, expected status is PENDING') LOG.info('Wait until the recordset is active') waiters.wait_for_recordset_status(self.client, zone['id'], body['id'], const.ACTIVE) # Add "project_id" into the recordset_data recordset_data['project_id'] = zone['project_id'] recordsets_created['primary'] = recordset_data if client == 'alt': # Create a zone and wait till it's ACTIVE zone_name = dns_data_utils.rand_zone_name(name="alt", suffix=self.tld_name) alt_zone = self.alt_zone_client.create_zone(name=zone_name)[1] self.addCleanup(self.wait_zone_delete, self.alt_zone_client, alt_zone['id']) waiters.wait_for_zone_status(self.alt_zone_client, alt_zone['id'], const.ACTIVE) # Create a recordset and wait till it's ACTIVE recordset_data = dns_data_utils.rand_recordset_data( record_type='A', zone_name=alt_zone['name']) resp, body = self.alt_client.create_recordset( alt_zone['id'], recordset_data) self.addCleanup(self.wait_recordset_delete, self.client, self.zone['id'], body['id']) self.assertEqual(const.PENDING, body['status'], 'Failed, expected status is PENDING') LOG.info('Wait until the recordset is active') waiters.wait_for_recordset_status(self.alt_client, alt_zone['id'], body['id'], const.ACTIVE) # Add "project_id" into the recordset_data recordset_data['project_id'] = alt_zone['project_id'] recordsets_created['alt'] = recordset_data LOG.info('Created resordsets are {}:'.format(recordsets_created)) return recordsets_created
def create_zone(self, name=None, email=None, ttl=None, description=None, attributes=None, wait_until=False, zone_type=const.PRIMARY_ZONE_TYPE, primaries=None, params=None, project_id=None): """Create a zone with the specified parameters. :param name: The name of the zone. Default: Random Value :param email: The email for the zone. Default: Random Value :param ttl: The ttl for the zone. Default: Random Value :param description: A description of the zone. Default: Random Value :param attributes: Key:Value pairs of information about this zone, and the pool the user would like to place the zone in. This information can be used by the scheduler to place zones on the correct pool. :param wait_until: Block until the zone reaches the desiered status :param zone_type: PRIMARY or SECONDARY Default: PRIMARY :param primaries: List of Primary nameservers. Required for SECONDARY Default: None :param params: A Python dict that represents the query paramaters to include in the request URI. :param project_id: When specified, overrides the project ID the zone will be associated with. :return: A tuple with the server response and the created zone. """ zone = { 'name': name or dns_data_utils.rand_zone_name() if name != '' else '', 'email': email or dns_data_utils.rand_email() if email != '' else '', 'ttl': ttl or dns_data_utils.rand_ttl() if ttl != 0 else 0, 'description': description or data_utils.rand_name('test-zone') if description != '' else '', 'attributes': attributes or { 'attribute_key': data_utils.rand_name('attribute_value') } } # If SECONDARY, "email" and "ttl" cannot be supplied if zone_type == const.SECONDARY_ZONE_TYPE: zone['type'] = zone_type del zone['email'] del zone['ttl'] if primaries is None: raise AttributeError( 'Error - "primaries" is mandatory parameter' ' for a SECONDARY zone type') zone['masters'] = primaries headers = None extra_headers = False if project_id: headers = {'x-auth-sudo-project-id': project_id} extra_headers = True resp, body = self._create_request('zones', zone, params=params, headers=headers, extra_headers=extra_headers) # Create Zone should Return a HTTP 202 self.expected_success(202, resp.status) if wait_until: waiters.wait_for_zone_status(self, body['id'], wait_until, headers=headers) return resp, body