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))
120 self.object = self.api.client_shell.keystone.tenants.update(self['tenant_id'], **nova_site)
121 AlchemyObj.update(self, {'site_id': self['site_id']}, dict(self))
123 def delete(self, commit=True):
124 assert 'site_id' in self
125 assert 'tenant_id' in self
128 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
129 self.api.client_shell.keystone.tenants.delete(tenant)
131 # delete relationships
132 SitePerson().delete(filter={'site_id': self['site_id']})
133 Slice().delete(filter={'site_id': self['site_id']})
134 PCU().delete(filter={'site_id': self['site_id']})
135 Node().delete(filter={'site_id': self['site_id']})
136 Address().delete(filter={'site_id': self['site_id']})
137 SiteTag().delete(filter={'site_id': self['site_id']})
140 AlchemyObj.delete(self, dict(self))
146 Representation of row(s) from the sites table in the
150 def __init__(self, api, site_filter = None, columns = None):
153 sites = Site().select()
154 elif isinstance(site_filter, int):
155 sites = Site().select(filter={'site_id': site_filter})
156 elif isinstance(site_filter, StringTypes):
157 sites = Site().select(filter={'login_base': site_filter})
158 elif isinstance(site_filter, dict):
159 sites = Site().select(filter=site_filter)
160 elif isinstance(site_filter, (list, tuple, set)):
161 sites = Site().select()
162 sites = [site for site in sites if site.id in site_filter]
164 raise PLCInvalidArgument, "Wrong site filter %s" % site_filter
168 site = Site(self.api, object = site)
169 if not columns or 'person_ids' in columns:
170 site_persons = SitePerson().select(filter={'site_id': site['site_id']})
171 site['person_ids'] = [rec.person_id for rec in site_persons]
173 if not columns or 'slice_ids' in columns:
174 site_slices = Slice().select(filter={'site_id': site['site_id']})
175 site['slice_ids'] = [rec.person_id for rec in site_slices]
177 if not columns or 'puc_ids' in columns:
178 site_pcus = PCU().select(filter={'site_id': site['site_id']})
179 site['pcu_ids'] = [rec.id for rec in site_pcus]
180 if not columns or 'node_ids' in columns:
181 site_nodes = Node().select(filter={'site_id': site['site_id']})
182 site['node_ids'] = [rec.id for rec in site_nodes]
183 if not columns or 'address_ids' in columns:
184 site_addresses = SiteAddress().select(filter={'site_id': site['site_id']})
185 site['address_ids'] = [rec.id for rec in site_addresses]
187 if not columns or 'site_tag_ids' in columns:
188 site_tags = SiteTag().select(filter={'site_id': site['site_id']})
189 site['site_tag_ids'] = [rec.id for rec in site_tags]