From: Stefan Schantl Date: Sun, 23 Sep 2012 12:54:19 +0000 (+0000) Subject: Initial import. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1336cd4e6fe498a73f19734532600f009b014044;p=people%2Fstevee%2Fpypdns.git Initial import. --- 1336cd4e6fe498a73f19734532600f009b014044 diff --git a/backend.py b/backend.py new file mode 100644 index 0000000..9f9e85b --- /dev/null +++ b/backend.py @@ -0,0 +1,176 @@ +############################################################################### +# # +# pyPDNS - A PDNS administration tool, written in pure python. # +# Copyright (C) 2012 Pakfire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### +# # +# More details about the database tables and fields can be found here: # +# http://wiki.powerdns.com/trac/wiki/fields # +# # +############################################################################### + +import database + +DB = "/var/lib/pdns/pdns.db" + +# Create the primary DNS class. +"""Use Database class from imported database module to connect to the PDNS sqlite database.""" +class DNS(object): + def __init__(self, db): + self.db = database.Database(db) + + # Get all configured domains. + def get_domains(self): + domains = [] + + """Fetch all configured domains, line by line and add them to the previous created empty list.""" + for row in self.db.query("SELECT id FROM domains"): + domain = Domain(self, row.id) + domains.append(domain) + + return domains + + # Get a domain by it's name. + def get_domain(self, name): + row = self.db.get("SELECT id FROM domains WHERE name = ?", name) + domain = Domain(self, row.id) + + return domain + +# Create Domain class. +"""Use query method from database module to get all requested information about our domain.""" +"""The domain is specified by it's unique id.""" +class Domain(object): + def __init__(self, dns, domain_id): + self.dns = dns + self.id = domain_id + + @property + def db(self): + return self.dns.db + + # Determine the name of the zone by a given id. + @property + def name(self): + row = self.db.get("SELECT name FROM domains WHERE id = ?", self.id) + return row.name + + # Get information of the master nameserver from which the domain should be slaved. + @property + def master(self): + row = self.db.get("SELECT master FROM domains WHERE id = ?", self.id) + return row.master + + # Fetch data of the last check from the domain. + @property + def last_check(self): + row = self.db.get("SELECT last_check FROM domains WHERE id = ?", self.id) + return row.last_check + + # Get the type of the domain. + @property + def type(self): + row = self.db.get("SELECT type FROM domains WHERE id = ?", self.id) + return row.type + + # Get the last notified serial of a used master domain. + @property + def notified_serial(self): + row = self.db.get("SELECT notified_serial FROM domains WHERE id = ?", self.id) + return row.notified_serial + + # Gain if a certain host is a supermaster for a certain domain name. + @property + def account(self): + row = self.db.get("SELECT account FROM domains WHERE id = ?", self.id) + return row.account + + # Get all records from zone. + @property + def records(self): + records = [] + + """Fetch all records from domain, line by line and add them to the previous created empty list.""" + for row in self.db.query("SELECT id FROM records WHERE domain_id = ?", self.id): + record = Record(self, row.id) + records.append(record) + + return records + + + +# Create class for domain records. +"""It is used to get more details about the configured records.""" +"""The domain is specified by it's unique id.""" +class Record(object): + def __init__(self, domain, record_id): + self.domain = domain + self.id = record_id + + @property + def db(self): + return self.domain.db + + # Determine the type of the record. + @property + def type(self): + row = self.db.get("SELECT type FROM records WHERE id = ?", self.id) + return row.type + + # Get the configured DNS name of the record. + @property + def dnsname(self): + row = self.db.get("SELECT name FROM records WHERE id = ?", self.id) + return row.name + + + # Fetch content like the address to which the record points. + @property + def content(self): + row = self.db.get("SELECT content FROM records WHERE id = ?", self.id) + return row.content + + + # Get the "Time to live" for the record. + @property + def ttl(self): + row = self.db.get("SELECT ttl FROM records WHERE id = ?", self.id) + return row.ttl + + # Gain the configured record priority. + @property + def priority(self): + row = self.db.get("SELECT prio FROM records WHERE id = ?" , self.id) + return row.prio + + # Get the change_date. + @property + def change_date(self): + row = self.db.get("SELECT change_date FROM records WHERE id = ?" , self.id) + return row.change_date + + # Fetch the ordername. + @property + def ordername(self): + row = self.db.get("SELECT ordername FROM records WHERE id = ?" , self.id) + return row.ordername + + # Gain all information about records authification. + @property + def authification(self): + row = self.db.get("SELECT auth FROM records WHERE id = ?" , self.id) + return row.auth diff --git a/database.py b/database.py new file mode 100644 index 0000000..6af90d6 --- /dev/null +++ b/database.py @@ -0,0 +1,87 @@ +#!/usr/bin/python + +import itertools +import logging +import os +import sqlite3 + +class Row(dict): + """A dict that allows for object-like property access syntax.""" + def __getattr__(self, name): + try: + return self[name] + except KeyError: + raise AttributeError(name) + + +class Database(object): + def __init__(self, filename): + self.filename = filename + + self._db = None + + try: + self.reconnect() + except: + logging.error("Cannot connect to database on %s", self.filename, exc_info=True) + + def __del__(self): + self.close() + + def close(self): + """Closes this database connection.""" + if self._db is not None: + self._db.commit() + self._db.close() + self._db = None + + def reconnect(self): + """Closes the existing database connection and re-opens it.""" + self.close() + self._db = sqlite3.connect(self.filename) + self._db.isolation_level = None # Enabled autocommit mode + + def query(self, query, *parameters): + """Returns a row list for the given query and parameters.""" + cursor = self._cursor() + try: + self._execute(cursor, query, parameters) + column_names = [d[0] for d in cursor.description] + return [Row(itertools.izip(column_names, row)) for row in cursor] + finally: + #cursor.close() + pass + + def get(self, query, *parameters): + """Returns the first row returned for the given query.""" + rows = self.query(query, *parameters) + if not rows: + return None + elif len(rows) > 1: + raise Exception("Multiple rows returned for Database.get() query") + else: + return rows[0] + + def execute(self, query, *parameters): + """Executes the given query, returning the lastrowid from the query.""" + cursor = self._cursor() + try: + self._execute(cursor, query, parameters) + return cursor.lastrowid + finally: + pass + #self._db.commit() + #cursor.close() + + def _cursor(self): + if self._db is None: + self.reconnect() + return self._db.cursor() + + def _execute(self, cursor, query, parameters): + try: + return cursor.execute(query, parameters) + except sqlite3.OperationalError: + logging.error("Error connecting to database on %s", self.filename) + self.close() + raise