|
|
@ -3,14 +3,13 @@
|
|
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
|
|
__metaclass__ = type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__metaclass__ = type
|
|
|
|
|
|
|
|
|
|
|
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|
|
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|
|
|
'status': ['preview'],
|
|
|
|
'status': ['preview'],
|
|
|
|
'supported_by': 'community'}
|
|
|
|
'supported_by': 'community'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DOCUMENTATION = '''
|
|
|
|
DOCUMENTATION = '''
|
|
|
|
---
|
|
|
|
---
|
|
|
|
module: gce
|
|
|
|
module: gce
|
|
|
@ -325,6 +324,7 @@ import logging
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
from ast import literal_eval
|
|
|
|
from ast import literal_eval
|
|
|
|
|
|
|
|
|
|
|
|
HAS_PYTHON26 = True
|
|
|
|
HAS_PYTHON26 = True
|
|
|
|
except ImportError:
|
|
|
|
except ImportError:
|
|
|
|
HAS_PYTHON26 = False
|
|
|
|
HAS_PYTHON26 = False
|
|
|
@ -336,6 +336,7 @@ try:
|
|
|
|
from libcloud.common.google import GoogleBaseError, QuotaExceededError, \
|
|
|
|
from libcloud.common.google import GoogleBaseError, QuotaExceededError, \
|
|
|
|
ResourceExistsError, ResourceInUseError, ResourceNotFoundError
|
|
|
|
ResourceExistsError, ResourceInUseError, ResourceNotFoundError
|
|
|
|
from libcloud.compute.drivers.gce import GCEAddress
|
|
|
|
from libcloud.compute.drivers.gce import GCEAddress
|
|
|
|
|
|
|
|
|
|
|
|
_ = Provider.GCE
|
|
|
|
_ = Provider.GCE
|
|
|
|
HAS_LIBCLOUD = True
|
|
|
|
HAS_LIBCLOUD = True
|
|
|
|
except ImportError:
|
|
|
|
except ImportError:
|
|
|
@ -378,7 +379,7 @@ def get_instance_info(inst):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
public_ip = inst.public_ips[0]
|
|
|
|
public_ip = inst.public_ips[0]
|
|
|
|
|
|
|
|
|
|
|
|
return({
|
|
|
|
return ({
|
|
|
|
'image': inst.image is not None and inst.image.split('/')[-1] or None,
|
|
|
|
'image': inst.image is not None and inst.image.split('/')[-1] or None,
|
|
|
|
'disks': disk_names,
|
|
|
|
'disks': disk_names,
|
|
|
|
'machine_type': inst.size,
|
|
|
|
'machine_type': inst.size,
|
|
|
@ -553,7 +554,7 @@ def create_instances(module, gce, instance_names, number, lc_zone):
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
except GoogleBaseError as e:
|
|
|
|
except GoogleBaseError as e:
|
|
|
|
module.fail_json(msg='Unexpected error attempting to create ' +
|
|
|
|
module.fail_json(msg='Unexpected error attempting to create ' +
|
|
|
|
'instance %s, error: %s' % (instance, e.value))
|
|
|
|
'instance %s, error: %s' % (instance, e.value))
|
|
|
|
if inst:
|
|
|
|
if inst:
|
|
|
|
new_instances.append(inst)
|
|
|
|
new_instances.append(inst)
|
|
|
|
|
|
|
|
|
|
|
@ -576,7 +577,7 @@ def create_instances(module, gce, instance_names, number, lc_zone):
|
|
|
|
# Work around libcloud bug: attached volumes don't get added
|
|
|
|
# Work around libcloud bug: attached volumes don't get added
|
|
|
|
# to the instance metadata. get_instance_info() only cares about
|
|
|
|
# to the instance metadata. get_instance_info() only cares about
|
|
|
|
# source and index.
|
|
|
|
# source and index.
|
|
|
|
if len(inst.extra['disks']) != i+1:
|
|
|
|
if len(inst.extra['disks']) != i + 1:
|
|
|
|
inst.extra['disks'].append(
|
|
|
|
inst.extra['disks'].append(
|
|
|
|
{'source': lc_disk.extra['selfLink'], 'index': i})
|
|
|
|
{'source': lc_disk.extra['selfLink'], 'index': i})
|
|
|
|
|
|
|
|
|
|
|
@ -589,6 +590,7 @@ def create_instances(module, gce, instance_names, number, lc_zone):
|
|
|
|
|
|
|
|
|
|
|
|
return (changed, instance_json_data, instance_names)
|
|
|
|
return (changed, instance_json_data, instance_names)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def change_instance_state(module, gce, instance_names, number, zone, state):
|
|
|
|
def change_instance_state(module, gce, instance_names, number, zone, state):
|
|
|
|
"""Changes the state of a list of instances. For example,
|
|
|
|
"""Changes the state of a list of instances. For example,
|
|
|
|
change from started to stopped, or started to absent.
|
|
|
|
change from started to stopped, or started to absent.
|
|
|
@ -633,47 +635,46 @@ def change_instance_state(module, gce, instance_names, number, zone, state):
|
|
|
|
if state in ['absent', 'deleted']:
|
|
|
|
if state in ['absent', 'deleted']:
|
|
|
|
gce.destroy_node(node)
|
|
|
|
gce.destroy_node(node)
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
elif state == 'started' and \
|
|
|
|
elif state == 'started' and node.state == libcloud.compute.types.NodeState.STOPPED:
|
|
|
|
node.state == libcloud.compute.types.NodeState.STOPPED:
|
|
|
|
|
|
|
|
gce.ex_start_node(node)
|
|
|
|
gce.ex_start_node(node)
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
elif state in ['stopped', 'terminated'] and \
|
|
|
|
elif state in ['stopped', 'terminated'] and node.state == libcloud.compute.types.NodeState.RUNNING:
|
|
|
|
node.state == libcloud.compute.types.NodeState.RUNNING:
|
|
|
|
|
|
|
|
gce.ex_stop_node(node)
|
|
|
|
gce.ex_stop_node(node)
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
|
|
|
|
|
|
|
|
return (changed, state_instance_names)
|
|
|
|
return (changed, state_instance_names)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
module = AnsibleModule(
|
|
|
|
module = AnsibleModule(
|
|
|
|
argument_spec = dict(
|
|
|
|
argument_spec=dict(
|
|
|
|
image = dict(default='debian-8'),
|
|
|
|
image=dict(default='debian-8'),
|
|
|
|
image_family = dict(),
|
|
|
|
image_family=dict(),
|
|
|
|
external_projects = dict(type='list'),
|
|
|
|
external_projects=dict(type='list'),
|
|
|
|
instance_names = dict(),
|
|
|
|
instance_names=dict(),
|
|
|
|
machine_type = dict(default='n1-standard-1'),
|
|
|
|
machine_type=dict(default='n1-standard-1'),
|
|
|
|
metadata = dict(),
|
|
|
|
metadata=dict(),
|
|
|
|
name = dict(aliases=['base_name']),
|
|
|
|
name=dict(aliases=['base_name']),
|
|
|
|
num_instances = dict(type='int'),
|
|
|
|
num_instances=dict(type='int'),
|
|
|
|
network = dict(default='default'),
|
|
|
|
network=dict(default='default'),
|
|
|
|
subnetwork = dict(),
|
|
|
|
subnetwork=dict(),
|
|
|
|
persistent_boot_disk = dict(type='bool', default=False),
|
|
|
|
persistent_boot_disk=dict(type='bool', default=False),
|
|
|
|
disks = dict(type='list'),
|
|
|
|
disks=dict(type='list'),
|
|
|
|
state = dict(choices=['active', 'present', 'absent', 'deleted',
|
|
|
|
state=dict(choices=['active', 'present', 'absent', 'deleted',
|
|
|
|
'started', 'stopped', 'terminated'],
|
|
|
|
'started', 'stopped', 'terminated'],
|
|
|
|
default='present'),
|
|
|
|
default='present'),
|
|
|
|
tags = dict(type='list'),
|
|
|
|
tags=dict(type='list'),
|
|
|
|
zone = dict(default='us-central1-a'),
|
|
|
|
zone=dict(default='us-central1-a'),
|
|
|
|
service_account_email = dict(),
|
|
|
|
service_account_email=dict(),
|
|
|
|
service_account_permissions = dict(type='list'),
|
|
|
|
service_account_permissions=dict(type='list'),
|
|
|
|
pem_file = dict(type='path'),
|
|
|
|
pem_file=dict(type='path'),
|
|
|
|
credentials_file = dict(type='path'),
|
|
|
|
credentials_file=dict(type='path'),
|
|
|
|
project_id = dict(),
|
|
|
|
project_id=dict(),
|
|
|
|
ip_forward = dict(type='bool', default=False),
|
|
|
|
ip_forward=dict(type='bool', default=False),
|
|
|
|
external_ip=dict(default='ephemeral'),
|
|
|
|
external_ip=dict(default='ephemeral'),
|
|
|
|
disk_auto_delete = dict(type='bool', default=True),
|
|
|
|
disk_auto_delete=dict(type='bool', default=True),
|
|
|
|
disk_size = dict(type='int', default=10),
|
|
|
|
disk_size=dict(type='int', default=10),
|
|
|
|
preemptible = dict(type='bool', default=None),
|
|
|
|
preemptible=dict(type='bool', default=None),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
mutually_exclusive=[('instance_names', 'name')]
|
|
|
|
mutually_exclusive=[('instance_names', 'name')]
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -751,6 +752,7 @@ class LazyDiskImage:
|
|
|
|
Object for lazy instantiation of disk image
|
|
|
|
Object for lazy instantiation of disk image
|
|
|
|
gce.ex_get_image is a very expensive call, so we want to avoid calling it as much as possible.
|
|
|
|
gce.ex_get_image is a very expensive call, so we want to avoid calling it as much as possible.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, module, gce, name, has_pd, family=None, projects=None):
|
|
|
|
def __init__(self, module, gce, name, has_pd, family=None, projects=None):
|
|
|
|
self.image = None
|
|
|
|
self.image = None
|
|
|
|
self.was_called = False
|
|
|
|
self.was_called = False
|
|
|
|