1 from types import StringTypes
2 from datetime import datetime
5 from PLC.Faults import *
6 from PLC.Logger import logger
7 from PLC.Parameter import Parameter, Mixed
8 from PLC.Storage.AlchemyObject import AlchemyObj
9 from PLC.Slices import Slice, Slices
10 from PLC.Persons import Person, Persons
11 from PLC.SitePersons import SitePerson, SitePersons
12 from PLC.SiteAddresses import SiteAddress, SiteAddress
13 from PLC.PCUs import PCU, PCUs
14 from PLC.Nodes import Node, Nodes
15 from PLC.Roles import Role, Roles
16 from PLC.SiteTags import SiteTag, SiteTags
18 class Site(AlchemyObj):
20 Representation of a row in the sites table. To use, optionally
21 instantiate with a dict of values. Update as you would a
22 dict. Commit to the database with sync().
28 'site_id': Parameter(int, "Site identifier", primary_key=True),
29 'tenant_id': Parameter(str, "Tenant identifier"),
30 'enabled': Parameter(bool, "Has been enabled"),
31 'abbreviated_name': Parameter(str, "Abbreviated site name", max = 50),
32 'login_base': Parameter(str, "Site slice prefix", max = 20),
33 'is_public': Parameter(bool, "Publicly viewable site"),
34 'name': Parameter(str, "Full site name", max = 254),
35 'description': Parameter(str, "Description", max = 254),
36 'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True),
37 'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True),
38 'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True),
39 'date_created': Parameter(datetime, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True, default=datetime.now()),
40 'last_updated': Parameter(datetime, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True, nullok=True),
41 'max_slices': Parameter(int, "Maximum number of slices that the site is able to create", default=10),
42 'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create", default=1000),
43 'person_ids': Parameter([int], "List of account identifiers", joined=True),
44 'slice_ids': Parameter([int], "List of slice identifiers", joined=True),
45 'address_ids': Parameter([int], "List of address identifiers", joined=True),
46 'pcu_ids': Parameter([int], "List of PCU identifiers", joined=True),
47 'node_ids': Parameter([int], "List of site node identifiers", joined=True),
48 'site_tag_ids' : Parameter ([int], "List of tags attached to this site", joined=True),
49 'peer_id': Parameter(int, "Peer to which this site belongs", nullok = True),
50 'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
51 'ext_consortium_id': Parameter(int, "external consortium id", nullok = True)
54 def validate_last_updated(self, last_updated):
55 # always return current timestamp
56 last_updated = datetime.now()
59 def add_person(self, person_filter, role_name=None):
60 assert 'site_id' in self
61 assert 'tenant_id' in self
64 roles = Roles(self.api, role_name)
66 raise PLCInvalidArgument, "No such role %s" % role_name
68 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
69 persons = Persons(self.api, person_filter)
70 for person in persons:
71 keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id'])
72 tenant.add_user(keystone_user, role.object)
73 site_person = SitePerson(self.api, {'site_id': self['site_id'],
74 'person_id': person['person_id']})
78 def delete_person(self, person_filter, role=None):
79 assert 'site_id' in self
80 assert 'tenant_id' in self
83 roles = Roles(self.api, role_name)
85 raise PLCInvalidArgument, "No such role %s" % role_name
87 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
88 persons = Persons(self.api, person_filter)
89 for person in persons:
90 keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id'])
91 tenant.remove_user(keystone_user, role.object)
92 site_persons = SitePersons(self.api, {'site_id': self['id'],
93 'person_id': person['person_id']})
94 for site_person in site_persons:
98 def sync(self, commit=True, validate=True):
100 Add or update the site.
102 assert 'login_base' in self
103 AlchemyObj.sync(self, commit=commit, validate=validate)
104 # filter out fields that are not supported in keystone
105 nova_fields = ['enabled', 'description']
106 nova_can_update = lambda (field, value): field in nova_fields
107 nova_site = dict(filter(nova_can_update, self.items()))
108 nova_site['tenant_name'] = self['login_base']
109 if 'site_id' not in self:
110 # check if keystone record exsits
111 tenants = self.api.client_shell.keystone.tenants.findall(name=self['login_base'])
113 self.object = self.api.client_shell.keystone.tenants.create(**nova_site)
115 self.object = tenants[0]
116 self['tenant_id'] = self.object.id
117 # sync the plc record
118 AlchemyObj.insert(self, dict(self))
119 site = AlchemyObj.select(self, filter={'tenant_id': self['tenant_id']})[0]
120 self['site_id'] = site.site_id
123 self.object = self.api.client_shell.keystone.tenants.update(self['tenant_id'], **nova_site)
124 AlchemyObj.update(self, {'site_id': self['site_id']}, dict(self))
126 def delete(self, commit=True):
127 assert 'site_id' in self
128 assert 'tenant_id' in self
131 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
132 self.api.client_shell.keystone.tenants.delete(tenant)
134 # delete relationships
135 for site_person in SitePerson().select(filter={'site_id': self['site_id']}):
137 for slice in Slice().select(filter={'site_id': self['site_id']}):
139 for pcu in PCU().select(filter={'site_id': self['site_id']}):
141 for node in Node().select(filter={'site_id': self['site_id']}):
143 for address in SiteAddress().select(filter={'site_id': self['site_id']}):
145 for site_tag in SiteTag().select(filter={'site_id': self['site_id']}):
149 AlchemyObj.delete(self, filter={'site_id': self['site_id']})
155 Representation of row(s) from the sites table in the
159 def __init__(self, api, site_filter = None, columns = None):
162 sites = Site().select()
163 elif isinstance(site_filter, int):
164 sites = Site().select(filter={'site_id': site_filter})
165 elif isinstance(site_filter, StringTypes):
166 sites = Site().select(filter={'login_base': site_filter})
167 elif isinstance(site_filter, dict):
168 sites = Site().select(filter=site_filter)
169 elif isinstance(site_filter, (list, tuple, set)):
170 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
171 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
172 site_filter = {'site_id': ints, 'login_base': strs}
173 sites = Site().select(filter=site_filter)
175 raise PLCInvalidArgument, "Wrong site filter %s" % site_filter
179 site = Site(self.api, object = site)
180 if not columns or 'person_ids' in columns:
181 site_persons = SitePerson().select(filter={'site_id': site['site_id']})
182 site['person_ids'] = [rec.person_id for rec in site_persons]
184 if not columns or 'slice_ids' in columns:
185 site_slices = Slice().select(filter={'site_id': site['site_id']})
186 site['slice_ids'] = [rec.slice_id for rec in site_slices]
188 if not columns or 'puc_ids' in columns:
189 site_pcus = PCU().select(filter={'site_id': site['site_id']})
190 site['pcu_ids'] = [rec.pcu_id for rec in site_pcus]
191 if not columns or 'node_ids' in columns:
192 site_nodes = Node().select(filter={'site_id': site['site_id']})
193 site['node_ids'] = [rec.node_id for rec in site_nodes]
194 if not columns or 'address_ids' in columns:
195 site_addresses = SiteAddress().select(filter={'site_id': site['site_id']})
196 site['address_ids'] = [rec.address_id for rec in site_addresses]
198 if not columns or 'site_tag_ids' in columns:
199 site_tags = SiteTag().select(filter={'site_id': site['site_id']})
200 site['site_tag_ids'] = [rec.tag_id for rec in site_tags]