29 |
29 |
30 |
30 |
31 class Domain(object): |
31 class Domain(object): |
32 """Class to manage e-mail domains.""" |
32 """Class to manage e-mail domains.""" |
33 __slots__ = ('_directory', '_gid', '_name', '_qlimit', '_services', |
33 __slots__ = ('_directory', '_gid', '_name', '_qlimit', '_services', |
34 '_transport', '_dbh', '_new') |
34 '_transport', '_note', '_dbh', '_new') |
35 |
35 |
36 def __init__(self, dbh, domainname): |
36 def __init__(self, dbh, domainname): |
37 """Creates a new Domain instance. |
37 """Creates a new Domain instance. |
38 |
38 |
39 Loads all relevant data from the database, if the domain could be |
39 Loads all relevant data from the database, if the domain could be |
66 |
67 |
67 Raises a DomainError if Domain._name isn't the primary name of the |
68 Raises a DomainError if Domain._name isn't the primary name of the |
68 domain. |
69 domain. |
69 """ |
70 """ |
70 dbc = self._dbh.cursor() |
71 dbc = self._dbh.cursor() |
71 dbc.execute('SELECT dd.gid, qid, ssid, tid, domaindir, is_primary ' |
72 dbc.execute('SELECT dd.gid, qid, ssid, tid, domaindir, is_primary, ' |
|
73 'note ' |
72 'FROM domain_data dd, domain_name dn WHERE domainname = ' |
74 'FROM domain_data dd, domain_name dn WHERE domainname = ' |
73 '%s AND dn.gid = dd.gid', (self._name,)) |
75 '%s AND dn.gid = dd.gid', (self._name,)) |
74 result = dbc.fetchone() |
76 result = dbc.fetchone() |
75 dbc.close() |
77 dbc.close() |
76 if result: |
78 if result: |
79 self._name, DOMAIN_ALIAS_EXISTS) |
81 self._name, DOMAIN_ALIAS_EXISTS) |
80 self._gid, self._directory = result[0], result[4] |
82 self._gid, self._directory = result[0], result[4] |
81 self._qlimit = QuotaLimit(self._dbh, qid=result[1]) |
83 self._qlimit = QuotaLimit(self._dbh, qid=result[1]) |
82 self._services = ServiceSet(self._dbh, ssid=result[2]) |
84 self._services = ServiceSet(self._dbh, ssid=result[2]) |
83 self._transport = Transport(self._dbh, tid=result[3]) |
85 self._transport = Transport(self._dbh, tid=result[3]) |
|
86 self._note = result[6] |
84 self._new = False |
87 self._new = False |
85 |
88 |
86 def _set_gid(self): |
89 def _set_gid(self): |
87 """Sets the ID of the domain - if not set yet.""" |
90 """Sets the ID of the domain - if not set yet.""" |
88 assert self._gid == 0 |
91 assert self._gid == 0 |
125 NO_SUCH_DOMAIN) |
128 NO_SUCH_DOMAIN) |
126 elif not must_exist and not self._new: |
129 elif not must_exist and not self._new: |
127 raise DomErr(_(u"The domain '%s' already exists.") % self._name, |
130 raise DomErr(_(u"The domain '%s' already exists.") % self._name, |
128 DOMAIN_EXISTS) |
131 DOMAIN_EXISTS) |
129 |
132 |
130 def _update_tables(self, column, value, force=False): |
133 def _update_tables(self, column, value): |
|
134 """Update table columns in the domain_data table.""" |
|
135 dbc = self._dbh.cursor() |
|
136 dbc.execute('UPDATE domain_data SET %s = %%s WHERE gid = %%s' % column, |
|
137 (value, self._gid)) |
|
138 if dbc.rowcount > 0: |
|
139 self._dbh.commit() |
|
140 dbc.close() |
|
141 |
|
142 def _update_tables_ref(self, column, value, force=False): |
131 """Update various columns in the domain_data table. When *force* is |
143 """Update various columns in the domain_data table. When *force* is |
132 `True`, the corresponding column in the users table will be reset to |
144 `True`, the corresponding column in the users table will be reset to |
133 NULL. |
145 NULL. |
134 |
146 |
135 Arguments: |
147 Arguments: |
141 `force` : bool |
153 `force` : bool |
142 reset existing users. Default: `False` |
154 reset existing users. Default: `False` |
143 """ |
155 """ |
144 if column not in ('qid', 'ssid', 'tid'): |
156 if column not in ('qid', 'ssid', 'tid'): |
145 raise ValueError('Unknown column: %r' % column) |
157 raise ValueError('Unknown column: %r' % column) |
146 dbc = self._dbh.cursor() |
158 self._update_tables(column, value) |
147 dbc.execute('UPDATE domain_data SET %s = %%s WHERE gid = %%s' % column, |
|
148 (value, self._gid)) |
|
149 if dbc.rowcount > 0: |
|
150 self._dbh.commit() |
|
151 if force: |
159 if force: |
|
160 dbc = self._dbh.cursor() |
152 dbc.execute('UPDATE users SET %s = NULL WHERE gid = %%s' % column, |
161 dbc.execute('UPDATE users SET %s = NULL WHERE gid = %%s' % column, |
153 (self._gid,)) |
162 (self._gid,)) |
154 if dbc.rowcount > 0: |
163 if dbc.rowcount > 0: |
155 self._dbh.commit() |
164 self._dbh.commit() |
156 dbc.close() |
165 dbc.close() |
157 |
166 |
158 @property |
167 @property |
159 def gid(self): |
168 def gid(self): |
160 """The GID of the Domain.""" |
169 """The GID of the Domain.""" |
161 return self._gid |
170 return self._gid |
233 """ |
247 """ |
234 self._chk_state(False) |
248 self._chk_state(False) |
235 assert isinstance(transport, Transport) |
249 assert isinstance(transport, Transport) |
236 self._transport = transport |
250 self._transport = transport |
237 |
251 |
|
252 def set_note(self, note): |
|
253 """Set the domain's (optional) note. |
|
254 |
|
255 Argument: |
|
256 |
|
257 `note` : basestring or None |
|
258 The note, or None to remove |
|
259 """ |
|
260 self._chk_state(False) |
|
261 assert note is None or isinstance(note, basestring) |
|
262 self._note = note |
|
263 |
238 def save(self): |
264 def save(self): |
239 """Stores the new domain in the database.""" |
265 """Stores the new domain in the database.""" |
240 self._chk_state(False) |
266 self._chk_state(False) |
241 assert all((self._directory, self._qlimit, self._services, |
267 assert all((self._directory, self._qlimit, self._services, |
242 self._transport)) |
268 self._transport)) |
243 dbc = self._dbh.cursor() |
269 dbc = self._dbh.cursor() |
244 dbc.execute('INSERT INTO domain_data (gid, qid, ssid, tid, domaindir) ' |
270 dbc.execute('INSERT INTO domain_data (gid, qid, ssid, tid, domaindir, ' |
245 'VALUES (%s, %s, %s, %s, %s)', (self._gid, |
271 'note) ' |
|
272 'VALUES (%s, %s, %s, %s, %s, %s)', (self._gid, |
246 self._qlimit.qid, self._services.ssid, self._transport.tid, |
273 self._qlimit.qid, self._services.ssid, self._transport.tid, |
247 self._directory)) |
274 self._directory, self._note)) |
248 dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary) ' |
275 dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary) ' |
249 'VALUES (%s, %s, TRUE)', (self._name, self._gid)) |
276 'VALUES (%s, %s, TRUE)', (self._name, self._gid)) |
250 self._dbh.commit() |
277 self._dbh.commit() |
251 dbc.close() |
278 dbc.close() |
252 self._new = False |
279 self._new = False |
297 u'Dovecot >= v1.1.2.'), VMM_ERROR) |
324 u'Dovecot >= v1.1.2.'), VMM_ERROR) |
298 self._chk_state() |
325 self._chk_state() |
299 assert isinstance(quotalimit, QuotaLimit) |
326 assert isinstance(quotalimit, QuotaLimit) |
300 if not force and quotalimit == self._qlimit: |
327 if not force and quotalimit == self._qlimit: |
301 return |
328 return |
302 self._update_tables('qid', quotalimit.qid, force) |
329 self._update_tables_ref('qid', quotalimit.qid, force) |
303 self._qlimit = quotalimit |
330 self._qlimit = quotalimit |
304 |
331 |
305 def update_serviceset(self, serviceset, force=False): |
332 def update_serviceset(self, serviceset, force=False): |
306 """Assign a different set of services to the Domain, |
333 """Assign a different set of services to the Domain, |
307 |
334 |
317 """ |
344 """ |
318 self._chk_state() |
345 self._chk_state() |
319 assert isinstance(serviceset, ServiceSet) |
346 assert isinstance(serviceset, ServiceSet) |
320 if not force and serviceset == self._services: |
347 if not force and serviceset == self._services: |
321 return |
348 return |
322 self._update_tables('ssid', serviceset.ssid, force) |
349 self._update_tables_ref('ssid', serviceset.ssid, force) |
323 self._services = serviceset |
350 self._services = serviceset |
324 |
351 |
325 def update_transport(self, transport, force=False): |
352 def update_transport(self, transport, force=False): |
326 """Sets a new transport for the Domain. |
353 """Sets a new transport for the Domain. |
327 |
354 |
338 """ |
365 """ |
339 self._chk_state() |
366 self._chk_state() |
340 assert isinstance(transport, Transport) |
367 assert isinstance(transport, Transport) |
341 if not force and transport == self._transport: |
368 if not force and transport == self._transport: |
342 return |
369 return |
343 self._update_tables('tid', transport.tid, force) |
370 self._update_tables_ref('tid', transport.tid, force) |
344 self._transport = transport |
371 self._transport = transport |
|
372 |
|
373 def update_note(self, note): |
|
374 """Sets a new note for the Domain. |
|
375 |
|
376 Arguments: |
|
377 |
|
378 `transport` : basestring or None |
|
379 the new note |
|
380 """ |
|
381 self._chk_state() |
|
382 assert note is None or isinstance(note, basestring) |
|
383 if note == self._note: |
|
384 return |
|
385 self._update_tables('note', note) |
|
386 self._note = note |
345 |
387 |
346 def get_info(self): |
388 def get_info(self): |
347 """Returns a dictionary with information about the domain.""" |
389 """Returns a dictionary with information about the domain.""" |
348 self._chk_state() |
390 self._chk_state() |
349 dbc = self._dbh.cursor() |
391 dbc = self._dbh.cursor() |