1 from types import StringTypes
4 from PLC.Faults import *
5 from PLC.Parameter import Parameter
6 from PLC.Filter import Filter
7 from PLC.Debug import profile
8 from PLC.Table import Row, Table
9 from PLC.Slices import Slice, Slices
10 from PLC.PCUs import PCU, PCUs
11 from PLC.Nodes import Node, Nodes
12 from PLC.NodeGroups import NodeGroup, NodeGroups
13 from PLC.Addresses import Address, Addresses
18 Representation of a row in the sites table. To use, optionally
19 instantiate with a dict of values. Update as you would a
20 dict. Commit to the database with sync().
24 primary_key = 'site_id'
26 'site_id': Parameter(int, "Site identifier"),
27 'name': Parameter(str, "Full site name", max = 254),
28 'abbreviated_name': Parameter(str, "Abbreviated site name", max = 50),
29 'login_base': Parameter(str, "Site slice prefix", max = 20),
30 'is_public': Parameter(bool, "Publicly viewable site"),
31 'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True),
32 'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True),
33 'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True),
34 'date_created': Parameter(int, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True),
35 'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True),
36 'max_slices': Parameter(int, "Maximum number of slices that the site is able to create"),
37 'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create"),
38 'person_ids': Parameter([int], "List of account identifiers"),
39 'slice_ids': Parameter([int], "List of slice identifiers"),
40 'address_ids': Parameter([int], "List of address identifiers"),
41 'pcu_ids': Parameter([int], "List of PCU identifiers"),
42 'node_ids': Parameter([int], "List of site node identifiers"),
45 def validate_name(self, name):
47 raise PLCInvalidArgument, "Name must be specified"
51 validate_abbreviated_name = validate_name
53 def validate_login_base(self, login_base):
54 if not len(login_base):
55 raise PLCInvalidArgument, "Login base must be specified"
57 if not set(login_base).issubset(string.ascii_letters.lower()):
58 raise PLCInvalidArgument, "Login base must consist only of lowercase ASCII letters"
60 conflicts = Sites(self.api, [login_base])
61 for site in conflicts:
62 if 'site_id' not in self or self['site_id'] != site['site_id']:
63 raise PLCInvalidArgument, "login_base already in use"
67 def validate_latitude(self, latitude):
68 if not self.has_key('longitude') or \
69 self['longitude'] is None:
70 raise PLCInvalidArgument, "Longitude must also be specified"
74 def validate_longitude(self, longitude):
75 if not self.has_key('latitude') or \
76 self['latitude'] is None:
77 raise PLCInvalidArgument, "Latitude must also be specified"
81 def add_person(self, person, commit = True):
83 Add person to existing site.
86 assert 'site_id' in self
87 assert isinstance(person, PLC.Persons.Person)
88 assert 'person_id' in person
90 site_id = self['site_id']
91 person_id = person['person_id']
93 if person_id not in self['person_ids']:
94 assert site_id not in person['site_ids']
96 self.api.db.do("INSERT INTO person_site (person_id, site_id)" \
97 " VALUES(%(person_id)d, %(site_id)d)",
103 self['person_ids'].append(person_id)
104 person['site_ids'].append(site_id)
106 def remove_person(self, person, commit = True):
108 Remove person from existing site.
111 assert 'site_id' in self
112 assert isinstance(person, PLC.Persons.Person)
113 assert 'person_id' in person
115 site_id = self['site_id']
116 person_id = person['person_id']
118 if person_id in self['person_ids']:
119 assert site_id in person['site_ids']
121 self.api.db.do("DELETE FROM person_site" \
122 " WHERE person_id = %(person_id)d" \
123 " AND site_id = %(site_id)d",
129 self['person_ids'].remove(person_id)
130 person['site_ids'].remove(site_id)
132 def add_address(self, address, commit = True):
134 Add address to existing site.
137 assert 'site_id' in self
138 assert isinstance(address, Address)
139 assert 'address_id' in address
141 site_id = self['site_id']
142 address_id = address['address_id']
144 if address_id not in self['address_ids']:
145 self.api.db.do("INSERT INTO site_address (address_id, site_id)" \
146 " VALUES(%(address_id)d, %(site_id)d)",
152 self['address_ids'].append(address_id)
154 def remove_address(self, address, commit = True):
156 Remove address from existing site.
159 assert 'site_id' in self
160 assert isinstance(address, Address)
161 assert 'address_id' in address
163 site_id = self['site_id']
164 address_id = address['address_id']
166 if address_id in self['address_ids']:
167 self.api.db.do("DELETE FROM site_address" \
168 " WHERE address_id = %(address_id)d" \
169 " AND site_id = %(site_id)d",
175 self['address_ids'].remove(address_id)
177 def delete(self, commit = True):
179 Delete existing site.
182 assert 'site_id' in self
184 # Delete accounts of all people at the site who are not
185 # members of at least one other non-deleted site.
186 persons = PLC.Persons.Persons(self.api, self['person_ids'])
187 for person in persons:
190 person_sites = Sites(self.api, person['site_ids'])
191 for person_site in person_sites:
192 if person_site['site_id'] != self['site_id']:
197 person.delete(commit = False)
199 # Delete all site addresses
200 addresses = Addresses(self.api, self['address_ids'])
201 for address in addresses:
202 address.delete(commit = False)
204 # Delete all site slices
205 slices = Slices(self.api, self['slice_ids'])
207 slice.delete(commit = False)
209 # Delete all site PCUs
210 pcus = PCUs(self.api, self['pcu_ids'])
212 pcu.delete(commit = False)
214 # Delete all site nodes
215 nodes = Nodes(self.api, self['node_ids'])
217 node.delete(commit = False)
219 # Clean up miscellaneous join tables
220 for table in ['person_site']:
221 self.api.db.do("DELETE FROM %s" \
222 " WHERE site_id = %d" % \
223 (table, self['site_id']), self)
226 self['deleted'] = True
231 Representation of row(s) from the sites table in the
235 def __init__(self, api, site_filter = None, columns = None):
236 Table.__init__(self, api, Site, columns)
238 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
239 ", ".join(self.columns)
241 if site_filter is not None:
242 if isinstance(site_filter, (list, tuple, set)):
243 # Separate the list into integers and strings
244 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
245 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
246 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
247 sql += " AND (%s)" % site_filter.sql(api, "OR")
248 elif isinstance(site_filter, dict):
249 site_filter = Filter(Site.fields, site_filter)
250 sql += " AND (%s)" % site_filter.sql(api, "AND")