Repository: apache/libcloud

Issue:
[LIBCLOUD-848] Fix NameError - 'body' is not defined
## Fix the NameError caused by missing 'body' variable
### Description

Small change to add, but would be a big help. When a response from Openstack fails, the missing 'body' variable caused an uncaught exception. I remedied this by adding the body variable, similar to what was done above the else statement.
### Status
- done, ready for review
### Checklist (tick everything that applies)
- [x] [Code linting](http://libcloud.readthedocs.org/en/latest/development.html#code-style-guide) (required, can be done after the PR checks)
- [x] [Link to Jira](https://issues.apache.org/jira/browse/LIBCLOUD-848)



Discussion:

Resolving patch:
diff --git a/libcloud/common/openstack_identity.py b/libcloud/common/openstack_identity.py
--- a/libcloud/common/openstack_identity.py
+++ b/libcloud/common/openstack_identity.py
@@ -780,8 +780,8 @@ def authenticate(self, force=False):
             self.auth_user_info = None
 
             if not self.auth_token:
-                raise MalformedResponseError('Missing X-Auth-Token in \
-                                              response headers')
+                raise MalformedResponseError('Missing X-Auth-Token in'
+                                             ' response headers')
 
         return self
 
@@ -1058,6 +1058,7 @@ def authenticate(self, force=False):
                                              missing required elements', e)
             body = 'code: %s body:%s' % (response.status, response.body)
         else:
+            body = 'code: %s body:%s' % (response.status, response.body)
             raise MalformedResponseError('Malformed response', body=body,
                                          driver=self.driver)
 
diff --git a/libcloud/loadbalancer/drivers/dimensiondata.py b/libcloud/loadbalancer/drivers/dimensiondata.py
--- a/libcloud/loadbalancer/drivers/dimensiondata.py
+++ b/libcloud/loadbalancer/drivers/dimensiondata.py
@@ -173,19 +173,27 @@ def create_balancer(self, name, port=None, protocol=None,
                    'listener_ip_address': ex_listener_ip_address}
         )
 
-    def list_balancers(self):
+    def list_balancers(self, ex_network_domain_id=None):
         """
-        List all loadbalancers inside a geography.
+        List all loadbalancers inside a geography or in given network.
 
         In Dimension Data terminology these are known as virtual listeners
 
+        :param ex_network_domain_id: UUID of Network Domain
+               if not None returns only balancers in the given network
+               if None then returns all pools for the organization
+        :type  ex_network_domain_id: ``str``
+
         :rtype: ``list`` of :class:`LoadBalancer`
         """
+        params = None
+        if ex_network_domain_id is not None:
+            params = {"networkDomainId": ex_network_domain_id}
 
         return self._to_balancers(
             self.connection
-            .request_with_orgId_api_2('networkDomainVip/virtualListener')
-            .object)
+            .request_with_orgId_api_2('networkDomainVip/virtualListener',
+                                      params=params).object)
 
     def get_balancer(self, balancer_id):
         """
@@ -685,15 +693,26 @@ def ex_create_virtual_listener(self,
             status=State.RUNNING
         )
 
-    def ex_get_pools(self):
+    def ex_get_pools(self, ex_network_domain_id=None):
         """
-        Get all of the pools inside the current geography
+        Get all of the pools inside the current geography or
+        in given network.
+
+        :param ex_network_domain_id: UUID of Network Domain
+               if not None returns only balancers in the given network
+               if None then returns all pools for the organization
+        :type  ex_network_domain_id: ``str``
 
         :return: Returns a ``list`` of type ``DimensionDataPool``
         :rtype: ``list`` of ``DimensionDataPool``
         """
+        params = None
+        if ex_network_domain_id is not None:
+            params = {"networkDomainId": ex_network_domain_id}
+
         pools = self.connection \
-            .request_with_orgId_api_2('networkDomainVip/pool').object
+            .request_with_orgId_api_2('networkDomainVip/pool',
+                                      params=params).object
         return self._to_pools(pools)
 
     def ex_get_pool(self, pool_id):
@@ -833,15 +852,25 @@ def ex_destroy_pool_member(self, member, destroy_node=False):
             response_code = findtext(result, 'responseCode', TYPES_URN)
             return response_code in ['IN_PROGRESS', 'OK']
 
-    def ex_get_nodes(self):
+    def ex_get_nodes(self, ex_network_domain_id=None):
         """
-        Get the nodes within this geography
+        Get the nodes within this geography or in given network.
+
+        :param ex_network_domain_id: UUID of Network Domain
+               if not None returns only balancers in the given network
+               if None then returns all pools for the organization
+        :type  ex_network_domain_id: ``str``
 
         :return: Returns an ``list`` of ``DimensionDataVIPNode``
         :rtype: ``list`` of ``DimensionDataVIPNode``
         """
+        params = None
+        if ex_network_domain_id is not None:
+            params = {"networkDomainId": ex_network_domain_id}
+
         nodes = self.connection \
-            .request_with_orgId_api_2('networkDomainVip/node').object
+            .request_with_orgId_api_2('networkDomainVip/node',
+                                      params=params).object
         return self._to_nodes(nodes)
 
     def ex_get_node(self, node_id):


Test patch: