from types import StringTypes from datetime import datetime import string from PLC.Faults import * from PLC.Logger import logger from PLC.Parameter import Parameter, Mixed from PLC.Storage.AlchemyObject import AlchemyObj from PLC.Slices import Slice, Slices from PLC.Persons import Person, Persons from PLC.SitePersons import SitePerson, SitePersons from PLC.SiteAddresses import SiteAddress, SiteAddress from PLC.PCUs import PCU, PCUs from PLC.Nodes import Node, Nodes from PLC.Roles import Role, Roles from PLC.SiteTags import SiteTag, SiteTags class Site(AlchemyObj): """ Representation of a row in the sites table. To use, optionally instantiate with a dict of values. Update as you would a dict. Commit to the database with sync(). """ tablename = 'sites' fields = { 'site_id': Parameter(int, "Site identifier", primary_key=True), 'tenant_id': Parameter(str, "Tenant identifier"), 'enabled': Parameter(bool, "Has been enabled"), 'abbreviated_name': Parameter(str, "Abbreviated site name", max = 50), 'login_base': Parameter(str, "Site slice prefix", max = 20), 'is_public': Parameter(bool, "Publicly viewable site"), 'name': Parameter(str, "Full site name", max = 254), 'description': Parameter(str, "Description", max = 254), 'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True), 'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True), 'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True), 'date_created': Parameter(datetime, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True, default=datetime.now()), 'last_updated': Parameter(datetime, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True, nullok=True), 'max_slices': Parameter(int, "Maximum number of slices that the site is able to create", default=10), 'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create", default=1000), 'person_ids': Parameter([int], "List of account identifiers", joined=True), 'slice_ids': Parameter([int], "List of slice identifiers", joined=True), 'address_ids': Parameter([int], "List of address identifiers", joined=True), 'pcu_ids': Parameter([int], "List of PCU identifiers", joined=True), 'node_ids': Parameter([int], "List of site node identifiers", joined=True), 'site_tag_ids' : Parameter ([int], "List of tags attached to this site", joined=True), 'peer_id': Parameter(int, "Peer to which this site belongs", nullok = True), 'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True), 'ext_consortium_id': Parameter(int, "external consortium id", nullok = True) } def validate_last_updated(self, last_updated): # always return current timestamp last_updated = datetime.now() return last_updated def add_person(self, person_filter, role_name=None): assert 'site_id' in self assert 'tenant_id' in self if not role_name: role_name = 'user' roles = Roles(self.api, role_name) if not roles: raise PLCInvalidArgument, "No such role %s" % role_name role = roles[0] tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id']) persons = Persons(self.api, person_filter) for person in persons: keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id']) tenant.add_user(keystone_user, role.object) site_person = SitePerson(self.api, {'site_id': self['site_id'], 'person_id': person['person_id']}) site_person.sync() def delete_person(self, person_filter, role=None): assert 'site_id' in self assert 'tenant_id' in self if not role: role = 'user' roles = Roles(self.api, role_name) if not roles: raise PLCInvalidArgument, "No such role %s" % role_name role = roles[0] tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id']) persons = Persons(self.api, person_filter) for person in persons: keystone_user = self.api.client_shell.keystone.users.find(id=person['keystone_id']) tenant.remove_user(keystone_user, role.object) site_persons = SitePersons(self.api, {'site_id': self['id'], 'person_id': person['person_id']}) for site_person in site_persons: site_person.delete() def sync(self, commit=True, validate=True): """ Add or update the site. """ assert 'login_base' in self AlchemyObj.sync(self, commit=commit, validate=validate) # filter out fields that are not supported in keystone nova_fields = ['enabled', 'description'] nova_can_update = lambda (field, value): field in nova_fields nova_site = dict(filter(nova_can_update, self.items())) nova_site['tenant_name'] = self['login_base'] if 'site_id' not in self: # check if keystone record exsits tenants = self.api.client_shell.keystone.tenants.findall(name=self['login_base']) if not tenants: self.object = self.api.client_shell.keystone.tenants.create(**nova_site) else: self.object = tenants[0] self['tenant_id'] = self.object.id # sync the plc record AlchemyObj.insert(self, dict(self)) else: self.object = self.api.client_shell.keystone.tenants.update(self['tenant_id'], **nova_site) AlchemyObj.update(self, {'site_id': self['site_id']}, dict(self)) def delete(self, commit=True): assert 'site_id' in self assert 'tenant_id' in self # delete nova object tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id']) self.api.client_shell.keystone.tenants.delete(tenant) # delete relationships SitePerson().delete(filter={'site_id': self['site_id']}) Slice().delete(filter={'site_id': self['site_id']}) PCU().delete(filter={'site_id': self['site_id']}) Node().delete(filter={'site_id': self['site_id']}) Address().delete(filter={'site_id': self['site_id']}) SiteTag().delete(filter={'site_id': self['site_id']}) # delete site AlchemyObj.delete(self, dict(self)) class Sites(list): """ Representation of row(s) from the sites table in the database. """ def __init__(self, api, site_filter = None, columns = None): self.api = api if not site_filter: sites = Site().select() elif isinstance(site_filter, int): sites = Site().select(filter={'site_id': site_filter}) elif isinstance(site_filter, StringTypes): sites = Site().select(filter={'login_base': site_filter}) elif isinstance(site_filter, dict): sites = Site().select(filter=site_filter) elif isinstance(site_filter, (list, tuple, set)): ints = filter(lambda x: isinstance(x, (int, long)), site_filter) strs = filter(lambda x: isinstance(x, StringTypes), site_filter) site_filter = {'site_id': ints, 'login_base': strs} sites = Site().select(filter=site_filter) else: raise PLCInvalidArgument, "Wrong site filter %s" % site_filter for site in sites: site = Site(self.api, object = site) if not columns or 'person_ids' in columns: site_persons = SitePerson().select(filter={'site_id': site['site_id']}) site['person_ids'] = [rec.person_id for rec in site_persons] if not columns or 'slice_ids' in columns: site_slices = Slice().select(filter={'site_id': site['site_id']}) site['slice_ids'] = [rec.person_id for rec in site_slices] if not columns or 'puc_ids' in columns: site_pcus = PCU().select(filter={'site_id': site['site_id']}) site['pcu_ids'] = [rec.id for rec in site_pcus] if not columns or 'node_ids' in columns: site_nodes = Node().select(filter={'site_id': site['site_id']}) site['node_ids'] = [rec.id for rec in site_nodes] if not columns or 'address_ids' in columns: site_addresses = SiteAddress().select(filter={'site_id': site['site_id']}) site['address_ids'] = [rec.id for rec in site_addresses] if not columns or 'site_tag_ids' in columns: site_tags = SiteTag().select(filter={'site_id': site['site_id']}) site['site_tag_ids'] = [rec.id for rec in site_tags] self.append(site)