def change_instance_state(module, gce, instance_names, number, zone, 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: GCEZone object where the instances reside prior to termination state: 'state' parameter passed into module as argument Returns a dictionary of instance names that were changed. """ changed = False nodes = [] state_instance_names = [] if isinstance(instance_names, str) and number: node_names = ['%s-%03d' % (instance_names, i) for i in range(number)] elif isinstance(instance_names, str) and not number: node_names = [instance_names] else: node_names = instance_names for name in node_names: inst = None try: inst = gce.ex_get_node(name, zone) except ResourceNotFoundError: state_instance_names.append(name) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) else: nodes.append(inst) state_instance_names.append(name) if state in ['absent', 'deleted'] and number: changed_nodes = gce.ex_destroy_multiple_nodes(nodes) or [False] changed = reduce(lambda x, y: x or y, changed_nodes) else: for node in nodes: if state in ['absent', 'deleted']: gce.destroy_node(node) changed = True elif state == 'started' and node.state == libcloud.compute.types.NodeState.STOPPED: gce.ex_start_node(node) changed = True elif state in [ 'stopped', 'terminated' ] and node.state == libcloud.compute.types.NodeState.RUNNING: gce.ex_stop_node(node) changed = True return (changed, state_instance_names)
def main(): module = AnsibleModule(argument_spec=dict( httphealthcheck_name=dict(), httphealthcheck_port=dict(default=80, type='int'), httphealthcheck_path=dict(default='/'), httphealthcheck_interval=dict(default=5, type='int'), httphealthcheck_timeout=dict(default=5, type='int'), httphealthcheck_unhealthy_count=dict(default=2, type='int'), httphealthcheck_healthy_count=dict(default=2, type='int'), httphealthcheck_host=dict(), name=dict(), protocol=dict(default='tcp'), region=dict(), external_ip=dict(), port_range=dict(), members=dict(type='list'), state=dict(default='present'), service_account_email=dict(), pem_file=dict(type='path'), credentials_file=dict(type='path'), project_id=dict(), )) if not HAS_LIBCLOUD: module.fail_json( msg='libcloud with GCE support (0.13.3+) required for this module.' ) gce = gce_connect(module) httphealthcheck_name = module.params.get('httphealthcheck_name') httphealthcheck_port = module.params.get('httphealthcheck_port') httphealthcheck_path = module.params.get('httphealthcheck_path') httphealthcheck_interval = module.params.get('httphealthcheck_interval') httphealthcheck_timeout = module.params.get('httphealthcheck_timeout') httphealthcheck_unhealthy_count = module.params.get( 'httphealthcheck_unhealthy_count') httphealthcheck_healthy_count = module.params.get( 'httphealthcheck_healthy_count') httphealthcheck_host = module.params.get('httphealthcheck_host') name = module.params.get('name') protocol = module.params.get('protocol') region = module.params.get('region') external_ip = module.params.get('external_ip') port_range = module.params.get('port_range') members = module.params.get('members') state = module.params.get('state') try: gcelb = get_driver_lb(Provider_lb.GCE)(gce_driver=gce) gcelb.connection.user_agent_append( "%s/%s" % (USER_AGENT_PRODUCT, USER_AGENT_VERSION)) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) changed = False json_output = {'name': name, 'state': state} if not name and not httphealthcheck_name: module.fail_json(msg='Nothing to do, please specify a "name" ' + 'or "httphealthcheck_name" parameter', changed=False) if state in ['active', 'present']: # first, create the httphealthcheck if requested hc = None if httphealthcheck_name: json_output['httphealthcheck_name'] = httphealthcheck_name try: hc = gcelb.ex_create_healthcheck( httphealthcheck_name, host=httphealthcheck_host, path=httphealthcheck_path, port=httphealthcheck_port, interval=httphealthcheck_interval, timeout=httphealthcheck_timeout, unhealthy_threshold=httphealthcheck_unhealthy_count, healthy_threshold=httphealthcheck_healthy_count) changed = True except ResourceExistsError: hc = gce.ex_get_healthcheck(httphealthcheck_name) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if hc is not None: json_output['httphealthcheck_host'] = hc.extra['host'] json_output['httphealthcheck_path'] = hc.path json_output['httphealthcheck_port'] = hc.port json_output['httphealthcheck_interval'] = hc.interval json_output['httphealthcheck_timeout'] = hc.timeout json_output[ 'httphealthcheck_unhealthy_count'] = hc.unhealthy_threshold json_output[ 'httphealthcheck_healthy_count'] = hc.healthy_threshold # create the forwarding rule (and target pool under the hood) lb = None if name: if not region: module.fail_json(msg='Missing required region name', changed=False) nodes = [] output_nodes = [] json_output['name'] = name # members is a python list of 'zone/inst' strings if members: for node in members: try: zone, node_name = node.split('/') nodes.append(gce.ex_get_node(node_name, zone)) output_nodes.append(node) except Exception: # skip nodes that are badly formatted or don't exist pass try: if hc is not None: lb = gcelb.create_balancer(name, port_range, protocol, None, nodes, ex_region=region, ex_healthchecks=[hc], ex_address=external_ip) else: lb = gcelb.create_balancer(name, port_range, protocol, None, nodes, ex_region=region, ex_address=external_ip) changed = True except ResourceExistsError: lb = gcelb.get_balancer(name) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if lb is not None: json_output['members'] = output_nodes json_output['protocol'] = protocol json_output['region'] = region json_output['external_ip'] = lb.ip json_output['port_range'] = lb.port hc_names = [] if 'healthchecks' in lb.extra: for hc in lb.extra['healthchecks']: hc_names.append(hc.name) json_output['httphealthchecks'] = hc_names if state in ['absent', 'deleted']: # first, delete the load balancer (forwarding rule and target pool) # if specified. if name: json_output['name'] = name try: lb = gcelb.get_balancer(name) gcelb.destroy_balancer(lb) changed = True except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) # destroy the health check if specified if httphealthcheck_name: json_output['httphealthcheck_name'] = httphealthcheck_name try: hc = gce.ex_get_healthcheck(httphealthcheck_name) gce.ex_destroy_healthcheck(hc) changed = True except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) json_output['changed'] = changed module.exit_json(**json_output)
def main(): module = AnsibleModule(argument_spec=dict( allowed=dict(), ipv4_range=dict(), fwname=dict(), name=dict(), src_range=dict(default=[], type='list'), src_tags=dict(default=[], type='list'), target_tags=dict(default=[], type='list'), state=dict(default='present'), service_account_email=dict(), pem_file=dict(type='path'), credentials_file=dict(type='path'), project_id=dict(), mode=dict(default='legacy', choices=['legacy', 'auto', 'custom']), subnet_name=dict(), subnet_region=dict(), subnet_desc=dict(), )) if not HAS_LIBCLOUD: module.fail_json( msg='libcloud with GCE support (0.17.0+) required for this module') gce = gce_connect(module) allowed = module.params.get('allowed') ipv4_range = module.params.get('ipv4_range') fwname = module.params.get('fwname') name = module.params.get('name') src_range = module.params.get('src_range') src_tags = module.params.get('src_tags') target_tags = module.params.get('target_tags') state = module.params.get('state') mode = module.params.get('mode') subnet_name = module.params.get('subnet_name') subnet_region = module.params.get('subnet_region') subnet_desc = module.params.get('subnet_desc') changed = False json_output = {'state': state} if state in ['active', 'present']: network = None subnet = None try: network = gce.ex_get_network(name) json_output['name'] = name if mode == 'legacy': json_output['ipv4_range'] = network.cidr if network and mode == 'custom' and subnet_name: if not hasattr(gce, 'ex_get_subnetwork'): module.fail_json( msg= "Update libcloud to a more recent version (>1.0) that supports network 'mode' parameter", changed=False) subnet = gce.ex_get_subnetwork(subnet_name, region=subnet_region) json_output['subnet_name'] = subnet_name json_output['ipv4_range'] = subnet.cidr except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) # user wants to create a new network that doesn't yet exist if name and not network: if not ipv4_range and mode != 'auto': module.fail_json( msg="Network '" + name + "' is not found. To create network in legacy or custom mode, 'ipv4_range' parameter is required", changed=False) args = [ipv4_range if mode == 'legacy' else None] kwargs = {} if mode != 'legacy': kwargs['mode'] = mode try: network = gce.ex_create_network(name, *args, **kwargs) json_output['name'] = name json_output['ipv4_range'] = ipv4_range changed = True except TypeError: module.fail_json( msg= "Update libcloud to a more recent version (>1.0) that supports network 'mode' parameter", changed=False) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if (subnet_name or ipv4_range) and not subnet and mode == 'custom': if not hasattr(gce, 'ex_create_subnetwork'): module.fail_json( msg= 'Update libcloud to a more recent version (>1.0) that supports subnetwork creation', changed=changed) if not subnet_name or not ipv4_range or not subnet_region: module.fail_json( msg= "subnet_name, ipv4_range, and subnet_region required for custom mode", changed=changed) try: subnet = gce.ex_create_subnetwork(subnet_name, cidr=ipv4_range, network=name, region=subnet_region, description=subnet_desc) json_output['subnet_name'] = subnet_name json_output['ipv4_range'] = ipv4_range changed = True except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=changed) if fwname: # user creating a firewall rule if not allowed and not src_range and not src_tags: if changed and network: module.fail_json( msg="Network created, but missing required " + "firewall rule parameter(s)", changed=True) module.fail_json( msg="Missing required firewall rule parameter(s)", changed=False) allowed_list = format_allowed(allowed) # Fetch existing rule and if it exists, compare attributes # update if attributes changed. Create if doesn't exist. try: fw_changed = False fw = gce.ex_get_firewall(fwname) # If old and new attributes are different, we update the firewall rule. # This implicitly lets us clear out attributes as well. # allowed_list is required and must not be None for firewall rules. if allowed_list and (sorted_allowed_list(allowed_list) != sorted_allowed_list(fw.allowed)): fw.allowed = allowed_list fw_changed = True # source_ranges might not be set in the project; cast it to an empty list fw.source_ranges = fw.source_ranges or [] # If these attributes are lists, we sort them first, then compare. # Otherwise, we update if they differ. if fw.source_ranges != src_range: if isinstance(src_range, list): if sorted(fw.source_ranges) != sorted(src_range): fw.source_ranges = src_range fw_changed = True else: fw.source_ranges = src_range fw_changed = True # source_tags might not be set in the project; cast it to an empty list fw.source_tags = fw.source_tags or [] if fw.source_tags != src_tags: if isinstance(src_tags, list): if sorted(fw.source_tags) != sorted(src_tags): fw.source_tags = src_tags fw_changed = True else: fw.source_tags = src_tags fw_changed = True # target_tags might not be set in the project; cast it to an empty list fw.target_tags = fw.target_tags or [] if fw.target_tags != target_tags: if isinstance(target_tags, list): if sorted(fw.target_tags) != sorted(target_tags): fw.target_tags = target_tags fw_changed = True else: fw.target_tags = target_tags fw_changed = True if fw_changed is True: try: gce.ex_update_firewall(fw) changed = True except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) # Firewall rule not found so we try to create it. except ResourceNotFoundError: try: gce.ex_create_firewall(fwname, allowed_list, network=name, source_ranges=src_range, source_tags=src_tags, target_tags=target_tags) changed = True except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) json_output['fwname'] = fwname json_output['allowed'] = allowed json_output['src_range'] = src_range json_output['src_tags'] = src_tags json_output['target_tags'] = target_tags if state in ['absent', 'deleted']: if fwname: json_output['fwname'] = fwname fw = None try: fw = gce.ex_get_firewall(fwname) except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if fw: gce.ex_destroy_firewall(fw) changed = True elif subnet_name: if not hasattr(gce, 'ex_get_subnetwork') or not hasattr( gce, 'ex_destroy_subnetwork'): module.fail_json( msg= 'Update libcloud to a more recent version (>1.0) that supports subnetwork creation', changed=changed) json_output['name'] = subnet_name subnet = None try: subnet = gce.ex_get_subnetwork(subnet_name, region=subnet_region) except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if subnet: gce.ex_destroy_subnetwork(subnet) changed = True elif name: json_output['name'] = name network = None try: network = gce.ex_get_network(name) except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) if network: try: gce.ex_destroy_network(network) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) changed = True json_output['changed'] = changed module.exit_json(**json_output)
def main(): module = AnsibleModule( argument_spec=dict( delete_on_termination=dict(type='bool'), detach_only=dict(type='bool'), instance_name=dict(), mode=dict(default='READ_ONLY', choices=['READ_WRITE', 'READ_ONLY']), name=dict(required=True), size_gb=dict(default=10), disk_type=dict(default='pd-standard'), image=dict(), image_family=dict(), external_projects=dict(type='list'), snapshot=dict(), state=dict(default='present'), zone=dict(default='us-central1-b'), service_account_email=dict(), pem_file=dict(type='path'), credentials_file=dict(type='path'), project_id=dict(), ) ) if not HAS_LIBCLOUD: module.fail_json(msg='libcloud with GCE support (0.17.0+) is required for this module') gce = gce_connect(module) delete_on_termination = module.params.get('delete_on_termination') detach_only = module.params.get('detach_only') instance_name = module.params.get('instance_name') mode = module.params.get('mode') name = module.params.get('name') size_gb = module.params.get('size_gb') disk_type = module.params.get('disk_type') image = module.params.get('image') image_family = module.params.get('image_family') external_projects = module.params.get('external_projects') snapshot = module.params.get('snapshot') state = module.params.get('state') zone = module.params.get('zone') if delete_on_termination and not instance_name: module.fail_json( msg='Must specify an instance name when requesting delete on termination', changed=False) if detach_only and not instance_name: module.fail_json( msg='Must specify an instance name when detaching a disk', changed=False) disk = inst = None changed = is_attached = False json_output = {'name': name, 'zone': zone, 'state': state, 'disk_type': disk_type} if detach_only: json_output['detach_only'] = True json_output['detached_from_instance'] = instance_name if instance_name: # user wants to attach/detach from an existing instance try: inst = gce.ex_get_node(instance_name, zone) # is the disk attached? for d in inst.extra['disks']: if d['deviceName'] == name: is_attached = True json_output['attached_mode'] = d['mode'] json_output['attached_to_instance'] = inst.name except Exception: pass # find disk if it already exists try: disk = gce.ex_get_volume(name) json_output['size_gb'] = int(disk.size) except ResourceNotFoundError: pass except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) # user wants a disk to exist. If "instance_name" is supplied the user # also wants it attached if state in ['active', 'present']: if not size_gb: module.fail_json(msg="Must supply a size_gb", changed=False) try: size_gb = int(round(float(size_gb))) if size_gb < 1: raise Exception except Exception: module.fail_json(msg="Must supply a size_gb larger than 1 GB", changed=False) if instance_name and inst is None: module.fail_json(msg='Instance %s does not exist in zone %s' % ( instance_name, zone), changed=False) if not disk: if image is not None and snapshot is not None: module.fail_json( msg='Cannot give both image (%s) and snapshot (%s)' % ( image, snapshot), changed=False) lc_image = None lc_snapshot = None if image_family is not None: lc_image = gce.ex_get_image_from_family(image_family, ex_project_list=external_projects) elif image is not None: lc_image = gce.ex_get_image(image, ex_project_list=external_projects) elif snapshot is not None: lc_snapshot = gce.ex_get_snapshot(snapshot) try: disk = gce.create_volume( size_gb, name, location=zone, image=lc_image, snapshot=lc_snapshot, ex_disk_type=disk_type) except ResourceExistsError: pass except QuotaExceededError: module.fail_json(msg='Requested disk size exceeds quota', changed=False) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) json_output['size_gb'] = size_gb if image is not None: json_output['image'] = image if snapshot is not None: json_output['snapshot'] = snapshot changed = True if inst and not is_attached: try: gce.attach_volume(inst, disk, device=name, ex_mode=mode, ex_auto_delete=delete_on_termination) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) json_output['attached_to_instance'] = inst.name json_output['attached_mode'] = mode if delete_on_termination: json_output['delete_on_termination'] = True changed = True # user wants to delete a disk (or perhaps just detach it). if state in ['absent', 'deleted'] and disk: if inst and is_attached: try: gce.detach_volume(disk, ex_node=inst) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) changed = True if not detach_only: try: gce.destroy_volume(disk) except ResourceInUseError as e: module.fail_json(msg=str(e.value), changed=False) except Exception as e: module.fail_json(msg=unexpected_error_msg(e), changed=False) changed = True json_output['changed'] = changed module.exit_json(**json_output)