nova client to set tenant quotas

Change-Id: I9fdbfa065b813ba7b6ccb905ce171da12baf106b
diff --git a/nova/_modules/novang.py b/nova/_modules/novang.py
new file mode 100644
index 0000000..018e41e
--- /dev/null
+++ b/nova/_modules/novang.py
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+from pprint import pprint
+
+# Import python libs
+import logging
+
+# Import salt libs
+import salt.utils.openstack.nova as suon
+
+# Get logging started
+log = logging.getLogger(__name__)
+
+# Function alias to not shadow built-ins
+__func_alias__ = {
+    'list_': 'list'
+}
+
+# Define the module's virtual name
+__virtualname__ = 'novang'
+
+
+def __virtual__():
+    '''
+    Only load this module if nova
+    is installed on this minion.
+    '''
+    if suon.check_nova():
+        return __virtualname__
+    return (False, 'The nova execution module failed to load: '
+            'only available if nova is installed.')
+
+
+__opts__ = {}
+
+
+def _auth(profile=None):
+    '''
+    Set up nova credentials
+    '''
+    if profile:
+        credentials = __salt__['config.option'](profile)
+        user = credentials['keystone.user']
+        password = credentials['keystone.password']
+        tenant = credentials['keystone.tenant']
+        auth_url = credentials['keystone.auth_url']
+        region_name = credentials.get('keystone.region_name', None)
+        api_key = credentials.get('keystone.api_key', None)
+        os_auth_system = credentials.get('keystone.os_auth_system', None)
+    else:
+        user = __salt__['config.option']('keystone.user')
+        password = __salt__['config.option']('keystone.password')
+        tenant = __salt__['config.option']('keystone.tenant')
+        auth_url = __salt__['config.option']('keystone.auth_url')
+        region_name = __salt__['config.option']('keystone.region_name')
+        api_key = __salt__['config.option']('keystone.api_key')
+        os_auth_system = __salt__['config.option']('keystone.os_auth_system')
+    kwargs = {
+        'username': user,
+        'password': password,
+        'api_key': api_key,
+        'project_id': tenant,
+        'auth_url': auth_url,
+        'region_name': region_name,
+        'os_auth_plugin': os_auth_system
+    }
+
+    return suon.SaltNova(**kwargs)
+
+
+def get_connection_args(profile=None):
+    '''
+    Set up profile credentials
+    '''
+    if profile:
+        credentials = __salt__['config.option'](profile)
+        user = credentials['keystone.user']
+        password = credentials['keystone.password']
+        tenant = credentials['keystone.tenant']
+        auth_url = credentials['keystone.auth_url']
+
+    kwargs = {
+        'username': user,
+        'password': password,
+        'tenant': tenant,
+        'auth_url': auth_url
+    }
+    return kwargs
+
+
+def quota_list(tenant_name, profile=None):
+    '''
+    list quotas of a tenant
+    '''
+    connection_args = get_connection_args(profile)
+    tenant = __salt__['keystone.tenant_get'](name=tenant_name, profile=profile, **connection_args)
+    tenant_id = tenant[tenant_name]['id']
+    conn = _auth(profile)
+    nt_ks = conn.compute_conn
+    item = nt_ks.quotas.get(tenant_id).__dict__
+    return item
+
+
+def quota_get(name, tenant_name, profile=None, quota_value=None):
+    '''
+    get specific quota value of a tenant
+    '''
+    item = quota_list(tenant_name, profile)
+    quota_value = item[name]
+    return quota_value
+
+
+def quota_update(tenant_name, profile=None, **quota_argument):
+    '''
+    update quota of specified tenant
+    '''
+    connection_args = get_connection_args(profile)
+    tenant = __salt__['keystone.tenant_get'](name=tenant_name, profile=profile, **connection_args)
+    tenant_id = tenant[tenant_name]['id']
+    conn = _auth(profile)
+    nt_ks = conn.compute_conn
+    item = nt_ks.quotas.update(tenant_id, **quota_argument)
+    return item
+
+
+
+
diff --git a/nova/_states/novang.py b/nova/_states/novang.py
index 13a713a..124faf4 100644
--- a/nova/_states/novang.py
+++ b/nova/_states/novang.py
@@ -2,28 +2,27 @@
 '''
 Nova state that ensures that defined flavor is present
 '''
+import logging
+from functools import wraps
+LOG = logging.getLogger(__name__)
 
 
 def __virtual__():
     '''
     Only load if the nova module is in __salt__
     '''
-    return 'novang' if 'nova.flavor_list' in __salt__ else False
+    return 'novang' if 'nova.flavor_list' in __salt__ else False   
 
 
 def flavor_present(name, flavor_id=0, ram=0, disk=0, vcpus=1, profile=None):
     '''
-    Ensures that the nova flavor exists
-    
+    Ensures that the nova flavor exists  
     '''
-    print profile
-    print name
     ret = {'name': name,
            'changes': {},
            'result': True,
            'comment': 'Flavor "{0}" already exists'.format(name)}
     project = __salt__['nova.flavor_list'](profile)
-    print project
     if 'Error' in project:
         pass
     elif name in project:
@@ -35,3 +34,45 @@
     return ret
 
 
+def quota_present(tenant_name, profile, name=None, **kwargs):
+    '''
+    Ensures that the nova quota exists
+    '''
+    changes = {}
+    for key, value in kwargs.items():
+        quota = __salt__['novang.quota_get'](key, tenant_name, profile)
+        if quota != value:
+            arg = {}
+            arg[key] = value
+            changes[key] = value
+            __salt__['novang.quota_update'](tenant_name, profile, **arg)
+    if bool(changes):
+        return _updated(tenant_name, 'tenant', changes)        
+    else:
+        return _no_change(tenant_name, 'tenant')
+
+def _updated(name, resource, resource_definition):
+    changes_dict = {'name': name,
+                    'changes': resource_definition,
+                    'result': True,
+                    'comment': '{0} {1} tenant was updated'.format(resource, name)}
+    return changes_dict
+
+def _update_failed(name, resource):
+    changes_dict = {'name': name,
+                    'changes': {},
+                    'comment': '{0} {1} failed to update'.format(resource, name),
+                    'result': False}
+    return changes_dict
+
+def _no_change(name, resource, test=False):
+    changes_dict = {'name': name,
+                    'changes': {},
+                    'result': True}
+    if test:
+        changes_dict['comment'] = \
+            '{0} {1} will be {2}'.format(resource, name, test)
+    else:
+        changes_dict['comment'] = \
+            '{0} {1} is in correct state'.format(resource, name)
+    return changes_dict