Beispiel #1
0
def delete_ns_rrs_from_parent(view, parent_view, user):
    '''Delete subzone NS rrs from parent_view'''
    for rr in RR.query.filter(RR.zoneview_id == parent_view.id).filter(RR.name == view.zone.name + '.')\
            .filter(RR.type == 'NS'):
        Messages.info("Deleting RR %s from %s" %
                      (rr.bind_str(relative=True), rr.view))
        delete_single_rr(rr, user)
Beispiel #2
0
def free_ipblocks(ipblocks):
    freed_ipblocks = Ipblock.query.outerjoin(RR, Ipblock.id == RR.ipblock_id)\
        .filter(Ipblock.id.in_(ipblocks)).group_by(*Ipblock.__table__.columns).having(func.count(RR.id) == 0)
    for ipblock in freed_ipblocks:
        Messages.info('Freeing IP %s from layer3domain %s' %
                      (ipblock, ipblock.layer3domain.name))
        db.session.delete(ipblock)
Beispiel #3
0
 def wrapped(*args, **kwargs):
     Messages.save()
     for i in range(attempts):
         if i > 0:
             Messages.restore()
         try:
             return f(*args, **kwargs)
         except OperationalError as e:
             if i == (attempts - 1) or all(msg not in e.message
                                           for msg in lock_messages_error):
                 raise
             logging.info('Error processing transaction: %s. Retrying', e)
Beispiel #4
0
 def wrapper(*args, **kwargs):
     start = time.time()
     name = "%s(%s)" % (f.__name__, ', '.join(
         [safe_repr(a) for a in args] +
         ["%s=%s" % (k, safe_repr(v)) for k, v in list(kwargs.items())]))
     try:
         Messages.clear()
         g.tid = uuid.uuid4().hex[16:]
         logging.info("%s called %s", get_session_username(), name)
         return f(*args, **kwargs)
     finally:
         logging.info("%.3lf for %s", time.time() - start, name)
Beispiel #5
0
def get_rr_zone(name, zone, profile, notfound_message=True):
    if zone is None:
        if not name.endswith('.'):
            raise InvalidParameterError('Name must be a FQDN')
        zone = Zone.find(name)
        if zone is None:
            if notfound_message:
                Messages.info('No zone found for %s' % name)
            return None
    else:
        zone = get_zone(zone, profile)
        if name.endswith('.') and (not name.endswith('.' + zone.name + '.') and name != zone.name + '.'):
            raise InvalidParameterError('RR name %s not in zone %s' % (name, zone.name))
    return zone
Beispiel #6
0
 def f(self, key, value):
     try:
         value = int(value)
     except:
         value = value.upper()
     if type(value) == int:
         if reserved and value in reserved:
             raise InvalidParameterError("Invalid %s: %s" % (key, value))
         if value not in enum.values():
             Messages.warn('%s value %s is unassigned' % (key, value))
         return validate_uint8(self, key, value)
     else:
         if value in enum:
             return enum[value]
         else:
             raise InvalidParameterError("Invalid %s: %s" % (key, value))
Beispiel #7
0
def delete_with_references(query, free_ips, references, user):
    if references not in ('warn', 'error', 'delete', 'ignore'):
        raise InvalidParameterError(
            'Invalid value for references (must be warn, error, delete or ignore)'
        )
    rrs = query.all()
    if free_ips:
        ipblocks = set()
    to_delete = set()
    done = False
    while rrs and not done:
        to_delete |= set(rrs)
        orphaned = set()  # RRs orphaned by deleting rrs
        forward_reverse = set()  # forward or reverse RRs corresponding to rrs
        for rr in rrs:
            for orr in orphaned_references(rr, to_delete).all():
                if (rr.type == 'PTR' and orr.type in ('A', 'AAAA')) or \
                   (rr.type in ('A', 'AAAA') and orr.type == 'PTR'):
                    if references != 'ignore':
                        forward_reverse.add(orr)
                elif orr not in rrs:
                    orphaned.add(orr)
        if references in ('warn', 'error', 'ignore'):
            for rr in orphaned:
                logging.debug('%s referenced by:\n%s' % (rr.target, rr))
            for rr_target in set(rr.target for rr in orphaned):
                if references == 'warn':
                    Messages.warn('%s is referenced by other records' %
                                  rr_target)
                elif references == 'error':
                    raise DimError('%s is referenced by other records' %
                                   rr_target)
            done = True
        rrs = (orphaned | forward_reverse) - to_delete
        to_delete |= forward_reverse
    for rr in sorted(to_delete,
                     key=lambda rr:
                     (rr.type, rr.name, rr.target, rr.value, rr.id)):
        Messages.info("Deleting RR %s from %s" %
                      (rr.bind_str(relative=True), rr.view))
        if free_ips and rr.ipblock_id:
            ipblocks.add(rr.ipblock_id)
        delete_single_rr(rr, user)
    if free_ips and ipblocks:
        free_ipblocks(ipblocks)
Beispiel #8
0
def validate_strings(self, key, value):
    if isinstance(value, basestring):
        strings = _parse_strings(value)
    elif isinstance(value, list):
        strings = map(lambda v: _unescapify(v), value)
    else:
        raise ValueError('%s must be either a string or a list of strings' %
                         key)
    # Split strings longer than 255
    split_strings = []
    splits = 0
    for s in strings:
        while len(s) > 255:
            splits += 1
            split_strings.append(s[:255])
            s = s[255:]
        if s:
            split_strings.append(s)
    if splits:
        Messages.warn(
            'A TXT record string was longer than 255 characters, it was automatically divided.'
        )
    return ' '.join('"' + dns.rdata._escapify(s) + '"' for s in split_strings)
Beispiel #9
0
def create_subzone(new_zone, parent_zone, from_profile, soa_attributes, user,
                   inherit_rights=True, inherit_zone_groups=True):
    '''
    Create views and move rrs from parent zone.
    Records from the parent zones have priority over the ones from the profile.
    Copy @ NS records from subzone to parent zone.
    If inherit_rights is True, inherit user rights from parent zone.
    If inherit_zone_groups is True, inherit zone-group membership from parent zone. No zone-group rights are checked.
    This is necessary so net_admins can create subnets without access to the zone-group
    where the parent reverse zone is a member.
    If inherit_owner is True, inherit the owner from parent zone.
    '''
    # map parent view id to child view
    view_id_map = {}
    parent_views_ids = [view.id for view in parent_zone.views]
    for view in parent_zone.views:
        view_id_map[view.id] = ZoneView.create(new_zone, view.name,
                                               from_profile=from_profile, soa_attributes=soa_attributes, copy_rrs=False)
    Messages.info('Creating views %s for zone %s' % (', '.join([view.name for view in new_zone.views]), new_zone.name))
    for rr in RR.query.filter(RR.zoneview_id.in_(parent_views_ids))\
            .filter(or_(RR.name.endswith('.' + new_zone.name + '.'),
                        RR.name == new_zone.name + '.')):
        view_msg = (' view ' + rr.view.name) if len(parent_zone.views) > 1 else ''
        msg_info = (rr.bind_str(relative=True),
                    new_zone.name + view_msg,
                    parent_zone.name + view_msg)
        rr.notify_delete()
        rr.view = view_id_map[rr.zoneview_id]
        rr.value = RR.get_class(rr.type).fqdn_target(rr.value, parent_zone.name)
        try:
            check_new_rr(rr)
            Messages.info('Moving RR %s in zone %s from zone %s' % msg_info)
            rr.notify_insert()
        except InvalidParameterError:
            db.session.delete(rr)
            Messages.warn('Rejected to move RR %s in zone %s, deleted RR from zone %s' % msg_info)
    if from_profile is not None:
        for view in new_zone.views:
            apply_profile(view, new_zone, from_profile)
    for parent_view in parent_zone.views:
        if inherit_zone_groups:
            for group in parent_view.groups:
                zone_group_add_zone(group, new_zone, view_id_map[parent_view.id])
        if inherit_rights:
            rights = AccessRight.query.filter_by(object_class='ZoneView', object_id=parent_view.id).all()
            for right in rights:
                for group in right.groups:
                    group.rights.add(AccessRight.find_or_create(access=right.access,
                                                                object_id=view_id_map[parent_view.id].id,
                                                                object_class=right.object_class))
Beispiel #10
0
def create_single_rr(name,
                     rr_type,
                     zone,
                     view,
                     user,
                     overwrite=False,
                     **kwargs):
    '''
    :type zone: Zone
    :type view: string
    :param view: name of the view
    :param rr_type: RR type (string)
    :return: True if the record was created or already existed
    '''
    view = get_view(zone, view)
    existed = False
    created = True
    name = make_fqdn(name, view.zone.name)
    rr_query = RR.query.filter(RR.name == name).filter(RR.type == rr_type)\
        .join(ZoneView).filter(RR.view == view)
    new_rr = RR.create(name=name, type=rr_type, view=view, **kwargs)
    rrs = rr_query.all()
    if rrs:
        if overwrite:
            for rr in rrs:
                Messages.warn("Deleting RR %s from %s" %
                              (rr.bind_str(relative=True), rr.view))
                delete_single_rr(rr, user)
        else:
            samerr = None
            for rr in rrs:
                if rr.value == new_rr.value and (rr.type not in (
                        'A', 'AAAA', 'PTR') or rr.ipblock == new_rr.ipblock):
                    samerr = rr
                    break
            if samerr:
                created = False
                existed = True
                Messages.info("%s already exists" % samerr)
            else:
                if rr_type == 'PTR':  # Don't allow PTR round robin records
                    created = False
                    Messages.warn("Not overwriting: %s" % rrs[0])
                else:
                    Messages.warn(
                        "The name %s already existed, creating round robin record"
                        % name)
    if created:
        if rr_type == 'RP':
            point_to = _same_view_or_different_zone(new_rr).filter(
                RR.name == new_rr.target)
            if point_to.filter(RR.type == 'TXT').count() == 0:
                Messages.warn('TXT Record %s not found' % (new_rr.target, ))
        elif rr_type == 'SSHFP':
            same_name = _same_view_or_different_zone(new_rr).filter(
                RR.name == new_rr.name)
            if same_name.filter(or_(RR.type == 'A',
                                    RR.type == 'AAAA')).count() == 0:
                Messages.warn('No A or AAAA found for %s' % (new_rr.name, ))
        check_new_rr(new_rr)
        Messages.info("Creating RR {rr}{comment_msg} in {view_msg}".format(
            rr=new_rr.bind_str(relative=True),
            comment_msg=' comment {0}'.format(kwargs['comment']) if kwargs.get(
                'comment', None) else '',
            view_msg=new_rr.view))
        if new_rr.target and rr_type not in ['PTR', 'RP']:
            # Creating a PTR record also creates the A/AAAA record
            if _same_view_or_different_zone(new_rr).filter(
                    RR.name == new_rr.target).count() == 0:
                Messages.warn('%s does not exist.' % new_rr.target)
        new_rr.insert()
    return created or existed