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