Add node_id to added_fields
[plcapi.git] / PLC / Keys.py
1 import re
2
3 from PLC.Faults import *
4 from PLC.Parameter import Parameter
5 from PLC.Filter import Filter
6 from PLC.Debug import profile
7 from PLC.Table import Row, Table
8 from PLC.KeyTypes import KeyType, KeyTypes
9 from PLC.Storage.AlchemyObject import AlchemyObj
10
11 class Key(AlchemyObj):
12     """
13     Representation of a row in the keys table. To use, instantiate with a
14     dict of values. Update as you would a dict. Commit to the database
15     with sync().
16     """
17
18     tablename = 'keys'
19     fields = {
20         'key_id': Parameter(str, "Key identifier", primary_key=True),
21         'key_type': Parameter(str, "Key type"),
22         'key': Parameter(str, "Key string", max = 4096), # backwards compatibility
23         'name': Parameter(str, "Key name"),
24         'uuid': Parameter(str, "Key name", ro=True)
25         }
26
27     def sync(self, commit = True, validate = True):
28         # sync the nova record and the plc record
29         assert 'key' in self
30         assert 'name' in self
31         AlchemyObj.sync(self, commit=commit, validate=validate)
32         nova_key = {
33             'public_key': self['key'],
34             'name': self['name'] 
35         }
36         self.object = self.api.client_shell.nova.keypairs.create(**nova_key)
37         self['uuid'] = self.object.uuid
38         AlchemyObj.insert(self, dict(self))
39
40     def delete(self):
41         assert 'key_id' in self
42         assert 'name' in self
43         self.api.client_shell.nova.keypairs.delete(self.id)
44
45     def validate_public_key(self, key):
46         # Key must not be blacklisted
47         pass
48         return key
49
50     def validate_name(self, name):
51         keys = Keys(self.api, name)
52         if keys:
53             raise PLCInvalidArgument, "Key name alredy in use"
54
55     def validate(self):
56         # Basic validation
57         NovaObject.validate(self)
58
59         assert 'public_key' in self
60         key = self['public_key']
61
62         if self['key_type'] == 'ssh':
63             # Accept only SSH version 2 keys without options. From
64             # sshd(8):
65             #
66             # Each protocol version 2 public key consists of: options,
67             # keytype, base64 encoded key, comment.  The options field
68             # is optional...The comment field is not used for anything
69             # (but may be convenient for the user to identify the
70             # key). For protocol version 2 the keytype is ``ssh-dss''
71             # or ``ssh-rsa''.
72
73             good_ssh_key = r'^.*(?:ssh-dss|ssh-rsa)[ ]+[A-Za-z0-9+/=]+(?: .*)?$'
74             if not re.match(good_ssh_key, key, re.IGNORECASE):
75                 raise PLCInvalidArgument, "Invalid SSH version 2 public key"
76
77     def blacklist(self, commit = True):
78         """
79         Permanently blacklist key (and all other identical keys),
80         preventing it from ever being added again. Because this could
81         affect multiple keys associated with multiple accounts, it
82         should be admin only.
83         """
84
85         assert 'key_id' in self
86         assert 'key' in self
87
88         pass
89
90 class Keys(list):
91     """
92     Representation of row(s) from the keys table in the
93     database.
94     """
95
96     def __init__(self, api, key_filter = None, columns = None):
97         self.api = api
98         keysManager = self.api.client_shell.nova.keypairs
99         keyPairs = []
100
101         if key_filter is not None:
102             if isinstance(key_filter, (list, tuple, set, int, long)):
103                 keyPairs = filter(lambda kp: kp.uuid in key_filter,
104                                   keysManager.findall())
105             elif isinstance(key_filter, dict):
106                 keyPairs = keysManager.findall(**key_filter)
107             elif isinstnace(key_filter, StringTypes):
108                 keyPairs = keyManagers.findall(uuid = key_filter)
109             else:
110                 raise PLCInvalidArgument, "Wrong key filter %r"%key_filter
111
112         self.extend(keyPairs)
113