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.Addresses import Address, Addresses
13 from PLC.Persons import Person, Persons
17 Representation of a row in the sites table. To use, optionally
18 instantiate with a dict of values. Update as you would a
19 dict. Commit to the database with sync().
23 primary_key = 'site_id'
24 join_tables = ['person_site', 'site_address', 'peer_site']
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 to which this site belongs", nullok = True),
44 'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
48 class_key = 'login_base'
49 foreign_fields = ['abbreviated_name', 'name', 'is_public', 'latitude', 'longitude',
50 'url', 'max_slices', 'max_slivers',
52 # forget about these ones, they are read-only anyway
53 # handling them causes Cache to re-sync all over again
54 # 'last_updated', 'date_created'
57 def validate_name(self, name):
59 raise PLCInvalidArgument, "Name must be specified"
63 validate_abbreviated_name = validate_name
65 def validate_login_base(self, login_base):
66 if not len(login_base):
67 raise PLCInvalidArgument, "Login base must be specified"
69 if not set(login_base).issubset(string.ascii_letters.lower()):
70 raise PLCInvalidArgument, "Login base must consist only of lowercase ASCII letters"
72 conflicts = Sites(self.api, [login_base])
73 for site in conflicts:
74 if 'site_id' not in self or self['site_id'] != site['site_id']:
75 raise PLCInvalidArgument, "login_base already in use"
79 def validate_latitude(self, latitude):
80 if not self.has_key('longitude') or \
81 self['longitude'] is None:
82 raise PLCInvalidArgument, "Longitude must also be specified"
86 def validate_longitude(self, longitude):
87 if not self.has_key('latitude') or \
88 self['latitude'] is None:
89 raise PLCInvalidArgument, "Latitude must also be specified"
93 validate_date_created = Row.validate_timestamp
94 validate_last_updated = Row.validate_timestamp
96 add_person = Row.add_object(Person, 'person_site')
97 remove_person = Row.remove_object(Person, 'person_site')
99 add_address = Row.add_object(Address, 'site_address')
100 remove_address = Row.remove_object(Address, 'site_address')
102 def delete(self, commit = True):
104 Delete existing site.
107 assert 'site_id' in self
109 # Delete accounts of all people at the site who are not
110 # members of at least one other non-deleted site.
111 persons = Persons(self.api, self['person_ids'])
112 for person in persons:
115 person_sites = Sites(self.api, person['site_ids'])
116 for person_site in person_sites:
117 if person_site['site_id'] != self['site_id']:
122 person.delete(commit = False)
124 # Delete all site addresses
125 addresses = Addresses(self.api, self['address_ids'])
126 for address in addresses:
127 address.delete(commit = False)
129 # Delete all site slices
130 slices = Slices(self.api, self['slice_ids'])
132 slice.delete(commit = False)
134 # Delete all site PCUs
135 pcus = PCUs(self.api, self['pcu_ids'])
137 pcu.delete(commit = False)
139 # Delete all site nodes
140 nodes = Nodes(self.api, self['node_ids'])
142 node.delete(commit = False)
144 # Clean up miscellaneous join tables
145 for table in self.join_tables:
146 self.api.db.do("DELETE FROM %s WHERE site_id = %d" % \
147 (table, self['site_id']))
150 self['deleted'] = True
155 Representation of row(s) from the sites table in the
159 def __init__(self, api, site_filter = None, columns = None):
160 Table.__init__(self, api, Site, columns)
162 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
163 ", ".join(self.columns)
165 if site_filter is not None:
166 if isinstance(site_filter, (list, tuple, set)):
167 # Separate the list into integers and strings
168 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
169 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
170 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
171 sql += " AND (%s)" % site_filter.sql(api, "OR")
172 elif isinstance(site_filter, dict):
173 site_filter = Filter(Site.fields, site_filter)
174 sql += " AND (%s)" % site_filter.sql(api, "AND")