forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
245 additions
and
0 deletions.
There are no files selected for viewing
245 changes: 245 additions & 0 deletions
245
lib/ansible/modules/extras/cloud/misc/proxmox_template.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
#!/usr/bin/python | ||
# This file is part of Ansible | ||
# | ||
# Ansible is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# Ansible is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
DOCUMENTATION = ''' | ||
--- | ||
module: proxmox_template | ||
short_description: management of OS templates in Proxmox VE cluster | ||
description: | ||
- allows you to list/upload/delete templates in Proxmox VE cluster | ||
version_added: "2.0" | ||
options: | ||
api_host: | ||
description: | ||
- the host of the Proxmox VE cluster | ||
required: true | ||
api_user: | ||
description: | ||
- the user to authenticate with | ||
required: true | ||
api_password: | ||
description: | ||
- the password to authenticate with | ||
- you can use PROXMOX_PASSWORD environment variable | ||
default: null | ||
required: false | ||
https_verify_ssl: | ||
description: | ||
- enable / disable https certificate verification | ||
default: false | ||
required: false | ||
type: boolean | ||
node: | ||
description: | ||
- Proxmox VE node, when you will operate with template | ||
default: null | ||
required: true | ||
src: | ||
description: | ||
- path to uploaded file | ||
- required only for C(state=present) | ||
default: null | ||
required: false | ||
aliases: ['path'] | ||
template: | ||
description: | ||
- the template name | ||
- required only for states C(absent), C(info) | ||
default: null | ||
required: false | ||
content_type: | ||
description: | ||
- content type | ||
- required only for C(state=present) | ||
default: 'vztmpl' | ||
required: false | ||
choices: ['vztmpl', 'iso'] | ||
storage: | ||
description: | ||
- target storage | ||
default: 'local' | ||
required: false | ||
type: string | ||
timeout: | ||
description: | ||
- timeout for operations | ||
default: 300 | ||
required: false | ||
type: integer | ||
force: | ||
description: | ||
- can be used only with C(state=present), exists template will be overwritten | ||
default: false | ||
required: false | ||
type: boolean | ||
state: | ||
description: | ||
- Indicate desired state of the template | ||
choices: ['present', 'absent', 'list'] | ||
default: present | ||
notes: | ||
- Requires proxmoxer and requests modules on host. This modules can be installed with pip. | ||
requirements: [ "proxmoxer", "requests" ] | ||
author: "Sergei Antipov @UnderGreen" | ||
''' | ||
|
||
EXAMPLES = ''' | ||
# Upload new openvz template with minimal options | ||
- proxmox_template: node='uk-mc02' api_user='root@pam' api_password='1q2w3e' api_host='node1' src='~/ubuntu-14.04-x86_64.tar.gz' | ||
# Upload new openvz template with minimal options use environment PROXMOX_PASSWORD variable(you should export it before) | ||
- proxmox_template: node='uk-mc02' api_user='root@pam' api_host='node1' src='~/ubuntu-14.04-x86_64.tar.gz' | ||
# Upload new openvz template with all options and force overwrite | ||
- proxmox_template: node='uk-mc02' api_user='root@pam' api_password='1q2w3e' api_host='node1' storage='local' content_type='vztmpl' src='~/ubuntu-14.04-x86_64.tar.gz' force=yes | ||
# Delete template with minimal options | ||
- proxmox_template: node='uk-mc02' api_user='root@pam' api_password='1q2w3e' api_host='node1' template='ubuntu-14.04-x86_64.tar.gz' state=absent | ||
# List content of storage(it returns list of dicts) | ||
- proxmox_template: node='uk-mc02' api_user='root@pam' api_password='1q2w3e' api_host='node1' storage='local' state=list | ||
''' | ||
|
||
import os | ||
import time | ||
|
||
try: | ||
from proxmoxer import ProxmoxAPI | ||
HAS_PROXMOXER = True | ||
except ImportError: | ||
HAS_PROXMOXER = False | ||
|
||
def get_template(proxmox, node, storage, content_type, template): | ||
return [ True for tmpl in proxmox.nodes(node).storage(storage).content.get() | ||
if tmpl['volid'] == '%s:%s/%s' % (storage, content_type, template) ] | ||
|
||
def get_content(proxmox, node, storage): | ||
return proxmox.nodes(node).storage(storage).content.get() | ||
|
||
def upload_template(module, proxmox, node, storage, content_type, realpath, timeout): | ||
taskid = proxmox.nodes(node).storage(storage).upload.post(content=content_type, filename=open(realpath)) | ||
while timeout: | ||
task_status = proxmox.nodes(node).tasks(taskid).status.get() | ||
if task_status['status'] == 'stopped' and task_status['exitstatus'] == 'OK': | ||
return True | ||
timeout = timeout - 1 | ||
if timeout == 0: | ||
module.fail_json(msg='Reached timeout while waiting for uploading template. Last line in task before timeout: %s' | ||
% proxmox.node(node).tasks(taskid).log.get()[:1]) | ||
|
||
time.sleep(1) | ||
return False | ||
|
||
def delete_template(module, proxmox, node, storage, content_type, template, timeout): | ||
volid = '%s:%s/%s' % (storage, content_type, template) | ||
proxmox.nodes(node).storage(storage).content.delete(volid) | ||
while timeout: | ||
if not get_template(proxmox, node, storage, content_type, template): | ||
return True | ||
timeout = timeout - 1 | ||
if timeout == 0: | ||
module.fail_json(msg='Reached timeout while waiting for deleting template.') | ||
|
||
time.sleep(1) | ||
return False | ||
|
||
def main(): | ||
module = AnsibleModule( | ||
argument_spec = dict( | ||
api_host = dict(required=True), | ||
api_user = dict(required=True), | ||
api_password = dict(no_log=True), | ||
https_verify_ssl = dict(type='bool', choices=BOOLEANS, default='no'), | ||
node = dict(), | ||
src = dict(), | ||
template = dict(), | ||
content_type = dict(default='vztmpl', choices=['vztmpl','iso']), | ||
storage = dict(default='local'), | ||
timeout = dict(type='int', default=300), | ||
force = dict(type='bool', choices=BOOLEANS, default='no'), | ||
state = dict(default='present', choices=['present', 'absent', 'list']), | ||
) | ||
) | ||
|
||
if not HAS_PROXMOXER: | ||
module.fail_json(msg='proxmoxer required for this module') | ||
|
||
state = module.params['state'] | ||
api_user = module.params['api_user'] | ||
api_host = module.params['api_host'] | ||
api_password = module.params['api_password'] | ||
https_verify_ssl = module.params['https_verify_ssl'] | ||
node = module.params['node'] | ||
storage = module.params['storage'] | ||
timeout = module.params['timeout'] | ||
|
||
# If password not set get it from PROXMOX_PASSWORD env | ||
if not api_password: | ||
try: | ||
api_password = os.environ['PROXMOX_PASSWORD'] | ||
except KeyError, e: | ||
module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') | ||
|
||
try: | ||
proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=https_verify_ssl) | ||
except Exception, e: | ||
module.fail_json(msg='authorization on proxmox cluster failed with exception: %s' % e) | ||
|
||
if state == 'present': | ||
try: | ||
content_type = module.params['content_type'] | ||
src = module.params['src'] | ||
|
||
from ansible import utils | ||
realpath = utils.path_dwim(None, src) | ||
template = os.path.basename(realpath) | ||
if get_template(proxmox, node, storage, content_type, template) and not module.params['force']: | ||
module.exit_json(changed=False, msg='template with volid=%s:%s/%s is already exists' % (storage, content_type, template)) | ||
elif not src: | ||
module.fail_json(msg='src param to uploading template file is mandatory') | ||
elif not (os.path.exists(realpath) and os.path.isfile(realpath)): | ||
module.fail_json(msg='template file on path %s not exists' % realpath) | ||
|
||
if upload_template(module, proxmox, node, storage, content_type, realpath, timeout): | ||
module.exit_json(changed=True, msg='template with volid=%s:%s/%s uploaded' % (storage, content_type, template)) | ||
except Exception, e: | ||
module.fail_json(msg="uploading of template %s failed with exception: %s" % ( template, e )) | ||
|
||
elif state == 'absent': | ||
try: | ||
content_type = module.params['content_type'] | ||
template = module.params['template'] | ||
|
||
if not template: | ||
module.fail_json(msg='template param is mandatory') | ||
elif not get_template(proxmox, node, storage, content_type, template): | ||
module.exit_json(changed=False, msg='template with volid=%s:%s/%s is already deleted' % (storage, content_type, template)) | ||
|
||
if delete_template(module, proxmox, node, storage, content_type, template, timeout): | ||
module.exit_json(changed=True, msg='template with volid=%s:%s/%s deleted' % (storage, content_type, template)) | ||
except Exception, e: | ||
module.fail_json(msg="deleting of template %s failed with exception: %s" % ( template, e )) | ||
|
||
elif state == 'list': | ||
try: | ||
|
||
module.exit_json(changed=False, templates=get_content(proxmox, node, storage)) | ||
except Exception, e: | ||
module.fail_json(msg="listing of templates %s failed with exception: %s" % ( template, e )) | ||
|
||
# import module snippets | ||
from ansible.module_utils.basic import * | ||
main() |