1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3 4# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> 5# 6# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 7 8from __future__ import absolute_import, division, print_function 9__metaclass__ = type 10 11 12ANSIBLE_METADATA = { 13 'metadata_version': '1.1', 14 'status': ['preview'], 15 'supported_by': 'community' 16} 17 18DOCUMENTATION = r''' 19--- 20module: vmware_host_ipv6 21short_description: Enables/Disables IPv6 support for an ESXi host system 22description: 23- This module can be used to enable or disable IPv6 support for ESXi host systems in given vCenter infrastructure. 24- It also checks if the host needs to be restarted. 25version_added: 2.8 26author: 27- Christian Kotte (@ckotte) <christian.kotte@gmx.de> 28notes: 29- Tested on vSphere 6.5 30requirements: 31- python >= 2.6 32- PyVmomi 33options: 34 state: 35 description: 36 - Enable or disable IPv6 support. 37 - You need to reboot the ESXi host if you change the configuration. 38 type: str 39 choices: [ enabled, disabled ] 40 default: 'enabled' 41 esxi_hostname: 42 description: 43 - Name of the host system to work with. 44 - This is required parameter if C(cluster_name) is not specified. 45 type: str 46 cluster_name: 47 description: 48 - Name of the cluster from which all host systems will be used. 49 - This is required parameter if C(esxi_hostname) is not specified. 50 type: str 51extends_documentation_fragment: vmware.documentation 52''' 53 54EXAMPLES = r''' 55- name: Enable IPv6 for an host system 56 vmware_host_ipv6: 57 hostname: '{{ vcenter_hostname }}' 58 username: '{{ vcenter_username }}' 59 password: '{{ vcenter_password }}' 60 esxi_hostname: '{{ esxi_hostname }}' 61 state: enabled 62 validate_certs: no 63 delegate_to: localhost 64 65- name: Disable IPv6 for an host system 66 vmware_host_ipv6: 67 hostname: '{{ vcenter_hostname }}' 68 username: '{{ vcenter_username }}' 69 password: '{{ vcenter_password }}' 70 esxi_hostname: '{{ esxi_hostname }}' 71 state: disabled 72 validate_certs: no 73 delegate_to: localhost 74 75- name: Disable IPv6 for all host systems from cluster 76 vmware_host_ipv6: 77 hostname: '{{ vcenter_hostname }}' 78 username: '{{ vcenter_username }}' 79 password: '{{ vcenter_password }}' 80 cluster_name: '{{ cluster_name }}' 81 state: disabled 82 validate_certs: no 83 delegate_to: localhost 84''' 85 86RETURN = r''' 87result: 88 description: metadata about host system's IPv6 configuration 89 returned: always 90 type: dict 91 sample: { 92 "esxi01": { 93 "changed": false, 94 "msg": "IPv6 is already enabled and active for host 'esxi01'", 95 }, 96 } 97''' 98 99try: 100 from pyVmomi import vim, vmodl 101except ImportError: 102 pass 103 104from ansible.module_utils.basic import AnsibleModule 105from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec 106from ansible.module_utils._text import to_native 107 108 109class VmwareHostIPv6(PyVmomi): 110 """Class to manage IPv6 for an ESXi host system""" 111 def __init__(self, module): 112 super(VmwareHostIPv6, self).__init__(module) 113 cluster_name = self.params.get('cluster_name') 114 esxi_host_name = self.params.get('esxi_hostname') 115 self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) 116 if not self.hosts: 117 self.module.fail_json(msg="Failed to find host system with given configuration.") 118 119 def ensure(self): 120 """Manage IPv6 for an ESXi host system""" 121 results = dict(changed=False, result=dict()) 122 desired_state = self.module.params['state'] 123 124 host_change_list = [] 125 for host in self.hosts: 126 changed = False 127 results['result'][host.name] = dict(msg='') 128 129 host_network_system = host.configManager.networkSystem 130 host_network_info = host_network_system.networkInfo 131 132 if desired_state == 'enabled': 133 # Don't do anything if IPv6 is already enabled 134 if host_network_info.atBootIpV6Enabled: 135 if host_network_info.ipV6Enabled: 136 results['result'][host.name]['msg'] = "IPv6 is already enabled and active for host '%s'" % \ 137 host.name 138 if not host_network_info.ipV6Enabled: 139 results['result'][host.name]['msg'] = ("IPv6 is already enabled for host '%s', but a reboot" 140 " is required!" % host.name) 141 # Enable IPv6 142 else: 143 if not self.module.check_mode: 144 try: 145 config = vim.host.NetworkConfig() 146 config.ipV6Enabled = True 147 host_network_system.UpdateNetworkConfig(config, "modify") 148 changed = True 149 results['result'][host.name]['changed'] = True 150 results['result'][host.name]['msg'] = "IPv6 enabled for host '%s'" % host.name 151 except (vim.fault.AlreadyExists, vim.fault.NotFound): 152 self.module.fail_json(msg="Network entity specified in the configuration for host '%s'" 153 " already exists" % host.name) 154 except vmodl.fault.InvalidArgument as invalid_argument: 155 self.module.fail_json(msg="Invalid parameter specified for host '%s' : %s" % 156 (host.name, to_native(invalid_argument.msg))) 157 except vim.fault.HostConfigFault as config_fault: 158 self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % 159 (host.name, to_native(config_fault.msg))) 160 except vmodl.fault.NotSupported as not_supported: 161 self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % 162 (host.name, to_native(not_supported.msg))) 163 except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: 164 self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % 165 (host.name, to_native(runtime_fault.msg))) 166 else: 167 changed = True 168 results['result'][host.name]['changed'] = True 169 results['result'][host.name]['msg'] = "IPv6 will be enabled for host '%s'" % host.name 170 elif desired_state == 'disabled': 171 # Don't do anything if IPv6 is already disabled 172 if not host_network_info.atBootIpV6Enabled: 173 if not host_network_info.ipV6Enabled: 174 results['result'][host.name]['msg'] = "IPv6 is already disabled for host '%s'" % host.name 175 if host_network_info.ipV6Enabled: 176 changed = True 177 results['result'][host.name]['msg'] = ("IPv6 is already disabled for host '%s'," 178 " but a reboot is required!" % host.name) 179 # Disable IPv6 180 else: 181 if not self.module.check_mode: 182 try: 183 config = vim.host.NetworkConfig() 184 config.ipV6Enabled = False 185 host_network_system.UpdateNetworkConfig(config, "modify") 186 changed = True 187 results['result'][host.name]['changed'] = True 188 results['result'][host.name]['msg'] = "IPv6 disabled for host '%s'" % host.name 189 except (vim.fault.AlreadyExists, vim.fault.NotFound): 190 self.module.fail_json(msg="Network entity specified in the configuration for host '%s'" 191 " already exists" % host.name) 192 except vmodl.fault.InvalidArgument as invalid_argument: 193 self.module.fail_json(msg="Invalid parameter specified for host '%s' : %s" % 194 (host.name, to_native(invalid_argument.msg))) 195 except vim.fault.HostConfigFault as config_fault: 196 self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % 197 (host.name, to_native(config_fault.msg))) 198 except vmodl.fault.NotSupported as not_supported: 199 self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % 200 (host.name, to_native(not_supported.msg))) 201 except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: 202 self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % 203 (host.name, to_native(runtime_fault.msg))) 204 else: 205 changed = True 206 results['result'][host.name]['changed'] = True 207 results['result'][host.name]['msg'] = "IPv6 will be disabled for host '%s'" % host.name 208 209 host_change_list.append(changed) 210 211 if any(host_change_list): 212 results['changed'] = True 213 self.module.exit_json(**results) 214 215 216def main(): 217 """ 218 Main 219 """ 220 argument_spec = vmware_argument_spec() 221 argument_spec.update( 222 state=dict(default='enabled', choices=['enabled', 'disabled']), 223 esxi_hostname=dict(type='str', required=False), 224 cluster_name=dict(type='str', required=False), 225 ) 226 227 module = AnsibleModule(argument_spec=argument_spec, 228 required_one_of=[ 229 ['cluster_name', 'esxi_hostname'], 230 ], 231 supports_check_mode=True 232 ) 233 234 ipv6 = VmwareHostIPv6(module) 235 ipv6.ensure() 236 237 238if __name__ == '__main__': 239 main() 240