]> git.ipfire.org Git - people/stevee/pypdns.git/blame - backend.py
Code rework of the CLI.
[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
209345ca 76 # Check if an id has been returned from database or return None.
9253a8af
SS
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
209345ca
SS
88 Uses query method from database module to get requested information
89 from domain.
90
a7ceb5de
SS
91 The domain is specified by it's unique database id.
92 """
1336cd4e
SS
93 def __init__(self, dns, domain_id):
94 self.dns = dns
95 self.id = domain_id
96
9253a8af
SS
97 self.__data = None
98
1336cd4e
SS
99 @property
100 def db(self):
101 return self.dns.db
102
9253a8af
SS
103 # Cache.
104 @property
105 def data(self):
106 if self.__data is None:
209345ca
SS
107 self.__data = self.db.get("SELECT * FROM domains \
108 WHERE id = ?", self.id)
9253a8af
SS
109 assert self.__data
110
111 return self.__data
112
1336cd4e
SS
113 # Determine the name of the zone by a given id.
114 @property
115 def name(self):
9253a8af 116 return self.data.name
1336cd4e 117
209345ca
SS
118 # Get information of the master nameserver from which the domain should
119 # be slaved.
1336cd4e
SS
120 @property
121 def master(self):
9253a8af 122 return self.data.master
1336cd4e
SS
123
124 # Fetch data of the last check from the domain.
125 @property
126 def last_check(self):
9253a8af 127 return self.data.last_check
1336cd4e
SS
128
129 # Get the type of the domain.
130 @property
131 def type(self):
9253a8af 132 return self.data.type
1336cd4e
SS
133
134 # Get the last notified serial of a used master domain.
135 @property
136 def notified_serial(self):
9253a8af 137 return self.data.notified_serial
1336cd4e
SS
138
139 # Gain if a certain host is a supermaster for a certain domain name.
140 @property
141 def account(self):
9253a8af 142 return self.data.account
1336cd4e 143
209345ca
SS
144 # Get count of records of a zone. Return true if there is at least one
145 # or false.
146 def has_records(self):
147 count = self.db.get("SELECT COUNT(*) AS num FROM records \
148 WHERE domain_id = ?", self.id)
149
150 if count.num > 0:
151 return True
152
153 return False
154
1336cd4e
SS
155 # Get all records from zone.
156 @property
157 def records(self):
259f19af
SS
158 """
159 Get all records from the zone.
160 """
209345ca
SS
161 # Fetch records from zone and categorize them into their
162 # different record types.
163 for row in self.db.query("SELECT id, type FROM records \
164 WHERE domain_id = ?", self.id):
165
abccf64a
SS
166 if row.type == "SOA":
167 record = SOARecord(self, row.id)
168 elif row.type == "A":
169 record = ARecord(self, row.id)
170 else:
9253a8af 171 record = Record(self, row.id)
1336cd4e 172
9253a8af 173 yield record
1336cd4e 174
abccf64a
SS
175 # Get records by a specified type.
176 def get_records_by_type(self, type):
177 records = []
178 for record in self.records:
179 if record.type == type:
180 records.append(record)
181
182 return records
183
184 # Quick function to get the first SOA record from the domain.
185 @property
186 def SOA(self):
187 records = self.get_records_by_type("SOA")
188 if records:
189 return records[0]
1336cd4e
SS
190
191
192# Create class for domain records.
1336cd4e 193class Record(object):
a7ceb5de
SS
194 """
195 Record class
259f19af 196
a7ceb5de
SS
197 It is used to get details about configured records.
198 The domain and record is's are specified by their unique database id's.
199 """
1336cd4e
SS
200 def __init__(self, domain, record_id):
201 self.domain = domain
202 self.id = record_id
203
9253a8af
SS
204 # Cache.
205 self.__data = None
206
1336cd4e
SS
207 @property
208 def db(self):
209 return self.domain.db
210
9253a8af
SS
211 @property
212 def data(self):
213 if self.__data is None:
209345ca
SS
214 self.__data = self.db.get("SELECT * FROM records \
215 WHERE id = ?", self.id)
9253a8af
SS
216 assert self.__data
217
218 return self.__data
219
1336cd4e
SS
220 # Determine the type of the record.
221 @property
222 def type(self):
9253a8af 223 return self.data.type
1336cd4e
SS
224
225 # Get the configured DNS name of the record.
226 @property
227 def dnsname(self):
9253a8af 228 return self.data.name
1336cd4e
SS
229
230
231 # Fetch content like the address to which the record points.
232 @property
233 def content(self):
9253a8af 234 return self.data.content
1336cd4e
SS
235
236 # Get the "Time to live" for the record.
237 @property
238 def ttl(self):
9253a8af 239 return self.data.ttl
1336cd4e
SS
240
241 # Gain the configured record priority.
242 @property
243 def priority(self):
9253a8af 244 return self.data.prio
1336cd4e
SS
245
246 # Get the change_date.
247 @property
248 def change_date(self):
9253a8af 249 return self.data.change_date
1336cd4e
SS
250
251 # Fetch the ordername.
252 @property
253 def ordername(self):
9253a8af 254 return self.data.ordername
1336cd4e 255
abccf64a 256 # Gain all information about records authentication.
1336cd4e 257 @property
abccf64a 258 def authentication(self):
9253a8af 259 return self.data.auth
abccf64a
SS
260
261
262# Create an own class to deal with "SOA" records.
abccf64a 263class SOARecord(Record):
a7ceb5de
SS
264 """
265 SOA Record class.
266 This is an own class to deal with "SOA" records.
259f19af 267
209345ca
SS
268 Uses splitt() to generate a list of the content string from the
269 database.
270
a7ceb5de
SS
271 Returns the requested entries.
272 """
abccf64a
SS
273 def __init__(self, domain, record_id):
274 Record.__init__(self, domain, record_id)
275
276 self.soa_attrs = self.content.split()
277
209345ca
SS
278 # Check if the content from database is valid.
279 # (It contains all 7 required information)
abccf64a 280 if not len(self.soa_attrs) == 7:
a7ceb5de
SS
281 raise InvalidRecordDataException, "Your SOA record \
282 doesn't contain all required seven elements."
abccf64a 283
209345ca
SS
284 # Primary NS - the domain name of the name server that was the
285 # original source of the data.
abccf64a
SS
286 @property
287 def mname(self):
288 return self.soa_attrs[0]
289
290 # E-mail address of the person which is responsible for this domain.
291 @property
292 def email(self):
293 return self.soa_attrs[1]
294
209345ca
SS
295 # The serial which increases allways after a change on the domain has
296 # been made.
abccf64a
SS
297 @property
298 def serial(self):
299 return self.soa_attrs[2]
300
209345ca
SS
301 # The number of seconds between the time that a secondary name server
302 # gets a copy of the domain.
abccf64a
SS
303 @property
304 def refresh(self):
305 return self.soa_attrs[3]
306
209345ca
SS
307 # The number of seconds during the next refresh attempt if the
308 # previous fails.
abccf64a
SS
309 @property
310 def retry(self):
311 return self.soa_attrs[4]
312
209345ca
SS
313 # The number of seconds that lets the secondary name server(s) know
314 # how long they can hold the information.
abccf64a
SS
315 @property
316 def expire(self):
317 return self.soa_attrs[5]
318
319 # The number of seconds that the records in the domain are valid.
320 @property
321 def minimum(self):
322 return self.soa_attrs[6]
323
324
325
326class ARecord(Record):
327 pass