]>
Commit | Line | Data |
---|---|---|
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 | ||
29 | import database | |
a7ceb5de SS |
30 | import errors |
31 | import sqlite3 | |
1336cd4e SS |
32 | |
33 | DB = "/var/lib/pdns/pdns.db" | |
34 | ||
35 | # Create the primary DNS class. | |
1336cd4e | 36 | class DNS(object): |
a7ceb5de SS |
37 | """ |
38 | Primary DNS class. | |
259f19af | 39 | |
a7ceb5de SS |
40 | Uses the database class from imported database module. |
41 | Connects to the PDNS sqlite database. | |
42 | """ | |
1336cd4e | 43 | def __init__(self, db): |
a7ceb5de SS |
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 | ||
1336cd4e SS |
52 | |
53 | # Get all configured domains. | |
54 | def get_domains(self): | |
259f19af SS |
55 | """ |
56 | Fetch all configured domains. | |
57 | """ | |
58 | # Create an empty list. | |
1336cd4e SS |
59 | domains = [] |
60 | ||
259f19af | 61 | # Add fetched domains to the previous created empty list. |
1336cd4e SS |
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): | |
259f19af SS |
70 | """ |
71 | Get a domain by a given name. | |
72 | """ | |
1336cd4e | 73 | row = self.db.get("SELECT id FROM domains WHERE name = ?", name) |
1336cd4e | 74 | |
d267bece SS |
75 | # Only do anything, if there is an existing domain. |
76 | if row: | |
77 | domain = Domain(self, row.id) | |
78 | ||
79 | return domain | |
1336cd4e SS |
80 | |
81 | # Create Domain class. | |
1336cd4e | 82 | class Domain(object): |
a7ceb5de SS |
83 | """ |
84 | Domain class. | |
259f19af | 85 | |
a7ceb5de SS |
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 | """ | |
1336cd4e SS |
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): | |
259f19af SS |
136 | """ |
137 | Get all records from the zone. | |
138 | """ | |
139 | # Create an empty list. | |
1336cd4e SS |
140 | records = [] |
141 | ||
259f19af | 142 | # Fetch records from zone and categorize them into their different record types. |
abccf64a SS |
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) | |
1336cd4e SS |
150 | records.append(record) |
151 | ||
152 | return records | |
153 | ||
abccf64a SS |
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] | |
1336cd4e SS |
169 | |
170 | ||
171 | # Create class for domain records. | |
1336cd4e | 172 | class Record(object): |
a7ceb5de SS |
173 | """ |
174 | Record class | |
259f19af | 175 | |
a7ceb5de SS |
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 | """ | |
1336cd4e SS |
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 | ||
abccf64a | 231 | # Gain all information about records authentication. |
1336cd4e | 232 | @property |
abccf64a | 233 | def authentication(self): |
1336cd4e SS |
234 | row = self.db.get("SELECT auth FROM records WHERE id = ?" , self.id) |
235 | return row.auth | |
abccf64a SS |
236 | |
237 | ||
238 | # Create an own class to deal with "SOA" records. | |
abccf64a | 239 | class SOARecord(Record): |
a7ceb5de SS |
240 | """ |
241 | SOA Record class. | |
242 | This is an own class to deal with "SOA" records. | |
259f19af | 243 | |
a7ceb5de SS |
244 | Uses splitt() to generate a list of the content string from the database. |
245 | Returns the requested entries. | |
246 | """ | |
abccf64a SS |
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: | |
a7ceb5de SS |
254 | raise InvalidRecordDataException, "Your SOA record \ |
255 | doesn't contain all required seven elements." | |
abccf64a SS |
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 |