Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions demos/gce_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,16 @@ def main_compute():
ex_disk_auto_delete=False)
display(' Node %s created' % name)

# Stop the node and change to a custom machine type (e.g. size)
display('Stopping node, setting custom size, starting node:')
name = '%s-np-node' % DEMO_BASE_NAME
gce.ex_stop_node(node_1)
gce.ex_set_machine_type(node_1, 'custom-2-4096') # 2 vCPU, 4GB RAM
gce.ex_start_node(node_1)
node_1 = gce.ex_get_node(name)
display(' %s: state=%s, size=%s' % (name, node_1.extra['status'],
node_1.size))

# == Create, and attach a disk ==
display('Creating a new disk:')
disk_name = '%s-attach-disk' % DEMO_BASE_NAME
Expand Down
24 changes: 24 additions & 0 deletions libcloud/compute/drivers/gce.py
Original file line number Diff line number Diff line change
Expand Up @@ -3685,6 +3685,30 @@ def ex_destroy_network(self, network):
self.connection.async_request(request, method='DELETE')
return True

def ex_set_machine_type(self, node, machine_type='n1-standard-1'):
"""
Set the machine type of the stopped instance. Can be the short-name,
a full, or partial URL.

:param node: Target node object to change
:type node: :class:`Node`

:param machine_type: Desired machine type
:type machine_type: ``str``

:return: True if successful
:rtype: ``bool``
"""
request = mt_url = '/zones/%s' % node.extra['zone'].name

mt = machine_type.split('/')[-1]
mt_url = '%s/machineTypes/%s' % (mt_url, mt)

request = '%s/instances/%s/setMachineType' % (request, node.name)
body = {"machineType": mt_url}
self.connection.async_request(request, method='POST', data=body)
return True

def ex_start_node(self, node):
"""
Start a node that is stopped and in TERMINATED state.
Expand Down
Original file line number Diff line number Diff line change
@@ -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": "custom-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/custom-node",
"status": "TERMINATED",
"tags": {
"fingerprint": "42WmSpB8rSM="
},
"zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"kind": "compute#operation",
"id": "18431811683007150988",
"name": "operation-setMachineType-notstopped",
"zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a",
"operationType": "setMachineType",
"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-setMachineType-notstopped"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"kind": "compute#operation",
"id": "18431811683007150988",
"name": "operation-setMachineType",
"zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a",
"operationType": "setMachineType",
"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-setMachineType"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"kind": "compute#operation",
"id": "18431811683007150988",
"name": "operation-setMachineType",
"zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a",
"operationType": "setMachineType",
"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-setMachineType"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"kind": "compute#operation",
"id": "1122640775725896976",
"name": "operation-setMachineType-notstopped",
"zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a",
"operationType": "setMachineType",
"targetLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name",
"targetId": "10940055899777330894",
"status": "DONE",
"user": "erjohnso@google.com",
"progress": 100,
"insertTime": "2016-03-07T08:09:34.445-08:00",
"startTime": "2016-03-07T08:09:34.679-08:00",
"endTime": "2016-03-07T08:09:35.161-08:00",
"error": {
"errors": [
{
"code": "RESOURCE_NOT_READY",
"message": "The resource 'projects/project_name/zones/us-central1-a/instances/node-name' is not ready"
}
]
},
"httpErrorStatusCode": 400,
"httpErrorMessage": "BAD REQUEST",
"selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMachineType-notstopped"
}
63 changes: 62 additions & 1 deletion libcloud/test/compute/test_gce.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
GCETargetHttpProxy, GCEUrlMap,
GCEZone)
from libcloud.common.google import (GoogleBaseAuthConnection,
ResourceNotFoundError, ResourceExistsError)
ResourceNotFoundError, ResourceExistsError,
InvalidRequestError, GoogleBaseError)
from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase
from libcloud.compute.base import Node, StorageVolume

Expand Down Expand Up @@ -478,6 +479,28 @@ def test_ex_create_network(self):
self.assertEqual(network.name, network_name)
self.assertEqual(network.cidr, cidr)

def test_ex_set_machine_type_notstopped(self):
# get running node, change machine type
zone = 'us-central1-a'
node = self.driver.ex_get_node('node-name', zone)
self.assertRaises(GoogleBaseError, self.driver.ex_set_machine_type,
node, 'custom-4-61440')

def test_ex_set_machine_type_invalid(self):
# get stopped node, change machine type
zone = 'us-central1-a'
node = self.driver.ex_get_node('custom-node', zone)
self.assertRaises(InvalidRequestError, self.driver.ex_set_machine_type,
node, 'custom-1-61440')

def test_ex_set_machine_type(self):
# get stopped node, change machine type
zone = 'us-central1-a'
node = self.driver.ex_get_node('stopped-node', zone)
self.assertEqual(node.size, 'n1-standard-1')
self.assertEqual(node.extra['status'], 'TERMINATED')
self.assertTrue(self.driver.ex_set_machine_type(node, 'custom-4-11264'))

def test_ex_node_start(self):
zone = 'us-central1-a'
node = self.driver.ex_get_node('stopped-node', zone)
Expand Down Expand Up @@ -1414,6 +1437,44 @@ 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_instances_custom_node(self, method, url, body, header):
body = self.fixtures.load('zones_us_central1_a_instances_custom_node.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])

def _zones_us_central1_a_instances_node_name_setMachineType(self, method, url, body, header):
body = self.fixtures.load('zones_us_central1_a_instances_node_name_setMachineType.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])

def _zones_us_central1_a_operations_operation_setMachineType_notstopped(self, method, url, body, header):
body = self.fixtures.load('zones_us_central1_a_operations_operation_setMachineType_notstopped.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])

def _zones_us_central1_a_instances_custom_node_setMachineType(self, method, url, body, header):
body = {
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "Invalid value for field 'resource.machineTypes': "
"'projects/project_name/zones/us-central1-a/machineTypes/custom-1-61440'. Resource was not found.",
}
],
"code": 400,
"message": "Invalid value for field 'resource.machineTypes': "
"'projects/project_name/zones/us-central1-a/machineTypes/custom-1-61440'. Resource was not found."
}
}
return (httplib.BAD_REQUEST, body, self.json_hdr, httplib.responses[httplib.BAD_REQUEST])

def _zones_us_central1_a_instances_stopped_node_setMachineType(self, method, url, body, header):
body = self.fixtures.load('zones_us_central1_a_instances_stopped_node_setMachineType.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])

def _zones_us_central1_a_operations_operation_setMachineType(self, method, url, body, header):
body = self.fixtures.load('zones_us_central1_a_operations_operation_setMachineType.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])
Expand Down