From b5da9d190de77a86d57363148fadd9e219a77d06 Mon Sep 17 00:00:00 2001 From: John Baublitz Date: Thu, 14 Jul 2016 17:14:43 +0000 Subject: [PATCH 1/2] Add states for stopping and starting machines --- cloud/google/gce.py | 74 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/cloud/google/gce.py b/cloud/google/gce.py index 8571b0fda93..e9c0efbfd24 100644 --- a/cloud/google/gce.py +++ b/cloud/google/gce.py @@ -121,7 +121,7 @@ options: - desired state of the resource required: false default: "present" - choices: ["active", "present", "absent", "deleted"] + choices: ["active", "present", "absent", "deleted", "started", "stopped", "terminated"] tags: description: - a comma-separated list of tags to associate with the instance @@ -502,6 +502,59 @@ def create_instances(module, gce, instance_names): return (changed, instance_json_data, instance_names) +def start_instances(module, gce, instance_names, zone_name): + """Starts a list of stopped instances. + + module: Ansible module object + gce: authenticated GCE connection object + instance_names: a list of instance names to start + zone_name: the zone where the instances reside prior to termination + + Returns a dictionary of instance names that were started. + """ + changed = False + started_instance_names = [] + for name in instance_names: + inst = None + try: + inst = gce.ex_get_node(name, zone_name) + except ResourceNotFoundError: + pass + except Exception as e: + module.fail_json(msg=unexpected_error_msg(e), changed=False) + if inst and inst.state == libcloud.compute.types.NodeState.STOPPED: + gce.ex_start_node(inst) + started_instance_names.append(inst.name) + changed = True + + return (changed, started_instance_names) + +def stop_instances(module, gce, instance_names, zone_name): + """Stops a list of instances. + + module: Ansible module object + gce: authenticated GCE connection object + instance_names: a list of instance names to stop + zone_name: the zone where the instances reside prior to termination + + Returns a dictionary of instance names that were stopped. + """ + changed = False + stopped_instance_names = [] + for name in instance_names: + inst = None + try: + inst = gce.ex_get_node(name, zone_name) + except ResourceNotFoundError: + pass + except Exception as e: + module.fail_json(msg=unexpected_error_msg(e), changed=False) + if inst and inst.state == libcloud.compute.types.NodeState.RUNNING: + gce.ex_stop_node(inst) + stopped_instance_names.append(inst.name) + changed = True + + return (changed, stopped_instance_names) def terminate_instances(module, gce, instance_names, zone_name): """Terminates a list of instances. @@ -544,7 +597,8 @@ def main(): subnetwork = dict(), persistent_boot_disk = dict(type='bool', default=False), disks = dict(type='list'), - state = dict(choices=['active', 'present', 'absent', 'deleted'], + state = dict(choices=['active', 'present', 'absent', 'deleted', + 'started', 'stopped', 'terminated'], default='present'), tags = dict(type='list'), zone = dict(default='us-central1-a'), @@ -626,6 +680,22 @@ def main(): elif name: json_output['name'] = name + elif state in ['started']: + json_output['state'] = 'started' + (changed, started_instance_names) = start_instances(module, gce, inames, zone) + if instance_names: + json_output['instance_names'] = started_instance_names + elif name: + json_output['name'] = name + + elif state in ['stopped', 'terminated']: + json_output['state'] = 'stopped' + (changed, stopped_instance_names) = stop_instances(module, gce, inames, zone) + if instance_names: + json_output['instance_names'] = stopped_instance_names + elif name: + json_output['name'] = name + json_output['changed'] = changed module.exit_json(**json_output) From e85c2f825350f15ef62262b56796ee76c8579be3 Mon Sep 17 00:00:00 2001 From: John Baublitz Date: Fri, 15 Jul 2016 18:40:56 +0000 Subject: [PATCH 2/2] Collapse boilerplate code into change_instance_state function --- cloud/google/gce.py | 107 ++++++++++---------------------------------- 1 file changed, 24 insertions(+), 83 deletions(-) diff --git a/cloud/google/gce.py b/cloud/google/gce.py index e9c0efbfd24..064a79e2f84 100644 --- a/cloud/google/gce.py +++ b/cloud/google/gce.py @@ -502,73 +502,21 @@ def create_instances(module, gce, instance_names): return (changed, instance_json_data, instance_names) -def start_instances(module, gce, instance_names, zone_name): - """Starts a list of stopped instances. - - module: Ansible module object - gce: authenticated GCE connection object - instance_names: a list of instance names to start - zone_name: the zone where the instances reside prior to termination - - Returns a dictionary of instance names that were started. - """ - changed = False - started_instance_names = [] - for name in instance_names: - inst = None - try: - inst = gce.ex_get_node(name, zone_name) - except ResourceNotFoundError: - pass - except Exception as e: - module.fail_json(msg=unexpected_error_msg(e), changed=False) - if inst and inst.state == libcloud.compute.types.NodeState.STOPPED: - gce.ex_start_node(inst) - started_instance_names.append(inst.name) - changed = True - - return (changed, started_instance_names) - -def stop_instances(module, gce, instance_names, zone_name): - """Stops a list of instances. - - module: Ansible module object - gce: authenticated GCE connection object - instance_names: a list of instance names to stop - zone_name: the zone where the instances reside prior to termination - - Returns a dictionary of instance names that were stopped. - """ - changed = False - stopped_instance_names = [] - for name in instance_names: - inst = None - try: - inst = gce.ex_get_node(name, zone_name) - except ResourceNotFoundError: - pass - except Exception as e: - module.fail_json(msg=unexpected_error_msg(e), changed=False) - if inst and inst.state == libcloud.compute.types.NodeState.RUNNING: - gce.ex_stop_node(inst) - stopped_instance_names.append(inst.name) - changed = True - - return (changed, stopped_instance_names) - -def terminate_instances(module, gce, instance_names, zone_name): - """Terminates a list of instances. +def change_instance_state(module, gce, instance_names, zone_name, state): + """Changes the state of a list of instances. For example, + change from started to stopped, or started to absent. module: Ansible module object gce: authenticated GCE connection object instance_names: a list of instance names to terminate zone_name: the zone where the instances reside prior to termination + state: 'state' parameter passed into module as argument - Returns a dictionary of instance names that were terminated. + Returns a dictionary of instance names that were changed. """ changed = False - terminated_instance_names = [] + changed_instance_names = [] for name in instance_names: inst = None try: @@ -577,13 +525,22 @@ def terminate_instances(module, gce, instance_names, zone_name): pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) - if inst: + if inst and state in ['absent', 'deleted']: gce.destroy_node(inst) - terminated_instance_names.append(inst.name) + changed_instance_names.append(inst.name) + changed = True + elif inst and state == 'started' and \ + inst.state == libcloud.compute.types.NodeState.STOPPED: + gce.ex_start_node(inst) + changed_instance_names.append(inst.name) + changed = True + elif inst and state in ['stopped', 'terminated'] and \ + inst.state == libcloud.compute.types.NodeState.RUNNING: + gce.ex_stop_node(inst) + changed_instance_names.append(inst.name) changed = True - return (changed, terminated_instance_names) - + return (changed, changed_instance_names) def main(): module = AnsibleModule( @@ -658,15 +615,15 @@ def main(): changed=False) json_output = {'zone': zone} - if state in ['absent', 'deleted']: - json_output['state'] = 'absent' - (changed, terminated_instance_names) = terminate_instances( - module, gce, inames, zone) + if state in ['absent', 'deleted', 'started', 'stopped', 'terminated']: + json_output['state'] = state + (changed, changed_instance_names) = change_instance_state( + module, gce, inames, zone, state) # based on what user specified, return the same variable, although # value could be different if an instance could not be destroyed if instance_names: - json_output['instance_names'] = terminated_instance_names + json_output['instance_names'] = changed_instance_names elif name: json_output['name'] = name @@ -680,22 +637,6 @@ def main(): elif name: json_output['name'] = name - elif state in ['started']: - json_output['state'] = 'started' - (changed, started_instance_names) = start_instances(module, gce, inames, zone) - if instance_names: - json_output['instance_names'] = started_instance_names - elif name: - json_output['name'] = name - - elif state in ['stopped', 'terminated']: - json_output['state'] = 'stopped' - (changed, stopped_instance_names) = stop_instances(module, gce, inames, zone) - if instance_names: - json_output['instance_names'] = stopped_instance_names - elif name: - json_output['name'] = name - json_output['changed'] = changed module.exit_json(**json_output)