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 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
162 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
163 site_filter = {'site_id': ints, 'login_base': strs}
164 sites = Site().select(filter=site_filter)
166 raise PLCInvalidArgument, "Wrong site filter %s" % site_filter
170 site = Site(self.api, object = site)
171 if not columns or 'person_ids' in columns:
172 site_persons = SitePerson().select(filter={'site_id': site['site_id']})
173 site['person_ids'] = [rec.person_id for rec in site_persons]
175 if not columns or 'slice_ids' in columns:
176 site_slices = Slice().select(filter={'site_id': site['site_id']})
177 site['slice_ids'] = [rec.person_id for rec in site_slices]
179 if not columns or 'puc_ids' in columns:
180 site_pcus = PCU().select(filter={'site_id': site['site_id']})
181 site['pcu_ids'] = [rec.id for rec in site_pcus]
182 if not columns or 'node_ids' in columns:
183 site_nodes = Node().select(filter={'site_id': site['site_id']})
184 site['node_ids'] = [rec.id for rec in site_nodes]
185 if not columns or 'address_ids' in columns:
186 site_addresses = SiteAddress().select(filter={'site_id': site['site_id']})
187 site['address_ids'] = [rec.id for rec in site_addresses]
189 if not columns or 'site_tag_ids' in columns:
190 site_tags = SiteTag().select(filter={'site_id': site['site_id']})
191 site['site_tag_ids'] = [rec.id for rec in site_tags]