1#!/usr/bin/python 2 3# (c) 2019, NetApp, Inc 4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 6from __future__ import absolute_import, division, print_function 7__metaclass__ = type 8 9 10ANSIBLE_METADATA = {'metadata_version': '1.1', 11 'status': ['preview'], 12 'supported_by': 'certified'} 13 14 15DOCUMENTATION = ''' 16 17module: na_ontap_object_store 18short_description: NetApp ONTAP manage object store config. 19extends_documentation_fragment: 20 - netapp.na_ontap 21version_added: '2.9' 22author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> 23 24description: 25- Create or delete object store config on ONTAP. 26 27options: 28 29 state: 30 description: 31 - Whether the specified object store config should exist or not. 32 choices: ['present', 'absent'] 33 default: 'present' 34 type: str 35 36 name: 37 required: true 38 description: 39 - The name of the object store config to manage. 40 type: str 41 42 provider_type: 43 required: false 44 description: 45 - The name of the object store config provider. 46 type: str 47 48 server: 49 required: false 50 description: 51 - Fully qualified domain name of the object store config. 52 type: str 53 54 container: 55 required: false 56 description: 57 - Data bucket/container name used in S3 requests. 58 type: str 59 60 access_key: 61 required: false 62 description: 63 - Access key ID for AWS_S3 and SGWS provider types. 64 type: str 65 66 secret_password: 67 required: false 68 description: 69 - Secret access key for AWS_S3 and SGWS provider types. 70 type: str 71''' 72 73EXAMPLES = """ 74- name: object store Create 75 na_ontap_object_store: 76 state: present 77 name: ansible 78 provider_type: SGWS 79 server: abc 80 container: abc 81 access_key: s3.amazonaws.com 82 secret_password: abc 83 hostname: "{{ hostname }}" 84 username: "{{ username }}" 85 password: "{{ password }}" 86 87- name: object store Create 88 na_ontap_object_store: 89 state: absent 90 name: ansible 91 hostname: "{{ hostname }}" 92 username: "{{ username }}" 93 password: "{{ password }}" 94""" 95 96RETURN = """ 97 98""" 99import traceback 100 101from ansible.module_utils.basic import AnsibleModule 102from ansible.module_utils._text import to_native 103import ansible.module_utils.netapp as netapp_utils 104from ansible.module_utils.netapp_module import NetAppModule 105 106HAS_NETAPP_LIB = netapp_utils.has_netapp_lib() 107 108 109class NetAppOntapObjectStoreConfig(object): 110 ''' object initialize and class methods ''' 111 112 def __init__(self): 113 self.argument_spec = netapp_utils.na_ontap_host_argument_spec() 114 self.argument_spec.update(dict( 115 name=dict(required=True, type='str'), 116 state=dict(required=False, choices=['present', 'absent'], default='present'), 117 provider_type=dict(required=False, type='str'), 118 server=dict(required=False, type='str'), 119 container=dict(required=False, type='str'), 120 access_key=dict(required=False, type='str'), 121 secret_password=dict(required=False, type='str', no_log=True) 122 )) 123 124 self.module = AnsibleModule( 125 argument_spec=self.argument_spec, 126 supports_check_mode=True 127 ) 128 129 self.na_helper = NetAppModule() 130 self.parameters = self.na_helper.set_parameters(self.module.params) 131 if HAS_NETAPP_LIB is False: 132 self.module.fail_json(msg="the python NetApp-Lib module is required") 133 else: 134 self.server = netapp_utils.setup_na_ontap_zapi(module=self.module) 135 136 def get_aggr_object_store(self): 137 """ 138 Fetch details if object store config exists. 139 :return: 140 Dictionary of current details if object store config found 141 None if object store config is not found 142 """ 143 aggr_object_store_get_iter = netapp_utils.zapi.NaElement.create_node_with_children( 144 'aggr-object-store-config-get', **{'object-store-name': self.parameters['name']}) 145 result = None 146 try: 147 result = self.server.invoke_successfully(aggr_object_store_get_iter, enable_tunneling=False) 148 except netapp_utils.zapi.NaApiError as error: 149 # Error 15661 denotes an object store not being found. 150 if to_native(error.code) == "15661": 151 pass 152 else: 153 self.module.fail_json(msg=to_native(error), exception=traceback.format_exc()) 154 return result 155 156 def create_aggr_object_store(self): 157 """ 158 Create aggregate object store config 159 :return: None 160 """ 161 required_keys = set(['provider_type', 'server', 'container', 'access_key']) 162 if not required_keys.issubset(set(self.parameters.keys())): 163 self.module.fail_json(msg='Error provisioning object store %s: one of the following parameters are missing ' 164 '%s' % (self.parameters['name'], ', '.join(required_keys))) 165 options = {'object-store-name': self.parameters['name'], 166 'provider-type': self.parameters['provider_type'], 167 'server': self.parameters['server'], 168 's3-name': self.parameters['container'], 169 'access-key': self.parameters['access_key']} 170 if self.parameters.get('secret_password'): 171 options['secret-password'] = self.parameters['secret_password'] 172 object_store_create = netapp_utils.zapi.NaElement.create_node_with_children('aggr-object-store-config-create', **options) 173 174 try: 175 self.server.invoke_successfully(object_store_create, enable_tunneling=False) 176 except netapp_utils.zapi.NaApiError as error: 177 self.module.fail_json(msg="Error provisioning object store config %s: %s" 178 % (self.parameters['name'], to_native(error)), 179 exception=traceback.format_exc()) 180 181 def delete_aggr_object_store(self): 182 """ 183 Delete aggregate object store config 184 :return: None 185 """ 186 object_store_destroy = netapp_utils.zapi.NaElement.create_node_with_children( 187 'aggr-object-store-config-delete', **{'object-store-name': self.parameters['name']}) 188 189 try: 190 self.server.invoke_successfully(object_store_destroy, 191 enable_tunneling=False) 192 except netapp_utils.zapi.NaApiError as error: 193 self.module.fail_json(msg="Error removing object store config %s: %s" % 194 (self.parameters['name'], to_native(error)), exception=traceback.format_exc()) 195 196 def asup_log_for_cserver(self, event_name): 197 """ 198 Fetch admin vserver for the given cluster 199 Create and Autosupport log event with the given module name 200 :param event_name: Name of the event log 201 :return: None 202 """ 203 results = netapp_utils.get_cserver(self.server) 204 cserver = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=results) 205 netapp_utils.ems_log_event(event_name, cserver) 206 207 def apply(self): 208 """ 209 Apply action to the object store config 210 :return: None 211 """ 212 self.asup_log_for_cserver("na_ontap_object_store_config") 213 current = self.get_aggr_object_store() 214 cd_action = self.na_helper.get_cd_action(current, self.parameters) 215 216 if self.na_helper.changed: 217 if self.module.check_mode: 218 pass 219 else: 220 if cd_action == 'create': 221 self.create_aggr_object_store() 222 elif cd_action == 'delete': 223 self.delete_aggr_object_store() 224 self.module.exit_json(changed=self.na_helper.changed) 225 226 227def main(): 228 """ 229 Create Object Store Config class instance and invoke apply 230 :return: None 231 """ 232 obj_store = NetAppOntapObjectStoreConfig() 233 obj_store.apply() 234 235 236if __name__ == '__main__': 237 main() 238