def test_create_zone(cloud): """ Unit test for creating a new DNS zone. """ global __zone_id__ global __num_zones__ kwargs = {} kwargs['domain'] = 'domain.com' kwargs['type'] = 'master' kwargs['ttl'] = 172800 kwargs['extra'] = {} __num_zones__ = len(Zone.objects(cloud=cloud)) print "Zones initially %d" % __num_zones__ print "**** Create DNS zone with domain %s" % kwargs['domain'] Zone.add(owner=cloud.owner, cloud=cloud, id='', **kwargs) zones = Zone.objects() for zone in zones: if zone.domain == 'domain.com.': __zone_id__ = zone.id break if __zone_id__: if __num_zones__ == len(Zone.objects(cloud=cloud)) - 1: print "**DNS zone created succesfully on the provider and the DB" __num_zones__ += 1 print "__num_zones__: %d" % __num_zones__ else: raise Exception
def create_dns_zone(request): """ Create a new DNS zone under a specific cloud. --- """ auth_context = auth_context_from_request(request) cloud_id = request.matchdict['cloud'] auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("cloud", "create_resources", cloud_id) tags = auth_context.check_perm("zone", "add", None) # Try to get the specific cloud for which we will create the zone. try: cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id) except me.DoesNotExist: raise CloudNotFoundError params = params_from_request(request) new_zone = Zone.add(owner=cloud.owner, cloud=cloud, **params).as_dict() if tags: resolve_id_and_set_tags(auth_context.owner, 'zone', new_zone['id'], tags, cloud_id=cloud_id) # Schedule a UI update trigger_session_update(auth_context.owner, ['zones']) return new_zone
def find_best_matching_zone(owner, name): """ This is a static method that tries to extract a valid domain from the name provided, trying to find the best matching DNS zone. This only works with 'A', 'AAAA' and 'CNAME' type records. This is common for all providers, there's no need to override this. --- """ # TODO: Adding here for circular dependency issue. Need to fix this. from mist.api.dns.models import Zone # Split hostname in dot separated parts. parts = [part for part in name.split('.') if part] # Find all possible domains for this domain name, # longest first all_domains = {} for i in range(1, len(parts) - 1): subdomain = '.'.join(parts[:i]) domain = '.'.join(parts[i:]) + '.' all_domains[domain] = subdomain if not all_domains: raise BadRequestError("Couldn't extract a valid domain from " "the provided '%s'." % name) zones = Zone.objects(owner=owner) # We need to iterate over all the cloud DNS zones to find # any that is matching based on the domain. If one is found # then create an "A" type record with the provided name. for zone_candidate in zones: for domain, subdomain in all_domains.iteritems(): if zone_candidate.domain == domain: return zone_candidate raise BadRequestError("No DNS zone found, can't proceed with " "creating record '%s'." % name)
def create_dns_zone(request): """ Tags: dns --- Creates a new DNS zone under the given cloud. CREATE_RESOURCES permission required on cloud. ADD permission required on zone. --- cloud: in: path required: true type: string """ auth_context = auth_context_from_request(request) cloud_id = request.matchdict['cloud'] auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("cloud", "create_resources", cloud_id) tags, _ = auth_context.check_perm("zone", "add", None) try: cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id) except me.DoesNotExist: raise CloudNotFoundError params = params_from_request(request) new_zone = Zone.add(owner=cloud.owner, cloud=cloud, **params) new_zone.assign_to(auth_context.user) if tags: resolve_id_and_set_tags(auth_context.owner, 'zone', new_zone.id, tags, cloud_id=cloud_id) return new_zone.as_dict()
def list_cached_zones(self): """Returns zones stored in database for a specific cloud """ # FIXME: Move these imports to the top of the file when circular # import issues are resolved from mist.api.dns.models import Zone return Zone.objects(cloud=self.cloud, deleted=None)
def test_list_zones(cloud, load_staging_l_zones): """ Testing listing DNS zones """ global __zone_id__ global __num_zones__ response = cloud.ctl.dns.list_zones() __num_zones__ = len(Zone.objects(cloud=cloud)) print "Num zones response: %d" % len(response) if len(response) == __num_zones__: print "Success, we have %d zones" % len(response) else: raise Exception
def create_zone(create_zone_request=None): # noqa: E501 """Create zone Creates one or more zones on the specified cloud. If async is true, a jobId will be returned. READ permission required on cloud. CREATE_RESOURCES permission required on cloud. CREATE permission required on zone. # noqa: E501 :param create_zone_request: :type create_zone_request: dict | bytes :rtype: CreateZoneResponse """ from mist.api.methods import list_resources if connexion.request.is_json: create_zone_request = CreateZoneRequest.from_dict(connexion.request.get_json()) # noqa: E501 try: auth_context = connexion.context['token_info']['auth_context'] except KeyError: return 'Authentication failed', 401 params = delete_none(create_zone_request.to_dict()) try: [cloud], total = list_resources( auth_context, 'cloud', search=params.pop('cloud'), limit=1) except ValueError: return 'Cloud does not exist', 404 try: auth_context.check_perm("cloud", "read", cloud.id) auth_context.check_perm("cloud", "create_resources", cloud.id) tags, _ = auth_context.check_perm("zone", "add", None) except PolicyUnauthorizedError: return 'You are not authorized to perform this action', 403 params['domain'] = params.pop('name') try: new_zone = Zone.add(owner=cloud.owner, cloud=cloud, **params) except BadRequestError as e: return str(e), 400 except CloudUnauthorizedError: return 'You are not authorized to perform this action', 403 except ZoneCreationError as e: return str(e), 503 except ZoneListingError as e: return str(e), 503 except CloudUnavailableError as e: return str(e), 503 new_zone.assign_to(auth_context.user) if tags: resolve_id_and_set_tags(auth_context.owner, 'zone', new_zone.id, tags, cloud_id=cloud.id) return new_zone.as_dict()
def test_list_records(cloud, load_staging_l_records): """ Testing listing DNS records """ global __zone_id__ global __num_records__ # zone = Zone.objects.get(owner=cloud.owner, id=__zone_id__) # records = zone.ctl.list_records() # print len(records) # if len(records) == __num_records__ + 2: # print "List Records success" # else: # raise Exception zones = Zone.objects(owner=cloud.owner) for zone in zones: records = zone.ctl.list_records() for record in records: print record.as_dict()
def test_delete_record(cloud): """ Testing deleting a particular records from a DNS zone """ global __zone_id__ global __record_id__ # zone = Zone.objects.get(owner=cloud.owner, id=__zone_id__) # record = Record.objects.get(id=__record_id__) # try: # record.ctl.delete_record() # except Exception: # print "can't delete record: %s" % record.record_id # print "**** Record deleted successfully" zones = Zone.objects(owner=cloud.owner) print "We got %d zones" % len(zones) for zone in zones: records = Record.objects(zone=zone, type='A') for record in records: try: record.ctl.delete_record() except Exception: print "can't delete record: %s" % record.record_id print "**** Record deleted successfully"
def list_zones(self): """ This is the public method to call when requesting all the DNS zones under a specific cloud. """ # TODO: Adding here for circular dependency issue. Need to fix this. from mist.api.dns.models import Zone # Fetch zones from libcloud connection. pr_zones = self._list_zones__fetch_zones() zones = [] new_zones = [] for pr_zone in pr_zones: # FIXME: We are using the zone_id and owner instead of the # cloud_id to search for existing zones because providers # allow access to the same zone from multiple clouds so # we can end up adding the same zone many times under # different clouds. try: zones_q = Zone.objects(owner=self.cloud.owner, zone_id=pr_zone.id, deleted=None) for zone in zones_q: if zone.cloud.ctl.provider == self.cloud.ctl.provider: break else: raise Zone.DoesNotExist except Zone.DoesNotExist: log.info("Zone: %s/domain: %s not in the database, creating.", pr_zone.id, pr_zone.domain) zone = Zone(cloud=self.cloud, owner=self.cloud.owner, zone_id=pr_zone.id) new_zones.append(zone) zone.domain = pr_zone.domain zone.type = pr_zone.type zone.ttl = pr_zone.ttl zone.extra = pr_zone.extra try: zone.save() except me.ValidationError as exc: log.error("Error updating %s: %s", zone, exc.to_dict()) raise BadRequestError({ 'msg': exc.message, 'errors': exc.to_dict() }) except me.NotUniqueError as exc: log.error("Zone %s not unique error: %s", zone, exc) raise ZoneExistsError() zones.append(zone) self.cloud.owner.mapper.update(new_zones) # Delete any zones in the DB that were not returned by the provider # meaning they were deleted otherwise. Zone.objects( cloud=self.cloud, id__nin=[z.id for z in zones], deleted=None).update(set__deleted=datetime.datetime.utcnow()) # Format zone information. return zones
def _list_zones(self): """ Requesting all the DNS zones under a specific cloud. """ from mist.api.dns.models import Zone # Fetch zones from libcloud connection. pr_zones = self._list_zones__fetch_zones() zones = [] new_zones = [] for pr_zone in pr_zones: try: zone = Zone.objects.get(cloud=self.cloud, zone_id=pr_zone.id) except Zone.DoesNotExist: log.info("Zone: %s/domain: %s not in the database, creating.", pr_zone.id, pr_zone.domain) zone = Zone(cloud=self.cloud, owner=self.cloud.owner, zone_id=pr_zone.id) new_zones.append(zone) zone.deleted = None zone.domain = pr_zone.domain zone.type = pr_zone.type zone.ttl = pr_zone.ttl zone.extra = pr_zone.extra try: zone.save() except me.ValidationError as exc: log.error("Error updating %s: %s", zone, exc.to_dict()) raise BadRequestError({ 'msg': str(exc), 'errors': exc.to_dict() }) except me.NotUniqueError as exc: log.error("Zone %s not unique error: %s", zone, exc) raise ZoneExistsError() zones.append(zone) self.cloud.owner.mapper.update(new_zones) # Delete any zones in the DB that were not returned by the provider # meaning they were deleted otherwise. Zone.objects( cloud=self.cloud, id__nin=[z.id for z in zones], deleted=None).update(set__deleted=datetime.datetime.utcnow()) # Format zone information. return zones