#!/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 . 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()