You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2014/01/29 17:00:55 UTC

[1/7] Add a new driver, tests and documentation for CloudSigma API v2.0.

Updated Branches:
  refs/heads/trunk 903e769d3 -> 23c3b44f1


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json
new file mode 100644
index 0000000..24eb4b2
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json
@@ -0,0 +1,104 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 2
+    },
+    "objects": [
+        {
+            "context": true,
+            "cpu": 1000,
+            "cpu_model": null,
+            "cpus_instead_of_cores": false,
+            "drives": [],
+            "enable_numa": false,
+            "hv_relaxed": false,
+            "hv_tsc": false,
+            "mem": 1073741824,
+            "meta": {
+                "description": "test description 2",
+                "ssh_public_key": ""
+            },
+            "name": "test no drives",
+            "nics": [
+                {
+                    "boot_order": null,
+                    "firewall_policy": null,
+                    "ip_v4_conf": {
+                        "conf": "dhcp",
+                        "ip": null
+                    },
+                    "ip_v6_conf": null,
+                    "mac": "22:98:ce:04:50:df",
+                    "model": "virtio",
+                    "runtime": null,
+                    "vlan": null
+                }
+            ],
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "requirements": [],
+            "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/",
+            "runtime": null,
+            "smp": 1,
+            "status": "stopped",
+            "tags": [],
+            "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911",
+            "vnc_password": "bar"
+        },
+        {
+            "context": true,
+            "cpu": 2000,
+            "cpu_model": null,
+            "cpus_instead_of_cores": false,
+            "drives": [
+                {
+                    "boot_order": 1,
+                    "dev_channel": "0:0",
+                    "device": "ide",
+                    "drive": {
+                        "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/",
+                        "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9"
+                    }
+                }
+            ],
+            "enable_numa": false,
+            "hv_relaxed": false,
+            "hv_tsc": false,
+            "mem": 2147483648,
+            "meta": {
+                "description": "test1"
+            },
+            "name": "test-1",
+            "nics": [
+                {
+                    "boot_order": null,
+                    "firewall_policy": null,
+                    "ip_v4_conf": {
+                        "conf": "dhcp",
+                        "ip": null
+                    },
+                    "ip_v6_conf": null,
+                    "mac": "22:22:4e:1e:e0:7e",
+                    "model": "virtio",
+                    "runtime": null,
+                    "vlan": null
+                }
+            ],
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "requirements": [],
+            "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/",
+            "runtime": null,
+            "smp": 1,
+            "status": "stopped",
+            "tags": [],
+            "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8",
+            "vnc_password": "foo"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json
new file mode 100644
index 0000000..b89ec2b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json
@@ -0,0 +1,162 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 2
+    },
+    "objects": [
+        {
+            "context": true,
+            "cpu": 1000,
+            "cpu_model": null,
+            "cpus_instead_of_cores": false,
+            "drives": [],
+            "enable_numa": false,
+            "hv_relaxed": false,
+            "hv_tsc": false,
+            "mem": 1073741824,
+            "meta": {
+                "description": "test description 2",
+                "ssh_public_key": ""
+            },
+            "name": "test no drives",
+            "nics": [
+                {
+                    "boot_order": null,
+                    "firewall_policy": null,
+                    "ip_v4_conf": {
+                        "conf": "dhcp",
+                        "ip": null
+                    },
+                    "ip_v6_conf": null,
+                    "mac": "22:98:ce:04:50:df",
+                    "model": "virtio",
+                    "runtime": {
+                        "interface_type": "public",
+                        "io": {
+                            "bytes_recv": "1323",
+                            "bytes_sent": "21535",
+                            "packets_recv": "3",
+                            "packets_sent": "278"
+                        },
+                        "ip_v4": {
+                            "resource_uri": "/api/2.0/ips/185.12.5.181/",
+                            "uuid": "185.12.5.181"
+                        },
+                        "ip_v6": null
+                    },
+                    "vlan": null
+                },
+                {
+                    "boot_order": null,
+                    "firewall_policy": null,
+                    "ip_v4_conf": {
+                        "conf": "dhcp",
+                        "ip": null
+                    },
+                    "ip_v6_conf": null,
+                    "mac": "22:2c:03:99:32:be",
+                    "model": "virtio",
+                    "runtime": {
+                        "interface_type": "public",
+                        "io": {
+                            "bytes_recv": "0",
+                            "bytes_sent": "0",
+                            "packets_recv": "0",
+                            "packets_sent": "0"
+                        },
+                        "ip_v4": {
+                            "resource_uri": "/api/2.0/ips/178.22.68.55/",
+                            "uuid": "178.22.68.55"
+                        },
+                        "ip_v6": null
+                    },
+                    "vlan": null
+                }
+            ],
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "requirements": [],
+            "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/",
+            "runtime": {
+                "active_since": "2013-11-05T10:15:42+00:00",
+                "nics": [
+                    {
+                        "interface_type": "public",
+                        "io": {
+                            "bytes_recv": "1323",
+                            "bytes_sent": "21535",
+                            "packets_recv": "3",
+                            "packets_sent": "278"
+                        },
+                        "ip_v4": {
+                            "resource_uri": "/api/2.0/ips/185.12.5.181/",
+                            "uuid": "185.12.5.181"
+                        },
+                        "ip_v6": null,
+                        "mac": "22:98:ce:04:50:df"
+                    }
+                ]
+            },
+            "smp": 1,
+            "status": "running",
+            "tags": [],
+            "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911",
+            "vnc_password": "foo"
+        },
+        {
+            "context": true,
+            "cpu": 2000,
+            "cpu_model": null,
+            "cpus_instead_of_cores": false,
+            "drives": [
+                {
+                    "boot_order": 1,
+                    "dev_channel": "0:0",
+                    "device": "ide",
+                    "drive": {
+                        "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/",
+                        "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9"
+                    }
+                }
+            ],
+            "enable_numa": false,
+            "hv_relaxed": false,
+            "hv_tsc": false,
+            "mem": 2147483648,
+            "meta": {
+                "description": "test1"
+            },
+            "name": "test-1",
+            "nics": [
+                {
+                    "boot_order": null,
+                    "firewall_policy": null,
+                    "ip_v4_conf": {
+                        "conf": "dhcp",
+                        "ip": null
+                    },
+                    "ip_v6_conf": null,
+                    "mac": "22:22:4e:1e:e0:7e",
+                    "model": "virtio",
+                    "runtime": null,
+                    "vlan": null
+                }
+            ],
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "requirements": [],
+            "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/",
+            "runtime": null,
+            "smp": 1,
+            "status": "stopped",
+            "tags": [],
+            "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8",
+            "vnc_password": "bar"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json
new file mode 100644
index 0000000..a04b183
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json
@@ -0,0 +1,6 @@
+{
+    "action": "open_vnc",
+    "result": "success",
+    "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40",
+    "vnc_url": "vnc://direct.lvs.cloudsigma.com:41111"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json
new file mode 100644
index 0000000..e612d8e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json
@@ -0,0 +1 @@
+[{"error_point": null, "error_type": "permission", "error_message": "Cannot start guest in state \"started\". Guest should be in state \"stopped\""}]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json
new file mode 100644
index 0000000..1e60e5d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json
@@ -0,0 +1 @@
+{"action": "start", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json
new file mode 100644
index 0000000..52abcfc
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json
@@ -0,0 +1 @@
+[{"error_point": null, "error_type": "permission", "error_message": "Cannot stop guest in state \"stopped\". Guest should be in state \"['started', 'running_legacy']\""}]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json
new file mode 100644
index 0000000..e35b107
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json
@@ -0,0 +1 @@
+{"action": "stop", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json
new file mode 100644
index 0000000..f57b6ef
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json
@@ -0,0 +1,105 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 5
+    },
+    "objects": [
+        {
+            "amount": "1",
+            "auto_renew": true,
+            "descendants": [],
+            "discount_amount": null,
+            "discount_percent": null,
+            "end_time": "2014-02-20T11:12:34.930946+00:00",
+            "id": "7272",
+            "last_notification": null,
+            "period": "345 days, 0:00:00",
+            "price": "0E-20",
+            "remaining": "1",
+            "resource": "vlan",
+            "resource_uri": "/api/2.0/subscriptions/7272/",
+            "start_time": "2013-03-12T11:12:34.930946+00:00",
+            "status": "active",
+            "subscribed_object": "96537817-f4b6-496b-a861-e74192d3ccb0",
+            "uuid": "509f8e27-1e64-49bb-aa5a-baec074b0210"
+        },
+        {
+            "amount": "1",
+            "auto_renew": true,
+            "descendants": [],
+            "discount_amount": null,
+            "discount_percent": null,
+            "end_time": "2014-02-20T11:12:41.837474+00:00",
+            "id": "7273",
+            "last_notification": null,
+            "period": "345 days, 0:00:00",
+            "price": "0E-20",
+            "remaining": "1",
+            "resource": "ip",
+            "resource_uri": "/api/2.0/subscriptions/7273/",
+            "start_time": "2013-03-12T11:12:41.837474+00:00",
+            "status": "active",
+            "subscribed_object": "185.12.6.183",
+            "uuid": "c2423c1a-8768-462c-bdc3-4ca09c1e650b"
+        },
+        {
+            "amount": "17179869184",
+            "auto_renew": true,
+            "descendants": [],
+            "discount_amount": null,
+            "discount_percent": null,
+            "end_time": "2014-02-20T14:04:14.142181+00:00",
+            "id": "3985",
+            "last_notification": null,
+            "period": "365 days, 0:00:00",
+            "price": "0E-20",
+            "remaining": "17179869184",
+            "resource": "mem",
+            "resource_uri": "/api/2.0/subscriptions/3985/",
+            "start_time": "2013-02-20T14:04:14.142181+00:00",
+            "status": "active",
+            "subscribed_object": null,
+            "uuid": "9bb117d3-4bc5-4e2d-a907-b20abd48eaf9"
+        },
+        {
+            "amount": "8000",
+            "auto_renew": true,
+            "descendants": [],
+            "discount_amount": null,
+            "discount_percent": null,
+            "end_time": "2014-02-20T14:04:29.040258+00:00",
+            "id": "3986",
+            "last_notification": null,
+            "period": "365 days, 0:00:00",
+            "price": "0E-20",
+            "remaining": "8000",
+            "resource": "cpu",
+            "resource_uri": "/api/2.0/subscriptions/3986/",
+            "start_time": "2013-02-20T14:04:29.040258+00:00",
+            "status": "active",
+            "subscribed_object": null,
+            "uuid": "a265c47f-1a00-4095-acfc-2193622bfbd8"
+        },
+        {
+            "amount": "32212254720",
+            "auto_renew": true,
+            "descendants": [],
+            "discount_amount": null,
+            "discount_percent": null,
+            "end_time": "2014-02-20T14:04:44.088984+00:00",
+            "id": "3987",
+            "last_notification": null,
+            "period": "365 days, 0:00:00",
+            "price": "0E-20",
+            "remaining": "32212254720",
+            "resource": "dssd",
+            "resource_uri": "/api/2.0/subscriptions/3987/",
+            "start_time": "2013-02-20T14:04:44.088984+00:00",
+            "status": "active",
+            "subscribed_object": null,
+            "uuid": "8965ff95-4924-40a9-b923-a58615149732"
+        }
+    ],
+    "price": "0E-20"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json
new file mode 100644
index 0000000..8b4d843
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json
@@ -0,0 +1,15 @@
+{
+    "objects": [
+        {
+            "meta": {},
+            "name": "test tag 3",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/",
+            "resources": [],
+            "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json
new file mode 100644
index 0000000..d2e1f2f
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json
@@ -0,0 +1,25 @@
+{
+    "objects": [
+        {
+            "meta": {},
+            "name": "test tag 3",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/",
+            "resources": [
+              {
+                    "owner": {
+                        "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                        "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+                    },
+                    "res_type": "vlans",
+                    "resource_uri": "/api/2.0/vlans/96537817-f4b6-496b-a861-e74192d3ccb0/",
+                    "uuid": "1"
+              }
+            ],
+            "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json
new file mode 100644
index 0000000..c54dd22
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json
@@ -0,0 +1,31 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 2
+    },
+    "objects": [
+        {
+            "meta": {},
+            "name": "test tag 2",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/",
+            "resources": [],
+            "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d"
+        },
+        {
+            "meta": {},
+            "name": "test tag 1",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/",
+            "resources": [],
+            "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json
new file mode 100644
index 0000000..cc794c2
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json
@@ -0,0 +1,11 @@
+{
+    "meta": {},
+    "name": "test tag 2",
+    "owner": {
+        "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+        "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+    },
+    "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/",
+    "resources": [],
+    "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json
new file mode 100644
index 0000000..28e7be6
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json
@@ -0,0 +1,30 @@
+{
+    "meta": {},
+    "name": "test tag 3",
+    "owner": {
+        "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+        "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+    },
+    "resource_uri": "/api/2.0/tags/900ac9c6-2f98-48a4-b406-5494b4ea4663/",
+    "resources": [
+        {
+            "owner": {
+                "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+            },
+            "res_type": "servers",
+            "resource_uri": "/api/2.0/servers/79f7853b-04bd-44f5-a2c2-fa56f6861994/",
+            "uuid": "79f7853b-04bd-44f5-a2c2-fa56f6861994"
+        },
+        {
+            "owner": {
+                "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+            },
+            "res_type": "drives",
+            "resource_uri": "/api/2.0/drives/8c48e0bd-e17b-49ca-8926-654107d2b7e7/",
+            "uuid": "8c48e0bd-e17b-49ca-8926-654107d2b7e7"
+        }
+    ],
+    "uuid": "900ac9c6-2f98-48a4-b406-5494b4ea4663"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json
new file mode 100644
index 0000000..8543d1c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json
@@ -0,0 +1 @@
+[{"error_point": null, "error_type": "backend", "error_message": "unknown error"}]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/test_cloudsigma.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma.py b/libcloud/test/compute/test_cloudsigma.py
deleted file mode 100644
index ecbe63a..0000000
--- a/libcloud/test/compute/test_cloudsigma.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import unittest
-from libcloud.utils.py3 import httplib
-
-from libcloud.compute.base import Node
-from libcloud.compute.drivers.cloudsigma import CloudSigmaZrhNodeDriver
-from libcloud.utils.misc import str2dicts, str2list, dict2str
-
-from libcloud.test import MockHttp               # pylint: disable-msg=E0611
-from libcloud.test.compute import TestCaseMixin  # pylint: disable-msg=E0611
-from libcloud.test.file_fixtures import ComputeFileFixtures  # pylint: disable-msg=E0611
-
-
-class CloudSigmaTestCase(unittest.TestCase, TestCaseMixin):
-
-    def setUp(self):
-        CloudSigmaZrhNodeDriver.connectionCls.conn_classes = (None,
-                                                              CloudSigmaHttp)
-        self.driver = CloudSigmaZrhNodeDriver('foo', 'bar')
-
-    def test_list_nodes(self):
-        nodes = self.driver.list_nodes()
-        self.assertTrue(isinstance(nodes, list))
-        self.assertEqual(len(nodes), 1)
-
-        node = nodes[0]
-        self.assertEqual(node.public_ips[0], "1.2.3.4")
-        self.assertEqual(node.extra['smp'], 1)
-        self.assertEqual(node.extra['cpu'], 1100)
-        self.assertEqual(node.extra['mem'], 640)
-
-    def test_list_sizes(self):
-        images = self.driver.list_sizes()
-        self.assertEqual(len(images), 9)
-
-    def test_list_images(self):
-        sizes = self.driver.list_images()
-        self.assertEqual(len(sizes), 10)
-
-    def test_list_locations_response(self):
-        pass
-
-    def test_start_node(self):
-        nodes = self.driver.list_nodes()
-        node = nodes[0]
-        self.assertTrue(self.driver.ex_start_node(node))
-
-    def test_shutdown_node(self):
-        nodes = self.driver.list_nodes()
-        node = nodes[0]
-        self.assertTrue(self.driver.ex_stop_node(node))
-        self.assertTrue(self.driver.ex_shutdown_node(node))
-
-    def test_reboot_node(self):
-        node = self.driver.list_nodes()[0]
-        self.assertTrue(self.driver.reboot_node(node))
-
-    def test_destroy_node(self):
-        node = self.driver.list_nodes()[0]
-        self.assertTrue(self.driver.destroy_node(node))
-        self.driver.list_nodes()
-
-    def test_create_node(self):
-        size = self.driver.list_sizes()[0]
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(
-            name="cloudsigma node", image=image, size=size)
-        self.assertTrue(isinstance(node, Node))
-
-    def test_ex_static_ip_list(self):
-        ips = self.driver.ex_static_ip_list()
-        self.assertEqual(len(ips), 3)
-
-    def test_ex_static_ip_create(self):
-        result = self.driver.ex_static_ip_create()
-        self.assertEqual(len(result), 2)
-        self.assertEqual(len(list(result[0].keys())), 6)
-        self.assertEqual(len(list(result[1].keys())), 6)
-
-    def test_ex_static_ip_destroy(self):
-        result = self.driver.ex_static_ip_destroy('1.2.3.4')
-        self.assertTrue(result)
-
-    def test_ex_drives_list(self):
-        result = self.driver.ex_drives_list()
-        self.assertEqual(len(result), 2)
-
-    def test_ex_drive_destroy(self):
-        result = self.driver.ex_drive_destroy(
-            # @@TR: this should be soft-coded:
-            'd18119ce_7afa_474a_9242_e0384b160220')
-        self.assertTrue(result)
-
-    def test_ex_set_node_configuration(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_set_node_configuration(node, **{'smp': 2})
-        self.assertTrue(result)
-
-    def test_str2dicts(self):
-        string = 'mem 1024\ncpu 2200\n\nmem2048\cpu 1100'
-        result = str2dicts(string)
-        self.assertEqual(len(result), 2)
-
-    def test_str2list(self):
-        string = 'ip 1.2.3.4\nip 1.2.3.5\nip 1.2.3.6'
-        result = str2list(string)
-        self.assertEqual(len(result), 3)
-        self.assertEqual(result[0], '1.2.3.4')
-        self.assertEqual(result[1], '1.2.3.5')
-        self.assertEqual(result[2], '1.2.3.6')
-
-    def test_dict2str(self):
-        d = {'smp': 5, 'cpu': 2200, 'mem': 1024}
-        result = dict2str(d)
-        self.assertTrue(len(result) > 0)
-        self.assertTrue(result.find('smp 5') >= 0)
-        self.assertTrue(result.find('cpu 2200') >= 0)
-        self.assertTrue(result.find('mem 1024') >= 0)
-
-
-class CloudSigmaHttp(MockHttp):
-    fixtures = ComputeFileFixtures('cloudsigma')
-
-    def _drives_standard_info(self, method, url, body, headers):
-        body = self.fixtures.load('drives_standard_info.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_start(
-            self, method, url, body, headers):
-
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_stop(
-            self, method, url, body, headers):
-
-        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_destroy(
-            self, method, url, body, headers):
-
-        return (httplib.NO_CONTENT,
-                body, {}, httplib.responses[httplib.NO_CONTENT])
-
-    def _drives_d18119ce_7afa_474a_9242_e0384b160220_clone(
-            self, method, url, body, headers):
-
-        body = self.fixtures.load('drives_clone.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _drives_a814def5_1789_49a0_bf88_7abe7bb1682a_info(
-            self, method, url, body, headers):
-
-        body = self.fixtures.load('drives_single_info.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _drives_info(self, method, url, body, headers):
-        body = self.fixtures.load('drives_info.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_create(self, method, url, body, headers):
-        body = self.fixtures.load('servers_create.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_info(self, method, url, body, headers):
-        body = self.fixtures.load('servers_info.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _resources_ip_list(self, method, url, body, headers):
-        body = self.fixtures.load('resources_ip_list.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _resources_ip_create(self, method, url, body, headers):
-        body = self.fixtures.load('resources_ip_create.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _resources_ip_1_2_3_4_destroy(self, method, url, body, headers):
-        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
-
-    def _drives_d18119ce_7afa_474a_9242_e0384b160220_destroy(
-            self, method, url, body, headers):
-
-        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
-
-    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_set(
-            self, method, url, body, headers):
-
-        body = self.fixtures.load('servers_set.txt')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-if __name__ == '__main__':
-    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/test_cloudsigma_v1_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v1_0.py b/libcloud/test/compute/test_cloudsigma_v1_0.py
new file mode 100644
index 0000000..d8fb310
--- /dev/null
+++ b/libcloud/test/compute/test_cloudsigma_v1_0.py
@@ -0,0 +1,223 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import unittest
+from libcloud.utils.py3 import httplib
+
+from libcloud.compute.base import Node
+from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver
+from libcloud.compute.drivers.cloudsigma import CloudSigmaZrhNodeDriver
+from libcloud.utils.misc import str2dicts, str2list, dict2str
+
+from libcloud.test import MockHttp
+from libcloud.test.file_fixtures import ComputeFileFixtures
+
+
+class CloudSigmaAPI10BaseTestCase(object):
+    should_list_locations = False
+
+    driver_klass = CloudSigmaZrhNodeDriver
+    driver_kwargs = {}
+
+    def setUp(self):
+        self.driver = self.driver_klass(*self.driver_args,
+                                        **self.driver_kwargs)
+
+        self.driver.connectionCls.conn_classes = (None,
+                                                  CloudSigmaHttp)
+
+    def test_list_nodes(self):
+        nodes = self.driver.list_nodes()
+        self.assertTrue(isinstance(nodes, list))
+        self.assertEqual(len(nodes), 1)
+
+        node = nodes[0]
+        self.assertEqual(node.public_ips[0], "1.2.3.4")
+        self.assertEqual(node.extra['smp'], 1)
+        self.assertEqual(node.extra['cpu'], 1100)
+        self.assertEqual(node.extra['mem'], 640)
+
+    def test_list_sizes(self):
+        images = self.driver.list_sizes()
+        self.assertEqual(len(images), 9)
+
+    def test_list_images(self):
+        sizes = self.driver.list_images()
+        self.assertEqual(len(sizes), 10)
+
+    def test_start_node(self):
+        nodes = self.driver.list_nodes()
+        node = nodes[0]
+        self.assertTrue(self.driver.ex_start_node(node))
+
+    def test_shutdown_node(self):
+        nodes = self.driver.list_nodes()
+        node = nodes[0]
+        self.assertTrue(self.driver.ex_stop_node(node))
+        self.assertTrue(self.driver.ex_shutdown_node(node))
+
+    def test_reboot_node(self):
+        node = self.driver.list_nodes()[0]
+        self.assertTrue(self.driver.reboot_node(node))
+
+    def test_destroy_node(self):
+        node = self.driver.list_nodes()[0]
+        self.assertTrue(self.driver.destroy_node(node))
+        self.driver.list_nodes()
+
+    def test_create_node(self):
+        size = self.driver.list_sizes()[0]
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name="cloudsigma node", image=image, size=size)
+        self.assertTrue(isinstance(node, Node))
+
+    def test_ex_static_ip_list(self):
+        ips = self.driver.ex_static_ip_list()
+        self.assertEqual(len(ips), 3)
+
+    def test_ex_static_ip_create(self):
+        result = self.driver.ex_static_ip_create()
+        self.assertEqual(len(result), 2)
+        self.assertEqual(len(list(result[0].keys())), 6)
+        self.assertEqual(len(list(result[1].keys())), 6)
+
+    def test_ex_static_ip_destroy(self):
+        result = self.driver.ex_static_ip_destroy('1.2.3.4')
+        self.assertTrue(result)
+
+    def test_ex_drives_list(self):
+        result = self.driver.ex_drives_list()
+        self.assertEqual(len(result), 2)
+
+    def test_ex_drive_destroy(self):
+        result = self.driver.ex_drive_destroy(
+            # @@TR: this should be soft-coded:
+            'd18119ce_7afa_474a_9242_e0384b160220')
+        self.assertTrue(result)
+
+    def test_ex_set_node_configuration(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_set_node_configuration(node, **{'smp': 2})
+        self.assertTrue(result)
+
+    def test_str2dicts(self):
+        string = 'mem 1024\ncpu 2200\n\nmem2048\cpu 1100'
+        result = str2dicts(string)
+        self.assertEqual(len(result), 2)
+
+    def test_str2list(self):
+        string = 'ip 1.2.3.4\nip 1.2.3.5\nip 1.2.3.6'
+        result = str2list(string)
+        self.assertEqual(len(result), 3)
+        self.assertEqual(result[0], '1.2.3.4')
+        self.assertEqual(result[1], '1.2.3.5')
+        self.assertEqual(result[2], '1.2.3.6')
+
+    def test_dict2str(self):
+        d = {'smp': 5, 'cpu': 2200, 'mem': 1024}
+        result = dict2str(d)
+        self.assertTrue(len(result) > 0)
+        self.assertTrue(result.find('smp 5') >= 0)
+        self.assertTrue(result.find('cpu 2200') >= 0)
+        self.assertTrue(result.find('mem 1024') >= 0)
+
+
+class CloudSigmaAPI10DirectTestCase(CloudSigmaAPI10BaseTestCase,
+                                    unittest.TestCase):
+    driver_klass = CloudSigmaZrhNodeDriver
+    driver_args = ('foo', 'bar')
+    driver_kwargs = {}
+
+
+class CloudSigmaAPI10IndiretTestCase(CloudSigmaAPI10BaseTestCase,
+                                     unittest.TestCase):
+    driver_klass = CloudSigmaNodeDriver
+    driver_args = ('foo', 'bar')
+    driver_kwargs = {'api_version': '1.0'}
+
+
+class CloudSigmaHttp(MockHttp):
+    fixtures = ComputeFileFixtures('cloudsigma')
+
+    def _drives_standard_info(self, method, url, body, headers):
+        body = self.fixtures.load('drives_standard_info.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_start(
+            self, method, url, body, headers):
+
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_stop(
+            self, method, url, body, headers):
+
+        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_destroy(
+            self, method, url, body, headers):
+
+        return (httplib.NO_CONTENT,
+                body, {}, httplib.responses[httplib.NO_CONTENT])
+
+    def _drives_d18119ce_7afa_474a_9242_e0384b160220_clone(
+            self, method, url, body, headers):
+
+        body = self.fixtures.load('drives_clone.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _drives_a814def5_1789_49a0_bf88_7abe7bb1682a_info(
+            self, method, url, body, headers):
+
+        body = self.fixtures.load('drives_single_info.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _drives_info(self, method, url, body, headers):
+        body = self.fixtures.load('drives_info.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_create(self, method, url, body, headers):
+        body = self.fixtures.load('servers_create.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_info(self, method, url, body, headers):
+        body = self.fixtures.load('servers_info.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _resources_ip_list(self, method, url, body, headers):
+        body = self.fixtures.load('resources_ip_list.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _resources_ip_create(self, method, url, body, headers):
+        body = self.fixtures.load('resources_ip_create.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _resources_ip_1_2_3_4_destroy(self, method, url, body, headers):
+        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
+
+    def _drives_d18119ce_7afa_474a_9242_e0384b160220_destroy(
+            self, method, url, body, headers):
+
+        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
+
+    def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_set(
+            self, method, url, body, headers):
+
+        body = self.fixtures.load('servers_set.txt')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/test_cloudsigma_v2_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v2_0.py b/libcloud/test/compute/test_cloudsigma_v2_0.py
new file mode 100644
index 0000000..9e6690c
--- /dev/null
+++ b/libcloud/test/compute/test_cloudsigma_v2_0.py
@@ -0,0 +1,573 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver
+from libcloud.compute.drivers.cloudsigma import CloudSigma_2_0_NodeDriver
+from libcloud.compute.drivers.cloudsigma import CloudSigmaError
+from libcloud.compute.types import NodeState
+
+from libcloud.test import unittest
+from libcloud.test import MockHttpTestCase
+from libcloud.test.file_fixtures import ComputeFileFixtures
+
+
+class CloudSigmaAPI20BaseTestCase(object):
+    def setUp(self):
+        self.driver_klass.connectionCls.conn_classes = \
+            (CloudSigmaMockHttp, CloudSigmaMockHttp)
+
+        CloudSigmaMockHttp.type = None
+        CloudSigmaMockHttp.use_param = 'do'
+
+        self.driver = self.driver_klass(*self.driver_args,
+                                        **self.driver_kwargs)
+        self.driver.DRIVE_TRANSITION_SLEEP_INTERVAL = 0.1
+        self.driver.DRIVE_TRANSITION_TIMEOUT = 1
+        self.node = self.driver.list_nodes()[0]
+
+    def test_invalid_api_versions(self):
+        expected_msg = 'Unsupported API version: invalid'
+        self.assertRaisesRegexp(NotImplementedError, expected_msg,
+                                CloudSigmaNodeDriver, 'username', 'password',
+                                api_version='invalid')
+
+    def test_invalid_credentials(self):
+        CloudSigmaMockHttp.type = 'INVALID_CREDS'
+        self.assertRaises(InvalidCredsError, self.driver.list_nodes)
+
+    def test_invalid_region(self):
+        expected_msg = 'Invalid region:'
+        self.assertRaisesRegexp(ValueError, expected_msg,
+                                CloudSigma_2_0_NodeDriver, 'foo', 'bar',
+                                region='invalid')
+
+    def test_list_sizes(self):
+        sizes = self.driver.list_sizes()
+
+        size = sizes[0]
+        self.assertEqual(size.id, 'micro-regular')
+
+    def test_list_images(self):
+        images = self.driver.list_images()
+
+        image = images[0]
+        self.assertEqual(image.name, 'ubuntu-10.04-toMP')
+        self.assertEqual(image.extra['image_type'], 'preinst')
+        self.assertEqual(image.extra['media'], 'disk')
+        self.assertEqual(image.extra['os'], 'linux')
+
+    def test_list_nodes(self):
+        nodes = self.driver.list_nodes()
+
+        node = nodes[0]
+        self.assertEqual(len(nodes), 2)
+        self.assertEqual(node.id, '9de75ed6-fd33-45e2-963f-d405f31fd911')
+        self.assertEqual(node.name, 'test no drives')
+        self.assertEqual(node.state, NodeState.RUNNING)
+        self.assertEqual(node.public_ips, ['185.12.5.181', '178.22.68.55'])
+        self.assertEqual(node.private_ips, [])
+
+    def test_create_node(self):
+        image = self.driver.list_images()[0]
+        size = self.driver.list_sizes()[0]
+        metadata = {'foo': 'bar'}
+
+        node = self.driver.create_node(name='test node', size=size, image=image,
+                                       ex_metadata=metadata)
+        self.assertEqual(node.name, 'test node')
+
+    def test_destroy_node(self):
+        status = self.driver.destroy_node(node=self.node)
+        self.assertTrue(status)
+
+    def test_ex_start_node(self):
+        status = self.driver.ex_start_node(node=self.node)
+        self.assertTrue(status)
+
+    def test_ex_start_node_avoid_mode(self):
+        CloudSigmaMockHttp.type = 'AVOID_MODE'
+        ex_avoid = ['1', '2']
+        status = self.driver.ex_start_node(node=self.node,
+                                           ex_avoid=ex_avoid)
+        self.assertTrue(status)
+
+    def test_ex_start_node_already_started(self):
+        CloudSigmaMockHttp.type = 'ALREADY_STARTED'
+
+        expected_msg = 'Cannot start guest in state "started". Guest should ' \
+                       'be in state "stopped'
+
+        self.assertRaisesRegexp(CloudSigmaError, expected_msg,
+                                self.driver.ex_start_node, node=self.node)
+
+    def test_ex_stop_node(self):
+        status = self.driver.ex_stop_node(node=self.node)
+        self.assertTrue(status)
+
+    def test_ex_stop_node_already_stopped(self):
+        CloudSigmaMockHttp.type = 'ALREADY_STOPPED'
+
+        expected_msg = 'Cannot stop guest in state "stopped"'
+        self.assertRaisesRegexp(CloudSigmaError, expected_msg,
+                                self.driver.ex_stop_node, node=self.node)
+
+    def test_ex_clone_node(self):
+        node_to_clone = self.driver.list_nodes()[0]
+
+        cloned_node = self.driver.ex_clone_node(node=node_to_clone,
+                                                name='test cloned node')
+        self.assertEqual(cloned_node.name, 'test cloned node')
+
+    def test_ex_open_vnc_tunnel(self):
+        node = self.driver.list_nodes()[0]
+        vnc_url = self.driver.ex_open_vnc_tunnel(node=node)
+        self.assertEqual(vnc_url, 'vnc://direct.lvs.cloudsigma.com:41111')
+
+    def test_ex_close_vnc_tunnel(self):
+        node = self.driver.list_nodes()[0]
+        status = self.driver.ex_close_vnc_tunnel(node=node)
+        self.assertTrue(status)
+
+    def test_ex_list_drives(self):
+        drives = self.driver.ex_list_drives()
+
+        drive = drives[0]
+        self.assertEqual(drive.name, 'test node 2-drive')
+        self.assertEqual(drive.size, 13958643712)
+        self.assertEqual(drive.media, 'disk')
+        self.assertEqual(drive.status, 'unmounted')
+
+    def test_ex_create_drive(self):
+        CloudSigmaMockHttp.type = 'CREATE'
+
+        name = 'test drive 5'
+        size = 2000 * 1024 * 1024
+
+        drive = self.driver.ex_create_drive(name=name, size=size, media='disk')
+        self.assertEqual(drive.name, 'test drive 5')
+        self.assertEqual(drive.media, 'disk')
+
+    def test_ex_clone_drive(self):
+        drive = self.driver.ex_list_drives()[0]
+        cloned_drive = self.driver.ex_clone_drive(drive=drive,
+                                                  name='cloned drive')
+
+        self.assertEqual(cloned_drive.name, 'cloned drive')
+
+    def test_ex_resize_drive(self):
+        drive = self.driver.ex_list_drives()[0]
+
+        size = 1111 * 1024 * 1024
+
+        resized_drive = self.driver.ex_resize_drive(drive=drive, size=size)
+        self.assertEqual(resized_drive.name, 'test drive 5')
+        self.assertEqual(resized_drive.media, 'disk')
+        self.assertEqual(resized_drive.size, size)
+
+    def test_ex_list_firewall_policies(self):
+        policies = self.driver.ex_list_firewall_policies()
+
+        policy = policies[1]
+        rule = policy.rules[0]
+        self.assertEqual(policy.name, 'My awesome policy')
+        self.assertEqual(rule.action, 'drop')
+        self.assertEqual(rule.direction, 'out')
+        self.assertEqual(rule.dst_ip, '23.0.0.0/32')
+        self.assertEqual(rule.ip_proto, 'tcp')
+        self.assertEqual(rule.dst_port, None)
+        self.assertEqual(rule.src_ip, None)
+        self.assertEqual(rule.src_port, None)
+        self.assertEqual(rule.comment, 'Drop traffic from the VM to IP address 23.0.0.0/32')
+
+    def test_ex_create_firewall_policy_no_rules(self):
+        CloudSigmaMockHttp.type = 'CREATE_NO_RULES'
+        policy = self.driver.ex_create_firewall_policy(name='test policy 1')
+
+        self.assertEqual(policy.name, 'test policy 1')
+        self.assertEqual(policy.rules, [])
+
+    def test_ex_create_firewall_policy_with_rules(self):
+        CloudSigmaMockHttp.type = 'CREATE_WITH_RULES'
+        rules = [
+            {
+                'action': 'accept',
+                'direction': 'out',
+                'ip_proto': 'tcp',
+                'src_ip': '127.0.0.1',
+                'dst_ip': '127.0.0.1'
+            }
+        ]
+
+        policy = self.driver.ex_create_firewall_policy(name='test policy 2',
+                                                       rules=rules)
+        rule = policy.rules[0]
+
+        self.assertEqual(policy.name, 'test policy 2')
+        self.assertEqual(len(policy.rules), 1)
+
+        self.assertEqual(rule.action, 'accept')
+        self.assertEqual(rule.direction, 'out')
+        self.assertEqual(rule.ip_proto, 'tcp')
+
+    def test_ex_attach_firewall_policy(self):
+        policy = self.driver.ex_list_firewall_policies()[0]
+        node = self.driver.list_nodes()[0]
+
+        CloudSigmaMockHttp.type = 'ATTACH_POLICY'
+        updated_node = self.driver.ex_attach_firewall_policy(policy=policy,
+                                                             node=node)
+        nic = updated_node.extra['nics'][0]
+        self.assertEqual(nic['firewall_policy']['uuid'],
+                         '461dfb8c-e641-43d7-a20e-32e2aa399086')
+
+    def test_ex_attach_firewall_policy_inexistent_nic(self):
+        policy = self.driver.ex_list_firewall_policies()[0]
+        node = self.driver.list_nodes()[0]
+
+        nic_mac = 'inexistent'
+        expected_msg = 'Cannot find the NIC interface to attach a policy to'
+        self.assertRaisesRegexp(ValueError, expected_msg,
+                                self.driver.ex_attach_firewall_policy,
+                                policy=policy,
+                                node=node,
+                                nic_mac=nic_mac)
+
+    def test_ex_delete_firewall_policy(self):
+        policy = self.driver.ex_list_firewall_policies()[0]
+        status = self.driver.ex_delete_firewall_policy(policy=policy)
+        self.assertTrue(status)
+
+    def test_ex_list_tags(self):
+        tags = self.driver.ex_list_tags()
+
+        tag = tags[0]
+        self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d')
+        self.assertEqual(tag.name, 'test tag 2')
+
+    def test_ex_get_tag(self):
+        tag = self.driver.ex_get_tag(tag_id='a010ec41-2ead-4630-a1d0-237fa77e4d4d')
+
+        self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d')
+        self.assertEqual(tag.name, 'test tag 2')
+
+    def test_ex_create_tag(self):
+        tag = self.driver.ex_create_tag(name='test tag 3')
+        self.assertEqual(tag.name, 'test tag 3')
+
+    def test_ex_create_tag_with_resources(self):
+        CloudSigmaMockHttp.type = 'WITH_RESOURCES'
+        resource_uuids = ['1']
+        tag = self.driver.ex_create_tag(name='test tag 3',
+                                        resource_uuids=resource_uuids)
+        self.assertEqual(tag.name, 'test tag 3')
+        self.assertEqual(tag.resources, resource_uuids)
+
+    def test_ex_tag_resource(self):
+        node = self.driver.list_nodes()[0]
+        tag = self.driver.ex_list_tags()[0]
+
+        updated_tag = self.driver.ex_tag_resource(resource=node, tag=tag)
+        self.assertEqual(updated_tag.name, 'test tag 3')
+
+    def test_ex_tag_resources(self):
+        nodes = self.driver.list_nodes()
+        tag = self.driver.ex_list_tags()[0]
+
+        updated_tag = self.driver.ex_tag_resources(resources=nodes, tag=tag)
+        self.assertEqual(updated_tag.name, 'test tag 3')
+
+    def test_ex_tag_resource_invalid_resource_object(self):
+        tag = self.driver.ex_list_tags()[0]
+
+        expected_msg = 'Resource doesn\'t have id attribute'
+        self.assertRaisesRegexp(ValueError, expected_msg,
+                                self.driver.ex_tag_resource, tag=tag,
+                                resource={})
+
+    def test_ex_delete_tag(self):
+        tag = self.driver.ex_list_tags()[0]
+        status = self.driver.ex_delete_tag(tag=tag)
+        self.assertTrue(status)
+
+    def test_ex_get_balance(self):
+        balance = self.driver.ex_get_balance()
+        self.assertEqual(balance['balance'], '10.00')
+        self.assertEqual(balance['currency'], 'USD')
+
+    def test_ex_get_pricing(self):
+        pricing = self.driver.ex_get_pricing()
+
+        self.assertTrue('current' in pricing)
+        self.assertTrue('next' in pricing)
+        self.assertTrue('objects' in pricing)
+
+    def test_ex_get_usage(self):
+        pricing = self.driver.ex_get_usage()
+
+        self.assertTrue('balance' in pricing)
+        self.assertTrue('usage' in pricing)
+
+    def test_ex_list_subscriptions(self):
+        subscriptions = self.driver.ex_list_subscriptions()
+
+        subscription = subscriptions[0]
+        self.assertEqual(len(subscriptions), 5)
+        self.assertEqual(subscription.id, '7272')
+        self.assertEqual(subscription.resource, 'vlan')
+        self.assertEqual(subscription.amount, '1')
+        self.assertEqual(subscription.period, '345 days, 0:00:00')
+        self.assertEqual(subscription.status, 'active')
+        self.assertEqual(subscription.price, '0E-20')
+
+    def test_ex_list_subscriptions_status_filterting(self):
+        CloudSigmaMockHttp.type = 'STATUS_FILTER'
+        self.driver.ex_list_subscriptions(status='active')
+
+    def test_ex_list_subscriptions_resource_filterting(self):
+        CloudSigmaMockHttp.type = 'RESOURCE_FILTER'
+        resources = ['cpu', 'mem']
+        self.driver.ex_list_subscriptions(resources=resources)
+
+    def test_ex_toggle_subscription_auto_renew(self):
+        subscription = self.driver.ex_list_subscriptions()[0]
+        status = self.driver.ex_toggle_subscription_auto_renew(subscription=
+                                                               subscription)
+        self.assertTrue(status)
+
+    def test_ex_list_capabilities(self):
+        capabilities = self.driver.ex_list_capabilities()
+        self.assertEqual(capabilities['servers']['cpu']['min'], 250)
+
+    def test_wait_for_drive_state_transition_timeout(self):
+        drive = self.driver.ex_list_drives()[0]
+        state = 'timeout'
+
+        expected_msg = 'Timed out while waiting for drive transition'
+        self.assertRaisesRegexp(Exception, expected_msg,
+                                self.driver._wait_for_drive_state_transition,
+                                drive=drive, state=state,
+                                timeout=0.5)
+
+    def test_wait_for_drive_state_transition_success(self):
+        drive = self.driver.ex_list_drives()[0]
+        state = 'unmounted'
+
+        drive = self.driver._wait_for_drive_state_transition(drive=drive,
+                                                             state=state,
+                                                             timeout=0.5)
+        self.assertEqual(drive.status, state)
+
+
+class CloudSigmaAPI20DirectTestCase(CloudSigmaAPI20BaseTestCase,
+                                    unittest.TestCase):
+    driver_klass = CloudSigma_2_0_NodeDriver
+    driver_args = ('foo', 'bar')
+    driver_kwargs = {}
+
+
+class CloudSigmaAPI20IndirectTestCase(CloudSigmaAPI20BaseTestCase,
+                                      unittest.TestCase):
+    driver_klass = CloudSigmaNodeDriver
+    driver_args = ('foo', 'bar')
+    driver_kwargs = {'api_version': '2.0'}
+
+
+class CloudSigmaMockHttp(MockHttpTestCase):
+    fixtures = ComputeFileFixtures('cloudsigma_2_0')
+
+    def _api_2_0_servers_detail_INVALID_CREDS(self, method, url, body, headers):
+        body = self.fixtures.load('libdrives.json')
+        return (httplib.UNAUTHORIZED, body, {},
+                httplib.responses[httplib.UNAUTHORIZED])
+
+    def _api_2_0_libdrives(self, method, url, body, headers):
+        body = self.fixtures.load('libdrives.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_servers_detail(self, method, url, body, headers):
+        body = self.fixtures.load('servers_detail_mixed_state.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911(self, method, url, body, headers):
+        body = ''
+        return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT])
+
+    def _api_2_0_servers(self, method, url, body, headers):
+        if method == 'POST':
+            # create_node
+            body = self.fixtures.load('servers_create.json')
+            return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_start(self, method, url, body, headers):
+        body = self.fixtures.load('start_success.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_AVOID_MODE_start(self, method, url, body, headers):
+        self.assertUrlContainsQueryParams(url, {'avoid': '1,2'})
+
+        body = self.fixtures.load('start_success.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STARTED_start(self, method, url, body, headers):
+        body = self.fixtures.load('start_already_started.json')
+        return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_stop(self, method, url, body, headers):
+        body = self.fixtures.load('stop_success.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STOPPED_stop(self, method, url, body, headers):
+        body = self.fixtures.load('stop_already_stopped.json')
+        return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_clone(self, method, url, body, headers):
+        body = self.fixtures.load('servers_clone.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_open_vnc(self, method, url, body, headers):
+        body = self.fixtures.load('servers_open_vnc.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_close_vnc(self, method, url, body, headers):
+        body = self.fixtures.load('servers_close_vnc.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_drives_detail(self, method, url, body, headers):
+        body = self.fixtures.load('drives_detail.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913(self, method, url, body, headers):
+        body = self.fixtures.load('drives_get.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809(self, method, url, body, headers):
+        body = self.fixtures.load('drives_get.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_drives_CREATE(self, method, url, body, headers):
+        body = self.fixtures.load('drives_create.json')
+        return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_clone(self, method, url, body, headers):
+        body = self.fixtures.load('drives_clone.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_drives_5236b9ee_f735_42fd_a236_17558f9e12d3_action_clone(self, method, url, body, headers):
+        body = self.fixtures.load('drives_clone.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913_action_resize(self, method, url, body, headers):
+        body = self.fixtures.load('drives_resize.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_resize(self, method, url, body, headers):
+        body = self.fixtures.load('drives_resize.json')
+        return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED])
+
+    def _api_2_0_fwpolicies_detail(self, method, url, body, headers):
+        body = self.fixtures.load('fwpolicies_detail.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_fwpolicies_CREATE_NO_RULES(self, method, url, body, headers):
+        body = self.fixtures.load('fwpolicies_create_no_rules.json')
+        return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_fwpolicies_CREATE_WITH_RULES(self, method, url, body, headers):
+        body = self.fixtures.load('fwpolicies_create_with_rules.json')
+        return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_ATTACH_POLICY(self, method, url, body, headers):
+        body = self.fixtures.load('servers_attach_policy.json')
+        return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_fwpolicies_0e339282_0cb5_41ac_a9db_727fb62ff2dc(self, method, url, body, headers):
+        if method == 'DELETE':
+            body = ''
+            return (httplib.NO_CONTENT, body, {},
+                    httplib.responses[httplib.NO_CONTENT])
+
+    def _api_2_0_tags_detail(self, method, url, body, headers):
+        body = self.fixtures.load('tags_detail.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_tags(self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load('tags_create.json')
+            return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_tags_WITH_RESOURCES(self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load('tags_create_with_resources.json')
+            return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
+
+    def _api_2_0_tags_a010ec41_2ead_4630_a1d0_237fa77e4d4d(self, method, url, body, headers):
+        if method == 'GET':
+            # ex_get_tag
+            body = self.fixtures.load('tags_get.json')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        elif method == 'PUT':
+            # ex_tag_resource
+            body = self.fixtures.load('tags_update.json')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        elif method == 'DELETE':
+            # ex_delete_tag
+            body = ''
+            return (httplib.NO_CONTENT, body, {},
+                    httplib.responses[httplib.NO_CONTENT])
+
+    def _api_2_0_balance(self, method, url, body, headers):
+        body = self.fixtures.load('balance.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_pricing(self, method, url, body, headers):
+        body = self.fixtures.load('pricing.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_currentusage(self, method, url, body, headers):
+        body = self.fixtures.load('currentusage.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_subscriptions(self, method, url, body, headers):
+        body = self.fixtures.load('subscriptions.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_subscriptions_STATUS_FILTER(self, method, url, body, headers):
+        self.assertUrlContainsQueryParams(url, {'status': 'active'})
+
+        body = self.fixtures.load('subscriptions.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_subscriptions_RESOURCE_FILTER(self, method, url, body, headers):
+        expected_params = {'resource': 'cpu,mem', 'status': 'all'}
+        self.assertUrlContainsQueryParams(url, expected_params)
+
+        body = self.fixtures.load('subscriptions.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_subscriptions_7272_action_auto_renew(self, method, url, body, headers):
+        body = ''
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _api_2_0_capabilities(self, method, url, body, headers):
+        body = self.fixtures.load('capabilities.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())


[2/7] Add a new driver, tests and documentation for CloudSigma API v2.0.

Posted by to...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json
new file mode 100644
index 0000000..5ddafd7
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json
@@ -0,0 +1,2889 @@
+{
+    "current": {
+        "cpu": 5,
+        "dssd": 1,
+        "ip": 1,
+        "mem": 7,
+        "msft_7jq_00341": 1,
+        "msft_7nq_00302": 1,
+        "msft_lwa_00135": 1,
+        "msft_p71_01031": 1,
+        "msft_p73_04837": 1,
+        "msft_p73_04837_core": 1,
+        "msft_tfa_00009": 1,
+        "msft_tfa_00523": 1,
+        "sms": 1,
+        "ssd": 1,
+        "tx": 8,
+        "vlan": 1
+    },
+    "meta": {
+        "limit": 0,
+        "offset": 0,
+        "total_count": 316
+    },
+    "next": {
+        "cpu": 5,
+        "dssd": 1,
+        "ip": 1,
+        "mem": 7,
+        "msft_7jq_00341": 1,
+        "msft_7nq_00302": 1,
+        "msft_lwa_00135": 1,
+        "msft_p71_01031": 1,
+        "msft_p73_04837": 1,
+        "msft_p73_04837_core": 1,
+        "msft_tfa_00009": 1,
+        "msft_tfa_00523": 1,
+        "sms": 1,
+        "ssd": 1,
+        "tx": 10,
+        "vlan": 1
+    },
+    "objects": [
+        {
+            "currency": "CHF",
+            "id": "18",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.26600000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "20",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.21000000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "22",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.18200000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "USD",
+            "id": "24",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.28000000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "26",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.76000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "28",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.60000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "30",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.52000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "USD",
+            "id": "32",
+            "level": 1,
+            "multiplier": 2783138807808000,
+            "price": "0.80000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "34",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "4.75000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "EUR",
+            "id": "36",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "3.75000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "GBP",
+            "id": "38",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "3.25000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "USD",
+            "id": "40",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "5.00000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "USD",
+            "id": "8",
+            "level": 1,
+            "multiplier": 3600000,
+            "price": "0.00790500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "42",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "19.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "USD",
+            "id": "104",
+            "level": 2,
+            "multiplier": 3600000,
+            "price": "0.00816000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "44",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "15.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "USD",
+            "id": "108",
+            "level": 3,
+            "multiplier": 3600000,
+            "price": "0.00841500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "46",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "13.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "USD",
+            "id": "112",
+            "level": 4,
+            "multiplier": 3600000,
+            "price": "0.00867000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "48",
+            "level": 1,
+            "multiplier": 2592000,
+            "price": "20.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "CHF",
+            "id": "2",
+            "level": 1,
+            "multiplier": 3600000,
+            "price": "0.00875500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "54",
+            "level": 1,
+            "multiplier": 1073741824,
+            "price": "0.01950000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "101",
+            "level": 2,
+            "multiplier": 3600000,
+            "price": "0.00901000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "105",
+            "level": 3,
+            "multiplier": 3600000,
+            "price": "0.00935000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "109",
+            "level": 4,
+            "multiplier": 3600000,
+            "price": "0.00960500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "113",
+            "level": 5,
+            "multiplier": 3600000,
+            "price": "0.01028500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "117",
+            "level": 6,
+            "multiplier": 3600000,
+            "price": "0.01088000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "121",
+            "level": 7,
+            "multiplier": 3600000,
+            "price": "0.01207000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "125",
+            "level": 8,
+            "multiplier": 3600000,
+            "price": "0.01385500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "10",
+            "level": 1,
+            "multiplier": 3865470566400,
+            "price": "0.01256000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "133",
+            "level": 10,
+            "multiplier": 3865470566400,
+            "price": "0.02080000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "137",
+            "level": 11,
+            "multiplier": 3865470566400,
+            "price": "0.02192000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "141",
+            "level": 12,
+            "multiplier": 3865470566400,
+            "price": "0.02288000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "116",
+            "level": 5,
+            "multiplier": 3600000,
+            "price": "0.00926500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "120",
+            "level": 6,
+            "multiplier": 3600000,
+            "price": "0.00977500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "124",
+            "level": 7,
+            "multiplier": 3600000,
+            "price": "0.01088000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "16",
+            "level": 1,
+            "multiplier": 3865470566400,
+            "price": "0.01128000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "136",
+            "level": 10,
+            "multiplier": 3865470566400,
+            "price": "0.01872000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "140",
+            "level": 11,
+            "multiplier": 3865470566400,
+            "price": "0.01968000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "144",
+            "level": 12,
+            "multiplier": 3865470566400,
+            "price": "0.02064000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "148",
+            "level": 13,
+            "multiplier": 3865470566400,
+            "price": "0.02136000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "152",
+            "level": 14,
+            "multiplier": 3865470566400,
+            "price": "0.02184000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "156",
+            "level": 15,
+            "multiplier": 3865470566400,
+            "price": "0.02232000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "160",
+            "level": 16,
+            "multiplier": 3865470566400,
+            "price": "0.02280000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "4",
+            "level": 1,
+            "multiplier": 3600000,
+            "price": "0.00612000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "102",
+            "level": 2,
+            "multiplier": 3600000,
+            "price": "0.00637500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "106",
+            "level": 3,
+            "multiplier": 3600000,
+            "price": "0.00654500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "110",
+            "level": 4,
+            "multiplier": 3600000,
+            "price": "0.00671500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "114",
+            "level": 5,
+            "multiplier": 3600000,
+            "price": "0.00714000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "128",
+            "level": 8,
+            "multiplier": 3600000,
+            "price": "0.01249500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "132",
+            "level": 9,
+            "multiplier": 3600000,
+            "price": "0.01411000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "60",
+            "level": 10,
+            "multiplier": 3600000,
+            "price": "0.01623500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "64",
+            "level": 11,
+            "multiplier": 3600000,
+            "price": "0.01734000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "68",
+            "level": 12,
+            "multiplier": 3600000,
+            "price": "0.01844500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "72",
+            "level": 13,
+            "multiplier": 3600000,
+            "price": "0.01921000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "76",
+            "level": 14,
+            "multiplier": 3600000,
+            "price": "0.01980500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "80",
+            "level": 15,
+            "multiplier": 3600000,
+            "price": "0.02031500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "118",
+            "level": 6,
+            "multiplier": 3600000,
+            "price": "0.00756500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "122",
+            "level": 7,
+            "multiplier": 3600000,
+            "price": "0.00841500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "126",
+            "level": 8,
+            "multiplier": 3600000,
+            "price": "0.00969000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "130",
+            "level": 9,
+            "multiplier": 3600000,
+            "price": "0.01096500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "58",
+            "level": 10,
+            "multiplier": 3600000,
+            "price": "0.01266500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "62",
+            "level": 11,
+            "multiplier": 3600000,
+            "price": "0.01351500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "66",
+            "level": 12,
+            "multiplier": 3600000,
+            "price": "0.01428000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "145",
+            "level": 13,
+            "multiplier": 3865470566400,
+            "price": "0.02376000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "149",
+            "level": 14,
+            "multiplier": 3865470566400,
+            "price": "0.02424000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "153",
+            "level": 15,
+            "multiplier": 3865470566400,
+            "price": "0.02480000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "157",
+            "level": 16,
+            "multiplier": 3865470566400,
+            "price": "0.02536000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "50",
+            "level": 1,
+            "multiplier": 1073741824,
+            "price": "0.03250000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "253",
+            "level": 2,
+            "multiplier": 1073741824,
+            "price": "0.03420000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "257",
+            "level": 3,
+            "multiplier": 1073741824,
+            "price": "0.03750000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "261",
+            "level": 4,
+            "multiplier": 1073741824,
+            "price": "0.04250000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "265",
+            "level": 5,
+            "multiplier": 1073741824,
+            "price": "0.04750000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "269",
+            "level": 6,
+            "multiplier": 1073741824,
+            "price": "0.05170000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "273",
+            "level": 7,
+            "multiplier": 1073741824,
+            "price": "0.05580000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "277",
+            "level": 8,
+            "multiplier": 1073741824,
+            "price": "0.05920000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "281",
+            "level": 9,
+            "multiplier": 1073741824,
+            "price": "0.06250000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "209",
+            "level": 10,
+            "multiplier": 1073741824,
+            "price": "0.06500000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "213",
+            "level": 11,
+            "multiplier": 1073741824,
+            "price": "0.06750000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "217",
+            "level": 12,
+            "multiplier": 1073741824,
+            "price": "0.07000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "221",
+            "level": 13,
+            "multiplier": 1073741824,
+            "price": "0.07330000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "225",
+            "level": 14,
+            "multiplier": 1073741824,
+            "price": "0.07830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "229",
+            "level": 15,
+            "multiplier": 1073741824,
+            "price": "0.08330000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "233",
+            "level": 16,
+            "multiplier": 1073741824,
+            "price": "0.08830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "84",
+            "level": 16,
+            "multiplier": 3600000,
+            "price": "0.02091000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "5",
+            "level": 0,
+            "multiplier": 3600000,
+            "price": "0.01105000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "13",
+            "level": 0,
+            "multiplier": 3865470566400,
+            "price": "0.01352000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "53",
+            "level": 0,
+            "multiplier": 1073741824,
+            "price": "0.04225000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "255",
+            "level": 2,
+            "multiplier": 1073741824,
+            "price": "0.02050000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "129",
+            "level": 9,
+            "multiplier": 3600000,
+            "price": "0.01564000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "57",
+            "level": 10,
+            "multiplier": 3600000,
+            "price": "0.01810500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "61",
+            "level": 11,
+            "multiplier": 3600000,
+            "price": "0.01929500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "65",
+            "level": 12,
+            "multiplier": 3600000,
+            "price": "0.02048500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "69",
+            "level": 13,
+            "multiplier": 3600000,
+            "price": "0.02142000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "73",
+            "level": 14,
+            "multiplier": 3600000,
+            "price": "0.02193000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "77",
+            "level": 15,
+            "multiplier": 3600000,
+            "price": "0.02261000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "81",
+            "level": 16,
+            "multiplier": 3600000,
+            "price": "0.02320500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "259",
+            "level": 3,
+            "multiplier": 1073741824,
+            "price": "0.02250000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "85",
+            "level": 17,
+            "multiplier": 3600000,
+            "price": "0.02558500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "263",
+            "level": 4,
+            "multiplier": 1073741824,
+            "price": "0.02550000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "89",
+            "level": 18,
+            "multiplier": 3600000,
+            "price": "0.02805000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "267",
+            "level": 5,
+            "multiplier": 1073741824,
+            "price": "0.02850000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "271",
+            "level": 6,
+            "multiplier": 1073741824,
+            "price": "0.03100000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "210",
+            "level": 10,
+            "multiplier": 1073741824,
+            "price": "0.04550000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "212",
+            "level": 10,
+            "multiplier": 1073741824,
+            "price": "0.05850000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "275",
+            "level": 7,
+            "multiplier": 1073741824,
+            "price": "0.03350000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "214",
+            "level": 11,
+            "multiplier": 1073741824,
+            "price": "0.04730000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "216",
+            "level": 11,
+            "multiplier": 1073741824,
+            "price": "0.06080000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "279",
+            "level": 8,
+            "multiplier": 1073741824,
+            "price": "0.03550000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "218",
+            "level": 12,
+            "multiplier": 1073741824,
+            "price": "0.04900000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "220",
+            "level": 12,
+            "multiplier": 1073741824,
+            "price": "0.06300000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "283",
+            "level": 9,
+            "multiplier": 1073741824,
+            "price": "0.03750000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "222",
+            "level": 13,
+            "multiplier": 1073741824,
+            "price": "0.05130000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "224",
+            "level": 13,
+            "multiplier": 1073741824,
+            "price": "0.06600000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "211",
+            "level": 10,
+            "multiplier": 1073741824,
+            "price": "0.03900000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "226",
+            "level": 14,
+            "multiplier": 1073741824,
+            "price": "0.05480000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "228",
+            "level": 14,
+            "multiplier": 1073741824,
+            "price": "0.07050000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "215",
+            "level": 11,
+            "multiplier": 1073741824,
+            "price": "0.04050000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "230",
+            "level": 15,
+            "multiplier": 1073741824,
+            "price": "0.05830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "232",
+            "level": 15,
+            "multiplier": 1073741824,
+            "price": "0.07500000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "219",
+            "level": 12,
+            "multiplier": 1073741824,
+            "price": "0.04200000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "234",
+            "level": 16,
+            "multiplier": 1073741824,
+            "price": "0.06180000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "236",
+            "level": 16,
+            "multiplier": 1073741824,
+            "price": "0.07950000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "223",
+            "level": 13,
+            "multiplier": 1073741824,
+            "price": "0.04400000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "238",
+            "level": 17,
+            "multiplier": 1073741824,
+            "price": "0.06530000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "240",
+            "level": 17,
+            "multiplier": 1073741824,
+            "price": "0.08400000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "227",
+            "level": 14,
+            "multiplier": 1073741824,
+            "price": "0.04700000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "242",
+            "level": 18,
+            "multiplier": 1073741824,
+            "price": "0.07000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "244",
+            "level": 18,
+            "multiplier": 1073741824,
+            "price": "0.09000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "231",
+            "level": 15,
+            "multiplier": 1073741824,
+            "price": "0.05000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "246",
+            "level": 19,
+            "multiplier": 1073741824,
+            "price": "0.07580000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "248",
+            "level": 19,
+            "multiplier": 1073741824,
+            "price": "0.09750000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "52",
+            "level": 1,
+            "multiplier": 1073741824,
+            "price": "0.02280000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "56",
+            "level": 1,
+            "multiplier": 1073741824,
+            "price": "0.02930000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "235",
+            "level": 16,
+            "multiplier": 1073741824,
+            "price": "0.05300000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "250",
+            "level": 20,
+            "multiplier": 1073741824,
+            "price": "0.08280000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "252",
+            "level": 20,
+            "multiplier": 1073741824,
+            "price": "0.10650000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "239",
+            "level": 17,
+            "multiplier": 1073741824,
+            "price": "0.05600000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "254",
+            "level": 2,
+            "multiplier": 1073741824,
+            "price": "0.02390000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "256",
+            "level": 2,
+            "multiplier": 1073741824,
+            "price": "0.03080000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "243",
+            "level": 18,
+            "multiplier": 1073741824,
+            "price": "0.06000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "258",
+            "level": 3,
+            "multiplier": 1073741824,
+            "price": "0.02630000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "260",
+            "level": 3,
+            "multiplier": 1073741824,
+            "price": "0.03380000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "247",
+            "level": 19,
+            "multiplier": 1073741824,
+            "price": "0.06500000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "262",
+            "level": 4,
+            "multiplier": 1073741824,
+            "price": "0.02980000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "264",
+            "level": 4,
+            "multiplier": 1073741824,
+            "price": "0.03830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "GBP",
+            "id": "251",
+            "level": 20,
+            "multiplier": 1073741824,
+            "price": "0.07100000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "266",
+            "level": 5,
+            "multiplier": 1073741824,
+            "price": "0.03330000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "268",
+            "level": 5,
+            "multiplier": 1073741824,
+            "price": "0.04280000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "270",
+            "level": 6,
+            "multiplier": 1073741824,
+            "price": "0.03620000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "272",
+            "level": 6,
+            "multiplier": 1073741824,
+            "price": "0.04650000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "274",
+            "level": 7,
+            "multiplier": 1073741824,
+            "price": "0.03910000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "276",
+            "level": 7,
+            "multiplier": 1073741824,
+            "price": "0.05030000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "278",
+            "level": 8,
+            "multiplier": 1073741824,
+            "price": "0.04140000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "280",
+            "level": 8,
+            "multiplier": 1073741824,
+            "price": "0.05330000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "282",
+            "level": 9,
+            "multiplier": 1073741824,
+            "price": "0.04380000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "284",
+            "level": 9,
+            "multiplier": 1073741824,
+            "price": "0.05630000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "180",
+            "level": 2,
+            "multiplier": 3865470566400,
+            "price": "0.01152000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "93",
+            "level": 19,
+            "multiplier": 3600000,
+            "price": "0.03162000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "97",
+            "level": 20,
+            "multiplier": 3600000,
+            "price": "0.03638000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "184",
+            "level": 3,
+            "multiplier": 3865470566400,
+            "price": "0.01176000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "306",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "15.69000000000000000000",
+            "resource": "msft_7nq_00302",
+            "unit": ""
+        },
+        {
+            "currency": "CHF",
+            "id": "297",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "8.50000000000000000000",
+            "resource": "msft_p71_01031",
+            "unit": ""
+        },
+        {
+            "currency": "CHF",
+            "id": "301",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "1.60000000000000000000",
+            "resource": "msft_p73_04837_core",
+            "unit": ""
+        },
+        {
+            "currency": "CHF",
+            "id": "307",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "0.98000000000000000000",
+            "resource": "msft_tfa_00523",
+            "unit": ""
+        },
+        {
+            "currency": "EUR",
+            "id": "295",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "350.00000000000000000000",
+            "resource": "msft_tfa_00009",
+            "unit": "count/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "313",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "0.73010000000000000000",
+            "resource": "msft_tfa_00523",
+            "unit": ""
+        },
+        {
+            "currency": "GBP",
+            "id": "314",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "38.51520000000000000000",
+            "resource": "msft_7jq_00341",
+            "unit": ""
+        },
+        {
+            "currency": "GBP",
+            "id": "315",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "10.04160000000000000000",
+            "resource": "msft_7nq_00302",
+            "unit": ""
+        },
+        {
+            "currency": "GBP",
+            "id": "288",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "15.00000000000000000000",
+            "resource": "msft_lwa_00135",
+            "unit": "count/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "300",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "5.44000000000000000000",
+            "resource": "msft_p71_01031",
+            "unit": ""
+        },
+        {
+            "currency": "GBP",
+            "id": "292",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "27.00000000000000000000",
+            "resource": "msft_p73_04837",
+            "unit": "count/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "304",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "1.02400000000000000000",
+            "resource": "msft_p73_04837_core",
+            "unit": ""
+        },
+        {
+            "currency": "GBP",
+            "id": "296",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "300.00000000000000000000",
+            "resource": "msft_tfa_00009",
+            "unit": "count/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "316",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "0.62720000000000000000",
+            "resource": "msft_tfa_00523",
+            "unit": ""
+        },
+        {
+            "currency": "USD",
+            "id": "188",
+            "level": 4,
+            "multiplier": 3865470566400,
+            "price": "0.01200000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "192",
+            "level": 5,
+            "multiplier": 3865470566400,
+            "price": "0.01248000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "196",
+            "level": 6,
+            "multiplier": 3865470566400,
+            "price": "0.01296000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "200",
+            "level": 7,
+            "multiplier": 3865470566400,
+            "price": "0.01392000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "204",
+            "level": 8,
+            "multiplier": 3865470566400,
+            "price": "0.01536000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "208",
+            "level": 9,
+            "multiplier": 3865470566400,
+            "price": "0.01680000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "164",
+            "level": 17,
+            "multiplier": 3865470566400,
+            "price": "0.02472000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "168",
+            "level": 18,
+            "multiplier": 3865470566400,
+            "price": "0.02664000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "172",
+            "level": 19,
+            "multiplier": 3865470566400,
+            "price": "0.02952000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "176",
+            "level": 20,
+            "multiplier": 3865470566400,
+            "price": "0.03336000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "178",
+            "level": 2,
+            "multiplier": 3865470566400,
+            "price": "0.00896000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "182",
+            "level": 3,
+            "multiplier": 3865470566400,
+            "price": "0.00912000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "186",
+            "level": 4,
+            "multiplier": 3865470566400,
+            "price": "0.00936000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "190",
+            "level": 5,
+            "multiplier": 3865470566400,
+            "price": "0.00976000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "194",
+            "level": 6,
+            "multiplier": 3865470566400,
+            "price": "0.01008000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "198",
+            "level": 7,
+            "multiplier": 3865470566400,
+            "price": "0.01080000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "202",
+            "level": 8,
+            "multiplier": 3865470566400,
+            "price": "0.01200000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "206",
+            "level": 9,
+            "multiplier": 3865470566400,
+            "price": "0.01304000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "162",
+            "level": 17,
+            "multiplier": 3865470566400,
+            "price": "0.01920000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "166",
+            "level": 18,
+            "multiplier": 3865470566400,
+            "price": "0.02072000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "170",
+            "level": 19,
+            "multiplier": 3865470566400,
+            "price": "0.02296000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "174",
+            "level": 20,
+            "multiplier": 3865470566400,
+            "price": "0.02592000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "179",
+            "level": 2,
+            "multiplier": 3865470566400,
+            "price": "0.00768000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "183",
+            "level": 3,
+            "multiplier": 3865470566400,
+            "price": "0.00784000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "187",
+            "level": 4,
+            "multiplier": 3865470566400,
+            "price": "0.00800000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "191",
+            "level": 5,
+            "multiplier": 3865470566400,
+            "price": "0.00832000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "195",
+            "level": 6,
+            "multiplier": 3865470566400,
+            "price": "0.00864000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "1",
+            "level": 0,
+            "multiplier": 3600000,
+            "price": "0.01700000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "3",
+            "level": 0,
+            "multiplier": 3600000,
+            "price": "0.01360000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "11",
+            "level": 0,
+            "multiplier": 3865470566400,
+            "price": "0.01664000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "51",
+            "level": 0,
+            "multiplier": 1073741824,
+            "price": "0.05200000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "EUR",
+            "id": "19",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.16000000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "27",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.16000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "35",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "4.00000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "EUR",
+            "id": "43",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "8.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "GBP",
+            "id": "21",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.01352000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "29",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.01352000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "GBP",
+            "id": "37",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "3.25000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "GBP",
+            "id": "45",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "6.50000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "CHF",
+            "id": "9",
+            "level": 0,
+            "multiplier": 3865470566400,
+            "price": "0.02080000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "49",
+            "level": 0,
+            "multiplier": 1073741824,
+            "price": "0.06500000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "17",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.20000000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "25",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.45000000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "33",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "5.00000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "CHF",
+            "id": "41",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "9.50000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "USD",
+            "id": "7",
+            "level": 0,
+            "multiplier": 3600000,
+            "price": "0.01640000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "15",
+            "level": 0,
+            "multiplier": 3865470566400,
+            "price": "0.01840000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "55",
+            "level": 0,
+            "multiplier": 1073741824,
+            "price": "0.05850000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "23",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.18000000000000000000",
+            "resource": "dssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "USD",
+            "id": "31",
+            "level": 0,
+            "multiplier": 2783138807808000,
+            "price": "0.47400000000000000000",
+            "resource": "ssd",
+            "unit": "GB/month"
+        },
+        {
+            "currency": "USD",
+            "id": "39",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "4.50000000000000000000",
+            "resource": "ip",
+            "unit": "IP"
+        },
+        {
+            "currency": "USD",
+            "id": "47",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "10.00000000000000000000",
+            "resource": "vlan",
+            "unit": "VLAN"
+        },
+        {
+            "currency": "CHF",
+            "id": "177",
+            "level": 2,
+            "multiplier": 3865470566400,
+            "price": "0.01280000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "181",
+            "level": 3,
+            "multiplier": 3865470566400,
+            "price": "0.01304000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "185",
+            "level": 4,
+            "multiplier": 3865470566400,
+            "price": "0.01328000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "189",
+            "level": 5,
+            "multiplier": 3865470566400,
+            "price": "0.01392000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "193",
+            "level": 6,
+            "multiplier": 3865470566400,
+            "price": "0.01440000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "197",
+            "level": 7,
+            "multiplier": 3865470566400,
+            "price": "0.01552000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "201",
+            "level": 8,
+            "multiplier": 3865470566400,
+            "price": "0.01712000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "205",
+            "level": 9,
+            "multiplier": 3865470566400,
+            "price": "0.01872000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "161",
+            "level": 17,
+            "multiplier": 3865470566400,
+            "price": "0.02744000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "165",
+            "level": 18,
+            "multiplier": 3865470566400,
+            "price": "0.02960000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "169",
+            "level": 19,
+            "multiplier": 3865470566400,
+            "price": "0.03280000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "173",
+            "level": 20,
+            "multiplier": 3865470566400,
+            "price": "0.03704000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "237",
+            "level": 17,
+            "multiplier": 1073741824,
+            "price": "0.09330000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "241",
+            "level": 18,
+            "multiplier": 1073741824,
+            "price": "0.10000000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "245",
+            "level": 19,
+            "multiplier": 1073741824,
+            "price": "0.10830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "CHF",
+            "id": "249",
+            "level": 20,
+            "multiplier": 1073741824,
+            "price": "0.11830000000000000000",
+            "resource": "tx",
+            "unit": "GB"
+        },
+        {
+            "currency": "USD",
+            "id": "88",
+            "level": 17,
+            "multiplier": 3600000,
+            "price": "0.02303500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "92",
+            "level": 18,
+            "multiplier": 3600000,
+            "price": "0.02524500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "96",
+            "level": 19,
+            "multiplier": 3600000,
+            "price": "0.02847500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "USD",
+            "id": "100",
+            "level": 20,
+            "multiplier": 3600000,
+            "price": "0.03281000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "70",
+            "level": 13,
+            "multiplier": 3600000,
+            "price": "0.01496000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "74",
+            "level": 14,
+            "multiplier": 3600000,
+            "price": "0.01538500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "78",
+            "level": 15,
+            "multiplier": 3600000,
+            "price": "0.01581000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "82",
+            "level": 16,
+            "multiplier": 3600000,
+            "price": "0.01623500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "86",
+            "level": 17,
+            "multiplier": 3600000,
+            "price": "0.01793500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "90",
+            "level": 18,
+            "multiplier": 3600000,
+            "price": "0.01955000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "94",
+            "level": 19,
+            "multiplier": 3600000,
+            "price": "0.02210000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "98",
+            "level": 20,
+            "multiplier": 3600000,
+            "price": "0.02550000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "12",
+            "level": 1,
+            "multiplier": 3865470566400,
+            "price": "0.00880000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "134",
+            "level": 10,
+            "multiplier": 3865470566400,
+            "price": "0.01456000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "138",
+            "level": 11,
+            "multiplier": 3865470566400,
+            "price": "0.01528000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "142",
+            "level": 12,
+            "multiplier": 3865470566400,
+            "price": "0.01608000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "146",
+            "level": 13,
+            "multiplier": 3865470566400,
+            "price": "0.01664000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "150",
+            "level": 14,
+            "multiplier": 3865470566400,
+            "price": "0.01696000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "154",
+            "level": 15,
+            "multiplier": 3865470566400,
+            "price": "0.01736000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "EUR",
+            "id": "158",
+            "level": 16,
+            "multiplier": 3865470566400,
+            "price": "0.01776000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "6",
+            "level": 1,
+            "multiplier": 3600000,
+            "price": "0.00527000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "103",
+            "level": 2,
+            "multiplier": 3600000,
+            "price": "0.00544000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "107",
+            "level": 3,
+            "multiplier": 3600000,
+            "price": "0.00561000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "111",
+            "level": 4,
+            "multiplier": 3600000,
+            "price": "0.00578000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "115",
+            "level": 5,
+            "multiplier": 3600000,
+            "price": "0.00612000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "119",
+            "level": 6,
+            "multiplier": 3600000,
+            "price": "0.00654500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "123",
+            "level": 7,
+            "multiplier": 3600000,
+            "price": "0.00722500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "127",
+            "level": 8,
+            "multiplier": 3600000,
+            "price": "0.00833000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "131",
+            "level": 9,
+            "multiplier": 3600000,
+            "price": "0.00943500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "59",
+            "level": 10,
+            "multiplier": 3600000,
+            "price": "0.01088000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "63",
+            "level": 11,
+            "multiplier": 3600000,
+            "price": "0.01156000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "67",
+            "level": 12,
+            "multiplier": 3600000,
+            "price": "0.01232500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "71",
+            "level": 13,
+            "multiplier": 3600000,
+            "price": "0.01283500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "75",
+            "level": 14,
+            "multiplier": 3600000,
+            "price": "0.01326000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "79",
+            "level": 15,
+            "multiplier": 3600000,
+            "price": "0.01360000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "83",
+            "level": 16,
+            "multiplier": 3600000,
+            "price": "0.01394000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "87",
+            "level": 17,
+            "multiplier": 3600000,
+            "price": "0.01538500000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "91",
+            "level": 18,
+            "multiplier": 3600000,
+            "price": "0.01683000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "95",
+            "level": 19,
+            "multiplier": 3600000,
+            "price": "0.01904000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "99",
+            "level": 20,
+            "multiplier": 3600000,
+            "price": "0.02193000000000000000",
+            "resource": "cpu",
+            "unit": "GHz/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "14",
+            "level": 1,
+            "multiplier": 3865470566400,
+            "price": "0.00752000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "199",
+            "level": 7,
+            "multiplier": 3865470566400,
+            "price": "0.00928000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "203",
+            "level": 8,
+            "multiplier": 3865470566400,
+            "price": "0.01024000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "207",
+            "level": 9,
+            "multiplier": 3865470566400,
+            "price": "0.01120000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "135",
+            "level": 10,
+            "multiplier": 3865470566400,
+            "price": "0.01248000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "139",
+            "level": 11,
+            "multiplier": 3865470566400,
+            "price": "0.01312000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "143",
+            "level": 12,
+            "multiplier": 3865470566400,
+            "price": "0.01376000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "147",
+            "level": 13,
+            "multiplier": 3865470566400,
+            "price": "0.01424000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "151",
+            "level": 14,
+            "multiplier": 3865470566400,
+            "price": "0.01456000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "155",
+            "level": 15,
+            "multiplier": 3865470566400,
+            "price": "0.01488000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "159",
+            "level": 16,
+            "multiplier": 3865470566400,
+            "price": "0.01520000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "163",
+            "level": 17,
+            "multiplier": 3865470566400,
+            "price": "0.01648000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "167",
+            "level": 18,
+            "multiplier": 3865470566400,
+            "price": "0.01776000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "171",
+            "level": 19,
+            "multiplier": 3865470566400,
+            "price": "0.01968000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "GBP",
+            "id": "175",
+            "level": 20,
+            "multiplier": 3865470566400,
+            "price": "0.02224000000000000000",
+            "resource": "mem",
+            "unit": "GB/hour"
+        },
+        {
+            "currency": "CHF",
+            "id": "305",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "60.18000000000000000000",
+            "resource": "msft_7jq_00341",
+            "unit": ""
+        },
+        {
+            "currency": "CHF",
+            "id": "285",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "25.00000000000000000000",
+            "resource": "msft_lwa_00135",
+            "unit": "count/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "289",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "45.00000000000000000000",
+            "resource": "msft_p73_04837",
+            "unit": "count/month"
+        },
+        {
+            "currency": "CHF",
+            "id": "293",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "500.00000000000000000000",
+            "resource": "msft_tfa_00009",
+            "unit": "count/month"
+        },
+        {
+            "currency": "USD",
+            "id": "308",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "58.07370000000000000000",
+            "resource": "msft_7jq_00341",
+            "unit": ""
+        },
+        {
+            "currency": "USD",
+            "id": "309",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "15.14085000000000000000",
+            "resource": "msft_7nq_00302",
+            "unit": ""
+        },
+        {
+            "currency": "USD",
+            "id": "286",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "22.50000000000000000000",
+            "resource": "msft_lwa_00135",
+            "unit": "count/month"
+        },
+        {
+            "currency": "USD",
+            "id": "298",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "8.20250000000000000000",
+            "resource": "msft_p71_01031",
+            "unit": ""
+        },
+        {
+            "currency": "USD",
+            "id": "290",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "40.50000000000000000000",
+            "resource": "msft_p73_04837",
+            "unit": "count/month"
+        },
+        {
+            "currency": "USD",
+            "id": "302",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "1.54400000000000000000",
+            "resource": "msft_p73_04837_core",
+            "unit": ""
+        },
+        {
+            "currency": "USD",
+            "id": "294",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "450.00000000000000000000",
+            "resource": "msft_tfa_00009",
+            "unit": "count/month"
+        },
+        {
+            "currency": "USD",
+            "id": "310",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "0.94570000000000000000",
+            "resource": "msft_tfa_00523",
+            "unit": ""
+        },
+        {
+            "currency": "EUR",
+            "id": "311",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "44.83410000000000000000",
+            "resource": "msft_7jq_00341",
+            "unit": ""
+        },
+        {
+            "currency": "EUR",
+            "id": "312",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "11.68905000000000000000",
+            "resource": "msft_7nq_00302",
+            "unit": ""
+        },
+        {
+            "currency": "EUR",
+            "id": "287",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "17.50000000000000000000",
+            "resource": "msft_lwa_00135",
+            "unit": "count/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "299",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "6.33250000000000000000",
+            "resource": "msft_p71_01031",
+            "unit": ""
+        },
+        {
+            "currency": "EUR",
+            "id": "291",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "31.50000000000000000000",
+            "resource": "msft_p73_04837",
+            "unit": "count/month"
+        },
+        {
+            "currency": "EUR",
+            "id": "303",
+            "level": 0,
+            "multiplier": 2592000,
+            "price": "1.19200000000000000000",
+            "resource": "msft_p73_04837_core",
+            "unit": ""
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json
new file mode 100644
index 0000000..55f1d39
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json
@@ -0,0 +1,43 @@
+{
+    "context": true,
+    "cpu": 2000,
+    "cpu_model": null,
+    "cpus_instead_of_cores": false,
+    "drives": [],
+    "enable_numa": false,
+    "hv_relaxed": false,
+    "hv_tsc": false,
+    "mem": 536870912,
+    "meta": {},
+    "name": "test_server_updated",
+    "nics": [
+        {
+            "boot_order": null,
+            "firewall_policy": {
+                "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/",
+                "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086"
+            },
+            "ip_v4_conf": {
+                "conf": "dhcp",
+                "ip": null
+            },
+            "ip_v6_conf": null,
+            "mac": "22:58:83:c4:07:fc",
+            "model": "virtio",
+            "runtime": null,
+            "vlan": null
+        }
+    ],
+    "owner": {
+        "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+        "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+    },
+    "requirements": [],
+    "resource_uri": "/api/2.0/servers/d6bde7f2-69ca-4825-909b-fcc08ea928ef/",
+    "runtime": null,
+    "smp": 1,
+    "status": "stopped",
+    "tags": [],
+    "uuid": "d6bde7f2-69ca-4825-909b-fcc08ea928ef",
+    "vnc_password": "updated_password"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json
new file mode 100644
index 0000000..44b03c6
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json
@@ -0,0 +1,61 @@
+{
+    "context": true,
+    "cpu": 1000,
+    "cpu_model": null,
+    "cpus_instead_of_cores": false,
+    "drives": [
+        {
+            "boot_order": 1,
+            "dev_channel": "0:0",
+            "device": "ide",
+            "drive": {
+                "resource_uri": "/api/2.0/drives/f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9/",
+                "uuid": "f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9"
+            }
+        }
+    ],
+    "enable_numa": false,
+    "hv_relaxed": false,
+    "hv_tsc": false,
+    "mem": 2147483648,
+    "meta": {
+        "description": "ddd",
+        "ssh_public_key": ""
+    },
+    "name": "test cloned node",
+    "nics": [
+        {
+            "boot_order": null,
+            "firewall_policy": {
+                "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/",
+                "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086"
+            },
+            "ip_v4_conf": {
+                "conf": "dhcp",
+                "ip": null
+            },
+            "ip_v6_conf": null,
+            "mac": "22:76:4c:96:e1:98",
+            "model": "virtio",
+            "runtime": null,
+            "vlan": null
+        }
+    ],
+    "owner": {
+        "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+        "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+    },
+    "requirements": [],
+    "resource_uri": "/api/2.0/servers/470ea5b9-3beb-4506-9cac-e3c63002480b/",
+    "runtime": null,
+    "smp": 1,
+    "status": "cloning",
+    "tags": [
+        {
+            "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/",
+            "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2"
+        }
+    ],
+    "uuid": "470ea5b9-3beb-4506-9cac-e3c63002480b",
+    "vnc_password": "xxxx"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json
new file mode 100644
index 0000000..e132273
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json
@@ -0,0 +1,5 @@
+{
+    "action": "close_vnc",
+    "result": "success",
+    "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json
new file mode 100644
index 0000000..257fb31
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json
@@ -0,0 +1,30 @@
+{
+    "objects": [
+        {
+            "context": true,
+            "cpu": 1000,
+            "cpu_model": null,
+            "cpus_instead_of_cores": false,
+            "drives": [],
+            "enable_numa": false,
+            "hv_relaxed": false,
+            "hv_tsc": false,
+            "mem": 536870912,
+            "meta": {},
+            "name": "test node",
+            "nics": [],
+            "owner": {
+                "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+            },
+            "requirements": [],
+            "resource_uri": "/api/2.0/servers/9de75ed6_fd33_45e2_963f_d405f31fd911/",
+            "runtime": null,
+            "smp": 1,
+            "status": "started",
+            "tags": [],
+            "uuid": "9de75ed6_fd33_45e2_963f_d405f31fd911",
+            "vnc_password": "testserver"
+        }
+    ]
+}


[4/7] git commit: Add a new driver, tests and documentation for CloudSigma API v2.0.

Posted by to...@apache.org.
Add a new driver, tests and documentation for CloudSigma API v2.0.

Also update existing driver for API v1.0 and other affected code:

- Update existing driver for API version 1.0 and prefix 1.0 classes with "1_0"
- Update existing 1.0 driver to support "region" argument. This way porting
  existing code to API v2.0 will be easier.
- Add new CloudSigmaNodeDriver class which can be instantiated directly. Which
  API version is used is dictated by the "api_version" kwarg which defaults to
  2.0.
- Add new libcloud.common.cloudsigma module which holds common functionality
  for CloudSigma drivers
- Update INSTANCE_TYPES to be a list so output of list_sizes() method is always
  returned in the same order.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/4d40ecd3
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/4d40ecd3
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/4d40ecd3

Branch: refs/heads/trunk
Commit: 4d40ecd328db72143fab75d940aaa047b68b7a22
Parents: 903e769
Author: Tomaz Muraus <to...@tomaz.me>
Authored: Thu Nov 7 12:02:32 2013 +0000
Committer: Tomaz Muraus <to...@apache.org>
Committed: Wed Jan 29 16:50:23 2014 +0100

----------------------------------------------------------------------
 .coveragerc                                     |    1 +
 .../generate_provider_feature_matrix_table.py   |    2 +
 docs/compute/drivers/cloudsigma.rst             |  152 +
 .../cloudsigma/attach_firewall_policy.py        |   14 +
 .../compute/cloudsigma/connect_to_api_1_0.py    |    5 +
 .../compute/cloudsigma/connect_to_api_2_0.py    |    7 +
 .../cloudsigma/create_server_custom_size.py     |   15 +
 .../cloudsigma/create_server_with_metadata.py   |   16 +
 .../compute/cloudsigma/open_vnc_tunnel.py       |   16 +
 docs/examples/compute/cloudsigma/tag_server.py  |   24 +
 libcloud/common/cloudsigma.py                   |  146 +
 libcloud/compute/drivers/cloudsigma.py          | 1533 +++++++++-
 libcloud/compute/providers.py                   |    8 +-
 libcloud/compute/types.py                       |    3 +-
 .../fixtures/cloudsigma_2_0/balance.json        |    1 +
 .../fixtures/cloudsigma_2_0/capabilities.json   |   26 +
 .../fixtures/cloudsigma_2_0/currentusage.json   |   88 +
 .../fixtures/cloudsigma_2_0/drives_clone.json   |   29 +
 .../fixtures/cloudsigma_2_0/drives_create.json  |   29 +
 .../fixtures/cloudsigma_2_0/drives_detail.json  |  154 +
 .../fixtures/cloudsigma_2_0/drives_get.json     |   25 +
 .../fixtures/cloudsigma_2_0/drives_resize.json  |   29 +
 .../fwpolicies_create_no_rules.json             |   16 +
 .../fwpolicies_create_with_rules.json           |   27 +
 .../cloudsigma_2_0/fwpolicies_detail.json       |   84 +
 .../fixtures/cloudsigma_2_0/libdrives.json      |  569 ++++
 .../fixtures/cloudsigma_2_0/pricing.json        | 2889 ++++++++++++++++++
 .../cloudsigma_2_0/servers_attach_policy.json   |   43 +
 .../fixtures/cloudsigma_2_0/servers_clone.json  |   61 +
 .../cloudsigma_2_0/servers_close_vnc.json       |    5 +
 .../fixtures/cloudsigma_2_0/servers_create.json |   30 +
 .../servers_detail_all_stopped.json             |  104 +
 .../servers_detail_mixed_state.json             |  162 +
 .../cloudsigma_2_0/servers_open_vnc.json        |    6 +
 .../cloudsigma_2_0/start_already_started.json   |    1 +
 .../fixtures/cloudsigma_2_0/start_success.json  |    1 +
 .../cloudsigma_2_0/stop_already_stopped.json    |    1 +
 .../fixtures/cloudsigma_2_0/stop_success.json   |    1 +
 .../fixtures/cloudsigma_2_0/subscriptions.json  |  105 +
 .../fixtures/cloudsigma_2_0/tags_create.json    |   15 +
 .../tags_create_with_resources.json             |   25 +
 .../fixtures/cloudsigma_2_0/tags_detail.json    |   31 +
 .../fixtures/cloudsigma_2_0/tags_get.json       |   11 +
 .../fixtures/cloudsigma_2_0/tags_update.json    |   30 +
 .../fixtures/cloudsigma_2_0/unknown_error.json  |    1 +
 libcloud/test/compute/test_cloudsigma.py        |  206 --
 libcloud/test/compute/test_cloudsigma_v1_0.py   |  223 ++
 libcloud/test/compute/test_cloudsigma_v2_0.py   |  573 ++++
 48 files changed, 7186 insertions(+), 357 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/.coveragerc
----------------------------------------------------------------------
diff --git a/.coveragerc b/.coveragerc
index 09d7308..61014db 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -11,6 +11,7 @@ exclude_lines =
 
     # Don't complain about missing debug-only code:
     def __repr__
+    def __str__
     if self\.debug
 
     # Don't complain if tests don't hit defensive assertion code:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/contrib/generate_provider_feature_matrix_table.py
----------------------------------------------------------------------
diff --git a/contrib/generate_provider_feature_matrix_table.py b/contrib/generate_provider_feature_matrix_table.py
index 14b20db..728ee9c 100755
--- a/contrib/generate_provider_feature_matrix_table.py
+++ b/contrib/generate_provider_feature_matrix_table.py
@@ -141,6 +141,8 @@ IGNORED_PROVIDERS = [
     'local',
 
     # Deprecated constants
+    'cloudsigma_us',
+
     'cloudfiles_swift'
 ]
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/compute/drivers/cloudsigma.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/cloudsigma.rst b/docs/compute/drivers/cloudsigma.rst
new file mode 100644
index 0000000..8823355
--- /dev/null
+++ b/docs/compute/drivers/cloudsigma.rst
@@ -0,0 +1,152 @@
+CloudSigma Compute Driver Documentation
+=======================================
+
+`CloudSigma`_ is a pure IaaS provided based in Zurich, Switzerland with
+data centers in Zurich, Switzerland, Las Vegas, United States and Washington DC,
+United States.
+
+CloudSigma driver supports working with legacy `API v1.0`_ and a new and
+actively supported `API v2.0`_. API v1.0 has been deprecated and as such,
+you are strongly encouraged to migrate any existing code which uses API v1.0 to
+API v2.0.
+
+Instantiating a driver
+----------------------
+
+CloudSigma driver constructor takes different arguments with which you tell
+it which region to connect to, which api version to use and so on.
+
+Available arguments:
+
+* ``region`` - Which region to connect to. Defaults to ``zrh``. All the
+  supported values: ``zrh``, ``lvs``, ``wdc``
+* ``api_version`` - Which API version to use. Defaults to ``2.0``. All the
+  supported values: ``1.0`` (deprecated), ``2.0``
+
+Examples
+--------
+
+1. Connect to zrh region using new API v2.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. literalinclude:: /examples/compute/cloudsigma/connect_to_api_2_0.py
+   :language: python
+
+2. Connect to zrh region using deprecated API v1.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As noted above, API 1.0 has been deprecated and you are strongly encouraged to
+migrate any code which uses API 1.0 to API 2.0. This example is only included
+here for completeness.
+
+.. literalinclude:: /examples/compute/cloudsigma/connect_to_api_1_0.py
+   :language: python
+
+3. Create a server using a custom node size
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Unlike most of the other cloud providers out there, CloudSigma is not limited
+to pre-defined instance sizes and allows you to specify your own custom size
+when creating a node.
+
+This means you can totally customize server for your work-load and specify
+exactly how much CPU, memory and disk space you want.
+
+To follow Libcloud standard API, CloudSigma driver also exposes some
+pre-defined instance sizes through the
+:meth:`libcloud.compute.drivers.cloudsigma.CloudSigma_2_0_NodeDriver.list_sizes`
+method.
+
+This example shows how to create a node using a custom size.
+
+.. literalinclude:: /examples/compute/cloudsigma/create_server_custom_size.py
+   :language: python
+
+Keep in mind that there are some limits in place:
+
+* CPU - 1 GHz to 80GHz
+* Memory - 1 GB to 128 GB
+* Disk - 1 GB to 8249 GB
+
+You can find exact limits and free capacity for your account's location using
+:meth:`libcloud.compute.drivers.cloudsigma.CloudSigma_2_0_NodeDriver.ex_list_capabilities`
+method.
+
+4. Associate metadata with a server upon creation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CloudSigma allows you to associate arbitrary key / value pairs with each
+server. This examples shows how to do that upon server creation.
+
+.. literalinclude:: /examples/compute/cloudsigma/create_server_with_metadata.py
+   :language: python
+
+4. Add a tag to the server
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CloudSigma allows you to ogranize resources such as servers and drivers by
+tagging them. This example shows how to do that.
+
+.. literalinclude:: /examples/compute/cloudsigma/tag_server.py
+   :language: python
+
+5. Open a VNC tunnel to the server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CloudSigma allows you to connect and manage your server using `VNC`_. To
+connect to the server using VNC, you can use clients such as ``vinagre`` or
+``vncviewer`` on Ubuntu and other Linux distributions.
+
+This example shows how to open a VNC connection to your server and retrieve
+a connection URL.
+
+After you have retrieved the URL, you will also need a password which you
+specified (or it was auto-generated if you haven't specified it) when creating a
+server.
+
+If you can't remember the password, you can use
+:meth:`libcloud.compute.drivers.CloudSigma_2_0_NodeDriver.list_nodes` method
+and access ``node.extra['vnc_password']`` attribute.
+
+After you are done using VNC, it's recommended to close a tunnel using
+:meth:`libcloud.compute.drivers.cloudsigma.CloudSigma_2_0_NodeDriver.ex_close_vnc_tunnel`
+method.
+
+.. literalinclude:: /examples/compute/cloudsigma/open_vnc_tunnel.py
+   :language: python
+
+6. Attach firewall policy to the server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CloudSigma allows you to restrict access to your servers by using firewall
+policies. This example shows how to attach an existing policy to all your
+servers tagged with ``database-server``.
+
+.. literalinclude:: /examples/compute/cloudsigma/attach_firewall_policy.py
+   :language: python
+
+API Docs
+--------
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigma_2_0_NodeDriver
+    :members:
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigmaDrive
+    :members:
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigmaTag
+    :members:
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigmaSubscription
+    :members:
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigmaFirewallPolicy
+    :members:
+
+.. autoclass:: libcloud.compute.drivers.cloudsigma.CloudSigmaFirewallPolicyRule
+    :members:
+
+.. _`CloudSigma`: http://www.cloudsigma.com/
+.. _`API v1.0`: https://www.cloudsigma.com/legacy/cloudsigma-api-1-0/
+.. _`API v2.0`: https://zrh.cloudsigma.com/docs/
+.. _`VNC`: http://en.wikipedia.org/wiki/Virtual_Network_Computing

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/attach_firewall_policy.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/attach_firewall_policy.py b/docs/examples/compute/cloudsigma/attach_firewall_policy.py
new file mode 100644
index 0000000..a2c93c2
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/attach_firewall_policy.py
@@ -0,0 +1,14 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='2.0')
+
+tags = driver.ex_list_tags()
+tag = [tag for tag in tags if tag.name == 'database-server'][0]
+
+nodes = driver.list_nodes(ex_tag=tag)
+policy = driver.ex_list_firewall_policies()[0]
+
+for node in nodes:
+    driver.ex_attach_firewall_policy(policy=policy, node=node)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/connect_to_api_1_0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/connect_to_api_1_0.py b/docs/examples/compute/cloudsigma/connect_to_api_1_0.py
new file mode 100644
index 0000000..dac1d4e
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/connect_to_api_1_0.py
@@ -0,0 +1,5 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='1.0')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/connect_to_api_2_0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/connect_to_api_2_0.py b/docs/examples/compute/cloudsigma/connect_to_api_2_0.py
new file mode 100644
index 0000000..608c46f
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/connect_to_api_2_0.py
@@ -0,0 +1,7 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+
+# "api_version" argument can be left out since it defaults to 2.0
+driver = cls('username', 'password', region='zrh', api_version='2.0')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/create_server_custom_size.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/create_server_custom_size.py b/docs/examples/compute/cloudsigma/create_server_custom_size.py
new file mode 100644
index 0000000..231bc2b
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/create_server_custom_size.py
@@ -0,0 +1,15 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeSize
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='2.0')
+
+name = 'test node custom size'
+image = driver.list_images()[0]
+
+# Custom node size with 56 GB of ram, 5000 MHz CPU and 200 GB SSD drive
+size = CloudSigmaNodeSize(id=1, name='my size', cpu=5000, ram=5600, disk=200,
+                          bandwidth=None, price=0, driver=driver)
+node = driver.create_node(name=name, size=size, image=image)
+print(node)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/create_server_with_metadata.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/create_server_with_metadata.py b/docs/examples/compute/cloudsigma/create_server_with_metadata.py
new file mode 100644
index 0000000..0087a8c
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/create_server_with_metadata.py
@@ -0,0 +1,16 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='2.0')
+
+name = 'test node sizeth metadata'
+size = driver.list_sizes()[0]
+image = driver.list_images()[0]
+
+metadata = {'ssh_public_key': 'my public key', 'role': 'database server',
+            'region': 'zrh'}
+
+node = driver.create_node(name=name, size=size, image=image,
+                          ex_metadata=metadata)
+print(node)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/open_vnc_tunnel.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/open_vnc_tunnel.py b/docs/examples/compute/cloudsigma/open_vnc_tunnel.py
new file mode 100644
index 0000000..428490a
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/open_vnc_tunnel.py
@@ -0,0 +1,16 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='2.0')
+
+node = driver.list_nodes()[0]
+
+vnc_url = driver.ex_open_vnc_tunnel(node=node)
+vnc_password = node.extra['vnc_password']
+
+values = {'url': vnc_url, 'password': vnc_password}
+print('URL: %(url)s, Password: %(password)s' % values)
+
+# When you are done
+driver.ex_close_vnc_tunnel(node=node)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/docs/examples/compute/cloudsigma/tag_server.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/cloudsigma/tag_server.py b/docs/examples/compute/cloudsigma/tag_server.py
new file mode 100644
index 0000000..b9030fd
--- /dev/null
+++ b/docs/examples/compute/cloudsigma/tag_server.py
@@ -0,0 +1,24 @@
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+cls = get_driver(Provider.CLOUDSIGMA)
+driver = cls('username', 'password', region='zrh', api_version='2.0')
+
+node = driver.list_nodes()[0]
+
+tag_names = [
+    'zrh',
+    'database-server',
+    'monited'
+]
+
+tags = []
+
+# 1. Create necessary tags
+for tag_name in tag_names:
+    tag = driver.ex_create_tag(name='database-servers')
+    tags.append(tag)
+
+# 2. Tag node with the created tags
+for tag in tags:
+    driver.ex_tag_resource(resource=node, tag=tag)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/common/cloudsigma.py
----------------------------------------------------------------------
diff --git a/libcloud/common/cloudsigma.py b/libcloud/common/cloudsigma.py
new file mode 100644
index 0000000..e0e6336
--- /dev/null
+++ b/libcloud/common/cloudsigma.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+__all__ = [
+    'API_ENDPOINTS_1_0',
+    'API_ENDPOINTS_2_0',
+    'API_VERSIONS',
+    'INSTANCE_TYPES'
+]
+
+# API end-points
+API_ENDPOINTS_1_0 = {
+    'zrh': {
+        'name': 'Zurich',
+        'country': 'Switzerland',
+        'host': 'api.zrh.cloudsigma.com'
+    },
+    'lvs': {
+        'name': 'Las Vegas',
+        'country': 'United States',
+        'host': 'api.lvs.cloudsigma.com'
+    }
+}
+
+API_ENDPOINTS_2_0 = {
+    'zrh': {
+        'name': 'Zurich',
+        'country': 'Switzerland',
+        'host': 'zrh.cloudsigma.com'
+    },
+    'lvs': {
+        'name': 'Las Vegas',
+        'country': 'United States',
+        'host': 'lvs.cloudsigma.com'
+    },
+    'wdc': {
+        'name': 'Las Vegas',
+        'country': 'United States',
+        'host': 'wdc.cloudsigma.com'
+    }
+
+}
+
+DEFAULT_REGION = 'zrh'
+
+# Supported API versions.
+API_VERSIONS = [
+    '1.0'  # old and deprecated
+    '2.0'
+]
+
+DEFAULT_API_VERSION = '2.0'
+
+# CloudSigma doesn't specify special instance types.
+# Basically for CPU any value between 0.5 GHz and 20.0 GHz should work,
+# 500 MB to 32000 MB for ram
+# and 1 GB to 1024 GB for hard drive size.
+# Plans in this file are based on examples listed on http://www.cloudsigma
+# .com/en/pricing/price-schedules
+INSTANCE_TYPES = [
+    {
+        'id': 'micro-regular',
+        'name': 'Micro/Regular instance',
+        'cpu': 1100,
+        'memory': 640,
+        'disk': 10 + 3,
+        'bandwidth': None,
+    },
+    {
+        'id': 'micro-high-cpu',
+        'name': 'Micro/High CPU instance',
+        'cpu': 2200,
+        'memory': 640,
+        'disk': 80,
+        'bandwidth': None,
+    },
+    {
+        'id': 'standard-small',
+        'name': 'Standard/Small instance',
+        'cpu': 1100,
+        'memory': 1741,
+        'disk': 50,
+        'bandwidth': None,
+    },
+    {
+        'id': 'standard-large',
+        'name': 'Standard/Large instance',
+        'cpu': 4400,
+        'memory': 7680,
+        'disk': 250,
+        'bandwidth': None,
+    },
+    {
+        'id': 'standard-extra-large',
+        'name': 'Standard/Extra Large instance',
+        'cpu': 8800,
+        'memory': 15360,
+        'disk': 500,
+        'bandwidth': None,
+    },
+    {
+        'id': 'high-memory-extra-large',
+        'name': 'High Memory/Extra Large instance',
+        'cpu': 7150,
+        'memory': 17510,
+        'disk': 250,
+        'bandwidth': None,
+    },
+    {
+        'id': 'high-memory-double-extra-large',
+        'name': 'High Memory/Double Extra Large instance',
+        'cpu': 14300,
+        'memory': 32768,
+        'disk': 500,
+        'bandwidth': None,
+    },
+    {
+        'id': 'high-cpu-medium',
+        'name': 'High CPU/Medium instance',
+        'cpu': 5500,
+        'memory': 1741,
+        'disk': 150,
+        'bandwidth': None,
+    },
+    {
+        'id': 'high-cpu-extra-large',
+        'name': 'High CPU/Extra Large instance',
+        'cpu': 20000,
+        'memory': 7168,
+        'disk': 500,
+        'bandwidth': None,
+    }
+]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/compute/drivers/cloudsigma.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudsigma.py b/libcloud/compute/drivers/cloudsigma.py
index 4a05831..0b23a85 100644
--- a/libcloud/compute/drivers/cloudsigma.py
+++ b/libcloud/compute/drivers/cloudsigma.py
@@ -13,130 +13,68 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-CloudSigma Driver
+Drivers for CloudSigma API v1.0 and v2.0.
 """
+
 import re
 import time
+import copy
 import base64
 
+try:
+    import simplejson as json
+except:
+    import json
+
 from libcloud.utils.py3 import b
+from libcloud.utils.py3 import httplib
 
 from libcloud.utils.misc import str2dicts, str2list, dict2str
-from libcloud.common.base import ConnectionUserAndKey, Response
-from libcloud.common.types import InvalidCredsError
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse, Response
+from libcloud.common.types import InvalidCredsError, ProviderError
+from libcloud.common.cloudsigma import INSTANCE_TYPES
+from libcloud.common.cloudsigma import API_ENDPOINTS_1_0
+from libcloud.common.cloudsigma import API_ENDPOINTS_2_0
+from libcloud.common.cloudsigma import DEFAULT_API_VERSION, DEFAULT_REGION
 from libcloud.compute.types import NodeState, Provider
 from libcloud.compute.base import NodeDriver, NodeSize, Node
 from libcloud.compute.base import NodeImage
+from libcloud.compute.base import is_private_subnet
+from libcloud.utils.iso8601 import parse_date
+from libcloud.utils.misc import get_secure_random_string
+
+__all__ = [
+    'CloudSigmaNodeDriver',
+    'CloudSigma_1_0_NodeDriver',
+    'CloudSigma_2_0_NodeDriver',
+    'CloudSigmaError',
+
+    'CloudSigmaNodeSize',
+    'CloudSigmaDrive',
+    'CloudSigmaTag',
+    'CloudSigmaSubscription',
+    'CloudSigmaFirewallPolicy',
+    'CloudSigmaFirewallPolicyRule'
+]
+
+
+class CloudSigmaNodeDriver(NodeDriver):
+    name = 'CloudSigma'
+    website = 'http://www.cloudsigma.com/'
 
-# API end-points
-API_ENDPOINTS = {
-    'zrh': {
-        'name': 'Zurich',
-        'country': 'Switzerland',
-        'host': 'api.zrh.cloudsigma.com'
-    },
-
-    'lvs': {
-        'name': 'Las Vegas',
-        'country': 'United States',
-        'host': 'api.lvs.cloudsigma.com'
-    }
-}
-
-# Default API end-point for the base connection clase.
-DEFAULT_ENDPOINT = 'zrh'
-
-# CloudSigma doesn't specify special instance types.
-# Basically for CPU any value between 0.5 GHz and 20.0 GHz should work,
-# 500 MB to 32000 MB for ram
-# and 1 GB to 1024 GB for hard drive size.
-# Plans in this file are based on examples listed on http://www.cloudsigma
-# .com/en/pricing/price-schedules
-INSTANCE_TYPES = {
-    'micro-regular': {
-        'id': 'micro-regular',
-        'name': 'Micro/Regular instance',
-        'cpu': 1100,
-        'memory': 640,
-        'disk': 10,
-        'bandwidth': None,
-    },
-    'micro-high-cpu': {
-        'id': 'micro-high-cpu',
-        'name': 'Micro/High CPU instance',
-        'cpu': 2200,
-        'memory': 640,
-        'disk': 80,
-        'bandwidth': None,
-    },
-    'standard-small': {
-        'id': 'standard-small',
-        'name': 'Standard/Small instance',
-        'cpu': 1100,
-        'memory': 1741,
-        'disk': 50,
-        'bandwidth': None,
-    },
-    'standard-large': {
-        'id': 'standard-large',
-        'name': 'Standard/Large instance',
-        'cpu': 4400,
-        'memory': 7680,
-        'disk': 250,
-        'bandwidth': None,
-    },
-    'standard-extra-large': {
-        'id': 'standard-extra-large',
-        'name': 'Standard/Extra Large instance',
-        'cpu': 8800,
-        'memory': 15360,
-        'disk': 500,
-        'bandwidth': None,
-    },
-    'high-memory-extra-large': {
-        'id': 'high-memory-extra-large',
-        'name': 'High Memory/Extra Large instance',
-        'cpu': 7150,
-        'memory': 17510,
-        'disk': 250,
-        'bandwidth': None,
-    },
-    'high-memory-double-extra-large': {
-        'id': 'high-memory-double-extra-large',
-        'name': 'High Memory/Double Extra Large instance',
-        'cpu': 14300,
-        'memory': 32768,
-        'disk': 500,
-        'bandwidth': None,
-    },
-    'high-cpu-medium': {
-        'id': 'high-cpu-medium',
-        'name': 'High CPU/Medium instance',
-        'cpu': 5500,
-        'memory': 1741,
-        'disk': 150,
-        'bandwidth': None,
-    },
-    'high-cpu-extra-large': {
-        'id': 'high-cpu-extra-large',
-        'name': 'High CPU/Extra Large instance',
-        'cpu': 20000,
-        'memory': 7168,
-        'disk': 500,
-        'bandwidth': None,
-    }
-}
-
-NODE_STATE_MAP = {
-    'active': NodeState.RUNNING,
-    'stopped': NodeState.TERMINATED,
-    'dead': NodeState.TERMINATED,
-    'dumped': NodeState.TERMINATED,
-}
-
-# Default timeout (in seconds) for the drive imaging process
-IMAGING_TIMEOUT = 20 * 60
+    def __new__(cls, key, secret=None, secure=True, host=None, port=None,
+                api_version=DEFAULT_API_VERSION, **kwargs):
+        if cls is CloudSigmaNodeDriver:
+            if api_version == '1.0':
+                cls = CloudSigma_1_0_NodeDriver
+            elif api_version == '2.0':
+                cls = CloudSigma_2_0_NodeDriver
+            else:
+                raise NotImplementedError('Unsupported API version: %s' %
+                                          (api_version))
+        return super(CloudSigmaNodeDriver, cls).__new__(cls)
 
 
 class CloudSigmaException(Exception):
@@ -152,23 +90,6 @@ class CloudSigmaInsufficientFundsException(Exception):
         return "<CloudSigmaInsufficientFundsException '%s'>" % (self.args[0])
 
 
-class CloudSigmaResponse(Response):
-    def success(self):
-        if self.status == 401:
-            raise InvalidCredsError()
-
-        return self.status >= 200 and self.status <= 299
-
-    def parse_body(self):
-        if not self.body:
-            return self.body
-
-        return str2dicts(self.body)
-
-    def parse_error(self):
-        return 'Error: %s' % (self.body.replace('errors:', '').strip())
-
-
 class CloudSigmaNodeSize(NodeSize):
     def __init__(self, id, name, cpu, ram, disk, bandwidth, price, driver):
         self.id = id
@@ -187,9 +108,26 @@ class CloudSigmaNodeSize(NodeSize):
                    self.bandwidth, self.price, self.driver.name))
 
 
-class CloudSigmaBaseConnection(ConnectionUserAndKey):
-    host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host']
-    responseCls = CloudSigmaResponse
+class CloudSigma_1_0_Response(Response):
+    def success(self):
+        if self.status == httplib.UNAUTHORIZED:
+            raise InvalidCredsError()
+
+        return self.status >= 200 and self.status <= 299
+
+    def parse_body(self):
+        if not self.body:
+            return self.body
+
+        return str2dicts(self.body)
+
+    def parse_error(self):
+        return 'Error: %s' % (self.body.replace('errors:', '').strip())
+
+
+class CloudSigma_1_0_Connection(ConnectionUserAndKey):
+    host = API_ENDPOINTS_1_0[DEFAULT_REGION]['host']
+    responseCls = CloudSigma_1_0_Response
 
     def add_default_headers(self, headers):
         headers['Accept'] = 'application/json'
@@ -200,11 +138,35 @@ class CloudSigmaBaseConnection(ConnectionUserAndKey):
         return headers
 
 
-class CloudSigmaBaseNodeDriver(NodeDriver):
+class CloudSigma_1_0_NodeDriver(CloudSigmaNodeDriver):
     type = Provider.CLOUDSIGMA
-    name = 'CloudSigma'
+    name = 'CloudSigma (API v1.0)'
     website = 'http://www.cloudsigma.com/'
-    connectionCls = CloudSigmaBaseConnection
+    connectionCls = CloudSigma_1_0_Connection
+
+    IMAGING_TIMEOUT = 20 * 60  # Default timeout (in seconds) for the drive
+                               # imaging process
+
+    NODE_STATE_MAP = {
+        'active': NodeState.RUNNING,
+        'stopped': NodeState.TERMINATED,
+        'dead': NodeState.TERMINATED,
+        'dumped': NodeState.TERMINATED,
+    }
+
+    def __init__(self, key, secret=None, secure=True, host=None, port=None,
+                 region=DEFAULT_REGION, **kwargs):
+        if region not in API_ENDPOINTS_1_0:
+            raise ValueError('Invalid region: %s' % (region))
+
+        self._host_argument_set = host is not None
+        self.api_name = 'cloudsigma_%s' % (region)
+        super(CloudSigma_1_0_NodeDriver, self).__init__(key=key, secret=secret,
+                                                        secure=secure,
+                                                        host=host,
+                                                        port=port,
+                                                        region=region,
+                                                        **kwargs)
 
     def reboot_node(self, node):
         """
@@ -280,7 +242,8 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
 
     def list_sizes(self, location=None):
         sizes = []
-        for key, value in INSTANCE_TYPES.items():
+        for value in INSTANCE_TYPES:
+            key = value['id']
             size = CloudSigmaNodeSize(id=value['id'], name=value['name'],
                                       cpu=value['cpu'], ram=value['memory'],
                                       disk=value['disk'],
@@ -360,7 +323,8 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
             response = self.connection.request(
                 action='/drives/%s/info' % (drive_uuid)).object
             elapsed_time = time.time() - imaging_start
-            if 'imaging' in response[0] and elapsed_time >= IMAGING_TIMEOUT:
+            timed_out = elapsed_time >= self.IMAGING_TIMEOUT
+            if 'imaging' in response[0] and timed_out:
                 raise CloudSigmaException('Drive imaging timed out')
             time.sleep(1)
 
@@ -400,7 +364,7 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
         Destroy a node and all the drives associated with it.
 
         :param      node: Node which should be used
-        :type       node: :class:`Node`
+        :type       node: :class:`libcloud.compute.base.Node`
 
         :rtype: ``bool``
         """
@@ -497,7 +461,7 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
         Changing most of the parameters requires node to be stopped.
 
         :param      node: Node which should be used
-        :type       node: :class:`Node`
+        :type       node: :class:`libcloud.compute.base.Node`
 
         :param      kwargs: keyword arguments
         :type       kwargs: ``dict``
@@ -539,7 +503,7 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
         Start a node.
 
         :param      node: Node which should be used
-        :type       node: :class:`Node`
+        :type       node: :class:`libcloud.compute.base.Node`
 
         :rtype: ``bool``
         """
@@ -554,7 +518,7 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
         Stop (shutdown) a node.
 
         :param      node: Node which should be used
-        :type       node: :class:`Node`
+        :type       node: :class:`libcloud.compute.base.Node`
 
         :rtype: ``bool``
         """
@@ -585,10 +549,20 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
             method='POST')
         return response.status == 204
 
+    def _ex_connection_class_kwargs(self):
+        """
+        Return the host value based on the user supplied region.
+        """
+        kwargs = {}
+        if not self._host_argument_set:
+            kwargs['host'] = API_ENDPOINTS_1_0[self.region]['host']
+
+        return kwargs
+
     def _to_node(self, data):
         if data:
             try:
-                state = NODE_STATE_MAP[data['status']]
+                state = self.NODE_STATE_MAP[data['status']]
             except KeyError:
                 state = NodeState.UNKNOWN
 
@@ -651,14 +625,14 @@ class CloudSigmaBaseNodeDriver(NodeDriver):
         return result[0]
 
 
-class CloudSigmaZrhConnection(CloudSigmaBaseConnection):
+class CloudSigmaZrhConnection(CloudSigma_1_0_Connection):
     """
     Connection class for the CloudSigma driver for the Zurich end-point
     """
-    host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host']
+    host = API_ENDPOINTS_1_0['zrh']['host']
 
 
-class CloudSigmaZrhNodeDriver(CloudSigmaBaseNodeDriver):
+class CloudSigmaZrhNodeDriver(CloudSigma_1_0_NodeDriver):
     """
     CloudSigma node driver for the Zurich end-point
     """
@@ -666,16 +640,1281 @@ class CloudSigmaZrhNodeDriver(CloudSigmaBaseNodeDriver):
     api_name = 'cloudsigma_zrh'
 
 
-class CloudSigmaLvsConnection(CloudSigmaBaseConnection):
+class CloudSigmaLvsConnection(CloudSigma_1_0_Connection):
     """
     Connection class for the CloudSigma driver for the Las Vegas end-point
     """
-    host = API_ENDPOINTS['lvs']['host']
+    host = API_ENDPOINTS_1_0['lvs']['host']
 
 
-class CloudSigmaLvsNodeDriver(CloudSigmaBaseNodeDriver):
+class CloudSigmaLvsNodeDriver(CloudSigma_1_0_NodeDriver):
     """
     CloudSigma node driver for the Las Vegas end-point
     """
     connectionCls = CloudSigmaLvsConnection
     api_name = 'cloudsigma_lvs'
+
+
+class CloudSigmaError(ProviderError):
+    """
+    Represents CloudSigma API error.
+    """
+
+    def __init__(self, http_code, error_type, error_msg, error_point, driver):
+        """
+        :param http_code: HTTP status code.
+        :type http_code: ``int``
+
+        :param error_type: Type of error (validation / notexist / backend /
+                           permissions  database / concurrency / billing /
+                           payment)
+        :type error_type: ``str``
+
+        :param error_msg: A description of the error that occurred.
+        :type error_msg: ``str``
+
+        :param error_point: Point at which the error occured. Can be None.
+        :type error_point: ``str`` or ``None``
+        """
+        super(CloudSigmaError, self).__init__(http_code=http_code,
+                                              value=error_msg, driver=driver)
+        self.error_type = error_type
+        self.error_msg = error_msg
+        self.error_point = error_point
+
+
+class CloudSigmaSubscription(object):
+    """
+    Represents CloudSigma subscription.
+    """
+
+    def __init__(self, id, resource, amount, period, status, price, start_time,
+                 end_time):
+        """
+        :param id: Subscription ID.
+        :type id: ``str``
+
+        :param resource: Resource (e.g vlan, ip, etc.).
+        :type resource: ``str``
+
+        :param period: Subscription period.
+        :type period: ``str``
+
+        :param status: Subscription status (active / inactive).
+        :type status: ``str``
+
+        :param price: Subscription price.
+        :type price: ``str``
+
+        :param start_time: Start time for this subscription.
+        :type start_time: ``datetime.datetime``
+
+        :param end_time: End time for this subscription.
+        :type end_time: ``datetime.datetime``
+        """
+        self.id = id
+        self.resource = resource
+        self.amount = amount
+        self.period = period
+        self.status = status
+        self.price = price
+        self.start_time = start_time
+        self.end_time = end_time
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        return ('<CloudSigmaSubscription id=%s, resource=%s, amount=%s>' %
+                (self.id, self.resource, self.amount))
+
+
+class CloudSigmaTag(object):
+    """
+    Represents a CloudSigma tag object.
+    """
+
+    def __init__(self, id, name, resources=None):
+        """
+        :param id: Tag ID.
+        :type id: ``str``
+
+        :param name: Tag name.
+        :type name: ``str``
+
+        :param resource: IDs of resources which are associated with this tag.
+        :type resources: ``list`` of ``str``
+        """
+        self.id = id
+        self.name = name
+        self.resources = resources if resources else []
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        return ('<CloudSigmaTag id=%s, name=%s, resources=%s>' %
+                (self.id, self.name, repr(self.resources)))
+
+
+class CloudSigmaDrive(NodeImage):
+    """
+    Represents a CloudSigma drive.
+    """
+
+    def __init__(self, id, name, size, media, status, driver, extra=None):
+        """
+        :param id: Drive ID.
+        :type id: ``str``
+
+        :param name: Drive name.
+        :type name: ``str``
+
+        :param size: Drive size (in bytes).
+        :type size: ``int``
+
+        :param media: Drive media (cdrom / disk).
+        :type media: ``str``
+
+        :param status: Drive status (unmounted / mounted).
+        :type status: ``str``
+        """
+        super(CloudSigmaDrive, self).__init__(id=id, name=name, driver=driver,
+                                              extra=extra)
+        self.size = size
+        self.media = media
+        self.status = status
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        return (('<CloudSigmaSize id=%s, name=%s size=%s, media=%s, '
+                'status=%s>') %
+                (self.id, self.name, self.size, self.media, self.status))
+
+
+class CloudSigmaFirewallPolicy(object):
+    """
+    Represents a CloudSigma firewall policy.
+    """
+
+    def __init__(self, id, name, rules):
+        """
+        :param id: Policy ID.
+        :type id: ``str``
+
+        :param name: Policy name.
+        :type name: ``str``
+
+        :param rules: Rules associated with this policy.
+        :type rules: ``list`` of :class:`.CloudSigmaFirewallPolicyRule` objects
+        """
+        self.id = id
+        self.name = name
+        self.rules = rules if rules else []
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        return (('<CloudSigmaFirewallPolicy id=%s, name=%s rules=%s>') %
+                (self.id, self.name, repr(self.rules)))
+
+
+class CloudSigmaFirewallPolicyRule(object):
+    """
+    Represents a CloudSigma firewall policy rule.
+    """
+
+    def __init__(self, action, direction, ip_proto=None, src_ip=None,
+                 src_port=None, dst_ip=None, dst_port=None, comment=None):
+        """
+        :param action: Action (drop / accept).
+        :type action: ``str``
+
+        :param direction: Rule direction (in / out / both)>
+        :type direction: ``str``
+
+        :param ip_proto: IP protocol (tcp / udp).
+        :type ip_proto: ``str``.
+
+        :param src_ip: Source IP in CIDR notation.
+        :type src_ip: ``str``
+
+        :param src_port: Source port or a port range.
+        :type src_port: ``str``
+
+        :param dst_ip: Destination IP in CIDR notation.
+        :type dst_ip: ``str``
+
+        :param src_port: Destination port or a port range.
+        :type src_port: ``str``
+
+        :param comment: Comment associated with the policy.
+        :type comment: ``str``
+        """
+        self.action = action
+        self.direction = direction
+        self.ip_proto = ip_proto
+        self.src_ip = src_ip
+        self.src_port = src_port
+        self.dst_ip = dst_ip
+        self.dst_port = dst_port
+        self.comment = comment
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        return (('<CloudSigmaFirewallPolicyRule action=%s, direction=%s>') %
+                (self.action, self.direction))
+
+
+class CloudSigma_2_0_Response(JsonResponse):
+    success_status_codes = [
+        httplib.OK,
+        httplib.ACCEPTED,
+        httplib.NO_CONTENT,
+        httplib.CREATED
+    ]
+
+    def success(self):
+        return self.status in self.success_status_codes
+
+    def parse_error(self):
+        if int(self.status) == httplib.UNAUTHORIZED:
+            raise InvalidCredsError('Invalid credentials')
+
+        body = self.parse_body()
+        errors = self._parse_errors_from_body(body=body)
+
+        if errors:
+            # Throw first error
+            raise errors[0]
+
+        return body
+
+    def _parse_errors_from_body(self, body):
+        """
+        Parse errors from the response body.
+
+        :return: List of error objects.
+        :rtype: ``list`` of :class:`.CloudSigmaError` objects
+        """
+        errors = []
+
+        if not isinstance(body, list):
+            return None
+
+        for item in body:
+            if not 'error_type' in item:
+                # Unrecognized error
+                continue
+
+            error = CloudSigmaError(http_code=self.status,
+                                    error_type=item['error_type'],
+                                    error_msg=item['error_message'],
+                                    error_point=item['error_point'],
+                                    driver=self.connection.driver)
+            errors.append(error)
+
+        return errors
+
+
+class CloudSigma_2_0_Connection(ConnectionUserAndKey):
+    host = API_ENDPOINTS_2_0[DEFAULT_REGION]['host']
+    responseCls = CloudSigma_2_0_Response
+    api_prefix = '/api/2.0'
+
+    def add_default_headers(self, headers):
+        headers['Accept'] = 'application/json'
+        headers['Content-Type'] = 'application/json'
+
+        headers['Authorization'] = 'Basic %s' % (base64.b64encode(
+            b('%s:%s' % (self.user_id, self.key))).decode('utf-8'))
+        return headers
+
+    def encode_data(self, data):
+        data = json.dumps(data)
+        return data
+
+    def request(self, action, params=None, data=None, headers=None,
+                method='GET', raw=False):
+        params = params or {}
+        action = self.api_prefix + action
+
+        if method == 'GET':
+            params['limit'] = 0  # we want all the items back
+
+        return super(CloudSigma_2_0_Connection, self).request(action=action,
+                                                              params=params,
+                                                              data=data,
+                                                              headers=headers,
+                                                              method=method,
+                                                              raw=raw)
+
+
+class CloudSigma_2_0_NodeDriver(CloudSigmaNodeDriver):
+    """
+    Driver for CloudSigma API v2.0.
+    """
+    name = 'CloudSigma (API v2.0)'
+    api_name = 'cloudsigma_zrh'
+    website = 'http://www.cloudsigma.com/'
+    connectionCls = CloudSigma_2_0_Connection
+
+    DRIVE_TRANSITION_TIMEOUT = 500  # Default drive transition timeout in
+                                    # seconds
+    DRIVE_TRANSITION_SLEEP_INTERVAL = 5  # How long to sleep between different
+                                         # polling periods while waiting for
+                                         # drive transition
+
+    NODE_STATE_MAP = {
+        'starting': NodeState.PENDING,
+        'stopping': NodeState.PENDING,
+        'unavailable': NodeState.PENDING,
+        'running': NodeState.RUNNING,
+        'stopped': NodeState.STOPPED,
+        'paused': NodeState.STOPPED
+    }
+
+    def __init__(self, key, secret, secure=True, host=None, port=None,
+                 region=DEFAULT_REGION, **kwargs):
+        if not region in API_ENDPOINTS_2_0:
+            raise ValueError('Invalid region: %s' % (region))
+
+        if not secure:
+            # CloudSigma drive uses Basic Auth authentication and we don't want
+            # to allow user to accidentally send credentials over the wire in
+            # plain-text
+            raise ValueError('CloudSigma driver only supports a '
+                             'secure connection')
+
+        self._host_argument_set = host is not None
+        super(CloudSigma_2_0_NodeDriver, self).__init__(key=key, secret=secret,
+                                                        secure=secure,
+                                                        host=host, port=port,
+                                                        region=region,
+                                                        **kwargs)
+
+    def list_nodes(self, ex_tag=None):
+        """
+        List available nodes.
+
+        :param ex_tag: If specified, only return servers tagged with the
+                       provided tag.
+        :type ex_tag: :class:`CloudSigmaTag`
+        """
+        if ex_tag:
+            action = '/tags/%s/servers/detail/' % (ex_tag.id)
+        else:
+            action = '/servers/detail/'
+
+        response = self.connection.request(action=action, method='GET').object
+        nodes = [self._to_node(data=item) for item in response['objects']]
+        return nodes
+
+    def list_sizes(self):
+        """
+        List available sizes.
+        """
+        sizes = []
+        for value in INSTANCE_TYPES:
+            key = value['id']
+            size = CloudSigmaNodeSize(id=value['id'], name=value['name'],
+                                      cpu=value['cpu'], ram=value['memory'],
+                                      disk=value['disk'],
+                                      bandwidth=value['bandwidth'],
+                                      price=self._get_size_price(size_id=key),
+                                      driver=self.connection.driver)
+            sizes.append(size)
+
+        return sizes
+
+    def list_images(self):
+        """
+        Return a list of available pre-installed library drives.
+
+        Note: If you want to list all the available images and drives, use
+        :meth:`ex_list_drives` method.
+        """
+        response = self.connection.request(action='/libdrives/').object
+        images = [self._to_image(data=item) for item in response['objects']]
+
+        # We filter out non pre-installed library drives by defafault because
+        # they can't be used directly following a default Libcloud server
+        # creation flow.
+        images = [image for image in images if
+                  image.extra['image_type'] == 'preinst']
+        return images
+
+    def create_node(self, name, size, image, ex_metadata=None,
+                    ex_vnc_password=None, ex_avoid=None):
+        """
+        Create a new server.
+
+        Server creation consists of 4 separate steps:
+
+        1. Clone provided library drive so we can use it
+        2. Resize cloned drive to the desired size
+        3. Create a server and attach cloned drive
+        4. Start a server.
+
+        :param ex_metadata: Key / value pairs to associate with the
+                            created node. (optional)
+        :type ex_metadata: ``dict``
+
+        :param ex_vnc_password: Password to use for VNC access. If not
+                                provided, random password is generated.
+        :type ex_vnc_password: ``str``
+
+        :param ex_avoid: A list of server UUIDs to avoid when starting this
+                         node. (optional)
+        :type ex_avoid: ``list``
+        """
+        # Only pre-installed images can be used with create_node
+
+        if ex_vnc_password:
+            vnc_password = ex_vnc_password
+        else:
+            # VNC password is not provided, generate a random one.
+            vnc_password = get_secure_random_string(size=12)
+
+        drive_name = '%s-drive' % (name)
+        drive_size = (size.disk * 1024 * 1024 * 1024)  # size is specified in
+                                                       # GB
+
+        # 1. Clone library drive so we can use it
+        drive = self.ex_clone_drive(drive=image, name=drive_name)
+
+        # Wait for drive clone to finish
+        drive = self._wait_for_drive_state_transition(drive=drive,
+                                                      state='unmounted')
+
+        # 2. Resize drive to the desired disk size if the desired disk size is
+        # larger than the cloned drive size.
+        if drive_size > drive.size:
+            drive = self.ex_resize_drive(drive=drive, size=drive_size)
+
+        # Wait for drive resize to finish
+        drive = self._wait_for_drive_state_transition(drive=drive,
+                                                      state='unmounted')
+
+        # 3. Create server and attach cloned drive
+        # ide 0:0
+        data = {}
+        data['name'] = name
+        data['cpu'] = size.cpu
+        data['mem'] = (size.ram * 1024 * 1024)
+        data['vnc_password'] = vnc_password
+
+        if ex_metadata:
+            data['meta'] = ex_metadata
+
+        data['drives'] = [
+            {
+                'boot_order': 1,
+                'dev_channel': '0:0',
+                'device': 'ide',
+                'drive': drive.id
+            }
+        ]
+
+        action = '/servers/'
+        response = self.connection.request(action=action, method='POST',
+                                           data=data)
+        node = self._to_node(response.object['objects'][0])
+
+        # 4. Start server
+        self.ex_start_node(node=node, ex_avoid=ex_avoid)
+
+        return node
+
+    def destroy_node(self, node):
+        """
+        Destroy the node and all the associated drives.
+
+        :return: ``True`` on success, ``False`` otherwise.
+        :rtype: ``bool``
+        """
+        action = '/servers/%s/' % (node.id)
+        params = {'recurse': 'all_drives'}
+        response = self.connection.request(action=action, method='DELETE',
+                                           params=params)
+        return response.status == httplib.NO_CONTENT
+
+    # Server extension methods
+
+    def ex_edit_node(self, node, params):
+        """
+        Edit a node.
+
+        :param node: Node to edit.
+        :type node: :class:`libcloud.compute.base.Node`
+
+        :param params: Node parameters to update.
+        :type params: ``dict``
+
+        :return Edited node.
+        :rtype: :class:`libcloud.compute.base.Node`
+        """
+        data = {}
+
+        # name, cpu, mem and vnc_password attributes must always be present so
+        # we just copy them from the to-be-edited node
+        data['name'] = node.name
+        data['cpu'] = node.extra['cpu']
+        data['mem'] = node.extra['mem']
+        data['vnc_password'] = node.extra['vnc_password']
+
+        nics = copy.deepcopy(node.extra.get('nics', []))
+
+        data['nics'] = nics
+
+        data.update(params)
+
+        action = '/servers/%s/' % (node.id)
+        response = self.connection.request(action=action, method='PUT',
+                                           data=data).object
+        node = self._to_node(data=response)
+        return node
+
+    def ex_start_node(self, node, ex_avoid=None):
+        """
+        Start a node.
+
+        :param node: Node to start.
+        :type node: :class:`libcloud.compute.base.Node`
+
+        :param ex_avoid: A list of other server uuids to avoid when
+                         starting this node. If provided, node will
+                         attempt to be started on a different
+                         physical infrastructure from other servers
+                         specified using this argument. (optional)
+        :type ex_avoid: ``list``
+        """
+        params = {}
+
+        if ex_avoid:
+            params['avoid'] = ','.join(ex_avoid)
+
+        path = '/servers/%s/action/' % (node.id)
+        response = self._perform_action(path=path, action='start',
+                                        params=params,
+                                        method='POST')
+        return response.status == httplib.ACCEPTED
+
+    def ex_stop_node(self, node):
+        """
+        Stop a node.
+        """
+        path = '/servers/%s/action/' % (node.id)
+        response = self._perform_action(path=path, action='stop',
+                                        method='POST')
+        return response.status == httplib.ACCEPTED
+
+    def ex_clone_node(self, node, name=None, random_vnc_password=None):
+        """
+        Clone the provided node.
+
+        :param name: Optional name for the cloned node.
+        :type name: ``str``
+        :param random_vnc_password: If True, a new random VNC password will be
+                                    generated for the cloned node. Otherwise
+                                    password from the cloned node will be
+                                    reused.
+        :type random_vnc_password: ``bool``
+
+        :return: Cloned node.
+        :rtype: :class:`libcloud.compute.base.Node`
+        """
+        data = {}
+
+        data['name'] = name
+        data['random_vnc_password'] = random_vnc_password
+
+        path = '/servers/%s/action/' % (node.id)
+        response = self._perform_action(path=path, action='clone',
+                                        method='POST', data=data).object
+        node = self._to_node(data=response)
+        return node
+
+    def ex_open_vnc_tunnel(self, node):
+        """
+        Open a VNC tunnel to the provided node and return the VNC url.
+
+        :param node: Node to open the VNC tunnel to.
+        :type node: :class:`libcloud.compute.base.Node`
+
+        :return: URL of the opened VNC tunnel.
+        :rtype: ``str``
+        """
+        path = '/servers/%s/action/' % (node.id)
+        response = self._perform_action(path=path, action='open_vnc',
+                                        method='POST').object
+        vnc_url = response['vnc_url']
+        return vnc_url
+
+    def ex_close_vnc_tunnel(self, node):
+        """
+        Close a VNC server to the provided node.
+
+        :param node: Node to close the VNC tunnel to.
+        :type node: :class:`libcloud.compute.base.Node`
+
+        :return: ``True`` on success, ``False`` otherwise.
+        :rtype: ``bool``
+        """
+        path = '/servers/%s/action/' % (node.id)
+        response = self._perform_action(path=path, action='close_vnc',
+                                        method='POST')
+        return response.status == httplib.ACCEPTED
+
+    # Drive extension methods
+
+    def ex_list_drives(self):
+        """
+        Return a list of all the available user's drives.
+
+        :rtype: ``list`` of :class:`.CloudSigmaDrive` objects
+        """
+        response = self.connection.request(action='/drives/detail/').object
+        drives = [self._to_drive(data=item) for item in response['objects']]
+        return drives
+
+    def ex_create_drive(self, name, size, media='disk'):
+        """
+        Create a new drive.
+
+        :param name: Drive name.
+        :type name: ``str``
+
+        :param size: Drive size in bytes.
+        :type size: ``int``
+
+        :param media: Drive media type (cdrom, disk).
+        :type media: ``str``
+        """
+        data = {
+            'name': name,
+            'size': size,
+            'media': media
+        }
+
+        action = '/drives/'
+        response = self.connection.request(action=action, method='POST',
+                                           data=data).object
+        drive = self._to_drive(data=response['objects'][0])
+        return drive
+
+    def ex_clone_drive(self, drive, name=None):
+        """
+        Clone a library or a standard drive.
+
+        :param drive: Drive to clone.
+        :type drive: :class:`libcloud.compute.base.NodeImage` or
+                     :class:`.CloudSigmaDrive`
+
+        :param name: Optional name for the cloned drive.
+        :type name: ``str``
+
+        :return: New cloned drive.
+        :rtype: :class:`.CloudSigmaDrive`
+        """
+        data = {}
+
+        if name:
+            data['name'] = name
+
+        path = '/drives/%s/action/' % (drive.id)
+        response = self._perform_action(path=path, action='clone',
+                                        method='POST', data=data)
+        drive = self._to_drive(data=response.object['objects'][0])
+        return drive
+
+    def ex_resize_drive(self, drive, size):
+        """
+        Resize a drive.
+
+        :param drive: Drive to resize.
+
+        :param size: New drive size in bytes.
+        :type size: ``int``
+
+        :return: Drive object which is being resized.
+        :rtype: :class:`.CloudSigmaDrive`
+        """
+        path = '/drives/%s/action/' % (drive.id)
+        data = {'name': drive.name, 'size': size, 'media': 'disk'}
+        response = self._perform_action(path=path, action='resize',
+                                        method='POST', data=data)
+
+        drive = self._to_drive(data=response.object['objects'][0])
+        return drive
+
+    def ex_attach_drive(self, node):
+        """
+        Attach a drive to the provided node.
+        """
+        # TODO
+        pass
+
+    def ex_get_drive(self, drive_id):
+        """
+        Retrieve information about a single drive.
+
+        :param drive_id: ID of the drive to retrieve.
+        :type drive_id: ``str``
+
+        :return: Drive object.
+        :rtype: :class:`.CloudSigmaDrive`
+        """
+        action = '/drives/%s/' % (drive_id)
+        response = self.connection.request(action=action).object
+        drive = self._to_drive(data=response)
+        return drive
+
+    # Firewall policies extension methods
+
+    def ex_list_firewall_policies(self):
+        """
+        List firewall policies.
+
+        :rtype: ``list`` of :class:`.CloudSigmaFirewallPolicy`
+        """
+        action = '/fwpolicies/detail/'
+        response = self.connection.request(action=action, method='GET').object
+        policies = [self._to_firewall_policy(data=item) for item
+                    in response['objects']]
+        return policies
+
+    def ex_create_firewall_policy(self, name, rules=None):
+        """
+        Create a firewall policy.
+
+        :param name: Policy name.
+        :type name: ``str``
+
+        :param rules: List of firewall policy rules to associate with this
+                      policy. (optional)
+        :type rules: ``list`` of ``dict``
+
+        :return: Created firewall policy object.
+        :rtype: :class:`.CloudSigmaFirewallPolicy`
+        """
+        data = {}
+        obj = {}
+        obj['name'] = name
+
+        if rules:
+            obj['rules'] = rules
+
+        data['objects'] = [obj]
+
+        action = '/fwpolicies/'
+        response = self.connection.request(action=action, method='POST',
+                                           data=data).object
+        policy = self._to_firewall_policy(data=response['objects'][0])
+        return policy
+
+    def ex_attach_firewall_policy(self, policy, node, nic_mac=None):
+        """
+        Attach firewall policy to a public NIC interface on the server.
+
+        :param policy: Firewall policy to attach.
+        :type policy: :class:`.CloudSigmaFirewallPolicy`
+
+        :param node: Node to attach policy to.
+        :type node: :class:`libcloud.compute.base.Node`
+
+        :param nic_mac: Optional MAC address of the NIC to add the policy to.
+                        If not specified, first public interface is used
+                        instead.
+        :type nic_mac: ``str``
+
+        :return: Node object to which the policy was attached to.
+        :rtype: :class:`libcloud.compute.base.Node`
+        """
+        nics = copy.deepcopy(node.extra.get('nics', []))
+
+        if nic_mac:
+            nic = [n for n in nics if n['mac'] == nic_mac]
+        else:
+            nic = nics
+
+        if len(nic) == 0:
+            raise ValueError('Cannot find the NIC interface to attach '
+                             'a policy to')
+
+        nic = nic[0]
+        nic['firewall_policy'] = policy.id
+
+        params = {'nics': nics}
+        node = self.ex_edit_node(node=node, params=params)
+        return node
+
+    def ex_delete_firewall_policy(self, policy):
+        """
+        Delete a firewall policy.
+
+        :param policy: Policy to delete to.
+        :type policy: :class:`.CloudSigmaFirewallPolicy`
+
+        :return: ``True`` on success, ``False`` otherwise.
+        :rtype: ``bool``
+        """
+        action = '/fwpolicies/%s/' % (policy.id)
+        response = self.connection.request(action=action, method='DELETE')
+        return response.status == httplib.NO_CONTENT
+
+    # Tag extension methods
+
+    def ex_list_tags(self):
+        """
+        List all the available tags.
+
+        :rtype: ``list`` of :class:`.CloudSigmaTag` objects
+        """
+        action = '/tags/detail/'
+        response = self.connection.request(action=action, method='GET').object
+        tags = [self._to_tag(data=item) for item in response['objects']]
+
+        return tags
+
+    def ex_get_tag(self, tag_id):
+        """
+        Retrieve a single tag.
+
+        :param id: ID of the tag to retrieve.
+        :type id: ``str``
+
+        :rtype: ``list`` of :class:`.CloudSigmaTag` objects
+        """
+        action = '/tags/%s/' % (tag_id)
+        response = self.connection.request(action=action, method='GET').object
+        tag = self._to_tag(data=response)
+        return tag
+
+    def ex_create_tag(self, name, resource_uuids=None):
+        """
+        Create a tag.
+
+        :param name: Tag name.
+        :type name: ``str``
+
+        :param resource_uuids: Optional list of resource UUIDs to assign this
+                               tag go.
+        :type resource_uuids: ``list`` of ``str``
+
+        :return: Created tag object.
+        :rtype: :class:`.CloudSigmaTag`
+        """
+        data = {}
+        data['objects'] = [
+            {
+                'name': name
+            }
+        ]
+
+        if resource_uuids:
+            data['resources'] = resource_uuids
+
+        action = '/tags/'
+        response = self.connection.request(action=action, method='POST',
+                                           data=data).object
+        tag = self._to_tag(data=response['objects'][0])
+        return tag
+
+    def ex_tag_resource(self, resource, tag):
+        """
+        Associate tag with the provided resource.
+
+        :param resource: Resource to associate a tag with.
+        :type resource: :class:`libcloud.compute.base.Node` or
+                        :class:`.CloudSigmaDrive`
+
+        :param tag: Tag to associate with the resources.
+        :type tag: :class:`.CloudSigmaTag`
+
+        :return: Updated tag object.
+        :rtype: :class:`.CloudSigmaTag`
+        """
+        if not hasattr(resource, 'id'):
+            raise ValueError('Resource doesn\'t have id attribute')
+
+        return self.ex_tag_resources(resources=[resource], tag=tag)
+
+    def ex_tag_resources(self, resources, tag):
+        """
+        Associate tag with the provided resources.
+
+        :param resource: Resources to associate a tag with.
+        :type resource: ``list`` of :class:`libcloud.compute.base.Node` or
+                        :class:`.CloudSigmaDrive`
+
+        :param tag: Tag to associate with the resources.
+        :type tag: :class:`.CloudSigmaTag`
+
+        :return: Updated tag object.
+        :rtype: :class:`.CloudSigmaTag`
+        """
+
+        resources = tag.resources[:]
+
+        for resource in resources:
+            if not hasattr(resource, 'id'):
+                raise ValueError('Resource doesn\'t have id attribute')
+
+            resources.append(resource.id)
+
+        resources = list(set(resources))
+
+        data = {
+            'name': tag.name,
+            'resources': resources
+        }
+
+        action = '/tags/%s/' % (tag.id)
+        response = self.connection.request(action=action, method='PUT',
+                                           data=data).object
+        tag = self._to_tag(data=response)
+        return tag
+
+    def ex_delete_tag(self, tag):
+        """
+        Delete a tag.
+
+        :param tag: Tag to delete.
+        :type tag: :class:`.CloudSigmaTag`
+
+        :return: ``True`` on success, ``False`` otherwise.
+        :rtype: ``bool``
+        """
+        action = '/tags/%s/' % (tag.id)
+        response = self.connection.request(action=action, method='DELETE')
+        return response.status == httplib.NO_CONTENT
+
+    # Account extension methods
+
+    def ex_get_balance(self):
+        """
+        Retrueve account balance information.
+
+        :return: Dictionary with two items ("balance" and "currency").
+        :rtype: ``dict``
+        """
+        action = '/balance/'
+        response = self.connection.request(action=action, method='GET')
+        return response.object
+
+    def ex_get_pricing(self):
+        """
+        Retrive pricing information that are applicable to the cloud.
+
+        :return: Dictionary with pricing information.
+        :rtype: ``dict``
+        """
+        action = '/pricing/'
+        response = self.connection.request(action=action, method='GET')
+        return response.object
+
+    def ex_get_usage(self):
+        """
+        Retrieve account current usage information.
+
+        :return: Dictionary with two items ("balance" and "usage").
+        :rtype: ``dict``
+        """
+        action = '/currentusage/'
+        response = self.connection.request(action=action, method='GET')
+        return response.object
+
+    def ex_list_subscriptions(self, status='all', resources=None):
+        """
+        List subscriptions for this account.
+
+        :param status: Only return subscriptions with the provided status
+                       (optional).
+        :type status: ``str``
+        :param resources: Only return subscriptions for the provided resources
+                          (optional).
+        :type resources: ``list``
+
+        :rtype: ``list``
+        """
+        params = {}
+
+        if status:
+            params['status'] = status
+
+        if resources:
+            params['resource'] = ','.join(resources)
+
+        response = self.connection.request(action='/subscriptions/',
+                                           params=params).object
+        subscriptions = self._to_subscriptions(data=response)
+        return subscriptions
+
+    def ex_toggle_subscription_auto_renew(self, subscription):
+        """
+        Toggle subscription auto renew status.
+
+        :param subscription: Subscription to toggle the auto renew flag for.
+        :type subscription: :class:`.CloudSigmaSubscription`
+
+        :return: ``True`` on success, ``False`` otherwise.
+        :rtype: ``bool``
+        """
+        path = '/subscriptions/%s/action/' % (subscription.id)
+        response = self._perform_action(path=path, action='auto_renew',
+                                        method='POST')
+        return response.status == httplib.OK
+
+    # Misc extension methods
+
+    def ex_list_capabilities(self):
+        """
+        Retrieve all the basic and sensible limits of the API.
+
+        :rtype: ``dict``
+        """
+        action = '/capabilities/'
+        response = self.connection.request(action=action,
+                                           method='GET')
+        capabilities = response.object
+        return capabilities
+
+    def _parse_ips_from_nic(self, nic):
+        """
+        Parse private and public IP addresses from the provided network
+        interface object.
+
+        :param nic: NIC object.
+        :type nic: ``dict``
+
+        :return: (public_ips, private_ips) tuple.
+        :rtype: ``tuple``
+        """
+        public_ips, private_ips = [], []
+
+        ipv4_conf = nic['ip_v4_conf']
+        ipv6_conf = nic['ip_v6_conf']
+
+        ipv4 = ipv4_conf['ip'] if ipv4_conf else None
+        ipv6 = ipv6_conf['ip'] if ipv6_conf else None
+
+        ips = []
+
+        if ipv4:
+            ips.append(ipv4)
+
+        if ipv6:
+            ips.append(ipv6)
+
+        runtime = nic['runtime']
+
+        ip_v4 = runtime['ip_v4'] if nic['runtime'] else None
+        ip_v6 = runtime['ip_v6'] if nic['runtime'] else None
+
+        ipv4 = ip_v4['uuid'] if ip_v4 else None
+        ipv6 = ip_v4['uuid'] if ip_v6 else None
+
+        if ipv4:
+            ips.append(ipv4)
+
+        if ipv6:
+            ips.append(ipv6)
+
+        ips = set(ips)
+
+        for ip in ips:
+            if is_private_subnet(ip):
+                private_ips.append(ip)
+            else:
+                public_ips.append(ip)
+
+        return public_ips, private_ips
+
+    def _to_node(self, data):
+        extra_keys = ['cpu', 'mem', 'nics', 'vnc_password', 'meta']
+
+        id = data['uuid']
+        name = data['name']
+        state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN)
+
+        public_ips = []
+        private_ips = []
+        extra = self._extract_values(obj=data, keys=extra_keys)
+
+        for nic in data['nics']:
+            _public_ips, _private_ips = self._parse_ips_from_nic(nic=nic)
+
+            public_ips.extend(_public_ips)
+            private_ips.extend(_private_ips)
+
+        node = Node(id=id, name=name, state=state, public_ips=public_ips,
+                    private_ips=private_ips, driver=self, extra=extra)
+        return node
+
+    def _to_image(self, data):
+        extra_keys = ['description', 'arch', 'image_type', 'os', 'licenses',
+                      'media', 'meta']
+
+        id = data['uuid']
+        name = data['name']
+        extra = self._extract_values(obj=data, keys=extra_keys)
+
+        image = NodeImage(id=id, name=name, driver=self, extra=extra)
+        return image
+
+    def _to_drive(self, data):
+        id = data['uuid']
+        name = data['name']
+        size = data['size']
+        media = data['media']
+        status = data['status']
+        extra = {}
+
+        drive = CloudSigmaDrive(id=id, name=name, size=size, media=media,
+                                status=status, driver=self, extra=extra)
+
+        return drive
+
+    def _to_tag(self, data):
+        resources = data['resources']
+        resources = [resource['uuid'] for resource in resources]
+
+        tag = CloudSigmaTag(id=data['uuid'], name=data['name'],
+                            resources=resources)
+        return tag
+
+    def _to_subscriptions(self, data):
+        subscriptions = []
+
+        for item in data['objects']:
+            subscription = self._to_subscription(data=item)
+            subscriptions.append(subscription)
+
+        return subscriptions
+
+    def _to_subscription(self, data):
+        start_time = parse_date(data['start_time'])
+        end_time = parse_date(data['end_time'])
+
+        subscription = CloudSigmaSubscription(id=data['id'],
+                                              resource=data['resource'],
+                                              amount=data['amount'],
+                                              period=data['period'],
+                                              status=data['status'],
+                                              price=data['price'],
+                                              start_time=start_time,
+                                              end_time=end_time)
+        return subscription
+
+    def _to_firewall_policy(self, data):
+        rules = []
+
+        for item in data.get('rules', []):
+            rule = CloudSigmaFirewallPolicyRule(action=item['action'],
+                                                direction=item['direction'],
+                                                ip_proto=item['ip_proto'],
+                                                src_ip=item['src_ip'],
+                                                src_port=item['src_port'],
+                                                dst_ip=item['dst_ip'],
+                                                dst_port=item['dst_port'],
+                                                comment=item['comment'])
+            rules.append(rule)
+
+        policy = CloudSigmaFirewallPolicy(id=data['uuid'], name=data['name'],
+                                          rules=rules)
+        return policy
+
+    def _perform_action(self, path, action, method='POST', params=None,
+                        data=None):
+        """
+        Perform API action and return response object.
+        """
+        if params:
+            params = params.copy()
+        else:
+            params = {}
+
+        params['do'] = action
+        response = self.connection.request(action=path, method=method,
+                                           params=params, data=data)
+        return response
+
+    def _extract_values(self, obj, keys):
+        """
+        Extract values from a dictionary and return a new dictionary with
+        extracted values.
+
+        :param obj: Dictionary to extract values from.
+        :type obj: ``dict``
+
+        :param keys: Keys to extract.
+        :type keys: ``list``
+
+        :return: Dictionary with extracted values.
+        :rtype: ``dict``
+        """
+        result = {}
+
+        for key in keys:
+            result[key] = obj[key]
+
+        return result
+
+    def _wait_for_drive_state_transition(self, drive, state,
+                                         timeout=DRIVE_TRANSITION_TIMEOUT):
+        """
+        Wait for a drive to transition to the provided state.
+
+        Note: This function blocks and periodically calls "GET drive" endpoint
+        to check if the drive has already transitioned to the desired state.
+
+        :param drive: Drive to wait for.
+        :type drive: :class:`.CloudSigmaDrive`
+
+        :param state: Desired drive state.
+        :type state: ``str``
+
+        :param timeout: How long to wait for the transition (in seconds) before
+                        timing out.
+        :type timeout: ``int``
+
+        :return: Drive object.
+        :rtype: :class:`.CloudSigmaDrive`
+        """
+
+        start_time = time.time()
+
+        while drive.status != state:
+            drive = self.ex_get_drive(drive_id=drive.id)
+
+            if drive.status == state:
+                break
+
+            current_time = time.time()
+            delta = (current_time - start_time)
+
+            if delta >= timeout:
+                msg = ('Timed out while waiting for drive transition '
+                       '(timeout=%s seconds)' % (timeout))
+                raise Exception(msg)
+
+            time.sleep(self.DRIVE_TRANSITION_SLEEP_INTERVAL)
+
+        return drive
+
+    def _ex_connection_class_kwargs(self):
+        """
+        Return the host value based on the user supplied region.
+        """
+        kwargs = {}
+
+        if not self._host_argument_set:
+            kwargs['host'] = API_ENDPOINTS_2_0[self.region]['host']
+
+        return kwargs

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/compute/providers.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/providers.py b/libcloud/compute/providers.py
index 343a7f2..8cc5a3c 100644
--- a/libcloud/compute/providers.py
+++ b/libcloud/compute/providers.py
@@ -70,9 +70,7 @@ DRIVERS = {
     Provider.SERVERLOVE:
     ('libcloud.compute.drivers.serverlove', 'ServerLoveNodeDriver'),
     Provider.CLOUDSIGMA:
-    ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaZrhNodeDriver'),
-    Provider.CLOUDSIGMA_US:
-    ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaLvsNodeDriver'),
+    ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaNodeDriver'),
     Provider.GCE:
     ('libcloud.compute.drivers.gce', 'GCENodeDriver'),
     Provider.GOGRID:
@@ -141,6 +139,10 @@ DRIVERS = {
     ('libcloud.compute.drivers.exoscale', 'ExoscaleNodeDriver'),
     Provider.IKOULA:
     ('libcloud.compute.drivers.ikoula', 'IkoulaNodeDriver'),
+
+    # Deprecated
+    Provider.CLOUDSIGMA_US:
+    ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaLvsNodeDriver'),
 }
 
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/compute/types.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
index dc83a03..b736b2f 100644
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -104,7 +104,6 @@ class Provider(object):
     NINEFOLD = 'ninefold'
     TERREMARK = 'terremark'
     CLOUDSTACK = 'cloudstack'
-    CLOUDSIGMA_US = 'cloudsigma_us'
     LIBVIRT = 'libvirt'
     JOYENT = 'joyent'
     VCL = 'vcl'
@@ -139,6 +138,8 @@ class Provider(object):
     ELASTICHOSTS_AU1 = 'elastichosts_au1'
     ELASTICHOSTS_CN1 = 'elastichosts_cn1'
 
+    CLOUDSIGMA_US = 'cloudsigma_us'
+
     # Deprecated constants which aren't supported anymore
     RACKSPACE_UK = 'rackspace_uk'
     RACKSPACE_NOVA_BETA = 'rackspace_nova_beta'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json
new file mode 100644
index 0000000..8f86b06
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json
@@ -0,0 +1 @@
+{"balance": "10.00", "currency": "USD"}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json
new file mode 100644
index 0000000..62ee576
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json
@@ -0,0 +1,26 @@
+{
+    "drives": {
+        "dssd": {
+            "max_size": 8858013190752,
+            "min_size": 536870912
+        }
+    },
+    "servers": {
+        "cpu": {
+            "max": 80000,
+            "min": 250
+        },
+        "cpu_per_smp": {
+            "max": 2200,
+            "min": 1000
+        },
+        "mem": {
+            "max": 137438953472,
+            "min": 268435456
+        },
+        "smp": {
+            "max": 40,
+            "min": 1
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json
new file mode 100644
index 0000000..8d5af60
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json
@@ -0,0 +1,88 @@
+{
+    "balance": {
+        "balance": "378.74599035374868510600",
+        "currency": "USD"
+    },
+    "usage": {
+        "cpu": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "dssd": {
+            "burst": 13958643712,
+            "subscribed": 0,
+            "using": 13958643712
+        },
+        "ip": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "mem": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_7jq_00341": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_7nq_00302": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_lwa_00135": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_p71_01031": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_p73_04837": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_p73_04837_core": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_tfa_00009": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "msft_tfa_00523": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "sms": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "ssd": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        },
+        "tx": {
+            "burst": 0,
+            "subscribed": 5368709120,
+            "using": 0
+        },
+        "vlan": {
+            "burst": 0,
+            "subscribed": 0,
+            "using": 0
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json
new file mode 100644
index 0000000..5e2b6e2
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json
@@ -0,0 +1,29 @@
+{
+    "objects": [
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "cloned drive",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": null
+            },
+            "size": 2097152000,
+            "snapshots": [],
+            "status": "creating",
+            "storage_type": null,
+            "tags": [],
+            "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json
new file mode 100644
index 0000000..02c4b35
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json
@@ -0,0 +1,29 @@
+{
+    "objects": [
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "test drive 5",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": null
+            },
+            "size": 2097152000,
+            "snapshots": [],
+            "status": "creating",
+            "storage_type": null,
+            "tags": [],
+            "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913"
+        }
+    ]
+}


[3/7] Add a new driver, tests and documentation for CloudSigma API v2.0.

Posted by to...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json
new file mode 100644
index 0000000..8fe0d43
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json
@@ -0,0 +1,154 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 4
+    },
+    "objects": [
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {
+                "arch": "64",
+                "category": "general",
+                "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.",
+                "favourite": "False",
+                "image_type": "preinst",
+                "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will app
 ly the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n",
+                "os": "linux",
+                "paid": "False",
+                "url": "http://www.debian.org/"
+            },
+            "mounted_on": [],
+            "name": "test node 2-drive",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/9d1d2cf3-08c1-462f-8485-f4b073560809/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": "dssd"
+            },
+            "size": 13958643712,
+            "snapshots": [],
+            "status": "unmounted",
+            "storage_type": "dssd",
+            "tags": [],
+            "uuid": "9d1d2cf3-08c1-462f-8485-f4b073560809"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {
+                "arch": "64",
+                "category": "general",
+                "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.",
+                "favourite": "False",
+                "image_type": "preinst",
+                "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will app
 ly the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n",
+                "os": "linux",
+                "paid": "False",
+                "url": "http://www.debian.org/"
+            },
+            "mounted_on": [],
+            "name": "test node 3-drive",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/c9799969-0016-4298-a72c-93cabc067c6e/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": "dssd"
+            },
+            "size": 13958643712,
+            "snapshots": [],
+            "status": "unmounted",
+            "storage_type": "dssd",
+            "tags": [],
+            "uuid": "c9799969-0016-4298-a72c-93cabc067c6e"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {
+                "arch": "64",
+                "category": "general",
+                "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.",
+                "favourite": "False",
+                "image_type": "preinst",
+                "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will app
 ly the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n",
+                "os": "linux",
+                "paid": "False",
+                "url": "http://www.debian.org/"
+            },
+            "mounted_on": [],
+            "name": "test node 2-drive",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/967c8bbd-ca32-42db-a9b8-95e270e0aae1/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": "dssd"
+            },
+            "size": 13958643712,
+            "snapshots": [],
+            "status": "unmounted",
+            "storage_type": "dssd",
+            "tags": [],
+            "uuid": "967c8bbd-ca32-42db-a9b8-95e270e0aae1"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {
+                "arch": "64",
+                "category": "general",
+                "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.",
+                "favourite": "False",
+                "image_type": "preinst",
+                "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will app
 ly the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n",
+                "os": "linux",
+                "paid": "False",
+                "url": "http://www.debian.org/"
+            },
+            "mounted_on": [
+                {
+                    "resource_uri": "/api/2.0/servers/e06cf7b3-ea46-4d38-87e0-3f918c4648d3/",
+                    "uuid": "e06cf7b3-ea46-4d38-87e0-3f918c4648d3"
+                }
+            ],
+            "name": "test node 2-drive",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/3e166706-188c-4f38-b8d5-7fc10a5019a1/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": "dssd"
+            },
+            "size": 13958643712,
+            "snapshots": [],
+            "status": "mounted",
+            "storage_type": "dssd",
+            "tags": [],
+            "uuid": "3e166706-188c-4f38-b8d5-7fc10a5019a1"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json
new file mode 100644
index 0000000..3a68140
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json
@@ -0,0 +1,25 @@
+{
+    "affinities": [],
+    "allow_multimount": false,
+    "jobs": [],
+    "licenses": [],
+    "media": "disk",
+    "meta": {},
+    "mounted_on": [],
+    "name": "test drive 5",
+    "owner": {
+        "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+        "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+    },
+    "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/",
+    "runtime": {
+        "snapshots_allocated_size": 0,
+        "storage_type": null
+    },
+    "size": 2097152000,
+    "snapshots": [],
+    "status": "unmounted",
+    "storage_type": null,
+    "tags": [],
+    "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json
new file mode 100644
index 0000000..b3f45e0
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json
@@ -0,0 +1,29 @@
+{
+    "objects": [
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "test drive 5",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/",
+            "runtime": {
+                "snapshots_allocated_size": 0,
+                "storage_type": null
+            },
+            "size": 1164967936,
+            "snapshots": [],
+            "status": "creating",
+            "storage_type": null,
+            "tags": [],
+            "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json
new file mode 100644
index 0000000..3a437bb
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json
@@ -0,0 +1,16 @@
+{
+    "objects": [
+        {
+            "meta": {},
+            "name": "test policy 1",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/fwpolicies/ae9e5982-33fd-4e89-a467-4480256ccdb6/",
+            "rules": [],
+            "servers": [],
+            "uuid": "ae9e5982-33fd-4e89-a467-4480256ccdb6"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json
new file mode 100644
index 0000000..95e604b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json
@@ -0,0 +1,27 @@
+{
+    "objects": [
+        {
+            "meta": {},
+            "name": "test policy 2",
+            "owner": {
+                "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/",
+                "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d"
+            },
+            "resource_uri": "/api/2.0/fwpolicies/324819a5-7a5b-4231-957d-662a7429fb8c/",
+            "rules": [
+                {
+                    "action": "accept",
+                    "comment": null,
+                    "direction": "out",
+                    "dst_ip": "127.0.0.1/32",
+                    "dst_port": null,
+                    "ip_proto": "tcp",
+                    "src_ip": "127.0.0.1/32",
+                    "src_port": null
+                }
+            ],
+            "servers": [],
+            "uuid": "324819a5-7a5b-4231-957d-662a7429fb8c"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json
new file mode 100644
index 0000000..d34616b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json
@@ -0,0 +1,84 @@
+{
+    "meta": {
+        "limit": 0,
+        "offset": 0,
+        "total_count": 2
+    },
+    "objects": [
+        {
+            "meta": {},
+            "name": "test policy",
+            "owner": {
+                "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+            },
+            "resource_uri": "/api/2.0/fwpolicies/0e339282-0cb5-41ac-a9db-727fb62ff2dc/",
+            "rules": [],
+            "servers": [],
+            "uuid": "0e339282-0cb5-41ac-a9db-727fb62ff2dc"
+        },
+        {
+            "meta": {},
+            "name": "My awesome policy",
+            "owner": {
+                "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/",
+                "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23"
+            },
+            "resource_uri": "/api/2.0/fwpolicies/0c754845-f2ed-4347-8758-4315f7fa9c22/",
+            "rules": [
+                {
+                    "action": "drop",
+                    "comment": "Drop traffic from the VM to IP address 23.0.0.0/32",
+                    "direction": "out",
+                    "dst_ip": "23.0.0.0/32",
+                    "dst_port": null,
+                    "ip_proto": "tcp",
+                    "src_ip": null,
+                    "src_port": null
+                },
+                {
+                    "action": "accept",
+                    "comment": "Allow SSH traffic to the VM from our office in Dubai",
+                    "direction": "in",
+                    "dst_ip": null,
+                    "dst_port": "22",
+                    "ip_proto": "tcp",
+                    "src_ip": "172.66.32.0/24",
+                    "src_port": null
+                },
+                {
+                    "action": "drop",
+                    "comment": "Drop all other SSH traffic to the VM",
+                    "direction": "in",
+                    "dst_ip": null,
+                    "dst_port": "22",
+                    "ip_proto": "tcp",
+                    "src_ip": null,
+                    "src_port": null
+                },
+                {
+                    "action": "drop",
+                    "comment": "Drop all UDP traffic to the VM, not originating from 172.66.32.55",
+                    "direction": "in",
+                    "dst_ip": null,
+                    "dst_port": null,
+                    "ip_proto": "udp",
+                    "src_ip": "!172.66.32.55/32",
+                    "src_port": null
+                },
+                {
+                    "action": "drop",
+                    "comment": "Drop any traffic, to the VM with destination port not between 1-1024",
+                    "direction": "in",
+                    "dst_ip": null,
+                    "dst_port": "!1:1024",
+                    "ip_proto": "tcp",
+                    "src_ip": null,
+                    "src_port": null
+                }
+            ],
+            "servers": [],
+            "uuid": "0c754845-f2ed-4347-8758-4315f7fa9c22"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4d40ecd3/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json b/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json
new file mode 100644
index 0000000..c55e9a5
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json
@@ -0,0 +1,569 @@
+{
+    "meta": {
+        "limit": 20,
+        "offset": 0,
+        "total_count": 89
+    },
+    "objects": [
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "32",
+            "category": [
+                "security"
+            ],
+            "description": "IPCop 2.0.2 - i486 - CD.\r\nThe IPCop Firewall is a Linux firewall distribution.",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD.\\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive.\\n Please be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n \\n 3. Connecting to your server via VNC.\\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements.\\n The recommended minimum hardware requirements as publishes by ipcop.org are: 32MB RAM and 386MHz CPU \\n We recommend specifying a higher level of RAM for a better user experience.\\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "IPCop 2.0.2",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/6eca8d96-44bc-4637-af97-77ccd7ba4144/",
+            "size": 1000000000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.ipcop.org/",
+            "uuid": "6eca8d96-44bc-4637-af97-77ccd7ba4144"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "FreeBSD-8.4-RELEASE-amd64-disc1",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD.\\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \\n\r\n\\n\r\n2. Attach a Drive.\\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n\r\n\\n\r\n3. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n\\n\r\n4. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by freebsd.org are: 0.5 GB RAM and 0.5\\n GHz CPU We recommend specifying a higher level of RAM for a better user experience.\\n\r\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "FreeBSD 8.4",
+            "os": "other",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/c143724d-4d40-4871-bc2c-5120b4263ab3/",
+            "size": 536870912,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.freebsd.org/",
+            "uuid": "c143724d-4d40-4871-bc2c-5120b4263ab3"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "32",
+            "category": [
+                "general"
+            ],
+            "description": "Ubuntu 12.04 Desktop - 32bit - Install CD",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Ubuntu 12.04 Desktop",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/703e693e-056d-4cd6-9531-36ec045fee7c/",
+            "size": 1000000000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.ubuntu.com/",
+            "uuid": "703e693e-056d-4cd6-9531-36ec045fee7c"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "32",
+            "category": [
+                "general"
+            ],
+            "description": "Ubuntu 12.04 Server - 32bit - Install CD",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Ubuntu 12.04 Server",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/36b01118-55f4-454f-92ee-578eb6d99867/",
+            "size": 1000000000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.ubuntu.com/",
+            "uuid": "36b01118-55f4-454f-92ee-578eb6d99867"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Windows Server 2012 Standard - 64bit Install CD",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD \\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive \\n Please be aware that the minimum drive size where you are going to install the OS should be 32 GB. \\n \\n 3. Connecting to your server via VNC \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements \\n The recommended minimum hardware requirements as publishes by Microsoft can be found through the following link: http://msdn.microsoft.com/library/dn303418.aspx We recommend specifying a higher level of RAM for a better user experience. \\n \\n 5. Enter your license key. \\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Windows Server Standard 2012",
+            "os": "windows",
+            "owner": null,
+            "paid": true,
+            "resource_uri": "/api/2.0/libdrives/b4273b6d-b227-4966-9e6e-5d48cebfcaa5/",
+            "size": 3694116864,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.microsoft.com/",
+            "uuid": "b4273b6d-b227-4966-9e6e-5d48cebfcaa5"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "32",
+            "category": [
+                "general"
+            ],
+            "description": "Knoppix 6 - 32bit - CD",
+            "favourite": false,
+            "image_type": "live",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Knoppix.net are: 512MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Knoppix 6.4.3",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b/",
+            "size": 3670016000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://knoppix.net/",
+            "uuid": "ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "This image is produced by SixSq specifically to work with SlipStream.",
+            "favourite": false,
+            "image_type": "preinst",
+            "install_notes": "",
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "ubuntu-10.04-toMP",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/5236b9ee-f735-42fd-a236-17558f9e12d3/",
+            "size": 3221225472,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "5236b9ee-f735-42fd-a236-17558f9e12d3"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "CentOS 6.4 Server - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/30.",
+            "favourite": false,
+            "image_type": "preinst",
+            "install_notes": "1. Clone the Image.\\n\r\nThe image needs to be cloned and then attached to the server.\\n\r\n\\n\r\n2. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI.\\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window.\\n\r\nc) Start to configure your server.\\n\r\n\\n\r\n3. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by centos.org: 0.5GB RAM and 0.5GHz CPU\\n\r\n\\n\r\n4. Update your administrator password.\\n\r\nBy default and for security reasons \"root\" login is completely disabled (including for ssh)\\n\r\nUser \"cloudsigma\" with password \"cloudsigma\" is available for access.\\n\r\nPlease be aware that on the first login you will be asked to change the current password \"cloudsigma\" and set a secure password.\\n\r\nFor \"root\" please use the command \"sudo su\"\\n\r\n\\n\r\n5. 
 Setup your CentOS.\\n\r\n\\n\r\n6. Configuring your Networking.\\n\r\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will assign the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\\n\r\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs.\\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "CentOS 6.4 Server",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/cc08cd15-0c17-429f-bd56-15fefaca9d88/",
+            "size": 10737418240,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.centos.org/",
+            "uuid": "cc08cd15-0c17-429f-bd56-15fefaca9d88"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.",
+            "favourite": false,
+            "image_type": "preinst",
+            "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply t
 he same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Debian 6.0.7 Desktop",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/e848e216-76bb-4c1d-a376-54e4bdf54fe4/",
+            "size": 10737418240,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.debian.org/",
+            "uuid": "e848e216-76bb-4c1d-a376-54e4bdf54fe4"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "CentOS 6.3 - 64bit - DVD\r\n",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "CentOS 6.3 DVD",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/65c99e46-296c-4d3f-ad1f-88dc06772624/",
+            "size": 4289396736,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "65c99e46-296c-4d3f-ad1f-88dc06772624"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "CentOS 6.4 - 64bit - DVD\r\n",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the DVD. \\n\r\nPlease be aware that the DVD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5GB RAM and 0.5GHz CPU We recommend specifying a higher level of RAM for a better user experience.",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "CentOS 6.4 DVD",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/608e784a-5bff-4d25-afeb-bf7f998f56ef/",
+            "size": 4353392640,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "608e784a-5bff-4d25-afeb-bf7f998f56ef"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Ubuntu 10.04.3 LTS Server Edition 64bit - CD",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "\r\n1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu,com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Ubuntu 10.04.3 Server",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/b69cbf27-d2a8-44f7-bc5a-3facc70021a8/",
+            "size": 1000000000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://ubuntu.com/",
+            "uuid": "b69cbf27-d2a8-44f7-bc5a-3facc70021a8"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Slackware-13.37 - 64bit - Install DVD",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Slackware.com are: 128MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Slackware 13.37",
+            "os": "linux",
+            "owner": null,
+            "paid": true,
+            "resource_uri": "/api/2.0/libdrives/e209e588-8c06-44ce-8d57-c10df32c5876/",
+            "size": 4613734400,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "e209e588-8c06-44ce-8d57-c10df32c5876"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "32",
+            "category": [
+                "general"
+            ],
+            "description": "RedHat Enterprise 6.0 - 32bit - Install DVD",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by RedHat.com are: 2GB RAM and 2GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "RedHat Enterprise 6.0",
+            "os": "linux",
+            "owner": null,
+            "paid": true,
+            "resource_uri": "/api/2.0/libdrives/a0638d80-bc5b-48a3-a7ba-dec2416239bf/",
+            "size": 2936012800,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.redhat.com/",
+            "uuid": "a0638d80-bc5b-48a3-a7ba-dec2416239bf"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "CentOS 6.3 SlipStream.  This image is produced by SixSq specifically to work with SlipStream.",
+            "favourite": false,
+            "image_type": "preinst",
+            "install_notes": "CentOS 6.3 SlipStream",
+            "jobs": [],
+            "licenses": [],
+            "media": "disk",
+            "meta": {},
+            "mounted_on": [],
+            "name": "CentOS 6.3 for SlipStream",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/ac51c08f-d22b-4da8-9591-d343947f7455/",
+            "size": 7516192768,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "ac51c08f-d22b-4da8-9591-d343947f7455"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Debian 6 - 64bit - CD",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Debian 6",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/98f810a3-b8f0-4441-89cd-02be4f2614d7/",
+            "size": 676331520,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "98f810a3-b8f0-4441-89cd-02be4f2614d7"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Ubuntu 12.10 Server - 64bit - Install CD",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Ubuntu 12.10 Server",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/6afbda4b-1027-4405-9ae9-c7d32f097d31/",
+            "size": 1000000000,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.ubuntu.com/",
+            "uuid": "6afbda4b-1027-4405-9ae9-c7d32f097d31"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Debian 7.1 - 64bit - CD",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience.",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Debian 7.1",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/958bf26c-f25b-457d-aedb-a5cfb36bdeef/",
+            "size": 536870912,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "958bf26c-f25b-457d-aedb-a5cfb36bdeef"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "CentOS 6.2 - 64bit - DVD\r\n",
+            "favourite": false,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.\r\n",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "CentOS 6.2 DVD",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/d7cdd30f-2197-47ac-a878-c285c1e67426/",
+            "size": 4423139328,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "",
+            "uuid": "d7cdd30f-2197-47ac-a878-c285c1e67426"
+        },
+        {
+            "affinities": [],
+            "allow_multimount": false,
+            "arch": "64",
+            "category": [
+                "general"
+            ],
+            "description": "Debian 5.0 - 64bit - CD",
+            "favourite": true,
+            "image_type": "install",
+            "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ",
+            "jobs": [],
+            "licenses": [],
+            "media": "cdrom",
+            "meta": {},
+            "mounted_on": [],
+            "name": "Debian 5.0",
+            "os": "linux",
+            "owner": null,
+            "paid": false,
+            "resource_uri": "/api/2.0/libdrives/794a068d-228c-4758-81f0-e1bc955a6cce/",
+            "size": 4697620480,
+            "status": "unmounted",
+            "storage_type": null,
+            "tags": [],
+            "url": "http://www.debian.org/",
+            "uuid": "794a068d-228c-4758-81f0-e1bc955a6cce"
+        }
+    ]
+}


[6/7] git commit: * add to node['extra']['block_device_mapping'] volume_id\n* fix in volume['extra'] parameter device (was incorrect xpath)\n* fix tests for coverage this

Posted by to...@apache.org.
* add to node['extra']['block_device_mapping'] volume_id\n* fix in volume['extra'] parameter device (was incorrect xpath)\n* fix tests for coverage this

Signed-off-by: Tomaz Muraus <to...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/050de41a
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/050de41a
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/050de41a

Branch: refs/heads/trunk
Commit: 050de41aaf490421af9d253642130e083b57e417
Parents: d7bf122
Author: gigimon <gi...@gmail.com>
Authored: Wed Jan 29 16:57:26 2014 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Wed Jan 29 16:55:58 2014 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py   | 7 +++++--
 libcloud/test/compute/test_ec2.py | 4 ++++
 2 files changed, 9 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/050de41a/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 1eef018..f138f3d 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -527,6 +527,10 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
             'xpath': 'ebs/snapshotId',
             'transform_func': str
         },
+        'volume_id': {
+            'xpath': 'ebs/volumeId',
+            'transform_func': str
+        },
         'volume_size': {
             'xpath': 'ebs/volumeSize',
             'transform_func': int
@@ -908,7 +912,7 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
     },
     'volume': {
         'device': {
-            'xpath': 'device',
+            'xpath': 'attachmentSet/item/device',
             'transform_func': str
         },
         'iops': {
@@ -3519,7 +3523,6 @@ class BaseEC2NodeDriver(NodeDriver):
             value = findattr(element=element,
                              xpath=values['xpath'],
                              namespace=NAMESPACE)
-
             if value is not None:
                 extra[attribute] = transform_func(value)
             else:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/050de41a/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index 1dbd809..4d28faa 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -183,6 +183,9 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(node.extra['image_id'], 'ami-3215fe5a')
         self.assertEqual(len(node.extra['groups']), 2)
         self.assertEqual(len(node.extra['block_device_mapping']), 1)
+        self.assertEqual(node.extra['block_device_mapping'][0]['device_name'], '/dev/sda1')
+        self.assertEqual(node.extra['block_device_mapping'][0]['ebs']['volume_id'], 'vol-5e312311')
+        self.assertTrue(node.extra['block_device_mapping'][0]['ebs']['delete'])
 
         self.assertEqual(public_ips[0], '1.2.3.4')
 
@@ -741,6 +744,7 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(8, volumes[2].size)
         self.assertEqual('in-use', volumes[2].extra['state'])
         self.assertEqual('i-d334b4b3', volumes[2].extra['instance_id'])
+        self.assertEqual('/dev/sda1', volumes[2].extra['device'])
 
     def test_create_volume(self):
         location = self.driver.list_locations()[0]


[7/7] git commit: Update CHANGES.

Posted by to...@apache.org.
Update CHANGES.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/23c3b44f
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/23c3b44f
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/23c3b44f

Branch: refs/heads/trunk
Commit: 23c3b44f1a24ab7dd7d1b8daa4b4ee1e2d87fae2
Parents: 050de41
Author: Tomaz Muraus <to...@apache.org>
Authored: Wed Jan 29 16:58:14 2014 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Wed Jan 29 16:58:14 2014 +0100

----------------------------------------------------------------------
 CHANGES.rst | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/23c3b44f/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index d1e0259..27ee4c0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -13,6 +13,11 @@ Compute
 - Add a new driver for CloudSigma API v2.0.
   [Tomaz Muraus]
 
+- Add "volume_id" attribute to the Node "extra" dictionary in the EC2 driver.
+  Also fix the value of the "device" extra attribute in the StorageVolume
+  object. (LIBCLOUD-501)
+  [Oleg Suharev]
+
 Load Balancer
 ~~~~~~~~~~~~~
 


[5/7] git commit: Update CHANGES.

Posted by to...@apache.org.
Update CHANGES.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d7bf1225
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d7bf1225
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d7bf1225

Branch: refs/heads/trunk
Commit: d7bf1225d339bd1c3fe02b9c821a2982b4d14444
Parents: 4d40ecd
Author: Tomaz Muraus <to...@apache.org>
Authored: Wed Jan 29 16:53:16 2014 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Wed Jan 29 16:53:16 2014 +0100

----------------------------------------------------------------------
 CHANGES.rst | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d7bf1225/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index e6951e0..d1e0259 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,9 @@ Compute
 - Add new m3.medium and m3.large instance information to the EC2 driver.
   [Tomaz Muraus]
 
+- Add a new driver for CloudSigma API v2.0.
+  [Tomaz Muraus]
+
 Load Balancer
 ~~~~~~~~~~~~~