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"),
43 'peer_id': Parameter(int, "Peer at which this slice was created", nullok = True),
47 class_key = 'login_base'
48 foreign_fields = ['abbreviated_name', 'name', 'is_public', 'latitude', 'longitude',
49 'url', 'date_created', 'last_updated', 'max_slices', 'max_slivers',
53 def validate_name(self, name):
55 raise PLCInvalidArgument, "Name must be specified"
59 validate_abbreviated_name = validate_name
61 def validate_login_base(self, login_base):
62 if not len(login_base):
63 raise PLCInvalidArgument, "Login base must be specified"
65 if not set(login_base).issubset(string.ascii_letters.lower()):
66 raise PLCInvalidArgument, "Login base must consist only of lowercase ASCII letters"
68 conflicts = Sites(self.api, [login_base])
69 for site in conflicts:
70 if 'site_id' not in self or self['site_id'] != site['site_id']:
71 raise PLCInvalidArgument, "login_base already in use"
75 def validate_latitude(self, latitude):
76 if not self.has_key('longitude') or \
77 self['longitude'] is None:
78 raise PLCInvalidArgument, "Longitude must also be specified"
82 def validate_longitude(self, longitude):
83 if not self.has_key('latitude') or \
84 self['latitude'] is None:
85 raise PLCInvalidArgument, "Latitude must also be specified"
90 def validate_date_created (self, timestamp):
91 return self.validate_timestamp (timestamp)
92 def validate_last_updated (self, timestamp):
93 return self.validate_timestamp (timestamp)
95 def add_person(self, person, commit = True):
97 Add person to existing site.
100 assert 'site_id' in self
101 assert isinstance(person, PLC.Persons.Person)
102 assert 'person_id' in person
104 site_id = self['site_id']
105 person_id = person['person_id']
107 if person_id not in self['person_ids']:
108 assert site_id not in person['site_ids']
110 self.api.db.do("INSERT INTO person_site (person_id, site_id)" \
111 " VALUES(%(person_id)d, %(site_id)d)",
117 self['person_ids'].append(person_id)
118 person['site_ids'].append(site_id)
120 def remove_person(self, person, commit = True):
122 Remove person from existing site.
125 assert 'site_id' in self
126 assert isinstance(person, PLC.Persons.Person)
127 assert 'person_id' in person
129 site_id = self['site_id']
130 person_id = person['person_id']
132 if person_id in self['person_ids']:
133 assert site_id in person['site_ids']
135 self.api.db.do("DELETE FROM person_site" \
136 " WHERE person_id = %(person_id)d" \
137 " AND site_id = %(site_id)d",
143 self['person_ids'].remove(person_id)
144 person['site_ids'].remove(site_id)
146 def add_address(self, address, commit = True):
148 Add address to existing site.
151 assert 'site_id' in self
152 assert isinstance(address, Address)
153 assert 'address_id' in address
155 site_id = self['site_id']
156 address_id = address['address_id']
158 if address_id not in self['address_ids']:
159 self.api.db.do("INSERT INTO site_address (address_id, site_id)" \
160 " VALUES(%(address_id)d, %(site_id)d)",
166 self['address_ids'].append(address_id)
168 def remove_address(self, address, commit = True):
170 Remove address from existing site.
173 assert 'site_id' in self
174 assert isinstance(address, Address)
175 assert 'address_id' in address
177 site_id = self['site_id']
178 address_id = address['address_id']
180 if address_id in self['address_ids']:
181 self.api.db.do("DELETE FROM site_address" \
182 " WHERE address_id = %(address_id)d" \
183 " AND site_id = %(site_id)d",
189 self['address_ids'].remove(address_id)
191 def delete(self, commit = True):
193 Delete existing site.
196 assert 'site_id' in self
198 # Delete accounts of all people at the site who are not
199 # members of at least one other non-deleted site.
200 persons = PLC.Persons.Persons(self.api, self['person_ids'])
201 for person in persons:
204 person_sites = Sites(self.api, person['site_ids'])
205 for person_site in person_sites:
206 if person_site['site_id'] != self['site_id']:
211 person.delete(commit = False)
213 # Delete all site addresses
214 addresses = Addresses(self.api, self['address_ids'])
215 for address in addresses:
216 address.delete(commit = False)
218 # Delete all site slices
219 slices = Slices(self.api, self['slice_ids'])
221 slice.delete(commit = False)
223 # Delete all site PCUs
224 pcus = PCUs(self.api, self['pcu_ids'])
226 pcu.delete(commit = False)
228 # Delete all site nodes
229 nodes = Nodes(self.api, self['node_ids'])
231 node.delete(commit = False)
233 # Clean up miscellaneous join tables
234 for table in ['person_site']:
235 self.api.db.do("DELETE FROM %s" \
236 " WHERE site_id = %d" % \
237 (table, self['site_id']), self)
240 self['deleted'] = True
245 Representation of row(s) from the sites table in the
249 def __init__(self, api, site_filter = None, columns = None):
250 Table.__init__(self, api, Site, columns)
252 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
253 ", ".join(self.columns)
255 if site_filter is not None:
256 if isinstance(site_filter, (list, tuple, set)):
257 # Separate the list into integers and strings
258 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
259 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
260 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
261 sql += " AND (%s)" % site_filter.sql(api, "OR")
262 elif isinstance(site_filter, dict):
263 site_filter = Filter(Site.fields, site_filter)
264 sql += " AND (%s)" % site_filter.sql(api, "AND")