create() calls get_table()
[plcapi.git] / PLC / Sites.py
1 from types import StringTypes
2 import string
3
4 from PLC.Faults import *
5 from PLC.Logger import logger
6 from PLC.Parameter import Parameter, Mixed
7 from PLC.NovaTable import NovaObject, NovaTable
8 from PLC.Storage.AlchemyObj import AlchemyObj
9 from PLC.Slices import Slice, Slices
10 from PLC.SitePersons import SitePerson, SitePersons
11 from PLC.Addresses import Address, Addresses
12 from PLC.PCUs import PCU, PCUs
13 from PLC.Nodes import Node, Nodes
14 from PLC.SiteTags import SiteTag, SiteTags
15
16 class Site(AlchemyObj):
17     """
18     Representation of a row in the sites table. To use, optionally
19     instantiate with a dict of values. Update as you would a
20     dict. Commit to the database with sync().
21     """
22
23     tablename = 'sites'
24
25     fields = {
26         'site_id': Parameter(int, "Site identifier", primary_key=True),
27         'tenant_id': Parameter(str, "Tenant identifier"),
28         'enabled': Parameter(bool, "Has been enabled"),
29         'abbreviated_name': Parameter(str, "Abbreviated site name", max = 50),
30         'login_base': Parameter(str, "Site slice prefix", max = 20),
31         'is_public': Parameter(bool, "Publicly viewable site"),
32         'name': Parameter(str, "Full site name", max = 254),
33         'description': Parameter(str, "Description", max = 254),
34         'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0, nullok = True),
35         'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0, nullok = True),
36         'url': Parameter(str, "URL of a page that describes the site", max = 254, nullok = True),
37         'date_created': Parameter(int, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True),
38         'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True),
39         'max_slices': Parameter(int, "Maximum number of slices that the site is able to create"),
40         'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create"),
41         'person_ids': Parameter([int], "List of account identifiers", joined=True),
42         'slice_ids': Parameter([int], "List of slice identifiers", joined=True),
43         'address_ids': Parameter([int], "List of address identifiers", joined=True),
44         'pcu_ids': Parameter([int], "List of PCU identifiers", joined=True),
45         'node_ids': Parameter([int], "List of site node identifiers", joined=True),
46         'site_tag_ids' : Parameter ([int], "List of tags attached to this site", joined=True),
47         'peer_id': Parameter(int, "Peer to which this site belongs", nullok = True),
48         'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
49         'ext_consortium_id': Parameter(int, "external consortium id", nullok = True) 
50         }
51
52     def sync(self, commit=True, validate=True):
53         """
54         Add or update the site.
55         """
56         # sync the nova record and the plc record
57         AlchemyObj.sync(self, commit=commit, validate=validate)     
58         nova_fields = ['enabled', 'name', 'description']
59         nova_can_update = lambda (field, value): field in nova_fields
60         nova_site = dict(filter(nova_can_update, self.items()))
61         if 'site_id' not in self:
62             self.object = self.api.client_shell.keystone.tenants.create(**nova_site)
63             self['tenant_id'] = self.object.id
64             AlchemyObj.insert(self, dict(self)) 
65         else:
66             self.object = self.api.client_shell.keystone.tenants.update(self['tenant_id'], **nova_site)
67             AlchemyObj.update(self, {'site_id': self['site_id']}, dict(self))
68
69     def delete(self, commit=True):
70         assert 'site_id' in self
71         assert 'tenant_id' in self
72         
73         # delete nova object
74         tenant = self.api.client_shell.keystone.tenants.find(id=self['tenant_id'])
75         self.api.client_shell.keystone.tenants.delete(tenant)
76         
77         # delete relationships
78         SitePerson().delete(filter={'site_id': self['site_id']}) 
79         Slice().delete(filter={'site_id': self['site_id']}) 
80         PCU().delete(filter={'site_id': self['site_id']}) 
81         Node().delete(filter={'site_id': self['site_id']}) 
82         Address().delete(filter={'site_id': self['site_id']}) 
83         SiteTag().delete(filter={'site_id': self['site_id']}) 
84         
85         # delete site
86         AlchemyObj.delete(self, dict(self))        
87         
88                
89
90 class Sites(list):
91     """
92     Representation of row(s) from the sites table in the
93     database.
94     """
95
96     def __init__(self, api, site_filter = None, columns = None):
97         self.api = api 
98         if not site_filter:
99             sites = Site().select() 
100         elif isinstance(site_filter, int):
101             sites = Site().select(filter={'site_id': site_filter})
102         elif isinstance(site_filter, StringTypes):
103             sites = Site().select(filter={'login_base': site_filter})
104         elif isinstance(site_filter, dict):
105             sites = Site().select(filter=site_filter)
106         elif isinstance(site_filter, (list, tuple, set)):
107             sites = Site().select() 
108             sites = [site for site in sites if site.id in site_filter]
109         else:
110             raise PLCInvalidArgument, "Wrong site filter %s" % site_filter         
111
112         for site in sites:
113             site = Site(self.api, object = site)
114             if not columns or 'person_ids' in columns:
115                 site_persons = SitePerson().select(filter={'site_id': site.id})
116                 site['person_ids'] = [rec.person_id for rec in site_persons]
117
118             if not columns or 'slice_ids' in columns:
119                 site_slices = Slice().select(filter={'site_id': site.id})
120                 site['slice_ids'] = [rec.person_id for rec in site_slices]
121
122             if not columns or 'puc_ids' in columns:
123                 site_pcus = PCU().select(filter={'site_id': site.id})
124                 site['pcu_ids'] = [rec.id for rec in site_pcus]
125
126             if not columns or 'node_ids' in columns:
127                 site_nodes = Node().select(filter={'site_id': site.id})
128                 site['node_ids'] = [rec.id for rec in site_nodes]
129
130             if not columns or 'address_ids' in columns:
131                 site_addresses = Address().select(filter={'site_id': site.id})
132                 site['address_ids'] = [rec.id for rec in site_addresses]
133
134             if not columns or 'site_tag_ids' in columns:
135                 site_tags = SiteTag().select(filter={'site_id': site.id})
136                 site['site_tag_ids'] = [rec.id for rec in site_tags]
137
138             self.append(site)