Fix KeyTypes, Keys
[plcapi.git] / PLC / Keys.py
index c174470..e633a43 100644 (file)
@@ -1,4 +1,7 @@
 import re
+import random
+import string
+from types import StringTypes
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
@@ -20,44 +23,71 @@ class Key(AlchemyObj):
         'key_id': Parameter(str, "Key identifier", primary_key=True),
         'key_type': Parameter(str, "Key type"),
         'key': Parameter(str, "Key string", max = 4096), # backwards compatibility
+        'person_id': Parameter(int, "User to which this key belongs", nullok = True),
+        'is_blacklisted': Parameter(bool, "Is the key blacklisted", default=False),
         'name': Parameter(str, "Key name"),
-        'uuid': Parameter(str, "Key name", ro=True)
+        'peer_id': Parameter(int, "Peer to which this key belongs", nullok = True),
+        'peer_key_id': Parameter(int, "Foreign key identifier at peer", nullok = True),
         }
 
     def sync(self, commit = True, validate = True):
+        from PLC.Persons import Person
         # sync the nova record and the plc record
         assert 'key' in self
-        assert 'name' in self
         AlchemyObj.sync(self, commit=commit, validate=validate)
-        nova_key = {
-            'public_key': self['key'],
-            'name': self['name'] 
-        }
-        self.object = self.api.client_shell.nova.keypairs.create(**nova_key)
-        self['uuid'] = self.object.uuid
-        AlchemyObj.insert(self, dict(self))
-
+        persons = Person().select(filter={'person_id': self['person_id']})
+        if not persons:
+            raise PLCInvalidArgument, "Invalid person id" 
+        person = persons[0]
+        if 'key_id' not in self:
+            rand = ''.join(random.choice(string.ascii_letters) for x in range(5))
+            self['name'] = person.email.split('@')[0] + rand
+            nova_key = {
+                'public_key': self['key'],
+                'name': self['name']
+            }
+            self.object = self.api.client_shell.nova.keypairs.create(**nova_key)
+            AlchemyObj.insert(self, dict(self))
+            key = Key().select(filter={'name': self['name']})[0]
+            self['key_id'] = key.key_id 
+        else:
+            # nova has no way to update existing keys. Just remove the old
+            # key and add a new one 
+            nova_key = {
+                'public_key': self['key'],
+                'name': self['name']
+            }    
+            self.api.client_shell.nova.keypairs.delete(self['name'])
+            self.object = self.api.client_shell.nova.keypairs.create(**nova_key)      
+            AlchemyObj.update(self, {'key_id': self['key_id']}, dict(self))
+            
     def delete(self):
         assert 'key_id' in self
         assert 'name' in self
-        self.api.client_shell.nova.keypairs.delete(self.id)
+        self.api.client_shell.nova.keypairs.delete(self['name'])
+        AlchemyObj.delete(self, filter={'key_id': self['key_id']}) 
+        
 
-    def validate_public_key(self, key):
-        # Key must not be blacklisted
-        pass
-        return key
+    def validate_key_type(self, key_type):
+        exists = KeyTypes(self.api, key_type)
+        if not exists:
+            raise PLCInvalidArgument, "Invalid key type"
+        return key_type
 
-    def validate_name(self, name):
-        keys = Keys(self.api, name)
+    def validate_key(self, key):
+        # Key must not be blacklisted
+        keys = Keys(self.api, {'key': key, 'is_blacklisted': True})
         if keys:
-            raise PLCInvalidArgument, "Key name alredy in use"
+            raise PLCInvalidArgument, "Key is blacklisted and cannot be used"
+
+        return key
 
     def validate(self):
         # Basic validation
-        NovaObject.validate(self)
+        AlchemyObj.validate(self)
 
-        assert 'public_key' in self
-        key = self['public_key']
+        assert 'key' in self
+        key = self['key']
 
         if self['key_type'] == 'ssh':
             # Accept only SSH version 2 keys without options. From
@@ -85,7 +115,8 @@ class Key(AlchemyObj):
         assert 'key_id' in self
         assert 'key' in self
 
-        pass
+        AlchemyObj.updatedb(self, filter={'key': self['key']}, values={'is_blacklisted': True}) 
+
 
 class Keys(list):
     """
@@ -95,19 +126,24 @@ class Keys(list):
 
     def __init__(self, api, key_filter = None, columns = None):
         self.api = api
-        keysManager = self.api.client_shell.nova.keypairs
-        keyPairs = []
-
-        if key_filter is not None:
-            if isinstance(key_filter, (list, tuple, set, int, long)):
-                keyPairs = filter(lambda kp: kp.uuid in key_filter,
-                                  keysManager.findall())
-            elif isinstance(key_filter, dict):
-                keyPairs = keysManager.findall(**key_filter)
-            elif isinstnace(key_filter, StringTypes):
-                keyPairs = keyManagers.findall(uuid = key_filter)
-            else:
-                raise PLCInvalidArgument, "Wrong key filter %r"%key_filter
-
-        self.extend(keyPairs)
+
+        if not key_filter:
+            keys = Key().select()
+        elif isinstance(key_filter, dict):
+            keys = Key().select(filter=key_filter) 
+        elif isinstance(key_filter, StringTypes):
+            keys = Key().select(filter={'name': key_filter})
+        elif isinstance(key_filter, int):
+            keys = Key().select(filter={'key_id': key_filter})
+        elif isinstance(key_filter, (list, tuple, set)):
+            ints = filter(lambda x: isinstance(x, (int, long)), key_filter)
+            strs = filter(lambda x: isinstance(x, StringTypes), key_filter)
+            key_filter = {'key_id': ints, 'name': strs}
+            keys = Key().select(filter=key_filter)  
+        else:
+            raise PLCInvalidArgument, "Wrong key filter %s" % key_filter  
+            
+        for key in keys:
+            key = Key(api, object=key, columns=columns)
+            self.append(key)