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 delete(self, commit = True):
106 Delete existing site.
109 assert 'site_id' in self
111 # Delete accounts of all people at the site who are not
112 # members of at least one other non-deleted site.
113 persons = Persons(self.api, self['person_ids'])
114 for person in persons:
117 person_sites = Sites(self.api, person['site_ids'])
118 for person_site in person_sites:
119 if person_site['site_id'] != self['site_id']:
124 person.delete(commit = False)
126 # Delete all site addresses
127 addresses = Addresses(self.api, self['address_ids'])
128 for address in addresses:
129 address.delete(commit = False)
131 # Delete all site slices
132 slices = Slices(self.api, self['slice_ids'])
134 slice.delete(commit = False)
136 # Delete all site PCUs
137 pcus = PCUs(self.api, self['pcu_ids'])
139 pcu.delete(commit = False)
141 # Delete all site nodes
142 nodes = Nodes(self.api, self['node_ids'])
144 node.delete(commit = False)
146 # Clean up miscellaneous join tables
147 for table in self.join_tables:
148 self.api.db.do("DELETE FROM %s WHERE site_id = %d" % \
149 (table, self['site_id']))
152 self['deleted'] = True
157 Representation of row(s) from the sites table in the
161 def __init__(self, api, site_filter = None, columns = None):
162 Table.__init__(self, api, Site, columns)
164 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
165 ", ".join(self.columns)
167 if site_filter is not None:
168 if isinstance(site_filter, (list, tuple, set)):
169 # Separate the list into integers and strings
170 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
171 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
172 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
173 sql += " AND (%s)" % site_filter.sql(api, "OR")
174 elif isinstance(site_filter, dict):
175 site_filter = Filter(Site.fields, site_filter)
176 sql += " AND (%s)" % site_filter.sql(api, "AND")