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 'enabled': Parameter(bool, "Has been enabled"),
32 'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True),
33 'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True),
34 'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True),
35 'date_created': Parameter(int, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True),
36 'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True),
37 'max_slices': Parameter(int, "Maximum number of slices that the site is able to create"),
38 'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create"),
39 'person_ids': Parameter([int], "List of account identifiers"),
40 'slice_ids': Parameter([int], "List of slice identifiers"),
41 'address_ids': Parameter([int], "List of address identifiers"),
42 'pcu_ids': Parameter([int], "List of PCU identifiers"),
43 'node_ids': Parameter([int], "List of site node identifiers"),
44 'peer_id': Parameter(int, "Peer to which this site belongs", nullok = True),
45 'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
46 'ext_consortium_id': Parameter(int, "external consortium id", nullok = True)
50 class_key = 'login_base'
51 foreign_fields = ['abbreviated_name', 'name', 'is_public', 'latitude', 'longitude',
52 'url', 'max_slices', 'max_slivers',
54 # forget about these ones, they are read-only anyway
55 # handling them causes Cache to re-sync all over again
56 # 'last_updated', 'date_created'
59 def validate_name(self, name):
61 raise PLCInvalidArgument, "Name must be specified"
65 validate_abbreviated_name = validate_name
67 def validate_login_base(self, login_base):
68 if not len(login_base):
69 raise PLCInvalidArgument, "Login base must be specified"
71 if not set(login_base).issubset(string.lowercase + string.digits):
72 raise PLCInvalidArgument, "Login base must consist only of lowercase ASCII letters or numbers"
74 conflicts = Sites(self.api, [login_base])
75 for site in conflicts:
76 if 'site_id' not in self or self['site_id'] != site['site_id']:
77 raise PLCInvalidArgument, "login_base already in use"
81 def validate_latitude(self, latitude):
82 if not self.has_key('longitude') or \
83 self['longitude'] is None:
84 raise PLCInvalidArgument, "Longitude must also be specified"
88 def validate_longitude(self, longitude):
89 if not self.has_key('latitude') or \
90 self['latitude'] is None:
91 raise PLCInvalidArgument, "Latitude must also be specified"
95 validate_date_created = Row.validate_timestamp
96 validate_last_updated = Row.validate_timestamp
98 add_person = Row.add_object(Person, 'person_site')
99 remove_person = Row.remove_object(Person, 'person_site')
101 add_address = Row.add_object(Address, 'site_address')
102 remove_address = Row.remove_object(Address, 'site_address')
104 def update_last_updated(self, commit = True):
106 Update last_updated field with current time
109 assert 'site_id' in self
110 assert self.table_name
112 self.api.db.do("UPDATE %s SET last_updated = CURRENT_TIMESTAMP " % (self.table_name) + \
113 " where site_id = %d" % (self['site_id']) )
116 def delete(self, commit = True):
118 Delete existing site.
121 assert 'site_id' in self
123 # Delete accounts of all people at the site who are not
124 # members of at least one other non-deleted site.
125 persons = Persons(self.api, self['person_ids'])
126 for person in persons:
129 person_sites = Sites(self.api, person['site_ids'])
130 for person_site in person_sites:
131 if person_site['site_id'] != self['site_id']:
136 person.delete(commit = False)
138 # Delete all site addresses
139 addresses = Addresses(self.api, self['address_ids'])
140 for address in addresses:
141 address.delete(commit = False)
143 # Delete all site slices
144 slices = Slices(self.api, self['slice_ids'])
146 slice.delete(commit = False)
148 # Delete all site PCUs
149 pcus = PCUs(self.api, self['pcu_ids'])
151 pcu.delete(commit = False)
153 # Delete all site nodes
154 nodes = Nodes(self.api, self['node_ids'])
156 node.delete(commit = False)
158 # Clean up miscellaneous join tables
159 for table in self.join_tables:
160 self.api.db.do("DELETE FROM %s WHERE site_id = %d" % \
161 (table, self['site_id']))
164 self['deleted'] = True
169 Representation of row(s) from the sites table in the
173 def __init__(self, api, site_filter = None, columns = None):
174 Table.__init__(self, api, Site, columns)
176 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
177 ", ".join(self.columns)
179 if site_filter is not None:
180 if isinstance(site_filter, (list, tuple, set)):
181 # Separate the list into integers and strings
182 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
183 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
184 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
185 sql += " AND (%s) %s" % site_filter.sql(api, "OR")
186 elif isinstance(site_filter, dict):
187 site_filter = Filter(Site.fields, site_filter)
188 sql += " AND (%s) %s" % site_filter.sql(api, "AND")
189 elif isinstance (site_filter, StringTypes):
190 site_filter = Filter(Site.fields, {'login_base':[site_filter]})
191 sql += " AND (%s) %s" % site_filter.sql(api, "AND")
192 elif isinstance (site_filter, int):
193 site_filter = Filter(Site.fields, {'site_id':[site_filter]})
194 sql += " AND (%s) %s" % site_filter.sql(api, "AND")
196 raise PLCInvalidArgument, "Wrong site filter %r"%site_filter