def _queue_auto_ptr_data(self, auto_ptr_data): """ Queue auto PTR data as incremental updates against respective reverse zones. """ if not auto_ptr_data: return if not len(auto_ptr_data): return if not settings['auto_reverse']: return db_session = self.db_session # Create new update_group ug_dict = {} auto_ptr_privilege_flag = False for ptr_data in auto_ptr_data: # Ignore addresses we don't have reverse zone for query = db_session.query(ZoneSM)\ .join(ReverseNetwork)\ .filter(":address <<= reverse_networks.network")\ .params(address = ptr_data['address']) query = ZoneSM.query_is_not_deleted(query) query = ZoneSM.query_inc_updates(query) query = query.order_by(ReverseNetwork.network.desc())\ .limit(1) try: zone_sm = query.one() except NoResultFound: continue # Ignore invalid host names if not is_inet_hostname(ptr_data['hostname'], absolute=True, wildcard=False): log_error("Hostname '%s' is not a valid hostname." % ptr_data['hostname']) continue # Determine proposed update operation update_op = RROP_PTR_UPDATE_FORCE if ptr_data['force_reverse'] \ else RROP_PTR_UPDATE # Execute privilege checks ahead of time to save unnecessary churn # Better than needlessly going through whole rigamorole of # incremental update processing later on for no effect #1 See if old PTR exists to retrieve any RR reference # Both following also used lower down when generating RR_PTR label = label_from_address(ptr_data['address']) rr_ref = find_reference(db_session, ptr_data['reference'], raise_exc=False) # query for old record - this generates one select # Optimization - if check has previously suceeded, don't check # again as this is all checked further in if not auto_ptr_privilege_flag: qlabel= label[:label.rfind(zone_sm.name)-1] query = db_session.query(ResourceRecord)\ .filter(ResourceRecord.label == qlabel)\ .filter(ResourceRecord.zi_id == zone_sm.zi_candidate_id)\ .filter(ResourceRecord.disable == False)\ .filter(ResourceRecord.type_ == RRTYPE_PTR) old_rrs = query.all() old_rr = old_rrs[0] if len(old_rrs) else None # Check that we can proceed, only if check has not succeded yet if not check_auto_ptr_privilege(rr_ref, self.sectag, zone_sm, old_rr): if old_rr: log_debug("Zone '%s' - can't replace '%s' PTR" " as neither" " sectags '%s' vs '%s'" " references '%s' vs '%s'/'%s' (old PTR/rev zone)" "match ," " or values not given." % (zone_sm.name, old_rr.label, self.sectag.sectag, settings['admin_sectag'], rr_ref, old_rr.reference, zone_sm.reference)) else: log_debug("Zone '%s' - can't add '%s' PTR as neither" " sectags '%s' vs '%s'" " references '%s' vs '%s' (rev zone) match," " or values not given." % (zone_sm.name, qlabel, self.sectag.sectag, settings['admin_sectag'], rr_ref, zone_sm.reference)) continue auto_ptr_privilege_flag = True # Create a new update group if zone has not been seen before. try: update_group, zone_ttl = ug_dict.get(zone_sm) except (ValueError, TypeError): # Obtain reverse zone_ttl so PTR rrs can be created # Use candidate ZI as it always is available. # zi is published zi zi = self._get_zi(zone_sm.zi_candidate_id) if not zi: log_error("Zone '%s': does not have candidate zi." % zone_sm.name) continue zone_ttl = zi.zone_ttl update_group = new_update_group(db_session, None, zone_sm, None, ptr_only=True, sectag=self.sectag.sectag) ug_dict[zone_sm] = (update_group, zone_ttl) # Allocate RR_PTR update record rr = RR_PTR(label=label, zone_ttl=zone_ttl, rdata=ptr_data['hostname'], disable=ptr_data['disable'], domain=zone_sm.name, update_op=update_op) rr.ref_id = rr_ref.id_ if rr_ref else None rr.reference = rr_ref # Chain on RR_PTR update record update_group.update_ops.append(rr) # Flush everything to disk db_session.flush() # Issue zone refreshes to implement PTR changes for zone_sm in ug_dict: if zone_sm.is_disabled(): continue exec_zonesm(zone_sm, ZoneSMDoRefresh) # Make sure everything is committed db_session.commit()
def _queue_auto_ptr_data(self, auto_ptr_data): """ Queue auto PTR data as incremental updates against respective reverse zones. """ if not auto_ptr_data: return if not len(auto_ptr_data): return if not settings['auto_reverse']: return db_session = self.db_session # Create new update_group ug_dict = {} auto_ptr_privilege_flag = False for ptr_data in auto_ptr_data: # Ignore addresses we don't have reverse zone for query = db_session.query(ZoneSM)\ .join(ReverseNetwork)\ .filter(text(":address <<= reverse_networks.network"))\ .params(address = ptr_data['address']) query = ZoneSM.query_is_not_deleted(query) query = ZoneSM.query_inc_updates(query) query = query.order_by(ReverseNetwork.network.desc())\ .limit(1) try: zone_sm = query.one() except NoResultFound: continue # Ignore invalid host names if not is_inet_hostname( ptr_data['hostname'], absolute=True, wildcard=False): log_error("Hostname '%s' is not a valid hostname." % ptr_data['hostname']) continue # Determine proposed update operation update_op = RROP_PTR_UPDATE_FORCE if ptr_data['force_reverse'] \ else RROP_PTR_UPDATE # Execute privilege checks ahead of time to save unnecessary churn # Better than needlessly going through whole rigamorole of # incremental update processing later on for no effect #1 See if old PTR exists to retrieve any RR reference # Both following also used lower down when generating RR_PTR label = label_from_address(ptr_data['address']) rr_ref = find_reference(db_session, ptr_data['reference'], raise_exc=False) # query for old record - this generates one select # Optimization - if check has previously suceeded, don't check # again as this is all checked further in if not auto_ptr_privilege_flag: qlabel = label[:label.rfind(zone_sm.name) - 1] query = db_session.query(ResourceRecord)\ .filter(ResourceRecord.label == qlabel)\ .filter(ResourceRecord.zi_id == zone_sm.zi_candidate_id)\ .filter(ResourceRecord.disable == False)\ .filter(ResourceRecord.type_ == RRTYPE_PTR) old_rrs = query.all() old_rr = old_rrs[0] if len(old_rrs) else None # Check that we can proceed, only if check has not succeded yet if not check_auto_ptr_privilege(rr_ref, self.sectag, zone_sm, old_rr): if old_rr: log_debug( "Zone '%s' - can't replace '%s' PTR" " as neither" " sectags '%s' vs '%s'" " references '%s' vs '%s'/'%s' (old PTR/rev zone)" "match ," " or values not given." % (zone_sm.name, old_rr.label, self.sectag.sectag, settings['admin_sectag'], rr_ref, old_rr.reference, zone_sm.reference)) else: log_debug("Zone '%s' - can't add '%s' PTR as neither" " sectags '%s' vs '%s'" " references '%s' vs '%s' (rev zone) match," " or values not given." % (zone_sm.name, qlabel, self.sectag.sectag, settings['admin_sectag'], rr_ref, zone_sm.reference)) continue auto_ptr_privilege_flag = True # Create a new update group if zone has not been seen before. try: update_group, zone_ttl = ug_dict.get(zone_sm) except (ValueError, TypeError): # Obtain reverse zone_ttl so PTR rrs can be created # Use candidate ZI as it always is available. # zi is published zi zi = self._get_zi(zone_sm.zi_candidate_id) if not zi: log_error("Zone '%s': does not have candidate zi." % zone_sm.name) continue zone_ttl = zi.zone_ttl update_group = new_update_group(db_session, None, zone_sm, None, ptr_only=True, sectag=self.sectag.sectag) ug_dict[zone_sm] = (update_group, zone_ttl) # Allocate RR_PTR update record rr = RR_PTR(label=label, zone_ttl=zone_ttl, rdata=ptr_data['hostname'], disable=ptr_data['disable'], domain=zone_sm.name, update_op=update_op) rr.ref_id = rr_ref.id_ if rr_ref else None rr.reference = rr_ref # Chain on RR_PTR update record update_group.update_ops.append(rr) # Flush everything to disk db_session.flush() # Issue zone refreshes to implement PTR changes for zone_sm in ug_dict: if zone_sm.is_disabled(): continue exec_zonesm(zone_sm, ZoneSMDoRefresh) # Make sure everything is committed db_session.commit()
def _data_to_update(self, name, update_data, update_type, change_by, admin_privilege=False, helpdesk_privilege=False): """ Construct an update group for a zone, from supplied RRS and comments. Functional equivalent of _data_to_zi() above, but for incremental updates """ # Function start db_session = self.db_session # Check that update_type is supplied if not update_type: raise UpdateTypeRequired(name) # Get zone_sm to get zone ID etc zone_sm = self._get_zone_sm(name) zone_id = zone_sm.id_ # See if incremental updates are enabled for zone before queuing any if not zone_sm.inc_updates: raise IncrementalUpdatesDisabled(name) # Don't queue updates for a disabled zone if zone_sm.is_disabled(): raise ZoneDisabled(name) # Privilege check for no apex zones - admin only if not zone_sm.use_apex_ns and not admin_privilege: raise ZoneAdminPrivilegeNeeded(name) # Use candidate ZI as it always is available. zi is published zi zi = self._get_zi(zone_sm.zi_candidate_id) if not zi: raise ZiNotFound(name, zone_sm.zi_candidate_id) # Get value of zone_ttl so that RRs can be created zone_ttl = zi.zone_ttl # Create RRs list from published ZI pzi = PseudoZi(db_session, zi) # initialise data and zone consistency checking zi_cname_flag = False if len([r for r in pzi.rrs if r.type_ == RRTYPE_CNAME]): zi_cname_flag = True data_tools = DataTools(db_session, zone_sm, zi_cname_flag) # Create comments, and set up comment IDs, and stuff for handlng # RR Groups zi_data structures data_tools.rr_data_create_comments(update_data, zone_ttl, creating_real_zi=False) try: # Create new update_group update_group = new_update_group(db_session, update_type, zone_sm, change_by) except IntegrityError as exc: raise UpdateTypeAlreadyQueued(name, update_type) # Add RRs to DB and operate on Pseudo ZI data_tools.add_rrs(lambda :pzi.rrs, pzi.trial_op_rr, admin_privilege, helpdesk_privilege, update_group=update_group) data_tools.check_zi_consistency(pzi.rrs) # Get all data out to DB, and ids etc established. db_session.flush() # Refresh zone to implement updates exec_zonesm(zone_sm, ZoneSMDoRefresh) # Return auto update info return data_tools.get_auto_ptr_data()
def _data_to_update(self, name, update_data, update_type, change_by, admin_privilege=False, helpdesk_privilege=False): """ Construct an update group for a zone, from supplied RRS and comments. Functional equivalent of _data_to_zi() above, but for incremental updates """ # Function start db_session = self.db_session # Check that update_type is supplied if not update_type: raise UpdateTypeRequired(name) # Get zone_sm to get zone ID etc zone_sm = self._get_zone_sm(name) zone_id = zone_sm.id_ # See if incremental updates are enabled for zone before queuing any if not zone_sm.inc_updates: raise IncrementalUpdatesDisabled(name) # Don't queue updates for a disabled zone if zone_sm.is_disabled(): raise ZoneDisabled(name) # Privilege check for no apex zones - admin only if not zone_sm.use_apex_ns and not admin_privilege: raise ZoneAdminPrivilegeNeeded(name) # Use candidate ZI as it always is available. zi is published zi zi = self._get_zi(zone_sm.zi_candidate_id) if not zi: raise ZiNotFound(name, zone_sm.zi_candidate_id) # Get value of zone_ttl so that RRs can be created zone_ttl = zi.zone_ttl # Create RRs list from published ZI pzi = PseudoZi(db_session, zi) # initialise data and zone consistency checking zi_cname_flag = False if len([r for r in pzi.rrs if r.type_ == RRTYPE_CNAME]): zi_cname_flag = True data_tools = DataTools(db_session, zone_sm, zi_cname_flag) # Create comments, and set up comment IDs, and stuff for handlng # RR Groups zi_data structures data_tools.rr_data_create_comments(update_data, zone_ttl, creating_real_zi=False) try: # Create new update_group update_group = new_update_group(db_session, update_type, zone_sm, change_by) except IntegrityError as exc: raise UpdateTypeAlreadyQueued(name, update_type) # Add RRs to DB and operate on Pseudo ZI data_tools.add_rrs(lambda: pzi.rrs, pzi.trial_op_rr, admin_privilege, helpdesk_privilege, update_group=update_group) data_tools.check_zi_consistency(pzi.rrs) # Get all data out to DB, and ids etc established. db_session.flush() # Refresh zone to implement updates exec_zonesm(zone_sm, ZoneSMDoRefresh) # Return auto update info return data_tools.get_auto_ptr_data()