diff --git a/lib/ansible/module_utils/xenserver.py b/lib/ansible/module_utils/xenserver.py index 2a19844f60..59ec8992e6 100644 --- a/lib/ansible/module_utils/xenserver.py +++ b/lib/ansible/module_utils/xenserver.py @@ -601,7 +601,7 @@ def set_vm_power_state(module, vm_ref, power_state, timeout=300): if task_result: module.fail_json(msg="Guest shutdown task failed: '%s'!" % task_result) else: - module.fail_json(msg="Cannot shutdown guest when VM is in state '%s'." % vm_power_state_current) + module.fail_json(msg="Cannot shutdown guest when VM is in state '%s'!" % vm_power_state_current) elif power_state == "rebootguest": # running state is required for guest reboot. if vm_power_state_current == "poweredon": @@ -615,7 +615,7 @@ def set_vm_power_state(module, vm_ref, power_state, timeout=300): if task_result: module.fail_json(msg="Guest reboot task failed: '%s'!" % task_result) else: - module.fail_json(msg="Cannot reboot guest when VM is in state '%s'." % vm_power_state_current) + module.fail_json(msg="Cannot reboot guest when VM is in state '%s'!" % vm_power_state_current) else: module.fail_json(msg="Requested VM power state '%s' is unsupported!" % power_state) @@ -807,10 +807,11 @@ class XAPI(object): hostname = "http://%s" % hostname try: - # ignore_ssl is supported in XenAPI.py 7.2 onward but there - # is no way to tell which version we are using. TypeError will - # be raised if ignore_ssl is not supported. Additionally, - # ignore_ssl requires Python 2.7.9 or newer. + # ignore_ssl is supported in XenAPI library from XenServer 7.2 + # SDK onward but there is no way to tell which version we + # are using. TypeError will be raised if ignore_ssl is not + # supported. Additionally, ignore_ssl requires Python 2.7.9 + # or newer. cls._xapi_session = XenAPI.Session(hostname, ignore_ssl=ignore_ssl) except TypeError: # Try without ignore_ssl. @@ -827,6 +828,7 @@ class XAPI(object): # Disabling atexit should be used in special cases only. if disconnect_atexit: atexit.register(cls._xapi_session.logout) + return cls._xapi_session @@ -854,7 +856,9 @@ class XenServerObject(object): module: Reference to Ansible module object. """ if not HAS_XENAPI: - module.fail_json(changed=False, msg="XenAPI.py required for this module! Please download XenServer SDK and copy XenAPI.py to your site-packages.") + module.fail_json(changed=False, msg=("XenAPI Python library is required for this module! " + "Please download XenServer SDK and copy XenAPI.py to your Python site-packages. " + "Check Notes section in module documentation for more info.")) if module: self.module = module diff --git a/lib/ansible/modules/cloud/xenserver/xenserver_guest.py b/lib/ansible/modules/cloud/xenserver/xenserver_guest.py index 88296ee30d..60ac77fd05 100644 --- a/lib/ansible/modules/cloud/xenserver/xenserver_guest.py +++ b/lib/ansible/modules/cloud/xenserver/xenserver_guest.py @@ -23,12 +23,15 @@ version_added: '2.8' author: - Bojan Vitnik (@bvitnik) notes: -- Minimal supported version of XenServer is 5.6 -- Module was tested with XenServer 6.5, 7.1 and 7.2 +- Minimal supported version of XenServer is 5.6. +- Module was tested with XenServer 6.5, 7.1 and 7.2. +- 'XenAPI Python library can be acquired from XenServer SDK (downloadable from Citrix website) or by running C(pip install XenAPI) (possibly very old + version, not compatible with Python 3.x). Latest version can also be acquired from GitHub: + https://raw.githubusercontent.com/xapi-project/xen-api/master/scripts/examples/python/XenAPI.py' - 'If no scheme is specified in C(hostname), module defaults to C(http://) because C(https://) is problematic in most setups. Make sure you are accessing XenServer host in trusted environment or use C(https://) scheme explicitly.' - 'To use C(https://) scheme for C(hostname) you have to either import host certificate to your OS certificate store or use C(validate_certs: no) - which requires XenAPI.py from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' + which requires XenAPI library from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' - 'Network configuration inside a guest OS, by using C(networks.type), C(networks.ip), C(networks.gateway) etc. parameters, is supported on XenServer 7.0 or newer for Windows guests by using official XenServer Guest agent support for network configuration. The module will try to detect if such support is available and utilize it, else it will use a custom method of configuration via xenstore. Since XenServer Guest @@ -52,8 +55,9 @@ options: - Specify the state VM should be in. - If C(state) is set to C(present) and VM exists, ensure the VM configuration conforms to given parameters. - If C(state) is set to C(present) and VM does not exist, then VM is deployed with given parameters. - - If C(state) is set to C(absent) and virtual machine exists, then VM is removed with its associated components. + - If C(state) is set to C(absent) and VM exists, then VM is removed with its associated components. - If C(state) is set to C(poweredon) and VM does not exist, then VM is deployed with given parameters and powered on automatically. + type: str default: present choices: [ present, absent, poweredon ] name: @@ -62,16 +66,19 @@ options: - VMs running on XenServer do not necessarily have unique names. The module will fail if multiple VMs with same name are found. - In case of multiple VMs with same name, use C(uuid) to uniquely specify VM to manage. - This parameter is case sensitive. + type: str required: yes - aliases: [ 'name_label' ] + aliases: [ name_label ] name_desc: description: - VM description. + type: str uuid: description: - - UUID of the VM to manage if known, this is XenServer's unique identifier. + - UUID of the VM to manage if known. This is XenServer's unique identifier. - It is required if name is not unique. - Please note that a supplied UUID will be ignored on VM creation, as XenServer creates the UUID internally. + type: str template: description: - Name of a template, an existing VM (must be shut down) or a snapshot that should be used to create VM. @@ -79,22 +86,25 @@ options: - In case of multiple templates/VMs/snapshots with same name, use C(template_uuid) to uniquely specify source template. - If VM already exists, this setting will be ignored. - This parameter is case sensitive. - aliases: [ 'template_src' ] + type: str + aliases: [ template_src ] template_uuid: description: - UUID of a template, an existing VM or a snapshot that should be used to create VM. - It is required if template name is not unique. + type: str is_template: description: - Convert VM to template. - default: 'no' type: bool + default: no folder: description: - Destination folder for VM. - This parameter is case sensitive. - 'Example:' - - ' folder: /folder1/folder2' + - ' folder: /folder1/folder2' + type: str hardware: description: - Manage VM's hardware parameters. VM needs to be shut down to reconfigure these parameters. @@ -102,6 +112,7 @@ options: - ' - C(num_cpus) (integer): Number of CPUs.' - ' - C(num_cpu_cores_per_socket) (integer): Number of Cores Per Socket. C(num_cpus) has to be a multiple of C(num_cpu_cores_per_socket).' - ' - C(memory_mb) (integer): Amount of memory in MB.' + type: dict disks: description: - A list of disks to add to VM. @@ -114,15 +125,17 @@ options: - ' - C(name_desc) (string): Disk description.' - ' - C(sr) (string): Storage Repository to create disk on. If not specified, will use default SR. Cannot be used for moving disk to other SR.' - ' - C(sr_uuid) (string): UUID of a SR to create disk on. Use if SR name is not unique.' - aliases: [ 'disk' ] + type: list + aliases: [ disk ] cdrom: description: - A CD-ROM configuration for the VM. - - All parameters case sensitive. + - All parameters are case sensitive. - 'Valid parameters are:' - ' - C(type) (string): The type of CD-ROM, valid options are C(none) or C(iso). With C(none) the CD-ROM device will be present but empty.' - ' - C(iso_name) (string): The file name of an ISO image from one of the XenServer ISO Libraries (implies C(type: iso)). Required if C(type) is set to C(iso).' + type: dict networks: description: - A list of networks (in the order of the NICs). @@ -141,47 +154,53 @@ options: On some operating systems it could be DHCP configured (e.g. Windows) or unconfigured interface (e.g. Linux).' - ' - C(ip6) (string): Static IPv6 address (implies C(type6: static)) with prefix in format /.' - ' - C(gateway6) (string): Static IPv6 gateway.' - aliases: [ 'network' ] + type: list + aliases: [ network ] home_server: description: - Name of a XenServer host that will be a Home Server for the VM. - This parameter is case sensitive. + type: str custom_params: description: - Define a list of custom VM params to set on VM. - - A custom value object takes two fields C(key) and C(value). + - Useful for advanced users familiar with managing VM params trough xe CLI. + - A custom value object takes two fields C(key) and C(value) (see example below). + type: list wait_for_ip_address: description: - Wait until XenServer detects an IP address for the VM. - - This requires XenServer Tools preinstaled on VM to properly work. - default: 'no' + - This requires XenServer Tools to be preinstalled on the VM to work properly. type: bool + default: no state_change_timeout: description: - 'By default, module will wait indefinitely for VM to accquire an IP address if C(wait_for_ip_address: yes).' - If this parameter is set to positive value, the module will instead wait specified number of seconds for the state change. - In case of timeout, module will generate an error message. + type: int default: 0 linked_clone: description: - Whether to create a Linked Clone from the template, existing VM or snapshot. If no, will create a full copy. - default: 'no' + - This is equivalent to C(Use storage-level fast disk clone) option in XenCenter. type: bool + default: no force: description: - Ignore warnings and complete the actions. - This parameter is useful for removing VM in running state or reconfiguring VM params that require VM to be shut down. - default: 'no' type: bool + default: no extends_documentation_fragment: xenserver.documentation ''' EXAMPLES = r''' - name: Create a VM from a template xenserver_guest: - hostname: 192.0.2.44 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" validate_certs: no folder: /testvms name: testvm_2 @@ -206,9 +225,9 @@ EXAMPLES = r''' - name: Create a VM template xenserver_guest: - hostname: 192.0.2.88 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" validate_certs: no folder: /testvms name: testvm_6 @@ -224,9 +243,9 @@ EXAMPLES = r''' - name: Rename a VM (requires the VM's UUID) xenserver_guest: - hostname: 192.168.1.209 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" uuid: 421e4592-c069-924d-ce20-7e7533fab926 name: new_name state: present @@ -234,18 +253,18 @@ EXAMPLES = r''' - name: Remove a VM by UUID xenserver_guest: - hostname: 192.168.1.209 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" uuid: 421e4592-c069-924d-ce20-7e7533fab926 state: absent delegate_to: localhost -- name: Modify custom params +- name: Modify custom params (boot order) xenserver_guest: - hostname: 192.168.1.210 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" name: testvm_8 state: present custom_params: @@ -255,9 +274,9 @@ EXAMPLES = r''' - name: Customize network parameters xenserver_guest: - hostname: 192.168.1.209 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" name: testvm_10 networks: - name: VM Network @@ -508,7 +527,7 @@ class XenServerVM(XenServerObject): if self.default_sr_ref != "OpaqueRef:NULL": sr_ref = self.default_sr_ref else: - self.module.fail_json(msg="VM deploy disks[0]: no default SR found! You must specify SR explicitely.") + self.module.fail_json(msg="VM deploy disks[0]: no default SR found! You must specify SR explicitly.") # Support for Ansible check mode. if self.module.check_mode: @@ -1258,7 +1277,7 @@ class XenServerVM(XenServerObject): get_object_ref(self.module, disk_sr, disk_sr_uuid, obj_type="SR", fail=True, msg_prefix="VM check disks[%s]: " % position) elif self.default_sr_ref == 'OpaqueRef:NULL': - self.module.fail_json(msg="VM check disks[%s]: no default SR found! You must specify SR explicitely." % position) + self.module.fail_json(msg="VM check disks[%s]: no default SR found! You must specify SR explicitly." % position) if not vbd_userdevices_allowed: self.module.fail_json(msg="VM check disks[%s]: maximum number of devices reached!" % position) diff --git a/lib/ansible/modules/cloud/xenserver/xenserver_guest_facts.py b/lib/ansible/modules/cloud/xenserver/xenserver_guest_facts.py index 2834179690..811d4e3193 100644 --- a/lib/ansible/modules/cloud/xenserver/xenserver_guest_facts.py +++ b/lib/ansible/modules/cloud/xenserver/xenserver_guest_facts.py @@ -21,37 +21,42 @@ version_added: '2.8' author: - Bojan Vitnik (@bvitnik) notes: -- Minimal supported version of XenServer is 5.6 -- Module was tested with XenServer 6.5, 7.1 and 7.2 +- Minimal supported version of XenServer is 5.6. +- Module was tested with XenServer 6.5, 7.1 and 7.2. +- 'XenAPI Python library can be acquired from XenServer SDK (downloadable from Citrix website) or by running C(pip install XenAPI) (possibly very old + version, not compatible with Python 3.x). Latest version can also be acquired from GitHub: + https://raw.githubusercontent.com/xapi-project/xen-api/master/scripts/examples/python/XenAPI.py' - 'If no scheme is specified in C(hostname), module defaults to C(http://) because C(https://) is problematic in most setups. Make sure you are accessing XenServer host in trusted environment or use C(https://) scheme explicitly.' - 'To use C(https://) scheme for C(hostname) you have to either import host certificate to your OS certificate store or use C(validate_certs: no) - which requires XenAPI.py from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' + which requires XenAPI library from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' requirements: - python >= 2.6 - XenAPI options: name: description: - - Name of the VM to gather fact. + - Name of the VM to gather facts from. - VMs running on XenServer do not necessarily have unique names. The module will fail if multiple VMs with same name are found. - In case of multiple VMs with same name, use C(uuid) to uniquely specify VM to manage. - This parameter is case sensitive. + type: str required: yes - aliases: [ 'name_label' ] + aliases: [ name_label ] uuid: description: - - UUID of the VM to gather fact of, this is XenServer's unique identifier. + - UUID of the VM to gather fact of. This is XenServer's unique identifier. - It is required if name is not unique. + type: str extends_documentation_fragment: xenserver.documentation ''' EXAMPLES = r''' - name: Gather facts xenserver_guest_facts: - hostname: 192.168.1.209 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" name: testvm_11 delegate_to: localhost register: facts @@ -203,6 +208,7 @@ def main(): result = {'failed': False, 'changed': False} + # Module will exit with an error message if no VM is found. vm = XenServerVM(module) # Gather facts. diff --git a/lib/ansible/modules/cloud/xenserver/xenserver_guest_powerstate.py b/lib/ansible/modules/cloud/xenserver/xenserver_guest_powerstate.py index a385c6dacd..d50680c8b0 100644 --- a/lib/ansible/modules/cloud/xenserver/xenserver_guest_powerstate.py +++ b/lib/ansible/modules/cloud/xenserver/xenserver_guest_powerstate.py @@ -21,12 +21,15 @@ version_added: '2.8' author: - Bojan Vitnik (@bvitnik) notes: -- Minimal supported version of XenServer is 5.6 -- Module was tested with XenServer 6.5, 7.1 and 7.2 +- Minimal supported version of XenServer is 5.6. +- Module was tested with XenServer 6.5, 7.1 and 7.2. +- 'XenAPI Python library can be acquired from XenServer SDK (downloadable from Citrix website) or by running C(pip install XenAPI) (possibly very old + version, not compatible with Python 3.x). Latest version can also be acquired from GitHub: + https://raw.githubusercontent.com/xapi-project/xen-api/master/scripts/examples/python/XenAPI.py' - 'If no scheme is specified in C(hostname), module defaults to C(http://) because C(https://) is problematic in most setups. Make sure you are accessing XenServer host in trusted environment or use C(https://) scheme explicitly.' - 'To use C(https://) scheme for C(hostname) you have to either import host certificate to your OS certificate store or use C(validate_certs: no) - which requires XenAPI.py from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' + which requires XenAPI library from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.' requirements: - python >= 2.6 - XenAPI @@ -36,31 +39,35 @@ options: - Specify the state VM should be in. - If C(state) is set to value other than C(present), then VM is transitioned into required state and facts are returned. - If C(state) is set to C(present), then VM is just checked for existance and facts are returned. + type: str default: present choices: [ powered-on, powered-off, restarted, shutdown-guest, reboot-guest, suspended, present ] name: description: - - Name of the VM to work with. + - Name of the VM to manage. - VMs running on XenServer do not necessarily have unique names. The module will fail if multiple VMs with same name are found. - In case of multiple VMs with same name, use C(uuid) to uniquely specify VM to manage. - This parameter is case sensitive. + type: str required: yes - aliases: [ 'name_label' ] + aliases: [ name_label ] uuid: description: - - UUID of the VM to manage if known, this is XenServer's unique identifier. + - UUID of the VM to manage if known. This is XenServer's unique identifier. - It is required if name is not unique. + type: str wait_for_ip_address: description: - Wait until XenServer detects an IP address for the VM. - - This requires XenServer Tools preinstaled on VM to properly work. - default: 'no' + - This requires XenServer Tools to be preinstalled on the VM to work properly. type: bool + default: no state_change_timeout: description: - 'By default, module will wait indefinitely for VM to change state or accquire an IP address if C(wait_for_ip_address: yes).' - If this parameter is set to positive value, the module will instead wait specified number of seconds for the state change. - In case of timeout, module will generate an error message. + type: int default: 0 extends_documentation_fragment: xenserver.documentation ''' @@ -68,9 +75,9 @@ extends_documentation_fragment: xenserver.documentation EXAMPLES = r''' - name: Power on VM xenserver_guest_powerstate: - hostname: 192.168.1.209 - username: root - password: xenserver + hostname: "{{ xenserver_hostname }}" + username: "{{ xenserver_username }}" + password: "{{ xenserver_password }}" name: testvm_11 state: powered-on delegate_to: localhost @@ -243,6 +250,7 @@ def main(): result = {'failed': False, 'changed': False} + # Module will exit with an error message if no VM is found. vm = XenServerVM(module) # Set VM power state. diff --git a/lib/ansible/plugins/doc_fragments/xenserver.py b/lib/ansible/plugins/doc_fragments/xenserver.py index 7fc3f74673..5be67da4c3 100644 --- a/lib/ansible/plugins/doc_fragments/xenserver.py +++ b/lib/ansible/plugins/doc_fragments/xenserver.py @@ -5,33 +5,33 @@ class ModuleDocFragment(object): - # Parameters for XenServer modules + # Common parameters for XenServer modules DOCUMENTATION = r''' options: - hostname: - description: - - The hostname or IP address of the XenServer host or XenServer pool master. - - If the value is not specified in the task, the value of environment variable C(XENSERVER_HOST) will be used instead. - type: str - default: localhost - aliases: [ host, pool ] - username: - description: - - The username to use for connecting to XenServer. - - If the value is not specified in the task, the value of environment variable C(XENSERVER_USER) will be used instead. - type: str - default: 'root' - aliases: [ admin, user ] - password: - description: - - The password to use for connecting to XenServer. - - If the value is not specified in the task, the value of environment variable C(XENSERVER_PASSWORD) will be used instead. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable C(XENSERVER_VALIDATE_CERTS) will be used instead. - type: bool - default: yes + hostname: + description: + - The hostname or IP address of the XenServer host or XenServer pool master. + - If the value is not specified in the task, the value of environment variable C(XENSERVER_HOST) will be used instead. + type: str + default: localhost + aliases: [ host, pool ] + username: + description: + - The username to use for connecting to XenServer. + - If the value is not specified in the task, the value of environment variable C(XENSERVER_USER) will be used instead. + type: str + default: root + aliases: [ admin, user ] + password: + description: + - The password to use for connecting to XenServer. + - If the value is not specified in the task, the value of environment variable C(XENSERVER_PASSWORD) will be used instead. + type: str + aliases: [ pass, pwd ] + validate_certs: + description: + - Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted. + - If the value is not specified in the task, the value of environment variable C(XENSERVER_VALIDATE_CERTS) will be used instead. + type: bool + default: yes ''' diff --git a/test/units/module_utils/xenserver/test_set_vm_power_state.py b/test/units/module_utils/xenserver/test_set_vm_power_state.py index bbe2180ff1..0cbf0119d3 100644 --- a/test/units/module_utils/xenserver/test_set_vm_power_state.py +++ b/test/units/module_utils/xenserver/test_set_vm_power_state.py @@ -19,12 +19,12 @@ testcase_set_vm_power_state_bad_transitions = { ('restarted', 'Suspended', "Cannot restart VM in state 'suspended'!"), ('suspended', 'Halted', "Cannot suspend VM in state 'poweredoff'!"), ('suspended', 'Paused', "Cannot suspend VM in state 'paused'!"), - ('shutdownguest', 'Halted', "Cannot shutdown guest when VM is in state 'poweredoff'."), - ('shutdownguest', 'Suspended', "Cannot shutdown guest when VM is in state 'suspended'."), - ('shutdownguest', 'Paused', "Cannot shutdown guest when VM is in state 'paused'."), - ('rebootguest', 'Halted', "Cannot reboot guest when VM is in state 'poweredoff'."), - ('rebootguest', 'Suspended', "Cannot reboot guest when VM is in state 'suspended'."), - ('rebootguest', 'Paused', "Cannot reboot guest when VM is in state 'paused'."), + ('shutdownguest', 'Halted', "Cannot shutdown guest when VM is in state 'poweredoff'!"), + ('shutdownguest', 'Suspended', "Cannot shutdown guest when VM is in state 'suspended'!"), + ('shutdownguest', 'Paused', "Cannot shutdown guest when VM is in state 'paused'!"), + ('rebootguest', 'Halted', "Cannot reboot guest when VM is in state 'poweredoff'!"), + ('rebootguest', 'Suspended', "Cannot reboot guest when VM is in state 'suspended'!"), + ('rebootguest', 'Paused', "Cannot reboot guest when VM is in state 'paused'!"), ], "ids": [ "poweredoff->restarted", diff --git a/test/units/module_utils/xenserver/test_xenserverobject.py b/test/units/module_utils/xenserver/test_xenserverobject.py index 1ff114d984..41728d27cf 100644 --- a/test/units/module_utils/xenserver/test_xenserverobject.py +++ b/test/units/module_utils/xenserver/test_xenserverobject.py @@ -20,7 +20,9 @@ def test_xenserverobject_xenapi_lib_detection(mocker, fake_ansible_module, xense with pytest.raises(FailJsonException) as exc_info: xenserver.XenServerObject(fake_ansible_module) - assert exc_info.value.kwargs['msg'] == "XenAPI.py required for this module! Please download XenServer SDK and copy XenAPI.py to your site-packages." + assert exc_info.value.kwargs['msg'] == ("XenAPI Python library is required for this module! " + "Please download XenServer SDK and copy XenAPI.py to your Python site-packages. " + "Check Notes section in module documentation for more info.") def test_xenserverobject_xenapi_failure(mock_xenapi_failure, fake_ansible_module, xenserver):