1#!/usr/local/bin/python3.8 2 3# (c) 2017-2019, NetApp, Inc 4# GNU General Public License v3.0+ 5# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10 11ANSIBLE_METADATA = {'metadata_version': '1.1', 12 'status': ['preview'], 13 'supported_by': 'certified'} 14 15 16DOCUMENTATION = ''' 17 18module: na_ontap_iscsi 19 20short_description: NetApp ONTAP manage iSCSI service 21extends_documentation_fragment: 22 - netapp.ontap.netapp.na_ontap 23version_added: 2.6.0 24author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> 25 26description: 27- create, delete, start, stop iSCSI service on SVM. 28 29options: 30 31 state: 32 description: 33 - Whether the service should be present or deleted. 34 choices: ['present', 'absent'] 35 type: str 36 default: present 37 38 service_state: 39 description: 40 - Whether the specified service should running. 41 choices: ['started', 'stopped'] 42 type: str 43 44 vserver: 45 required: true 46 type: str 47 description: 48 - The name of the vserver to use. 49 50''' 51 52EXAMPLES = """ 53- name: Create iscsi service 54 na_ontap_iscsi: 55 state: present 56 service_state: started 57 vserver: ansibleVServer 58 hostname: "{{ netapp_hostname }}" 59 username: "{{ netapp_username }}" 60 password: "{{ netapp_password }}" 61 62- name: Stop Iscsi service 63 na_ontap_iscsi: 64 state: present 65 service_state: stopped 66 vserver: ansibleVServer 67 hostname: "{{ netapp_hostname }}" 68 username: "{{ netapp_username }}" 69 password: "{{ netapp_password }}" 70 71- name: Delete Iscsi service 72 na_ontap_iscsi: 73 state: absent 74 vserver: ansibleVServer 75 hostname: "{{ netapp_hostname }}" 76 username: "{{ netapp_username }}" 77 password: "{{ netapp_password }}" 78""" 79 80RETURN = """ 81 82""" 83 84import traceback 85 86from ansible.module_utils.basic import AnsibleModule 87from ansible.module_utils._text import to_native 88import ansible_collections.netapp.ontap.plugins.module_utils.netapp as netapp_utils 89 90HAS_NETAPP_LIB = netapp_utils.has_netapp_lib() 91 92 93class NetAppOntapISCSI(object): 94 95 def __init__(self): 96 97 self.argument_spec = netapp_utils.na_ontap_host_argument_spec() 98 self.argument_spec.update(dict( 99 state=dict(required=False, type='str', choices=['present', 'absent'], default='present'), 100 service_state=dict(required=False, type='str', choices=['started', 'stopped'], default=None), 101 vserver=dict(required=True, type='str'), 102 )) 103 104 self.module = AnsibleModule( 105 argument_spec=self.argument_spec, 106 supports_check_mode=True 107 ) 108 109 params = self.module.params 110 111 # set up state variables 112 self.state = params['state'] 113 self.service_state = params['service_state'] 114 if self.state == 'present' and self.service_state is None: 115 self.service_state = 'started' 116 self.vserver = params['vserver'] 117 self.is_started = None 118 119 if HAS_NETAPP_LIB is False: 120 self.module.fail_json( 121 msg="the python NetApp-Lib module is required") 122 else: 123 self.server = netapp_utils.setup_na_ontap_zapi( 124 module=self.module, vserver=self.vserver) 125 126 def get_iscsi(self): 127 """ 128 Return details about the iscsi service 129 130 :return: Details about the iscsi service 131 :rtype: dict 132 """ 133 iscsi_info = netapp_utils.zapi.NaElement('iscsi-service-get-iter') 134 iscsi_attributes = netapp_utils.zapi.NaElement('iscsi-service-info') 135 136 iscsi_attributes.add_new_child('vserver', self.vserver) 137 138 query = netapp_utils.zapi.NaElement('query') 139 query.add_child_elem(iscsi_attributes) 140 141 iscsi_info.add_child_elem(query) 142 143 result = self.server.invoke_successfully(iscsi_info, True) 144 return_value = None 145 146 if result.get_child_by_name('num-records') and \ 147 int(result.get_child_content('num-records')) >= 1: 148 149 iscsi = result.get_child_by_name( 150 'attributes-list').get_child_by_name('iscsi-service-info') 151 if iscsi: 152 is_started = iscsi.get_child_content('is-available') == 'true' 153 return_value = { 154 'is_started': is_started 155 } 156 157 return return_value 158 159 def create_iscsi_service(self): 160 """ 161 Create iscsi service and start if requested 162 """ 163 iscsi_service = netapp_utils.zapi.NaElement.create_node_with_children( 164 'iscsi-service-create', 165 **{'start': 'true' if self.state == 'started' else 'false' 166 }) 167 168 try: 169 self.server.invoke_successfully( 170 iscsi_service, enable_tunneling=True) 171 except netapp_utils.zapi.NaApiError as e: 172 self.module.fail_json(msg="Error creating iscsi service: % s" 173 % (to_native(e)), 174 exception=traceback.format_exc()) 175 176 def delete_iscsi_service(self): 177 """ 178 Delete the iscsi service 179 """ 180 if self.is_started: 181 self.stop_iscsi_service() 182 183 iscsi_delete = netapp_utils.zapi.NaElement.create_node_with_children( 184 'iscsi-service-destroy') 185 186 try: 187 self.server.invoke_successfully( 188 iscsi_delete, enable_tunneling=True) 189 except netapp_utils.zapi.NaApiError as e: 190 self.module.fail_json(msg="Error deleting iscsi service \ 191 on vserver %s: %s" 192 % (self.vserver, to_native(e)), 193 exception=traceback.format_exc()) 194 195 def stop_iscsi_service(self): 196 """ 197 Stop iscsi service 198 """ 199 200 iscsi_stop = netapp_utils.zapi.NaElement.create_node_with_children( 201 'iscsi-service-stop') 202 203 try: 204 self.server.invoke_successfully(iscsi_stop, enable_tunneling=True) 205 except netapp_utils.zapi.NaApiError as e: 206 self.module.fail_json(msg="Error Stopping iscsi service \ 207 on vserver %s: %s" 208 % (self.vserver, to_native(e)), 209 exception=traceback.format_exc()) 210 211 def start_iscsi_service(self): 212 """ 213 Start iscsi service 214 """ 215 iscsi_start = netapp_utils.zapi.NaElement.create_node_with_children( 216 'iscsi-service-start') 217 218 try: 219 self.server.invoke_successfully(iscsi_start, enable_tunneling=True) 220 except netapp_utils.zapi.NaApiError as e: 221 self.module.fail_json(msg="Error starting iscsi service \ 222 on vserver %s: %s" 223 % (self.vserver, to_native(e)), 224 exception=traceback.format_exc()) 225 226 def apply(self): 227 property_changed = False 228 iscsi_service_exists = False 229 netapp_utils.ems_log_event("na_ontap_iscsi", self.server) 230 iscsi_service_detail = self.get_iscsi() 231 232 if iscsi_service_detail: 233 self.is_started = iscsi_service_detail['is_started'] 234 iscsi_service_exists = True 235 236 if self.state == 'absent': 237 property_changed = True 238 239 elif self.state == 'present': 240 is_started = 'started' if self.is_started else 'stopped' 241 property_changed = is_started != self.service_state 242 243 else: 244 if self.state == 'present': 245 property_changed = True 246 247 if property_changed: 248 if self.module.check_mode: 249 pass 250 else: 251 if self.state == 'present': 252 if not iscsi_service_exists: 253 self.create_iscsi_service() # the service is stopped when initially created 254 if self.service_state == 'started': 255 self.start_iscsi_service() 256 if iscsi_service_exists and self.service_state == 'stopped': 257 self.stop_iscsi_service() 258 259 elif self.state == 'absent': 260 self.delete_iscsi_service() 261 262 changed = property_changed 263 # TODO: include other details about the lun (size, etc.) 264 self.module.exit_json(changed=changed) 265 266 267def main(): 268 v = NetAppOntapISCSI() 269 v.apply() 270 271 272if __name__ == '__main__': 273 main() 274