mirror of https://github.com/ansible/ansible.git
vultr: new module vr_server (#30869)
* vultr: new module vr_server * minor restyling * fix method namepull/34087/head
parent
b3ff93e129
commit
cfd7325ac4
@ -0,0 +1,872 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# (c) 2017, René Moser <mail@renemoser.net>
|
||||
# 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)
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: vr_server
|
||||
short_description: Manages virtual servers on Vultr.
|
||||
description:
|
||||
- Deploy, start, stop, update, restart, reinstall servers.
|
||||
version_added: "2.5"
|
||||
author: "René Moser (@resmo)"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of the server.
|
||||
required: true
|
||||
aliases: [ label ]
|
||||
hostname:
|
||||
description:
|
||||
- Hostname to assign to this server.
|
||||
os:
|
||||
description:
|
||||
- The operating system.
|
||||
- Required if the server does not yet exist.
|
||||
firewall_group:
|
||||
description:
|
||||
- The firewall group to assign this server to.
|
||||
plan:
|
||||
description:
|
||||
- Plan to use for the server.
|
||||
- Required if the server does not yet exist.
|
||||
force:
|
||||
description:
|
||||
- Force stop/start the server if required to apply changes
|
||||
- Otherwise a running server will not be changed.
|
||||
notify_activate:
|
||||
description:
|
||||
- Whether to send an activation email when the server is ready or not.
|
||||
- Only considered on creation.
|
||||
type: bool
|
||||
private_network_enabled:
|
||||
description:
|
||||
- Whether to enable private networking or not.
|
||||
type: bool
|
||||
auto_backup_enabled:
|
||||
description:
|
||||
- Whether to enable automatic backups or not.
|
||||
type: bool
|
||||
ipv6_enabled:
|
||||
description:
|
||||
- Whether to enable IPv6 or not.
|
||||
type: bool
|
||||
tag:
|
||||
description:
|
||||
- Tag for the server.
|
||||
user_data:
|
||||
description:
|
||||
- User data to be passed to the server.
|
||||
ssh_keys:
|
||||
description:
|
||||
- List of SSH keys passed to the server on creation.
|
||||
aliases: [ ssh_key ]
|
||||
reserved_ip_v4:
|
||||
description:
|
||||
- IP address of the floating IP to use as the main IP of this server.
|
||||
- Only considered on creation.
|
||||
region:
|
||||
description:
|
||||
- Region the server is deployed into.
|
||||
- Required if the server does not yet exist.
|
||||
state:
|
||||
description:
|
||||
- State of the server.
|
||||
default: present
|
||||
choices: [ present, absent, restarted, reinstalled, started, stopped ]
|
||||
extends_documentation_fragment: vultr
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: create server
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
os: CentOS 7 x64
|
||||
plan: 1024 MB RAM,25 GB SSD,1.00 TB BW
|
||||
region: Amsterdam
|
||||
state: present
|
||||
|
||||
- name: ensure a server is present and started
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
os: CentOS 7 x64
|
||||
plan: 1024 MB RAM,25 GB SSD,1.00 TB BW
|
||||
region: Amsterdam
|
||||
state: started
|
||||
|
||||
- name: ensure a server is present and stopped
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
os: CentOS 7 x64
|
||||
plan: 1024 MB RAM,25 GB SSD,1.00 TB BW
|
||||
region: Amsterdam
|
||||
state: stopped
|
||||
|
||||
- name: ensure an existing server is stopped
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
state: stopped
|
||||
|
||||
- name: ensure an existing server is started
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
state: started
|
||||
|
||||
- name: ensure a server is absent
|
||||
local_action:
|
||||
module: vr_server
|
||||
name: "{{ vr_server_name }}"
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
vultr_api:
|
||||
description: Response from Vultr API with a few additions/modification
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
api_account:
|
||||
description: Account used in the ini file to select the key
|
||||
returned: success
|
||||
type: string
|
||||
sample: default
|
||||
api_timeout:
|
||||
description: Timeout used for the API requests
|
||||
returned: success
|
||||
type: int
|
||||
sample: 60
|
||||
vultr_server:
|
||||
description: Response from Vultr API with a few additions/modification
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: ID of the server
|
||||
returned: success
|
||||
type: int
|
||||
sample: 10194376
|
||||
name:
|
||||
description: Name (label) of the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "ansible-test-vm"
|
||||
plan:
|
||||
description: Plan used for the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "1024 MB RAM,25 GB SSD,1.00 TB BW"
|
||||
allowed_bandwidth_gb:
|
||||
description: Allowed bandwidth to use in GB
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
auto_backup_enabled:
|
||||
description: Whether automatic backups are enabled
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
cost_per_month:
|
||||
description: Cost per month for the server
|
||||
returned: success
|
||||
type: float
|
||||
sample: 5.00
|
||||
current_bandwidth_gb:
|
||||
description: Current bandwidth used for the server
|
||||
returned: success
|
||||
type: int
|
||||
sample: 0
|
||||
date_created:
|
||||
description: Date when the server was created
|
||||
returned: success
|
||||
type: string
|
||||
sample: "2017-08-26 12:47:48"
|
||||
default_password:
|
||||
description: Password to login as root into the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "!p3EWYJm$qDWYaFr"
|
||||
disk:
|
||||
description: Information about the disk
|
||||
returned: success
|
||||
type: string
|
||||
sample: "Virtual 25 GB"
|
||||
v4_gateway:
|
||||
description: IPv4 gateway
|
||||
returned: success
|
||||
type: string
|
||||
sample: "45.32.232.1"
|
||||
internal_ip:
|
||||
description: Internal IP
|
||||
returned: success
|
||||
type: string
|
||||
sample: ""
|
||||
kvm_url:
|
||||
description: URL to the VNC
|
||||
returned: success
|
||||
type: string
|
||||
sample: "https://my.vultr.com/subs/vps/novnc/api.php?data=xyz"
|
||||
region:
|
||||
description: Region the server was deployed into
|
||||
returned: success
|
||||
type: string
|
||||
sample: "Amsterdam"
|
||||
v4_main_ip:
|
||||
description: Main IPv4
|
||||
returned: success
|
||||
type: string
|
||||
sample: "45.32.233.154"
|
||||
v4_netmask:
|
||||
description: Netmask IPv4
|
||||
returned: success
|
||||
type: string
|
||||
sample: "255.255.254.0"
|
||||
os:
|
||||
description: Operating system used for the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "CentOS 6 x64"
|
||||
firewall_group:
|
||||
description: Firewall group the server is assinged to
|
||||
returned: success and available
|
||||
type: string
|
||||
sample: "CentOS 6 x64"
|
||||
pending_charges:
|
||||
description: Pending charges
|
||||
returned: success
|
||||
type: float
|
||||
sample: 0.01
|
||||
power_status:
|
||||
description: Power status of the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "running"
|
||||
ram:
|
||||
description: Information about the RAM size
|
||||
returned: success
|
||||
type: string
|
||||
sample: "1024 MB"
|
||||
server_state:
|
||||
description: State about the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "ok"
|
||||
status:
|
||||
description: Status about the deployment of the server
|
||||
returned: success
|
||||
type: string
|
||||
sample: "active"
|
||||
tag:
|
||||
description: TBD
|
||||
returned: success
|
||||
type: string
|
||||
sample: ""
|
||||
v6_main_ip:
|
||||
description: Main IPv6
|
||||
returned: success
|
||||
type: string
|
||||
sample: ""
|
||||
v6_network:
|
||||
description: Network IPv6
|
||||
returned: success
|
||||
type: string
|
||||
sample: ""
|
||||
v6_network_size:
|
||||
description: Network size IPv6
|
||||
returned: success
|
||||
type: string
|
||||
sample: ""
|
||||
v6_networks:
|
||||
description: Networks IPv6
|
||||
returned: success
|
||||
type: list
|
||||
sample: []
|
||||
vcpu_count:
|
||||
description: Virtual CPU count
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1
|
||||
'''
|
||||
|
||||
import time
|
||||
import base64
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.vultr import (
|
||||
Vultr,
|
||||
vultr_argument_spec,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleVultrServer(Vultr):
|
||||
|
||||
def __init__(self, module):
|
||||
super(AnsibleVultrServer, self).__init__(module, "vultr_server")
|
||||
|
||||
self.server = None
|
||||
self.returns = {
|
||||
'SUBID': dict(key='id', convert_to='int'),
|
||||
'label': dict(key='name'),
|
||||
'date_created': dict(),
|
||||
'allowed_bandwidth_gb': dict(convert_to='int'),
|
||||
'auto_backups': dict(key='auto_backup_enabled', convert_to='bool'),
|
||||
'current_bandwidth_gb': dict(),
|
||||
'kvm_url': dict(),
|
||||
'default_password': dict(),
|
||||
'internal_ip': dict(),
|
||||
'disk': dict(),
|
||||
'cost_per_month': dict(convert_to='float'),
|
||||
'location': dict(key='region'),
|
||||
'main_ip': dict(key='v4_main_ip'),
|
||||
'network_v4': dict(key='v4_network'),
|
||||
'gateway_v4': dict(key='v4_gateway'),
|
||||
'os': dict(),
|
||||
'pending_charges': dict(convert_to='float'),
|
||||
'power_status': dict(),
|
||||
'ram': dict(),
|
||||
'plan': dict(),
|
||||
'server_state': dict(),
|
||||
'status': dict(),
|
||||
'firewall_group': dict(),
|
||||
'tag': dict(),
|
||||
'v6_main_ip': dict(),
|
||||
'v6_network': dict(),
|
||||
'v6_network_size': dict(),
|
||||
'v6_networks': dict(),
|
||||
'vcpu_count': dict(convert_to='int'),
|
||||
}
|
||||
self.server_power_state = None
|
||||
|
||||
def get_os(self):
|
||||
name = self.module.params.get('os')
|
||||
if not name:
|
||||
return {}
|
||||
|
||||
return self.query_resource_by_key(
|
||||
key='name',
|
||||
value=name,
|
||||
resource='os',
|
||||
use_cache=True
|
||||
)
|
||||
|
||||
def get_ssh_key(self):
|
||||
name = self.module.params.get('ssh_key')
|
||||
if not name:
|
||||
return {}
|
||||
|
||||
return self.query_resource_by_key(
|
||||
key='name',
|
||||
value=name,
|
||||
resource='sshkey',
|
||||
use_cache=True
|
||||
)
|
||||
|
||||
def get_region(self):
|
||||
name = self.module.params.get('region')
|
||||
if not name:
|
||||
return {}
|
||||
|
||||
return self.query_resource_by_key(
|
||||
key='name',
|
||||
value=name,
|
||||
resource='regions',
|
||||
use_cache=True
|
||||
)
|
||||
|
||||
def get_plan(self):
|
||||
name = self.module.params.get('plan')
|
||||
if not name:
|
||||
return {}
|
||||
|
||||
return self.query_resource_by_key(
|
||||
key='name',
|
||||
value=name,
|
||||
resource='plans',
|
||||
use_cache=True
|
||||
)
|
||||
|
||||
def get_firewall_group(self):
|
||||
name = self.module.params.get('firewall_group')
|
||||
if not name:
|
||||
return {}
|
||||
return self.query_resource_by_key(
|
||||
key='description',
|
||||
value=name,
|
||||
resource='firewall',
|
||||
query_by='group_list'
|
||||
)
|
||||
|
||||
def get_user_data(self):
|
||||
user_data = self.module.params.get('user_data')
|
||||
if user_data is not None:
|
||||
user_data = base64.b64encode(str(user_data))
|
||||
return user_data
|
||||
|
||||
def get_server_user_data(self, server):
|
||||
if not server or not server.get('SUBID'):
|
||||
return None
|
||||
|
||||
user_data = self.api_query(path="/v1/server/get_user_data?SUBID=%s" % server.get('SUBID'))
|
||||
return user_data.get('userdata')
|
||||
|
||||
def get_server(self, refresh=False):
|
||||
if self.server is None or refresh:
|
||||
self.server = None
|
||||
server_list = self.api_query(path="/v1/server/list")
|
||||
if server_list:
|
||||
for server_id, server_data in server_list.items():
|
||||
if server_data.get('label') == self.module.params.get('name'):
|
||||
self.server = server_data
|
||||
|
||||
plan = self.query_resource_by_key(
|
||||
key='VPSPLANID',
|
||||
value=server_data['VPSPLANID'],
|
||||
resource='plans',
|
||||
use_cache=True
|
||||
)
|
||||
self.server['plan'] = plan.get('name')
|
||||
|
||||
os = self.query_resource_by_key(
|
||||
key='OSID',
|
||||
value=int(server_data['OSID']),
|
||||
resource='os',
|
||||
use_cache=True
|
||||
)
|
||||
self.server['os'] = os.get('name')
|
||||
|
||||
fwg_id = server_data.get('FIREWALLGROUPID')
|
||||
fw = self.query_resource_by_key(
|
||||
key='FIREWALLGROUPID',
|
||||
value=server_data.get('FIREWALLGROUPID') if fwg_id and fwg_id != "0" else None,
|
||||
resource='firewall',
|
||||
query_by='group_list',
|
||||
use_cache=True
|
||||
)
|
||||
self.server['firewall_group'] = fw.get('description')
|
||||
return self.server
|
||||
|
||||
def present_server(self, start_server=True):
|
||||
server = self.get_server()
|
||||
if not server:
|
||||
server = self._create_server(server=server)
|
||||
else:
|
||||
server = self._update_server(server=server, start_server=start_server)
|
||||
return server
|
||||
|
||||
def _create_server(self, server=None):
|
||||
required_params = [
|
||||
'os',
|
||||
'plan',
|
||||
'region',
|
||||
]
|
||||
self.module.fail_on_missing_params(required_params=required_params)
|
||||
|
||||
self.result['changed'] = True
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'DCID': self.get_region().get('DCID'),
|
||||
'VPSPLANID': self.get_plan().get('VPSPLANID'),
|
||||
'FIREWALLGROUPID': self.get_firewall_group().get('FIREWALLGROUPID'),
|
||||
'OSID': self.get_os().get('OSID'),
|
||||
'label': self.module.params.get('name'),
|
||||
'hostname': self.module.params.get('hostname'),
|
||||
'SSHKEYID': self.get_ssh_key().get('SSHKEYID'),
|
||||
'enable_ipv6': self.get_yes_or_no('ipv6_enabled'),
|
||||
'enable_private_network': self.get_yes_or_no('private_network_enabled'),
|
||||
'auto_backups': self.get_yes_or_no('auto_backup_enabled'),
|
||||
'notify_activate': self.get_yes_or_no('notify_activate'),
|
||||
'tag': self.module.params.get('tag'),
|
||||
'reserved_ip_v4': self.module.params.get('reserved_ip_v4'),
|
||||
'user_data': self.get_user_data(),
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/create",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(key='status', state='active')
|
||||
server = self._wait_for_state(state='running')
|
||||
return server
|
||||
|
||||
def _update_auto_backups_setting(self, server, start_server):
|
||||
auto_backup_enabled_changed = self.switch_enable_disable(server, 'auto_backup_enabled', 'auto_backups')
|
||||
|
||||
if auto_backup_enabled_changed:
|
||||
if auto_backup_enabled_changed == "enable" and server['auto_backups'] == 'disable':
|
||||
self.module.warn("Backups are disabled. Once disabled, backups can only be enabled again by customer support")
|
||||
else:
|
||||
server, warned = self._handle_power_status_for_update(server, start_server)
|
||||
if not warned:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['auto_backup_enabled'] = server.get('auto_backups')
|
||||
self.result['diff']['after']['auto_backup_enabled'] = self.get_yes_or_no('auto_backup_enabled')
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/backup_%s" % auto_backup_enabled_changed,
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(key='server_state', state='ok')
|
||||
return server
|
||||
|
||||
def _update_ipv6_setting(self, server, start_server):
|
||||
ipv6_enabled_changed = self.switch_enable_disable(server, 'ipv6_enabled', 'v6_main_ip')
|
||||
|
||||
if ipv6_enabled_changed:
|
||||
if ipv6_enabled_changed == "disable":
|
||||
self.module.warn("The Vultr API does not allow to disable IPv6")
|
||||
else:
|
||||
server, warned = self._handle_power_status_for_update(server, start_server)
|
||||
if not warned:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['ipv6_enabled'] = False
|
||||
self.result['diff']['after']['ipv6_enabled'] = True
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/ipv6_%s" % ipv6_enabled_changed,
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(key='server_state', state='ok')
|
||||
server = self._wait_for_state(key='v6_main_ip')
|
||||
return server
|
||||
|
||||
def _update_private_network_setting(self, server, start_server):
|
||||
private_network_enabled_changed = self.switch_enable_disable(server, 'private_network_enabled', 'internal_ip')
|
||||
if private_network_enabled_changed:
|
||||
if private_network_enabled_changed == "disable":
|
||||
self.module.warn("The Vultr API does not allow to disable private network")
|
||||
else:
|
||||
server, warned = self._handle_power_status_for_update(server, start_server)
|
||||
if not warned:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['private_network_enabled'] = False
|
||||
self.result['diff']['after']['private_network_enabled'] = True
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/private_network_%s" % private_network_enabled_changed,
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(key='server_state', state='ok')
|
||||
return server
|
||||
|
||||
def _update_plan_setting(self, server, start_server):
|
||||
plan = self.get_plan()
|
||||
plan_changed = True if plan and plan['VPSPLANID'] != server.get('VPSPLANID') else False
|
||||
if plan_changed:
|
||||
server, warned = self._handle_power_status_for_update(server, start_server)
|
||||
if not warned:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['plan'] = server.get('plan')
|
||||
self.result['diff']['after']['plan'] = plan['name']
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID'],
|
||||
'VPSPLANID': plan['VPSPLANID'],
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/upgrade_plan",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(key='server_state', state='ok')
|
||||
return server
|
||||
|
||||
def _handle_power_status_for_update(self, server, start_server):
|
||||
# Remember the power state before we handle any action
|
||||
if self.server_power_state is None:
|
||||
self.server_power_state = server['power_status']
|
||||
|
||||
# A stopped server can be updated
|
||||
if self.server_power_state == "stopped":
|
||||
return server, False
|
||||
|
||||
# A running server must be forced to update unless the wanted state is stopped
|
||||
elif self.module.params.get('force') or not start_server:
|
||||
warned = False
|
||||
if not self.module.check_mode:
|
||||
# Some update APIs would restart the VM, we handle the restart manually
|
||||
# by stopping the server and start it at the end of the changes
|
||||
server = self.stop_server(skip_results=True)
|
||||
|
||||
# Warn the user that a running server won't get changed
|
||||
else:
|
||||
warned = True
|
||||
self.module.warn("Some changes won't be applied to running instances. " +
|
||||
"Use force=true to allow the instance %s to be stopped/started." % server['label'])
|
||||
|
||||
return server, warned
|
||||
|
||||
def _update_server(self, server=None, start_server=True):
|
||||
# Update auto backups settings, stops server
|
||||
server = self._update_auto_backups_setting(server=server, start_server=start_server)
|
||||
|
||||
# Update IPv6 settings, stops server
|
||||
server = self._update_ipv6_setting(server=server, start_server=start_server)
|
||||
|
||||
# Update private network settings, stops server
|
||||
server = self._update_private_network_setting(server=server, start_server=start_server)
|
||||
|
||||
# Update plan settings, stops server
|
||||
server = self._update_plan_setting(server=server, start_server=start_server)
|
||||
|
||||
# User data
|
||||
user_data = self.get_user_data()
|
||||
server_user_data = self.get_server_user_data(server=server)
|
||||
if user_data is not None and user_data != server_user_data:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['tag'] = server_user_data
|
||||
self.result['diff']['after']['tag'] = user_data
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID'],
|
||||
'userdata': user_data,
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/set_user_data",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
|
||||
# Tags
|
||||
tag = self.module.params.get('tag')
|
||||
if tag is not None and tag != server.get('tag'):
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['tag'] = server.get('tag')
|
||||
self.result['diff']['after']['tag'] = tag
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID'],
|
||||
'tag': tag,
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/tag_set",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
|
||||
# Firewall group
|
||||
firewall_group = self.get_firewall_group()
|
||||
if firewall_group and firewall_group.get('description') != server.get('firewall_group'):
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['firewall_group'] = server.get('firewall_group')
|
||||
self.result['diff']['after']['firewall_group'] = firewall_group.get('description')
|
||||
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID'],
|
||||
'FIREWALLGROUPID': firewall_group.get('FIREWALLGROUPID'),
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/firewall_group_set",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
# Start server again if it was running before the changes
|
||||
if not self.module.check_mode:
|
||||
if self.server_power_state in ['starting', 'running'] and start_server:
|
||||
server = self.start_server(skip_results=True)
|
||||
|
||||
server = self._wait_for_state(key='server_state', state='ok')
|
||||
return server
|
||||
|
||||
def absent_server(self):
|
||||
server = self.get_server()
|
||||
if server:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['id'] = server['SUBID']
|
||||
self.result['diff']['after']['id'] = ""
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/destroy",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
for s in range(0, 30):
|
||||
if server is not None:
|
||||
break
|
||||
time.sleep(2)
|
||||
server = self.get_server(refresh=True)
|
||||
else:
|
||||
self.fail_json(msg="Wait for server '%s' to get deleted timed out" % server['label'])
|
||||
return server
|
||||
|
||||
def restart_server(self):
|
||||
self.result['changed'] = True
|
||||
server = self.get_server()
|
||||
if server:
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/reboot",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(state='running')
|
||||
return server
|
||||
|
||||
def reinstall_server(self):
|
||||
self.result['changed'] = True
|
||||
server = self.get_server()
|
||||
if server:
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/reinstall",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(state='running')
|
||||
return server
|
||||
|
||||
def _wait_for_state(self, key='power_status', state=None):
|
||||
time.sleep(1)
|
||||
server = self.get_server(refresh=True)
|
||||
for s in range(0, 30):
|
||||
# Check for Truely if wanted state is None
|
||||
if state is None and server.get(key):
|
||||
break
|
||||
elif server.get(key) == state:
|
||||
break
|
||||
time.sleep(2)
|
||||
server = self.get_server(refresh=True)
|
||||
|
||||
# Timed out
|
||||
else:
|
||||
if state is None:
|
||||
msg = "Wait for '%s' timed out" % key
|
||||
else:
|
||||
msg = "Wait for '%s' to get into state '%s' timed out" % (key, state)
|
||||
self.fail_json(msg=msg)
|
||||
return server
|
||||
|
||||
def start_server(self, skip_results=False):
|
||||
server = self.get_server()
|
||||
if server:
|
||||
if server['power_status'] == 'starting':
|
||||
server = self._wait_for_state(state='running')
|
||||
|
||||
elif server['power_status'] != 'running':
|
||||
if not skip_results:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['power_status'] = server['power_status']
|
||||
self.result['diff']['after']['power_status'] = "running"
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID']
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/start",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(state='running')
|
||||
return server
|
||||
|
||||
def stop_server(self, skip_results=False):
|
||||
server = self.get_server()
|
||||
if server and server['power_status'] != "stopped":
|
||||
if not skip_results:
|
||||
self.result['changed'] = True
|
||||
self.result['diff']['before']['power_status'] = server['power_status']
|
||||
self.result['diff']['after']['power_status'] = "stopped"
|
||||
if not self.module.check_mode:
|
||||
data = {
|
||||
'SUBID': server['SUBID'],
|
||||
}
|
||||
self.api_query(
|
||||
path="/v1/server/halt",
|
||||
method="POST",
|
||||
data=data
|
||||
)
|
||||
server = self._wait_for_state(state='stopped')
|
||||
return server
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = vultr_argument_spec()
|
||||
argument_spec.update(dict(
|
||||
name=dict(required=True, aliases=['label']),
|
||||
hostname=dict(),
|
||||
os=dict(),
|
||||
plan=dict(),
|
||||
force=dict(type='bool', default=False),
|
||||
notify_activate=dict(type='bool', default=False),
|
||||
private_network_enabled=dict(type='bool'),
|
||||
auto_backup_enabled=dict(type='bool'),
|
||||
ipv6_enabled=dict(type='bool'),
|
||||
tag=dict(),
|
||||
reserved_ip_v4=dict(),
|
||||
firewall_group=dict(),
|
||||
user_data=dict(),
|
||||
ssh_keys=dict(type='list', aliases=['ssh_key']),
|
||||
region=dict(),
|
||||
state=dict(choices=['present', 'absent', 'restarted', 'reinstalled', 'started', 'stopped'], default='present'),
|
||||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
vr_server = AnsibleVultrServer(module)
|
||||
if module.params.get('state') == "absent":
|
||||
server = vr_server.absent_server()
|
||||
else:
|
||||
if module.params.get('state') == "started":
|
||||
server = vr_server.present_server()
|
||||
server = vr_server.start_server()
|
||||
elif module.params.get('state') == "stopped":
|
||||
server = vr_server.present_server(start_server=False)
|
||||
server = vr_server.stop_server()
|
||||
elif module.params.get('state') == "restarted":
|
||||
server = vr_server.present_server()
|
||||
server = vr_server.restart_server()
|
||||
elif module.params.get('state') == "reinstalled":
|
||||
server = vr_server.reinstall_server()
|
||||
else:
|
||||
server = vr_server.present_server()
|
||||
|
||||
result = vr_server.get_result(server)
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue