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.Addresses import Address, Addresses
13 from PLC.PCUs import PCU, PCUs
14 from PLC.Nodes import Node, Nodes
15 from PLC.SiteTags import SiteTag, SiteTags
17 class Site(AlchemyObj):
19 Representation of a row in the sites table. To use, optionally
20 instantiate with a dict of values. Update as you would a
21 dict. Commit to the database with sync().
27 'site_id': Parameter(int, "Site identifier", primary_key=True),
28 'tenant_id': Parameter(str, "Tenant identifier"),
29 'enabled': Parameter(bool, "Has been enabled"),
30 'abbreviated_name': Parameter(str, "Abbreviated site name", max = 50),
31 'login_base': Parameter(str, "Site slice prefix", max = 20),
32 'is_public': Parameter(bool, "Publicly viewable site"),
33 'name': Parameter(str, "Full site name", max = 254),
34 'description': Parameter(str, "Description", max = 254),
35 'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True),
36 'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True),
37 'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True),
38 'date_created': Parameter(datetime, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True, default=datetime.now()),
39 'last_updated': Parameter(datetime, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True, nullok=True),
40 'max_slices': Parameter(int, "Maximum number of slices that the site is able to create", default=10),
41 'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create", default=1000),
42 'person_ids': Parameter([int], "List of account identifiers", joined=True),
43 'slice_ids': Parameter([int], "List of slice identifiers", joined=True),
44 'address_ids': Parameter([int], "List of address identifiers", joined=True),
45 'pcu_ids': Parameter([int], "List of PCU identifiers", joined=True),
46 'node_ids': Parameter([int], "List of site node identifiers", joined=True),
47 'site_tag_ids' : Parameter ([int], "List of tags attached to this site", joined=True),
48 'peer_id': Parameter(int, "Peer to which this site belongs", nullok = True),
49 'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
50 'ext_consortium_id': Parameter(int, "external consortium id", nullok = True)
53 def validate_last_updated(self, last_updated):
54 # always return current timestamp
55 last_updated = datetime.now()
58 def add_person(self, person_filter, role=None):
59 assert 'site_id' in self
60 assert 'tenant_id' in self
63 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
64 persons = Persons(self.api, person_filter)
65 for person in persons:
66 keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id'])
67 tenant.add_user(keystone_user, role)
68 site_person = SitePerson(self.api, {'site_id': self['id'],
69 'person_id': person['person_id']})
73 def delete_person(self, person_filter, role=None):
74 assert 'site_id' in self
75 assert 'tenant_id' in self
78 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
79 persons = Persons(self.api, person_filter)
80 for person in persons:
81 keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id'])
82 tenant.remove_user(keystone_user, role)
83 site_persons = SitePersons(self.api, {'site_id': self['id'],
84 'person_id': person['person_id']})
85 for site_person in site_persons:
89 def sync(self, commit=True, validate=True):
91 Add or update the site.
93 assert 'login_base' in self
94 # sync the nova record and the plc record
95 AlchemyObj.sync(self, commit=commit, validate=validate)
96 nova_fields = ['enabled', 'description']
97 nova_can_update = lambda (field, value): field in nova_fields
98 nova_site = dict(filter(nova_can_update, self.items()))
99 nova_site['tenant_name'] = self['login_base']
100 if 'site_id' not in self:
101 tenants = self.api.client_shell.keystone.tenants.findall(name=self['login_base'])
103 self.object = self.api.client_shell.keystone.tenants.create(**nova_site)
105 self.object = tenants[0]
106 self['tenant_id'] = self.object.id
107 AlchemyObj.insert(self, dict(self))
109 self.object = self.api.client_shell.keystone.tenants.update(self['tenant_id'], **nova_site)
110 AlchemyObj.update(self, {'site_id': self['site_id']}, dict(self))
112 def delete(self, commit=True):
113 assert 'site_id' in self
114 assert 'tenant_id' in self
117 tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
118 self.api.client_shell.keystone.tenants.delete(tenant)
120 # delete relationships
121 SitePerson().delete(filter={'site_id': self['site_id']})
122 Slice().delete(filter={'site_id': self['site_id']})
123 PCU().delete(filter={'site_id': self['site_id']})
124 Node().delete(filter={'site_id': self['site_id']})
125 Address().delete(filter={'site_id': self['site_id']})
126 SiteTag().delete(filter={'site_id': self['site_id']})
129 AlchemyObj.delete(self, dict(self))
135 Representation of row(s) from the sites table in the
139 def __init__(self, api, site_filter = None, columns = None):
142 sites = Site().select()
143 elif isinstance(site_filter, int):
144 sites = Site().select(filter={'site_id': site_filter})
145 elif isinstance(site_filter, StringTypes):
146 sites = Site().select(filter={'login_base': site_filter})
147 elif isinstance(site_filter, dict):
148 sites = Site().select(filter=site_filter)
149 elif isinstance(site_filter, (list, tuple, set)):
150 sites = Site().select()
151 sites = [site for site in sites if site.id in site_filter]
153 raise PLCInvalidArgument, "Wrong site filter %s" % site_filter
156 site = Site(self.api, object = site)
157 if not columns or 'person_ids' in columns:
158 site_persons = SitePerson().select(filter={'site_id': site.id})
159 site['person_ids'] = [rec.person_id for rec in site_persons]
161 if not columns or 'slice_ids' in columns:
162 site_slices = Slice().select(filter={'site_id': site.id})
163 site['slice_ids'] = [rec.person_id for rec in site_slices]
165 if not columns or 'puc_ids' in columns:
166 site_pcus = PCU().select(filter={'site_id': site.id})
167 site['pcu_ids'] = [rec.id for rec in site_pcus]
169 if not columns or 'node_ids' in columns:
170 site_nodes = Node().select(filter={'site_id': site.id})
171 site['node_ids'] = [rec.id for rec in site_nodes]
173 if not columns or 'address_ids' in columns:
174 site_addresses = Address().select(filter={'site_id': site.id})
175 site['address_ids'] = [rec.id for rec in site_addresses]
177 if not columns or 'site_tag_ids' in columns:
178 site_tags = SiteTag().select(filter={'site_id': site.id})
179 site['site_tag_ids'] = [rec.id for rec in site_tags]