Network RBAC rule management implemented.

Change-Id: Ia7f06b5e5c3fa7cef56173758d268c58e7f274f1
Related-Prod: SSMCP-149
diff --git a/README.rst b/README.rst
index 2ef3f49..ca02600 100644
--- a/README.rst
+++ b/README.rst
@@ -1291,7 +1291,7 @@
 Neutron Client
 --------------
 
-Neutron networks:
+Neutron networks and RBAC:
 
 .. code-block:: yaml
 
@@ -1300,6 +1300,18 @@
         enabled: true
         server:
           identity:
+            rbac:
+              network:
+                rule1:
+                  absent: True
+                  target_tenant:  admin
+                  action: access_as_shared
+                  network: public
+                rule2:
+                  absent: False
+                  target_tenant: service
+                  action: access_as_external
+                  network: public
             endpoint_type: internalURL
             network:
               inet1:
diff --git a/_modules/neutronv2/__init__.py b/_modules/neutronv2/__init__.py
index 74b6fb1..c6ebe0f 100644
--- a/_modules/neutronv2/__init__.py
+++ b/_modules/neutronv2/__init__.py
@@ -14,6 +14,7 @@
 from neutronv2 import routers
 from neutronv2 import ports
 from neutronv2 import common
+from neutronv2 import rbac
 
 
 network_get_details = networks.network_get_details
@@ -69,6 +70,10 @@
 port_get_details = ports.port_get_details
 
 
+rbac_policies_list = lists.rbac_policies_list
+rbac_policies_create = rbac.rbac_policies_create
+rbac_policies_delete = rbac.rbac_policies_delete
+
 wait_for_network_services = agents.wait_for_network_services
 
 wait_for_api_ready = common.wait_for_api_ready
@@ -88,6 +93,7 @@
     'router_list', 'router_create', 'router_delete', 'router_get_details',
     'router_interface_add', 'router_interface_remove', 'router_update',
     'port_create', 'port_delete', 'port_update', 'port_list', 'port_get_details',
+    'rbac_policies_create' 'rbac_policies_delete', 'rbac_policies_list',
 )
 
 
diff --git a/_modules/neutronv2/lists.py b/_modules/neutronv2/lists.py
index eea4a7a..13958ee 100644
--- a/_modules/neutronv2/lists.py
+++ b/_modules/neutronv2/lists.py
@@ -39,4 +39,10 @@
 @send('get')
 def port_list(**kwargs):
     url = '/ports?{}'.format(urlencode(kwargs))
-    return url, {}
\ No newline at end of file
+    return url, {}
+
+
+@send('get')
+def rbac_policies_list(**kwargs):
+    url = '/rbac-policies?{}'.format(urlencode(kwargs))
+    return url, {}
diff --git a/_modules/neutronv2/rbac.py b/_modules/neutronv2/rbac.py
new file mode 100644
index 0000000..021d535
--- /dev/null
+++ b/_modules/neutronv2/rbac.py
@@ -0,0 +1,27 @@
+from neutronv2.common import send
+from neutronv2.arg_converter import get_by_name_or_uuid_multiple
+
+try:
+    from urllib.parse import urlencode
+except ImportError:
+    from urllib import urlencode
+
+
+@send('delete')
+def rbac_policies_delete(id):
+    url = '/rbac-policies/{}'.format(id)
+    return url, {}
+
+
+@get_by_name_or_uuid_multiple([('network', 'object_id')])
+@send('post')
+def rbac_policies_create(object_id,**kwargs):
+
+    url = '/rbac-policies'
+    kwargs.update({'object_type': 'network'})
+    kwargs.update({'object_id': object_id})
+    json = {
+        'rbac_policy': kwargs,
+    }
+
+    return url, {'json': json}
diff --git a/_states/neutronv2.py b/_states/neutronv2.py
index 81c8fa4..7bfa7fb 100644
--- a/_states/neutronv2.py
+++ b/_states/neutronv2.py
@@ -271,6 +271,58 @@
                              cloud_name, **kwargs)
 
 
+def rbac_get_rule_id(cloud_name, **kwargs):
+    existing_rules = _neutronv2_call('rbac_policies_list',
+    cloud_name=cloud_name)
+
+    match_condition_fields = ['action',
+                              'target_tenant',
+                              'object_id',
+                             ]
+
+    for rule in existing_rules['rbac_policies']:
+      match = True
+      for field in match_condition_fields:
+        if rule[field] != kwargs[field]:
+          match = False
+          break
+      if match: return rule['id']
+
+
+def rbac_present(name, cloud_name, **kwargs):
+    resource = 'rbac_policies'
+    # Resolve network name to UID if needed
+    kwargs['object_id'] = __salt__['neutronv2.network_get_details'] \
+      (network_id=kwargs['object_id'],cloud_name=cloud_name)['network']['id']
+
+    if rbac_get_rule_id(cloud_name, **kwargs):
+      return _succeeded('no_changes', name, resource)
+
+    r = _neutronv2_call('{}_create'.format(resource),
+                            cloud_name=cloud_name,
+                            **kwargs)
+    if r:
+      return _succeeded('create', name, resource, changes=r)
+    else:
+      return _failed('create', name, kwargs)
+
+def rbac_absent(name, cloud_name, **kwargs):
+    resource = 'rbac_policies'
+    # Resolve network name to UID if needed
+    kwargs['object_id'] = __salt__['neutronv2.network_get_details'] \
+      (network_id=kwargs['object_id'],cloud_name=cloud_name)['network']['id']
+
+    rule_id = rbac_get_rule_id(cloud_name, **kwargs)
+
+    if rule_id:
+        r = _neutronv2_call('{}_delete'.format(resource),
+                                cloud_name=cloud_name,
+                                id=rule_id)
+        return _succeeded('delete', name, resource, changes=r)
+
+    return _succeeded('no_changes', name, resource)
+
+
 def _succeeded(op, name, resource, changes=None):
     msg_map = {
         'create': '{0} {1} created',
diff --git a/neutron/client/resources/v2.sls b/neutron/client/resources/v2.sls
index 3bd57b9..43db50e 100644
--- a/neutron/client/resources/v2.sls
+++ b/neutron/client/resources/v2.sls
@@ -118,5 +118,33 @@
   {%- endfor %}
   {%- endif %}
 
+  {%- if identity.rbac is defined %}
+  {%- for rule_name, rule in identity.rbac.network.iteritems() %}
+
+  {%- if rule.absent is defined and rule.absent %}
+neutron_openstack_rbac_network_{{ rule_name }}:
+  neutronv2.rbac_absent:
+    - name: {{ rule_name }}
+    - cloud_name: {{ identity_name }}
+    - target_tenant: {{ rule.target_tenant }}
+    - action: {{ rule.action }}
+    - object_id: {{ rule.network }}
+
+  {%- else %}
+neutron_openstack_rbac_network_{{ rule_name }}:
+  neutronv2.rbac_present:
+    - name: {{ rule_name }}
+    - cloud_name: {{ identity_name }}
+    - target_tenant: {{ rule.target_tenant }}
+    - action: {{ rule.action }}
+    - object_id: {{ rule.network }}
+
+
+  {%- endif %}
+
+  {%- endfor %}
+  {%- endif %}
+
+
 {%- endfor %}
 {%- endif %}