|
|
@ -153,9 +153,13 @@ class AnsibleCloudStack(object):
|
|
|
|
'api_http_method': api_config['method'],
|
|
|
|
'api_http_method': api_config['method'],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if not all([api_config['endpoint'], api_config['key'], api_config['secret']]):
|
|
|
|
if not all([api_config['endpoint'], api_config['key'], api_config['secret']]):
|
|
|
|
self.module.fail_json(msg="Missing api credentials: can not authenticate", result=self.result)
|
|
|
|
self.fail_json(msg="Missing api credentials: can not authenticate")
|
|
|
|
self.cs = CloudStack(**api_config)
|
|
|
|
self.cs = CloudStack(**api_config)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fail_json(self, **kwargs):
|
|
|
|
|
|
|
|
self.result.update(kwargs)
|
|
|
|
|
|
|
|
self.module.fail_json(**self.result)
|
|
|
|
|
|
|
|
|
|
|
|
def get_or_fallback(self, key=None, fallback_key=None):
|
|
|
|
def get_or_fallback(self, key=None, fallback_key=None):
|
|
|
|
value = self.module.params.get(key)
|
|
|
|
value = self.module.params.get(key)
|
|
|
|
if not value:
|
|
|
|
if not value:
|
|
|
@ -217,7 +221,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if key:
|
|
|
|
if key:
|
|
|
|
if key in my_dict:
|
|
|
|
if key in my_dict:
|
|
|
|
return my_dict[key]
|
|
|
|
return my_dict[key]
|
|
|
|
self.module.fail_json(msg="Something went wrong: %s not found" % key)
|
|
|
|
self.fail_json(msg="Something went wrong: %s not found" % key)
|
|
|
|
return my_dict
|
|
|
|
return my_dict
|
|
|
|
|
|
|
|
|
|
|
|
def get_vpc(self, key=None):
|
|
|
|
def get_vpc(self, key=None):
|
|
|
@ -239,18 +243,19 @@ class AnsibleCloudStack(object):
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vpcs = self.cs.listVPCs(**args)
|
|
|
|
vpcs = self.cs.listVPCs(**args)
|
|
|
|
if not vpcs:
|
|
|
|
if not vpcs:
|
|
|
|
self.module.fail_json(msg="No VPCs available.")
|
|
|
|
self.fail_json(msg="No VPCs available.")
|
|
|
|
|
|
|
|
|
|
|
|
for v in vpcs['vpc']:
|
|
|
|
for v in vpcs['vpc']:
|
|
|
|
if vpc in [v['name'], v['displaytext'], v['id']]:
|
|
|
|
if vpc in [v['name'], v['displaytext'], v['id']]:
|
|
|
|
# Fail if the identifyer matches more than one VPC
|
|
|
|
# Fail if the identifyer matches more than one VPC
|
|
|
|
if self.vpc:
|
|
|
|
if self.vpc:
|
|
|
|
self.module.fail_json(msg="More than one VPC found with the provided identifyer '%s'" % vpc)
|
|
|
|
self.fail_json(msg="More than one VPC found with the provided identifyer '%s'" % vpc)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.vpc = v
|
|
|
|
self.vpc = v
|
|
|
|
|
|
|
|
self.result['vpc'] = v['name']
|
|
|
|
if self.vpc:
|
|
|
|
if self.vpc:
|
|
|
|
return self._get_by_key(key, self.vpc)
|
|
|
|
return self._get_by_key(key, self.vpc)
|
|
|
|
self.module.fail_json(msg="VPC '%s' not found" % vpc)
|
|
|
|
self.fail_json(msg="VPC '%s' not found" % vpc)
|
|
|
|
|
|
|
|
|
|
|
|
def is_vpc_network(self, network_id):
|
|
|
|
def is_vpc_network(self, network_id):
|
|
|
|
"""Returns True if network is in VPC."""
|
|
|
|
"""Returns True if network is in VPC."""
|
|
|
@ -279,7 +284,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if not network:
|
|
|
|
if not network:
|
|
|
|
vpc_name = self.get_vpc(key='name')
|
|
|
|
vpc_name = self.get_vpc(key='name')
|
|
|
|
if vpc_name:
|
|
|
|
if vpc_name:
|
|
|
|
self.module.fail_json(msg="Could not find network for VPC '%s' due missing argument: network" % vpc_name)
|
|
|
|
self.fail_json(msg="Could not find network for VPC '%s' due missing argument: network" % vpc_name)
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
args = {
|
|
|
|
args = {
|
|
|
@ -291,16 +296,17 @@ class AnsibleCloudStack(object):
|
|
|
|
}
|
|
|
|
}
|
|
|
|
networks = self.cs.listNetworks(**args)
|
|
|
|
networks = self.cs.listNetworks(**args)
|
|
|
|
if not networks:
|
|
|
|
if not networks:
|
|
|
|
self.module.fail_json(msg="No networks available.")
|
|
|
|
self.fail_json(msg="No networks available.")
|
|
|
|
|
|
|
|
|
|
|
|
for n in networks['network']:
|
|
|
|
for n in networks['network']:
|
|
|
|
# ignore any VPC network if vpc param is not given
|
|
|
|
# ignore any VPC network if vpc param is not given
|
|
|
|
if 'vpcid' in n and not self.get_vpc(key='id'):
|
|
|
|
if 'vpcid' in n and not self.get_vpc(key='id'):
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
if network in [n['displaytext'], n['name'], n['id']]:
|
|
|
|
if network in [n['displaytext'], n['name'], n['id']]:
|
|
|
|
|
|
|
|
self.result['network'] = n['name']
|
|
|
|
self.network = n
|
|
|
|
self.network = n
|
|
|
|
return self._get_by_key(key, self.network)
|
|
|
|
return self._get_by_key(key, self.network)
|
|
|
|
self.module.fail_json(msg="Network '%s' not found" % network)
|
|
|
|
self.fail_json(msg="Network '%s' not found" % network)
|
|
|
|
|
|
|
|
|
|
|
|
def get_project(self, key=None):
|
|
|
|
def get_project(self, key=None):
|
|
|
|
if self.project:
|
|
|
|
if self.project:
|
|
|
@ -319,9 +325,10 @@ class AnsibleCloudStack(object):
|
|
|
|
if projects:
|
|
|
|
if projects:
|
|
|
|
for p in projects['project']:
|
|
|
|
for p in projects['project']:
|
|
|
|
if project.lower() in [p['name'].lower(), p['id']]:
|
|
|
|
if project.lower() in [p['name'].lower(), p['id']]:
|
|
|
|
|
|
|
|
self.result['project'] = p['name']
|
|
|
|
self.project = p
|
|
|
|
self.project = p
|
|
|
|
return self._get_by_key(key, self.project)
|
|
|
|
return self._get_by_key(key, self.project)
|
|
|
|
self.module.fail_json(msg="project '%s' not found" % project)
|
|
|
|
self.fail_json(msg="project '%s' not found" % project)
|
|
|
|
|
|
|
|
|
|
|
|
def get_ip_address(self, key=None):
|
|
|
|
def get_ip_address(self, key=None):
|
|
|
|
if self.ip_address:
|
|
|
|
if self.ip_address:
|
|
|
@ -329,7 +336,7 @@ class AnsibleCloudStack(object):
|
|
|
|
|
|
|
|
|
|
|
|
ip_address = self.module.params.get('ip_address')
|
|
|
|
ip_address = self.module.params.get('ip_address')
|
|
|
|
if not ip_address:
|
|
|
|
if not ip_address:
|
|
|
|
self.module.fail_json(msg="IP address param 'ip_address' is required")
|
|
|
|
self.fail_json(msg="IP address param 'ip_address' is required")
|
|
|
|
|
|
|
|
|
|
|
|
args = {
|
|
|
|
args = {
|
|
|
|
'ipaddress': ip_address,
|
|
|
|
'ipaddress': ip_address,
|
|
|
@ -341,7 +348,7 @@ class AnsibleCloudStack(object):
|
|
|
|
ip_addresses = self.cs.listPublicIpAddresses(**args)
|
|
|
|
ip_addresses = self.cs.listPublicIpAddresses(**args)
|
|
|
|
|
|
|
|
|
|
|
|
if not ip_addresses:
|
|
|
|
if not ip_addresses:
|
|
|
|
self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress'])
|
|
|
|
self.fail_json(msg="IP address '%s' not found" % args['ipaddress'])
|
|
|
|
|
|
|
|
|
|
|
|
self.ip_address = ip_addresses['publicipaddress'][0]
|
|
|
|
self.ip_address = ip_addresses['publicipaddress'][0]
|
|
|
|
return self._get_by_key(key, self.ip_address)
|
|
|
|
return self._get_by_key(key, self.ip_address)
|
|
|
@ -356,7 +363,7 @@ class AnsibleCloudStack(object):
|
|
|
|
for secondary_ip in default_nic['secondaryip']:
|
|
|
|
for secondary_ip in default_nic['secondaryip']:
|
|
|
|
if vm_guest_ip == secondary_ip['ipaddress']:
|
|
|
|
if vm_guest_ip == secondary_ip['ipaddress']:
|
|
|
|
return vm_guest_ip
|
|
|
|
return vm_guest_ip
|
|
|
|
self.module.fail_json(msg="Secondary IP '%s' not assigned to VM" % vm_guest_ip)
|
|
|
|
self.fail_json(msg="Secondary IP '%s' not assigned to VM" % vm_guest_ip)
|
|
|
|
|
|
|
|
|
|
|
|
def get_vm_default_nic(self):
|
|
|
|
def get_vm_default_nic(self):
|
|
|
|
if self.vm_default_nic:
|
|
|
|
if self.vm_default_nic:
|
|
|
@ -368,7 +375,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if n['isdefault']:
|
|
|
|
if n['isdefault']:
|
|
|
|
self.vm_default_nic = n
|
|
|
|
self.vm_default_nic = n
|
|
|
|
return self.vm_default_nic
|
|
|
|
return self.vm_default_nic
|
|
|
|
self.module.fail_json(msg="No default IP address of VM '%s' found" % self.module.params.get('vm'))
|
|
|
|
self.fail_json(msg="No default IP address of VM '%s' found" % self.module.params.get('vm'))
|
|
|
|
|
|
|
|
|
|
|
|
def get_vm(self, key=None):
|
|
|
|
def get_vm(self, key=None):
|
|
|
|
if self.vm:
|
|
|
|
if self.vm:
|
|
|
@ -376,7 +383,7 @@ class AnsibleCloudStack(object):
|
|
|
|
|
|
|
|
|
|
|
|
vm = self.module.params.get('vm')
|
|
|
|
vm = self.module.params.get('vm')
|
|
|
|
if not vm:
|
|
|
|
if not vm:
|
|
|
|
self.module.fail_json(msg="Virtual machine param 'vm' is required")
|
|
|
|
self.fail_json(msg="Virtual machine param 'vm' is required")
|
|
|
|
|
|
|
|
|
|
|
|
args = {
|
|
|
|
args = {
|
|
|
|
'account': self.get_account(key='name'),
|
|
|
|
'account': self.get_account(key='name'),
|
|
|
@ -391,7 +398,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if vm.lower() in [v['name'].lower(), v['displayname'].lower(), v['id']]:
|
|
|
|
if vm.lower() in [v['name'].lower(), v['displayname'].lower(), v['id']]:
|
|
|
|
self.vm = v
|
|
|
|
self.vm = v
|
|
|
|
return self._get_by_key(key, self.vm)
|
|
|
|
return self._get_by_key(key, self.vm)
|
|
|
|
self.module.fail_json(msg="Virtual machine '%s' not found" % vm)
|
|
|
|
self.fail_json(msg="Virtual machine '%s' not found" % vm)
|
|
|
|
|
|
|
|
|
|
|
|
def get_zone(self, key=None):
|
|
|
|
def get_zone(self, key=None):
|
|
|
|
if self.zone:
|
|
|
|
if self.zone:
|
|
|
@ -403,7 +410,7 @@ class AnsibleCloudStack(object):
|
|
|
|
zones = self.cs.listZones()
|
|
|
|
zones = self.cs.listZones()
|
|
|
|
|
|
|
|
|
|
|
|
if not zones:
|
|
|
|
if not zones:
|
|
|
|
self.module.fail_json(msg="No zones available. Please create a zone first")
|
|
|
|
self.fail_json(msg="No zones available. Please create a zone first")
|
|
|
|
|
|
|
|
|
|
|
|
# use the first zone if no zone param given
|
|
|
|
# use the first zone if no zone param given
|
|
|
|
if not zone:
|
|
|
|
if not zone:
|
|
|
@ -413,9 +420,10 @@ class AnsibleCloudStack(object):
|
|
|
|
if zones:
|
|
|
|
if zones:
|
|
|
|
for z in zones['zone']:
|
|
|
|
for z in zones['zone']:
|
|
|
|
if zone.lower() in [z['name'].lower(), z['id']]:
|
|
|
|
if zone.lower() in [z['name'].lower(), z['id']]:
|
|
|
|
|
|
|
|
self.result['zone'] = z['name']
|
|
|
|
self.zone = z
|
|
|
|
self.zone = z
|
|
|
|
return self._get_by_key(key, self.zone)
|
|
|
|
return self._get_by_key(key, self.zone)
|
|
|
|
self.module.fail_json(msg="zone '%s' not found" % zone)
|
|
|
|
self.fail_json(msg="zone '%s' not found" % zone)
|
|
|
|
|
|
|
|
|
|
|
|
def get_os_type(self, key=None):
|
|
|
|
def get_os_type(self, key=None):
|
|
|
|
if self.os_type:
|
|
|
|
if self.os_type:
|
|
|
@ -431,7 +439,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if os_type in [o['description'], o['id']]:
|
|
|
|
if os_type in [o['description'], o['id']]:
|
|
|
|
self.os_type = o
|
|
|
|
self.os_type = o
|
|
|
|
return self._get_by_key(key, self.os_type)
|
|
|
|
return self._get_by_key(key, self.os_type)
|
|
|
|
self.module.fail_json(msg="OS type '%s' not found" % os_type)
|
|
|
|
self.fail_json(msg="OS type '%s' not found" % os_type)
|
|
|
|
|
|
|
|
|
|
|
|
def get_hypervisor(self):
|
|
|
|
def get_hypervisor(self):
|
|
|
|
if self.hypervisor:
|
|
|
|
if self.hypervisor:
|
|
|
@ -449,7 +457,7 @@ class AnsibleCloudStack(object):
|
|
|
|
if hypervisor.lower() == h['name'].lower():
|
|
|
|
if hypervisor.lower() == h['name'].lower():
|
|
|
|
self.hypervisor = h['name']
|
|
|
|
self.hypervisor = h['name']
|
|
|
|
return self.hypervisor
|
|
|
|
return self.hypervisor
|
|
|
|
self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor)
|
|
|
|
self.fail_json(msg="Hypervisor '%s' not found" % hypervisor)
|
|
|
|
|
|
|
|
|
|
|
|
def get_account(self, key=None):
|
|
|
|
def get_account(self, key=None):
|
|
|
|
if self.account:
|
|
|
|
if self.account:
|
|
|
@ -463,7 +471,7 @@ class AnsibleCloudStack(object):
|
|
|
|
|
|
|
|
|
|
|
|
domain = self.module.params.get('domain')
|
|
|
|
domain = self.module.params.get('domain')
|
|
|
|
if not domain:
|
|
|
|
if not domain:
|
|
|
|
self.module.fail_json(msg="Account must be specified with Domain")
|
|
|
|
self.fail_json(msg="Account must be specified with Domain")
|
|
|
|
|
|
|
|
|
|
|
|
args = {
|
|
|
|
args = {
|
|
|
|
'name': account,
|
|
|
|
'name': account,
|
|
|
@ -473,8 +481,9 @@ class AnsibleCloudStack(object):
|
|
|
|
accounts = self.cs.listAccounts(**args)
|
|
|
|
accounts = self.cs.listAccounts(**args)
|
|
|
|
if accounts:
|
|
|
|
if accounts:
|
|
|
|
self.account = accounts['account'][0]
|
|
|
|
self.account = accounts['account'][0]
|
|
|
|
|
|
|
|
self.result['account'] = self.account['name']
|
|
|
|
return self._get_by_key(key, self.account)
|
|
|
|
return self._get_by_key(key, self.account)
|
|
|
|
self.module.fail_json(msg="Account '%s' not found" % account)
|
|
|
|
self.fail_json(msg="Account '%s' not found" % account)
|
|
|
|
|
|
|
|
|
|
|
|
def get_domain(self, key=None):
|
|
|
|
def get_domain(self, key=None):
|
|
|
|
if self.domain:
|
|
|
|
if self.domain:
|
|
|
@ -494,8 +503,9 @@ class AnsibleCloudStack(object):
|
|
|
|
for d in domains['domain']:
|
|
|
|
for d in domains['domain']:
|
|
|
|
if d['path'].lower() in [domain.lower(), "root/" + domain.lower(), "root" + domain.lower()]:
|
|
|
|
if d['path'].lower() in [domain.lower(), "root/" + domain.lower(), "root" + domain.lower()]:
|
|
|
|
self.domain = d
|
|
|
|
self.domain = d
|
|
|
|
|
|
|
|
self.result['domain'] = d['path']
|
|
|
|
return self._get_by_key(key, self.domain)
|
|
|
|
return self._get_by_key(key, self.domain)
|
|
|
|
self.module.fail_json(msg="Domain '%s' not found" % domain)
|
|
|
|
self.fail_json(msg="Domain '%s' not found" % domain)
|
|
|
|
|
|
|
|
|
|
|
|
def get_tags(self, resource=None):
|
|
|
|
def get_tags(self, resource=None):
|
|
|
|
existing_tags = []
|
|
|
|
existing_tags = []
|
|
|
@ -528,7 +538,7 @@ class AnsibleCloudStack(object):
|
|
|
|
|
|
|
|
|
|
|
|
def ensure_tags(self, resource, resource_type=None):
|
|
|
|
def ensure_tags(self, resource, resource_type=None):
|
|
|
|
if not resource_type or not resource:
|
|
|
|
if not resource_type or not resource:
|
|
|
|
self.module.fail_json(msg="Error: Missing resource or resource_type for tags.")
|
|
|
|
self.fail_json(msg="Error: Missing resource or resource_type for tags.")
|
|
|
|
|
|
|
|
|
|
|
|
if 'tags' in resource:
|
|
|
|
if 'tags' in resource:
|
|
|
|
tags = self.module.params.get('tags')
|
|
|
|
tags = self.module.params.get('tags')
|
|
|
@ -551,7 +561,7 @@ class AnsibleCloudStack(object):
|
|
|
|
res = self.cs.queryAsyncJobResult(jobid=job['jobid'])
|
|
|
|
res = self.cs.queryAsyncJobResult(jobid=job['jobid'])
|
|
|
|
if res['jobstatus'] != 0 and 'jobresult' in res:
|
|
|
|
if res['jobstatus'] != 0 and 'jobresult' in res:
|
|
|
|
if 'errortext' in res['jobresult']:
|
|
|
|
if 'errortext' in res['jobresult']:
|
|
|
|
self.module.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext'])
|
|
|
|
self.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext'])
|
|
|
|
if key and key in res['jobresult']:
|
|
|
|
if key and key in res['jobresult']:
|
|
|
|
job = res['jobresult'][key]
|
|
|
|
job = res['jobresult'][key]
|
|
|
|
break
|
|
|
|
break
|
|
|
|