]> git.ipfire.org Git - people/stevee/pypdns.git/blob - backend.py
Add exceptions for database handling and invalid SOA records.
[people/stevee/pypdns.git] / backend.py
1 ###############################################################################
2 # #
3 # pyPDNS - A PDNS administration tool, written in pure python. #
4 # Copyright (C) 2012 IPFire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 ###############################################################################
20 # #
21 # Basic information about the database layout can be found here: #
22 # http://doc.powerdns.com/gsqlite.html #
23 # #
24 # More details about the database tables and fields can be found here: #
25 # http://wiki.powerdns.com/trac/wiki/fields #
26 # #
27 ###############################################################################
28
29 import database
30 import errors
31 import sqlite3
32
33 DB = "/var/lib/pdns/pdns.db"
34
35 # Create the primary DNS class.
36 class DNS(object):
37 """
38 Primary DNS class.
39
40 Uses the database class from imported database module.
41 Connects to the PDNS sqlite database.
42 """
43 def __init__(self, db):
44 # Try to connect to database or raise an exception.
45 try:
46 self.db = database.Database(db)
47
48 except sqlite3.OperationalError, e:
49 raise errors.DatabaseException, "Could not open database: %s" % e
50
51
52
53 # Get all configured domains.
54 def get_domains(self):
55 """
56 Fetch all configured domains.
57 """
58 # Create an empty list.
59 domains = []
60
61 # Add fetched domains to the previous created empty list.
62 for row in self.db.query("SELECT id FROM domains"):
63 domain = Domain(self, row.id)
64 domains.append(domain)
65
66 return domains
67
68 # Get a domain by it's name.
69 def get_domain(self, name):
70 """
71 Get a domain by a given name.
72 """
73 row = self.db.get("SELECT id FROM domains WHERE name = ?", name)
74
75 # Only do anything, if there is an existing domain.
76 if row:
77 domain = Domain(self, row.id)
78
79 return domain
80
81 # Create Domain class.
82 class Domain(object):
83 """
84 Domain class.
85
86 Uses query method from database module to get requested information from domain.
87 The domain is specified by it's unique database id.
88 """
89 def __init__(self, dns, domain_id):
90 self.dns = dns
91 self.id = domain_id
92
93 @property
94 def db(self):
95 return self.dns.db
96
97 # Determine the name of the zone by a given id.
98 @property
99 def name(self):
100 row = self.db.get("SELECT name FROM domains WHERE id = ?", self.id)
101 return row.name
102
103 # Get information of the master nameserver from which the domain should be slaved.
104 @property
105 def master(self):
106 row = self.db.get("SELECT master FROM domains WHERE id = ?", self.id)
107 return row.master
108
109 # Fetch data of the last check from the domain.
110 @property
111 def last_check(self):
112 row = self.db.get("SELECT last_check FROM domains WHERE id = ?", self.id)
113 return row.last_check
114
115 # Get the type of the domain.
116 @property
117 def type(self):
118 row = self.db.get("SELECT type FROM domains WHERE id = ?", self.id)
119 return row.type
120
121 # Get the last notified serial of a used master domain.
122 @property
123 def notified_serial(self):
124 row = self.db.get("SELECT notified_serial FROM domains WHERE id = ?", self.id)
125 return row.notified_serial
126
127 # Gain if a certain host is a supermaster for a certain domain name.
128 @property
129 def account(self):
130 row = self.db.get("SELECT account FROM domains WHERE id = ?", self.id)
131 return row.account
132
133 # Get all records from zone.
134 @property
135 def records(self):
136 """
137 Get all records from the zone.
138 """
139 # Create an empty list.
140 records = []
141
142 # Fetch records from zone and categorize them into their different record types.
143 for row in self.db.query("SELECT id, type FROM records WHERE domain_id = ?", self.id):
144 if row.type == "SOA":
145 record = SOARecord(self, row.id)
146 elif row.type == "A":
147 record = ARecord(self, row.id)
148 else:
149 record = Record(self, row.id)
150 records.append(record)
151
152 return records
153
154 # Get records by a specified type.
155 def get_records_by_type(self, type):
156 records = []
157 for record in self.records:
158 if record.type == type:
159 records.append(record)
160
161 return records
162
163 # Quick function to get the first SOA record from the domain.
164 @property
165 def SOA(self):
166 records = self.get_records_by_type("SOA")
167 if records:
168 return records[0]
169
170
171 # Create class for domain records.
172 class Record(object):
173 """
174 Record class
175
176 It is used to get details about configured records.
177 The domain and record is's are specified by their unique database id's.
178 """
179 def __init__(self, domain, record_id):
180 self.domain = domain
181 self.id = record_id
182
183 @property
184 def db(self):
185 return self.domain.db
186
187 # Determine the type of the record.
188 @property
189 def type(self):
190 row = self.db.get("SELECT type FROM records WHERE id = ?", self.id)
191 return row.type
192
193 # Get the configured DNS name of the record.
194 @property
195 def dnsname(self):
196 row = self.db.get("SELECT name FROM records WHERE id = ?", self.id)
197 return row.name
198
199
200 # Fetch content like the address to which the record points.
201 @property
202 def content(self):
203 row = self.db.get("SELECT content FROM records WHERE id = ?", self.id)
204 return row.content
205
206
207 # Get the "Time to live" for the record.
208 @property
209 def ttl(self):
210 row = self.db.get("SELECT ttl FROM records WHERE id = ?", self.id)
211 return row.ttl
212
213 # Gain the configured record priority.
214 @property
215 def priority(self):
216 row = self.db.get("SELECT prio FROM records WHERE id = ?" , self.id)
217 return row.prio
218
219 # Get the change_date.
220 @property
221 def change_date(self):
222 row = self.db.get("SELECT change_date FROM records WHERE id = ?" , self.id)
223 return row.change_date
224
225 # Fetch the ordername.
226 @property
227 def ordername(self):
228 row = self.db.get("SELECT ordername FROM records WHERE id = ?" , self.id)
229 return row.ordername
230
231 # Gain all information about records authentication.
232 @property
233 def authentication(self):
234 row = self.db.get("SELECT auth FROM records WHERE id = ?" , self.id)
235 return row.auth
236
237
238 # Create an own class to deal with "SOA" records.
239 class SOARecord(Record):
240 """
241 SOA Record class.
242 This is an own class to deal with "SOA" records.
243
244 Uses splitt() to generate a list of the content string from the database.
245 Returns the requested entries.
246 """
247 def __init__(self, domain, record_id):
248 Record.__init__(self, domain, record_id)
249
250 self.soa_attrs = self.content.split()
251
252 # Check if the content from database is valid (It contains all 7 required information).
253 if not len(self.soa_attrs) == 7:
254 raise InvalidRecordDataException, "Your SOA record \
255 doesn't contain all required seven elements."
256
257 # Primary NS - the domain name of the name server that was the original source of the data.
258 @property
259 def mname(self):
260 return self.soa_attrs[0]
261
262 # E-mail address of the person which is responsible for this domain.
263 @property
264 def email(self):
265 return self.soa_attrs[1]
266
267 # The serial which increases allways after a change on the domain has been made.
268 @property
269 def serial(self):
270 return self.soa_attrs[2]
271
272 # The number of seconds between the time that a secondary name server gets a copy of the domain.
273 @property
274 def refresh(self):
275 return self.soa_attrs[3]
276
277 # The number of seconds during the next refresh attempt if the previous fails.
278 @property
279 def retry(self):
280 return self.soa_attrs[4]
281
282 # The number of seconds that lets the secondary name server(s) know how long they can hold the information.
283 @property
284 def expire(self):
285 return self.soa_attrs[5]
286
287 # The number of seconds that the records in the domain are valid.
288 @property
289 def minimum(self):
290 return self.soa_attrs[6]
291
292
293
294 class ARecord(Record):
295 pass