Add ex_get_size_extra_specs function: #1516
diff --git a/libcloud/compute/drivers/openstack.py b/libcloud/compute/drivers/openstack.py
index 5b88fac..ee01350 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -2254,6 +2254,18 @@
         return self._to_size(self.connection.request(
             '/flavors/%s' % (size_id,)) .object['flavor'])
 
+    def ex_get_size_extra_specs(self, size_id):
+        """
+        Get the extra_specs field of a NodeSize
+
+        :param      size_id: ID of the size which should be used
+        :type       size_id: ``str``
+
+        :rtype: `dict`
+        """
+        return self.connection.request(
+            '/flavors/%s/os-extra_specs' % (size_id,)) .object['extra_specs']
+
     def get_image(self, image_id):
         """
         Get a NodeImage
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_flavor_extra_specs.json b/libcloud/test/compute/fixtures/openstack_v1.1/_flavor_extra_specs.json
new file mode 100644
index 0000000..b9084c3
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_flavor_extra_specs.json
@@ -0,0 +1,6 @@
+{
+    "extra_specs": {
+        "hw:cpu_policy": "shared",
+        "hw:numa_nodes": "1"
+    }
+}
\ No newline at end of file
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index a8bbb9a..6169e7f 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -1184,6 +1184,12 @@
         self.assertEqual(size.id, size_id)
         self.assertEqual(size.name, '15.5GB slice')
 
+    def test_ex_get_size_extra_specs(self):
+        size_id = '7'
+        extra_specs = self.driver.ex_get_size_extra_specs(size_id)
+        self.assertEqual(extra_specs, {"hw:cpu_policy": "shared",
+                                       "hw:numa_nodes": "1"})
+
     def test_get_image(self):
         image_id = '13'
         image = self.driver.get_image(image_id)
@@ -2807,6 +2813,13 @@
             body = self.fixtures.load('_v2_0__quota_set.json')
             return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
 
+    def _v2_1337_flavors_7_os_extra_specs(self, method, url, body, headers):
+        if method == "GET":
+            body = self.fixtures.load('_flavor_extra_specs.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        else:
+            raise NotImplementedError()
+
     def _v2_1337_servers_1000_action(self, method, url, body, headers):
         if method != 'POST' or body != '{"removeSecurityGroup": {"name": "sgname"}}':
             raise NotImplementedError(body)