Ejemplo n.º 1
0
 def lock(self):
     """
     Tryies to write a lock file. Returns True if we get the lock, else
     return False.
     """
     try:
         if not os.path.exists(os.path.dirname(self.LOCK_FILE)):
             os.makedirs(os.path.dirname(self.LOCK_FILE))
         self.log("Attempting acquire mutext "
                  "({0})...".format(self.LOCK_FILE))
         self.lock_fd = open(self.LOCK_FILE, 'w+')
         fcntl.flock(self.lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
         self.log(self.format_title("Mutex Acquired"))
         return True
     except IOError, exc_value:
         self.lock_fd = None
         #  IOError: [Errno 11] Resource temporarily unavailable
         if exc_value[0] == 11:
             self.log(
                 "DNS build script attempted to acquire the "
                 "build mutux but another process already has it."
             )
             fail_mail(
                 "An attempt was made to start the DNS build script "
                 "while an instance of the script was already running. "
                 "The attempt was denied.",
                 subject="Concurrent DNS builds attempted.")
             return False
         else:
             raise
Ejemplo n.º 2
0
def build_zone_data(view, root_domain, soa, logf=None):
    """
    This function does the heavy lifting of building a zone. It coordinates
    getting all of the data out of the db into BIND format.

        :param soa: The SOA corresponding to the zone being built.
        :type soa: SOA

        :param root_domain: The root domain of this zone.
        :type root_domain: str

        :returns public_file_path: The path to the zone file in the STAGEING
            dir
        :type public_file_path: str
        :returns public_data: The data that should be written to
            public_file_path
        :type public_data: str

        :returns view_zone_file: The path to the zone file in the STAGEING dir
        :type view_zone_file: str
        :param view_data: The data that should be written to view_zone_file
        :type view_data: str
    """
    ztype = 'reverse' if root_domain.is_reverse else 'forward'
    if (soa.has_record_set(view=view, exclude_ns=True) and
            not root_domain.nameserver_set.filter(views=view).exists()):
        msg = ("The {0} zone has a records in the {1} view, but there are "
               "no nameservers in that view. A zone file for {1} won't be "
               "built. Use the search string 'zone=:{0} view=:{1}' to find "
               "the troublesome records".format(root_domain, view.name))
        fail_mail(msg, subject="Shitty edge case detected.")
        logf('LOG_WARNING', msg)
        return ''

    domains = soa.domain_set.all().order_by('name')

    # Bulid the mega filter!
    domain_mega_filter = Q(domain=root_domain)
    for domain in domains:
        domain_mega_filter = domain_mega_filter | Q(domain=domain)

    rdomain_mega_filter = Q(reverse_domain=root_domain)
    for reverse_domain in domains:
        rdomain_mega_filter = rdomain_mega_filter | Q(
            reverse_domain=reverse_domain)

    soa_data = render_soa_only(soa=soa, root_domain=root_domain)
    try:
        if ztype == "forward":
            view_data = render_forward_zone(view, domain_mega_filter)
        else:
            view_data = render_reverse_zone(view, domain_mega_filter,
                                            rdomain_mega_filter)
    except View.DoesNotExist:
        view_data = ""

    if view_data:
        view_data = soa_data + view_data

    return view_data
Ejemplo n.º 3
0
 def lock(self):
     """
     Tryies to write a lock file. Returns True if we get the lock, else
     return False.
     """
     try:
         if not os.path.exists(os.path.dirname(self.LOCK_FILE)):
             os.makedirs(os.path.dirname(self.LOCK_FILE))
         self.log("Attempting acquire mutext "
                  "({0})...".format(self.LOCK_FILE))
         self.lock_fd = open(self.LOCK_FILE, 'w+')
         fcntl.flock(self.lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
         self.log(self.format_title("Mutex Acquired"))
         return True
     except IOError, exc_value:
         self.lock_fd = None
         #  IOError: [Errno 11] Resource temporarily unavailable
         if exc_value[0] == 11:
             self.log("DNS build script attempted to acquire the "
                      "build mutux but another process already has it.")
             fail_mail(
                 "An attempt was made to start the DNS build script "
                 "while an instance of the script was already running. "
                 "The attempt was denied.",
                 subject="Concurrent DNS builds attempted.")
             return False
         else:
             raise
Ejemplo n.º 4
0
def build_zone_data(view, root_domain, soa, logf=None):
    """
    This function does the heavy lifting of building a zone. It coordinates
    getting all of the data out of the db into BIND format.

        :param soa: The SOA corresponding to the zone being built.
        :type soa: SOA

        :param root_domain: The root domain of this zone.
        :type root_domain: str

        :returns public_file_path: The path to the zone file in the STAGEING
            dir
        :type public_file_path: str
        :returns public_data: The data that should be written to
            public_file_path
        :type public_data: str

        :returns view_zone_file: The path to the zone file in the STAGEING dir
        :type view_zone_file: str
        :param view_data: The data that should be written to view_zone_file
        :type view_data: str
    """
    ztype = "reverse" if root_domain.is_reverse else "forward"
    if soa.has_record_set(view=view, exclude_ns=True) and not root_domain.nameserver_set.filter(views=view).exists():
        msg = (
            "The {0} zone has a records in the {1} view, but there are "
            "no nameservers in that view. A zone file for {1} won't be "
            "built. Use the search string 'zone=:{0} view=:{1}' to find "
            "the troublesome records".format(root_domain, view.name)
        )
        fail_mail(msg, subject="Shitty edge case detected.")
        logf("LOG_WARNING", msg)
        return ""

    domains = soa.domain_set.all().order_by("name")

    # Bulid the mega filter!
    domain_mega_filter = Q(domain=root_domain)
    for domain in domains:
        domain_mega_filter = domain_mega_filter | Q(domain=domain)

    rdomain_mega_filter = Q(reverse_domain=root_domain)
    for reverse_domain in domains:
        rdomain_mega_filter = rdomain_mega_filter | Q(reverse_domain=reverse_domain)

    soa_data = render_soa_only(soa=soa, root_domain=root_domain)
    try:
        if ztype == "forward":
            view_data = render_forward_zone(view, domain_mega_filter)
        else:
            view_data = render_reverse_zone(view, domain_mega_filter, rdomain_mega_filter)
    except View.DoesNotExist:
        view_data = ""

    if view_data:
        view_data = soa_data + view_data

    return view_data
Ejemplo n.º 5
0
 def _lock_failure(self, pid):
     fail_mail(
         'An attempt was made to start the DNS build script while an '
         'instance of the script was already running. The attempt was '
         'denied.',
         subject="Concurrent DNS builds attempted.")
     self.error('Failed to acquire lock on {0}. Process {1} currently '
                'has it.'.format(self.lock_file, pid))
Ejemplo n.º 6
0
 def _lock_failure(self, pid):
     fail_mail(
         'An attempt was made to start the DNS build script while an '
         'instance of the script was already running. The attempt was '
         'denied.',
         subject='Concurrent Cyder DNS builds attempted')
     self.error(
         'Failed to acquire lock on {0}. Process {1} currently '
         'has it.'.format(self.lock_file, pid))
Ejemplo n.º 7
0
 def _lock_failure(self, pid):
     self.log_err('Failed to acquire lock on {0}. Process {1} currently '
                  'has it.'.format(self.lock_file, pid),
                  to_stderr=False)
     fail_mail(
         'An attempt was made to start the DHCP build script while an '
         'instance of the script was already running. The attempt was '
         'denied.',
         subject="Concurrent DHCP builds attempted.")
     super(DHCPBuilder, self)._lock_failure(pid)
Ejemplo n.º 8
0
 def _lock_failure(self, pid):
     self.log_err(
         'Failed to acquire lock on {0}. Process {1} currently '
         'has it.'.format(self.lock_file, pid),
         to_stderr=False)
     fail_mail(
         'An attempt was made to start the DHCP build script while an '
         'instance of the script was already running. The attempt was '
         'denied.',
         subject="Concurrent DHCP builds attempted.")
     super(DHCPBuilder, self)._lock_failure(pid)
Ejemplo n.º 9
0
 def stop_update_exists(self):
     """
     Look for a file referenced by `STOP_UPDATE_FILE` and if it exists,
     cancel the build.
     """
     if os.path.exists(self.STOP_UPDATE_FILE):
         msg = ("The STOP_UPDATE_FILE ({0}) exists. Build canceled. \n"
                "Reason for skipped build: \n"
                "{1}".format(self.STOP_UPDATE_FILE,
                             open(self.STOP_UPDATE_FILE).read()))
         fail_mail(msg, subject="DNS builds have stoped")
         self.log(msg)
         return True
Ejemplo n.º 10
0
 def stop_update_exists(self):
     """
     Look for a file referenced by `STOP_UPDATE_FILE` and if it exists,
     cancel the build.
     """
     if os.path.exists(self.STOP_UPDATE_FILE):
         msg = ("The STOP_UPDATE_FILE ({0}) exists. Build canceled. \n"
                "Reason for skipped build: \n"
                "{1}".format(self.STOP_UPDATE_FILE,
                             open(self.STOP_UPDATE_FILE).read()))
         fail_mail(msg, subject="DNS builds have stoped")
         self.log(msg)
         return True
Ejemplo n.º 11
0
    def build(self):
        try:
            with open(self.stop_file) as stop_fd:
                now = time.time()
                contents = stop_fd.read()
            last = os.path.getmtime(self.stop_file)

            msg = ('The stop file ({0}) exists. Build canceled.\n'
                   'Reason for skipped build:\n'
                   '{1}'.format(self.stop_file, contents))
            self.log_notice(msg, to_stderr=False)
            if (self.stop_file_email_interval is not None
                    and now - last > self.stop_file_email_interval):
                os.utime(self.stop_file, (now, now))
                fail_mail(msg, subject="DHCP builds have stopped")

            raise Exception(msg)
        except IOError as e:
            if e.errno == errno.ENOENT:  # IOError: [Errno 2] No such file or directory
                pass
            else:
                raise

        try:
            for ip_type, files in (('4', self.files_v4), ('6', self.files_v6)):
                self.log_info('Building v{}...'.format(ip_type))
                with open(os.path.join(self.stage_dir, files['target_file']),
                          'w') as f:
                    for ctnr in Ctnr.objects.all():
                        f.write(ctnr.build_legacy_classes(ip_type))
                    for vrf in Vrf.objects.all():
                        f.write(vrf.build_vrf(ip_type))
                    for network in Network.objects.filter(ip_type=ip_type,
                                                          enabled=True):
                        f.write(network.build_subnet())
                    for workgroup in Workgroup.objects.all():
                        f.write(workgroup.build_workgroup(ip_type))

                if files['check_file']:
                    self.check_syntax(ip_type=ip_type,
                                      filename=files['check_file'])
        except:
            self.log(syslog.LOG_ERR,
                     'DHCP build failed.\nOriginal exception: ' + e.message)
            raise

        self.log_info('DHCP build successful')
Ejemplo n.º 12
0
    def build(self):
        try:
            with open(self.stop_file) as stop_fd:
                now = time.time()
                contents = stop_fd.read()
            last = os.path.getmtime(self.stop_file)

            msg = ('The stop file ({0}) exists. Build canceled.\n'
                   'Reason for skipped build:\n'
                   '{1}'.format(self.stop_file, contents))
            self.log_notice(msg, to_stderr=False)
            if (self.stop_file_email_interval is not None and
                    now - last > self.stop_file_email_interval):
                os.utime(self.stop_file, (now, now))
                fail_mail(msg, subject="DHCP builds have stopped")

            raise Exception(msg)
        except IOError as e:
            if e.errno == errno.ENOENT:  # IOError: [Errno 2] No such file or directory
                pass
            else:
                raise

        try:
            for ip_type, files in (('4', self.files_v4), ('6', self.files_v6)):
                self.log_info('Building v{}...'.format(ip_type))
                with open(os.path.join(self.stage_dir, files['target_file']),
                          'w') as f:
                    for ctnr in Ctnr.objects.all():
                        f.write(ctnr.build_legacy_classes(ip_type))
                    for vrf in Vrf.objects.all():
                        f.write(vrf.build_vrf(ip_type))
                    for network in Network.objects.filter(
                            ip_type=ip_type, enabled=True):
                        f.write(network.build_subnet())
                    for workgroup in Workgroup.objects.all():
                        f.write(workgroup.build_workgroup(ip_type))

                if files['check_file']:
                    self.check_syntax(
                        ip_type=ip_type, filename=files['check_file'])
        except:
            self.log(syslog.LOG_ERR,
                'DHCP build failed.\nOriginal exception: ' + e.message)
            raise

        self.log_info('DHCP build successful')
Ejemplo n.º 13
0
    def build(self):
        try:
            with open(self.stop_file) as stop_fd:
                now = time.time()
                contents = stop_fd.read()
            last = os.path.getmtime(self.stop_file)

            msg = ('The stop file ({0}) exists. Build canceled.\n'
                   'Reason for skipped build:\n'
                   '{1}'.format(self.stop_file, contents))
            self.log_notice(msg, to_stderr=False)
            if (self.stop_file_email_interval is not None
                    and now - last > self.stop_file_email_interval):
                os.utime(self.stop_file, (now, now))
                fail_mail(msg, subject="DHCP builds have stopped")

            raise Exception(msg)
        except IOError as e:
            if e.errno == 2:  # IOError: [Errno 2] No such file or directory
                pass
            else:
                raise

        self.log_info('Building...')

        try:
            with open(os.path.join(self.stage_dir, self.target_file), 'w') \
                    as f:
                for ctnr in Ctnr.objects.all():
                    f.write(ctnr.build_legacy_classes())
                for vrf in Vrf.objects.all():
                    f.write(vrf.build_vrf())
                for network in Network.objects.filter(enabled=True):
                    f.write(network.build_subnet())
                for workgroup in Workgroup.objects.all():
                    f.write(workgroup.build_workgroup())
        except:
            self.error()

        if self.check_file:
            self.check_syntax()

        self.log_info('DHCP build successful')
Ejemplo n.º 14
0
    def build(self, force=False):
        try:
            with open(self.stop_file) as stop_fd:
                now = time.time()
                contents = stop_fd.read()
            last = os.path.getmtime(self.stop_file)

            msg = ("The stop file ({0}) exists. Build canceled.\n"
                   "Reason for skipped build:\n"
                   "{1}".format(self.stop_file, contents))
            self.log_notice(msg)
            if (self.stop_file_email_interval is not None and
                    now - last > self.stop_file_email_interval):
                os.utime(self.stop_file, (now, now))
                fail_mail(msg, subject="DNS builds have stopped")

            raise Exception(msg)
        except IOError as e:
            if e.errno != 2:  # IOError: [Errno 2] No such file or directory
                raise

        self.log_info('Building...')

        try:
            remove_dir_contents(self.stage_dir)
            self.dns_tasks = self.get_scheduled()

            if not self.dns_tasks and not force:
                self.log_info('Nothing to do!')
                return

            # zone files
            soa_pks_to_rebuild = set(int(t.task) for t in self.dns_tasks)
            self.build_config_files(self.build_zone_files(soa_pks_to_rebuild,
                                    force=force))

            self.log_info('DNS build successful')
        except Exception as e:
            self.log(syslog.LOG_ERR,
                'DNS build failed.\nOriginal exception: ' + e.message)
            raise
Ejemplo n.º 15
0
    def build(self, force=False):
        try:
            with open(self.stop_file) as stop_fd:
                now = time.time()
                contents = stop_fd.read()
            last = os.path.getmtime(self.stop_file)

            msg = ("The stop file ({0}) exists. Build canceled.\n"
                   "Reason for skipped build:\n"
                   "{1}".format(self.stop_file, contents))
            self.log_notice(msg)
            if (self.stop_file_email_interval is not None
                    and now - last > self.stop_file_email_interval):
                os.utime(self.stop_file, (now, now))
                fail_mail(msg, subject="DNS builds have stopped")

            raise Exception(msg)
        except IOError as e:
            if e.errno != errno.ENOENT:  # IOError: [Errno 2] No such file or directory
                raise

        self.log_info('Building...')

        try:
            remove_dir_contents(self.stage_dir)
            self.dns_tasks = self.get_scheduled()

            if not self.dns_tasks and not force:
                self.log_info('Nothing to do!')
                return

            # zone files
            soa_pks_to_rebuild = set(int(t.task) for t in self.dns_tasks)
            self.build_config_files(
                self.build_zone_files(soa_pks_to_rebuild, force=force))

            self.log_info('DNS build successful')
        except Exception as e:
            self.log(syslog.LOG_ERR,
                     'DNS build failed.\nOriginal exception: ' + e.message)
            raise
Ejemplo n.º 16
0
def build_zone_data(view, root_domain, soa, logf):
    """
    This function does the heavy lifting of building a zone. It coordinates
    getting all of the data out of the db into BIND format.

        :param soa: The SOA corresponding to the zone being built.
        :type soa: SOA

        :param root_domain: The root domain of this zone.
        :type root_domain: str

        :returns public_file_path: The path to the zone file in the STAGEING
            dir
        :type public_file_path: str
        :returns public_data: The data that should be written to
            public_file_path
        :type public_data: str

        :returns view_zone_file: The path to the zone file in the STAGEING dir
        :type view_zone_file: str
        :param view_data: The data that should be written to view_zone_file
        :type view_data: str
    """
    ztype = 'reverse' if root_domain.is_reverse else 'forward'
    if (soa.has_record_set(view=view, exclude_ns=True)
            and not root_domain.nameserver_set.filter(views=view).exists()):
        msg = ("The {0} zone has at least one record in the {1} view, but "
               "there are no nameservers in that view. A zone file for {1} "
               "won't be built. Use the search string 'zone=:{0} view=:{1}' "
               "to find the troublesome record(s)".format(
                   root_domain, view.name))
        fail_mail(msg, subject="Record(s) without NS records can't be built")
        logf(msg)
        return ''

    domains = soa.domain_set.all().order_by('name')

    # Build the mega filter!
    domain_mega_filter = Q(domain=root_domain)
    for domain in domains:
        domain_mega_filter = domain_mega_filter | Q(domain=domain)

    rdomain_mega_filter = Q(reverse_domain=root_domain)
    for reverse_domain in domains:
        rdomain_mega_filter = rdomain_mega_filter | Q(
            reverse_domain=reverse_domain)

    soa_data = render_soa_only(soa=soa, root_domain=root_domain)
    if root_domain.ip_type == '4':
        range_set = (root_domain.get_related_ranges().filter(
            views__name=view.name).order_by('start_upper', 'start_lower'))
    else:
        range_set = []

    try:
        if ztype == "forward":
            view_data = render_forward_zone(view, domain_mega_filter)
        else:
            ip_type = (IP_TYPE_6
                       if root_domain.name.endswith('ip6.arpa') else IP_TYPE_4)
            view_data = render_reverse_zone(view,
                                            domain_mega_filter,
                                            rdomain_mega_filter,
                                            ip_type=ip_type,
                                            range_set=range_set)
    except View.DoesNotExist:
        view_data = ""

    if view_data:
        view_data = soa_data + view_data

    return view_data
Ejemplo n.º 17
0
def build_zone_data(view, root_domain, soa, logf):
    """
    This function does the heavy lifting of building a zone. It coordinates
    getting all of the data out of the db into BIND format.

        :param soa: The SOA corresponding to the zone being built.
        :type soa: SOA

        :param root_domain: The root domain of this zone.
        :type root_domain: str

        :returns public_file_path: The path to the zone file in the STAGEING
            dir
        :type public_file_path: str
        :returns public_data: The data that should be written to
            public_file_path
        :type public_data: str

        :returns view_zone_file: The path to the zone file in the STAGEING dir
        :type view_zone_file: str
        :param view_data: The data that should be written to view_zone_file
        :type view_data: str
    """
    ztype = 'reverse' if root_domain.is_reverse else 'forward'
    if (soa.has_record_set(view=view, exclude_ns=True) and
            not root_domain.nameserver_set.filter(views=view).exists()):
        msg = ("The {0} zone has at least one record in the {1} view, but "
               "there are no nameservers in that view. A zone file for {1} "
               "won't be built. Use the search string 'zone=:{0} view=:{1}' "
               "to find the troublesome record(s)"
               .format(root_domain, view.name))
        fail_mail(msg, subject="Record(s) without NS records can't be built")
        logf(msg)
        return ''

    domains = soa.domain_set.all().order_by('name')

    # Build the mega filter!
    domain_mega_filter = Q(domain=root_domain)
    for domain in domains:
        domain_mega_filter = domain_mega_filter | Q(domain=domain)

    rdomain_mega_filter = Q(reverse_domain=root_domain)
    for reverse_domain in domains:
        rdomain_mega_filter = rdomain_mega_filter | Q(
            reverse_domain=reverse_domain)

    soa_data = render_soa_only(soa=soa, root_domain=root_domain)
    if root_domain.ip_type == '4':
        range_set = (root_domain.get_related_ranges()
                                .filter(views__name=view.name)
                                .order_by('start_upper', 'start_lower'))
    else:
        range_set = []

    try:
        if ztype == "forward":
            view_data = render_forward_zone(view, domain_mega_filter)
        else:
            ip_type = (IP_TYPE_6 if root_domain.name.endswith('ip6.arpa')
                       else IP_TYPE_4)
            view_data = render_reverse_zone(
                view, domain_mega_filter, rdomain_mega_filter, ip_type=ip_type,
                range_set=range_set)
    except View.DoesNotExist:
        view_data = ""

    if view_data:
        view_data = soa_data + view_data

    return view_data