From 7e5699b984a56a7ffc506a97684a709738ae7045 Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Fri, 30 Jan 2015 22:29:54 +0000 Subject: [PATCH] [google compute] Add node stop/start support --- libcloud/compute/drivers/gce.py | 30 ++++++++++++ ...s_central1_a_instances_node_name_stop.json | 15 ++++++ ..._us_central1_a_instances_stopped_node.json | 48 +++++++++++++++++++ ...ntral1_a_instances_stopped_node_start.json | 15 ++++++ ...entral1_a_instances_stopped_node_stop.json | 15 ++++++ ...ral1_a_operations_operation_startnode.json | 15 ++++++ ...tral1_a_operations_operation_stopnode.json | 15 ++++++ libcloud/test/compute/test_gce.py | 39 +++++++++++++++ 8 files changed, 192 insertions(+) create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.json create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.json create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.json create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.json create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.json create mode 100644 libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.json diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py index 1778818343..1f29601a0d 100644 --- a/libcloud/compute/drivers/gce.py +++ b/libcloud/compute/drivers/gce.py @@ -3447,6 +3447,36 @@ def ex_destroy_network(self, network): self.connection.async_request(request, method='DELETE') return True + def ex_start_node(self, node): + """ + Start a node that is stopped and in TERMINATED state. + + :param node: Node object to start + :type node: :class:`Node` + + :return: True if successful + :rtype: ``bool`` + """ + request = '/zones/%s/instances/%s/start' % (node.extra['zone'].name, + node.name) + self.connection.async_request(request, method='POST') + return True + + def ex_stop_node(self, node): + """ + Stop a running node. + + :param node: Node object to stop + :type node: :class:`Node` + + :return: True if successful + :rtype: ``bool`` + """ + request = '/zones/%s/instances/%s/stop' % (node.extra['zone'].name, + node.name) + self.connection.async_request(request, method='POST') + return True + def destroy_node(self, node, destroy_boot_disk=False): """ Destroy a node. diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.json new file mode 100644 index 0000000000..e68e06ab20 --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.json @@ -0,0 +1,15 @@ +{ + "kind": "compute#operation", + "id": "18431811683007150988", + "name": "operation-stopnode", + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", + "operationType": "stop", + "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", + "targetId": "12335588484913203363", + "status": "PENDING", + "user": "erjohnso@google.com", + "progress": 0, + "insertTime": "2015-01-30T06:55:11.503-08:00", + "startTime": "2015-01-30T06:55:11.847-08:00", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" +} diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.json new file mode 100644 index 0000000000..a47c75f84a --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.json @@ -0,0 +1,48 @@ +{ + "canIpForward": false, + "creationTimestamp": "2013-12-13T10:45:23.351-08:00", + "disks": [ + { + "boot": true, + "deviceName": "persistent-disk-0", + "index": 0, + "kind": "compute#attachedDisk", + "mode": "READ_WRITE", + "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", + "type": "PERSISTENT" + } + ], + "id": "4006034190819017667", + "kind": "compute#instance", + "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", + "metadata": { + "fingerprint": "42WmSpB8rSM=", + "kind": "compute#metadata" + }, + "name": "stopped-node", + "networkInterfaces": [ + { + "accessConfigs": [ + { + "kind": "compute#accessConfig", + "name": "External NAT", + "natIP": "23.236.58.15", + "type": "ONE_TO_ONE_NAT" + } + ], + "name": "nic0", + "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", + "networkIP": "10.240.72.75" + } + ], + "scheduling": { + "automaticRestart": true, + "onHostMaintenance": "MIGRATE" + }, + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", + "status": "TERMINATED", + "tags": { + "fingerprint": "42WmSpB8rSM=" + }, + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" +} diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.json new file mode 100644 index 0000000000..d531709878 --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.json @@ -0,0 +1,15 @@ +{ + "kind": "compute#operation", + "id": "18431811683007150988", + "name": "operation-startnode", + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", + "operationType": "start", + "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", + "targetId": "12335588484913203363", + "status": "PENDING", + "user": "erjohnso@google.com", + "progress": 0, + "insertTime": "2015-01-30T06:55:11.503-08:00", + "startTime": "2015-01-30T06:55:11.847-08:00", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-startnode" +} diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.json new file mode 100644 index 0000000000..5febcc6f9d --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.json @@ -0,0 +1,15 @@ +{ + "kind": "compute#operation", + "id": "18431811683007150988", + "name": "operation-stopnode", + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", + "operationType": "stop", + "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", + "targetId": "12335588484913203363", + "status": "PENDING", + "user": "erjohnso@google.com", + "progress": 0, + "insertTime": "2015-01-30T06:55:11.503-08:00", + "startTime": "2015-01-30T06:55:11.847-08:00", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" +} diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.json new file mode 100644 index 0000000000..68276b208a --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.json @@ -0,0 +1,15 @@ +{ + "kind": "compute#operation", + "id": "18431811683007150988", + "name": "operation-startnode", + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", + "operationType": "start", + "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", + "targetId": "12335588484913203363", + "status": "DONE", + "user": "erjohnso@google.com", + "progress": 100, + "insertTime": "2015-01-30T06:55:11.503-08:00", + "startTime": "2015-01-30T06:55:11.847-08:00", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-startnode" +} diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.json new file mode 100644 index 0000000000..30275b64bd --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.json @@ -0,0 +1,15 @@ +{ + "kind": "compute#operation", + "id": "18431811683007150988", + "name": "operation-stopnode", + "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", + "operationType": "stop", + "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", + "targetId": "12335588484913203363", + "status": "DONE", + "user": "erjohnso@google.com", + "progress": 100, + "insertTime": "2015-01-30T06:55:11.503-08:00", + "startTime": "2015-01-30T06:55:11.847-08:00", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" +} diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py index 35ec80fbb5..3b2c34e305 100644 --- a/libcloud/test/compute/test_gce.py +++ b/libcloud/test/compute/test_gce.py @@ -443,6 +443,21 @@ def test_ex_create_network(self): self.assertEqual(network.name, network_name) self.assertEqual(network.cidr, cidr) + def test_ex_node_start(self): + zone = 'us-central1-a' + node = self.driver.ex_get_node('stopped-node', zone) + self.assertTrue(self.driver.ex_start_node(node)) + + def test_ex_node_stop(self): + zone = 'us-central1-a' + node = self.driver.ex_get_node('node-name', zone) + self.assertTrue(self.driver.ex_stop_node(node)) + + # try and stop a stopped node (should work) + zone = 'us-central1-a' + node = self.driver.ex_get_node('stopped-node', zone) + self.assertTrue(self.driver.ex_stop_node(node)) + def test_create_node_req(self): image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') @@ -1314,6 +1329,30 @@ def _setUsageExportBucket(self, method, url, body, headers): body = self.fixtures.load('setUsageExportBucket_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _zones_us_central1_a_operations_operation_startnode(self, method, url, body, header): + body = self.fixtures.load('zones_us_central1_a_operations_operation_startnode.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _zones_us_central1_a_instances_stopped_node_start(self, method, url, body, header): + body = self.fixtures.load('zones_us_central1_a_instances_stopped_node_start.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _zones_us_central1_a_instances_stopped_node_stop(self, method, url, body, header): + body = self.fixtures.load('zones_us_central1_a_instances_stopped_node_stop.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _zones_us_central1_a_instances_stopped_node(self, method, url, body, headers): + body = self.fixtures.load('zones_us_central1_a_instances_stopped_node.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _zones_us_central1_a_operations_operation_stopnode(self, method, url, body, headers): + body = self.fixtures.load('zones_us_central1_a_operations_operation_stopnode.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _zones_us_central1_a_instances_node_name_stop(self, method, url, body, headers): + body = self.fixtures.load('zones_us_central1_a_instances_node_name_stop.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _zones_us_central1_a_instances_node_name_setMetadata(self, method, url, body, headers): body = self.fixtures.load('zones_us_central1_a_instances_node_name_setMetadata_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])