Allow nova client state to create keypairs

- Added a state `keypair_present` that ensures that a keypair with
  a given name is present
- Extended nova/client.sls to call the `keypair_present` state if
  keypairs are defined in metadata

Related PROD: PROD-12876

Change-Id: I928b4e75759069cd0214013688ce82709ad0232e
diff --git a/_states/novang.py b/_states/novang.py
index d5bcb35..00c74d8 100644
--- a/_states/novang.py
+++ b/_states/novang.py
@@ -251,6 +251,23 @@
             'result': True,
             'comment': 'Instance "{0}" was successfuly created'.format(name)}
 
+
+def keypair_present(name, pub_file, profile=None):
+    """
+    Ensures that the Nova key-pair exists
+    """
+
+    existing_keypairs = __salt__['novang.keypair_list'](profile)
+    if name in existing_keypairs:
+        return _already_exists(name, 'Keypair')
+    else:
+        res = __salt__['novang.keypair_add'](name, pubfile=pub_file,
+                                             profile=profile)
+        if res and res['name'] == name:
+            return _created(name, 'Keypair', res)
+        return _create_failed(name, 'Keypair')
+
+
 def _already_exists(name, resource):
     changes_dict = {'name': name,
                     'changes': {},
@@ -293,3 +310,11 @@
             '{0} {1} is in correct state'.format(resource, name)
     return changes_dict
 
+
+def _create_failed(name, resource):
+    changes_dict = {'name': name,
+                    'changes': {},
+                    'comment': '{0} {1} failed to create'.format(resource,
+                                                                 name),
+                    'result': False}
+    return changes_dict
diff --git a/metadata/service/client/init.yml b/metadata/service/client/init.yml
new file mode 100644
index 0000000..46046d6
--- /dev/null
+++ b/metadata/service/client/init.yml
@@ -0,0 +1,6 @@
+applications:
+  - nova
+parameters:
+  nova:
+    client:
+      enabled: true
diff --git a/nova/client.sls b/nova/client.sls
index 57d62e5..ea4aaa0 100644
--- a/nova/client.sls
+++ b/nova/client.sls
@@ -33,6 +33,18 @@
 
 {%- endif %}
 
+{%- if identity.keypair is defined %}
+
+{%- for keypair_name, keypair in identity.keypair.iteritems() %}
+nova_keypair_{{ keypair_name }}:
+  novang.keypair_present:
+    - name: {{ keypair_name }}
+    - pub_file: {{ keypair.pub_file }}
+    - profile: {{ identity_name }}
+{%- endfor %}
+
+{%- endif %}
+
 {%- if identity.availability_zones is defined %}
 
 {%- for availability_zone_name in identity.availability_zones %}