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.NovaTable import NovaObject, NovaTable
11 class Key(NovaObject):
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
19 join_tables = ['person_key', 'peer_key']
21 'id': Parameter(str, "Key identifier", primary_key=True),
22 #'key_type': Parameter(str, "Key type"),
23 'public_key': Parameter(str, "Key string", max = 4096),
24 'name': Parameter(str, "Key name",)
27 def sync(self, insert = False, validate = True):
28 NovaObject.sync(self, insert, validate)
29 if insert == True or 'id' not in self:
30 self.object = self.api.client_shell.nova.keypairs.create(self.id,
33 self.object = self.api.client_shell.nova.keypairs.update(self.id, dict(self))
37 self.api.client_shell.nova.keypairs.delete(self.id)
39 def validate_public_key(self, key):
40 # Key must not be blacklisted
44 def validate_name(self, name)
45 keys = Keys(self.api, name)
47 raise PLCInvalidArgument, "Key name alredy in use"
51 NovaObject.validate(self)
53 assert 'public_key' in self
54 key = self['public_key']
56 if self['key_type'] == 'ssh':
57 # Accept only SSH version 2 keys without options. From
60 # Each protocol version 2 public key consists of: options,
61 # keytype, base64 encoded key, comment. The options field
62 # is optional...The comment field is not used for anything
63 # (but may be convenient for the user to identify the
64 # key). For protocol version 2 the keytype is ``ssh-dss''
67 good_ssh_key = r'^.*(?:ssh-dss|ssh-rsa)[ ]+[A-Za-z0-9+/=]+(?: .*)?$'
68 if not re.match(good_ssh_key, key, re.IGNORECASE):
69 raise PLCInvalidArgument, "Invalid SSH version 2 public key"
71 def blacklist(self, commit = True):
73 Permanently blacklist key (and all other identical keys),
74 preventing it from ever being added again. Because this could
75 affect multiple keys associated with multiple accounts, it
79 assert 'key_id' in self
82 # Get all matching keys
83 rows = self.api.db.selectall("SELECT key_id FROM keys WHERE key = %(key)s",
85 key_ids = [row['key_id'] for row in rows]
87 assert self['key_id'] in key_ids
89 # Keep the keys in the table
90 self.api.db.do("UPDATE keys SET is_blacklisted = True" \
91 " WHERE key_id IN (%s)" % ", ".join(map(str, key_ids)))
93 # But disassociate them from all join tables
94 for table in self.join_tables:
95 self.api.db.do("DELETE FROM %s WHERE key_id IN (%s)" % \
96 (table, ", ".join(map(str, key_ids))))
101 class Keys(NovaTable):
103 Representation of row(s) from the keys table in the
107 def __init__(self, api, key_filter = None, columns = None):
109 keysManager = self.api.client_shell.nova.keypairs
112 if key_filter is not None:
113 if isinstance(key_filter, (list, tuple, set, int, long)):
114 keyPairs = filter(lambda kp: kp.uuid in key_filter,
115 keysManager.findall())
116 elif isinstance(key_filter, dict):
117 keyPairs = keysManager.findall(**key_filter)
118 elif isinstnace(key_filter, StringTypes):
119 keyPairs = keyManagers.findall(uuid = key_filter)
121 raise PLCInvalidArgument, "Wrong key filter %r"%key_filter
123 self.extend(keyPairs)