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),
49 class_key = 'login_base'
50 foreign_fields = ['abbreviated_name', 'name', 'is_public', 'latitude', 'longitude',
51 'url', 'max_slices', 'max_slivers',
53 # forget about these ones, they are read-only anyway
54 # handling them causes Cache to re-sync all over again
55 # 'last_updated', 'date_created'
58 def validate_name(self, name):
60 raise PLCInvalidArgument, "Name must be specified"
64 validate_abbreviated_name = validate_name
66 def validate_login_base(self, login_base):
67 if not len(login_base):
68 raise PLCInvalidArgument, "Login base must be specified"
70 if not set(login_base).issubset(string.lowercase + string.digits):
71 raise PLCInvalidArgument, "Login base must consist only of lowercase ASCII letters or numbers"
73 conflicts = Sites(self.api, [login_base])
74 for site in conflicts:
75 if 'site_id' not in self or self['site_id'] != site['site_id']:
76 raise PLCInvalidArgument, "login_base already in use"
80 def validate_latitude(self, latitude):
81 if not self.has_key('longitude') or \
82 self['longitude'] is None:
83 raise PLCInvalidArgument, "Longitude must also be specified"
87 def validate_longitude(self, longitude):
88 if not self.has_key('latitude') or \
89 self['latitude'] is None:
90 raise PLCInvalidArgument, "Latitude must also be specified"
94 validate_date_created = Row.validate_timestamp
95 validate_last_updated = Row.validate_timestamp
97 add_person = Row.add_object(Person, 'person_site')
98 remove_person = Row.remove_object(Person, 'person_site')
100 add_address = Row.add_object(Address, 'site_address')
101 remove_address = Row.remove_object(Address, 'site_address')
103 def delete(self, commit = True):
105 Delete existing site.
108 assert 'site_id' in self
110 # Delete accounts of all people at the site who are not
111 # members of at least one other non-deleted site.
112 persons = Persons(self.api, self['person_ids'])
113 for person in persons:
116 person_sites = Sites(self.api, person['site_ids'])
117 for person_site in person_sites:
118 if person_site['site_id'] != self['site_id']:
123 person.delete(commit = False)
125 # Delete all site addresses
126 addresses = Addresses(self.api, self['address_ids'])
127 for address in addresses:
128 address.delete(commit = False)
130 # Delete all site slices
131 slices = Slices(self.api, self['slice_ids'])
133 slice.delete(commit = False)
135 # Delete all site PCUs
136 pcus = PCUs(self.api, self['pcu_ids'])
138 pcu.delete(commit = False)
140 # Delete all site nodes
141 nodes = Nodes(self.api, self['node_ids'])
143 node.delete(commit = False)
145 # Clean up miscellaneous join tables
146 for table in self.join_tables:
147 self.api.db.do("DELETE FROM %s WHERE site_id = %d" % \
148 (table, self['site_id']))
151 self['deleted'] = True
156 Representation of row(s) from the sites table in the
160 def __init__(self, api, site_filter = None, columns = None):
161 Table.__init__(self, api, Site, columns)
163 sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
164 ", ".join(self.columns)
166 if site_filter is not None:
167 if isinstance(site_filter, (list, tuple, set)):
168 # Separate the list into integers and strings
169 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
170 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
171 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
172 sql += " AND (%s)" % site_filter.sql(api, "OR")
173 elif isinstance(site_filter, dict):
174 site_filter = Filter(Site.fields, site_filter)
175 sql += " AND (%s)" % site_filter.sql(api, "AND")