예제 #1
0
class NetAppONTAPasup(object):
    """Class with autosupport methods"""
    def __init__(self):

        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
        self.argument_spec.update(
            dict(
                state=dict(required=False,
                           choices=['present', 'absent'],
                           default='present'),
                node_name=dict(required=True, type='str'),
                transport=dict(required=False,
                               type='str',
                               choices=['smtp', 'http', 'https']),
                noteto=dict(required=False, type='list'),
                post_url=dict(reuired=False, type='str'),
                support=dict(required=False, type='bool'),
                mail_hosts=dict(required=False, type='list'),
                from_address=dict(required=False, type='str'),
                partner_addresses=dict(required=False, type='list'),
                to_addresses=dict(required=False, type='list'),
                proxy_url=dict(required=False, type='str'),
                hostname_in_subject=dict(required=False, type='bool'),
            ))

        self.module = AnsibleModule(argument_spec=self.argument_spec,
                                    supports_check_mode=False)

        self.na_helper = NetAppModule()
        self.parameters = self.na_helper.set_parameters(self.module.params)
        # present or absent requires modifying state to enabled or disabled
        self.parameters['service_state'] = 'started' if self.parameters[
            'state'] == 'present' else 'stopped'
        self.set_playbook_zapi_key_map()

        if HAS_NETAPP_LIB is False:
            self.module.fail_json(
                msg="the python NetApp-Lib module is required")
        else:
            self.server = netapp_utils.setup_ontap_zapi(module=self.module)

    def set_playbook_zapi_key_map(self):
        self.na_helper.zapi_string_keys = {
            'node_name': 'node-name',
            'transport': 'transport',
            'post_url': 'post-url',
            'from_address': 'from',
            'proxy_url': 'proxy-url'
        }
        self.na_helper.zapi_list_keys = {
            'noteto': ('noteto', 'mail-address'),
            'mail_hosts': ('mail-hosts', 'string'),
            'partner_addresses': ('partner-address', 'mail-address'),
            'to_addresses': ('to', 'mail-address'),
        }
        self.na_helper.zapi_bool_keys = {
            'support': 'is-support-enabled',
            'hostname_in_subject': 'is-node-in-subject'
        }

    def get_autosupport_config(self):
        """
        Invoke zapi - get current autosupport details
        :return: dict()
        """
        asup_details = netapp_utils.zapi.NaElement('autosupport-config-get')
        asup_details.add_new_child('node-name', self.parameters['node_name'])
        asup_info = dict()
        try:
            result = self.server.invoke_successfully(asup_details,
                                                     enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='%s' % to_native(error),
                                  exception=traceback.format_exc())
        # zapi invoke successful
        asup_attr_info = result.get_child_by_name(
            'attributes').get_child_by_name('autosupport-config-info')
        asup_info['service_state'] = 'started' if asup_attr_info[
            'is-enabled'] == 'true' else 'stopped'
        for item_key, zapi_key in self.na_helper.zapi_string_keys.items():
            asup_info[item_key] = asup_attr_info[zapi_key]
        for item_key, zapi_key in self.na_helper.zapi_bool_keys.items():
            asup_info[item_key] = self.na_helper.get_value_for_bool(
                from_zapi=True, value=asup_attr_info[zapi_key])
        for item_key, zapi_key in self.na_helper.zapi_list_keys.items():
            parent, dummy = zapi_key
            asup_info[item_key] = self.na_helper.get_value_for_list(
                from_zapi=True,
                zapi_parent=asup_attr_info.get_child_by_name(parent))
        return asup_info

    def modify_autosupport_config(self, modify):
        """
        Invoke zapi - modify autosupport config
        @return: NaElement object / FAILURE with an error_message
        """
        asup_details = {'node-name': self.parameters['node_name']}
        if modify.get('service_state'):
            asup_details['is-enabled'] = 'true' if modify.get(
                'service_state') == 'started' else 'false'
        asup_config = netapp_utils.zapi.NaElement('autosupport-config-modify')
        for item_key in modify:
            if item_key in self.na_helper.zapi_string_keys:
                zapi_key = self.na_helper.zapi_string_keys.get(item_key)
                asup_details[zapi_key] = modify[item_key]
            elif item_key in self.na_helper.zapi_bool_keys:
                zapi_key = self.na_helper.zapi_bool_keys.get(item_key)
                asup_details[zapi_key] = self.na_helper.get_value_for_bool(
                    from_zapi=False, value=modify[item_key])
            elif item_key in self.na_helper.zapi_list_keys:
                parent_key, child_key = self.na_helper.zapi_list_keys.get(
                    item_key)
                asup_config.add_child_elem(
                    self.na_helper.get_value_for_list(
                        from_zapi=False,
                        zapi_parent=parent_key,
                        zapi_child=child_key,
                        data=modify.get(item_key)))
        asup_config.translate_struct(asup_details)
        try:
            return self.server.invoke_successfully(asup_config,
                                                   enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='%s' % to_native(error),
                                  exception=traceback.format_exc())

    def autosupport_log(self):
        results = netapp_utils.get_cserver(self.server)
        cserver = netapp_utils.setup_na_ontap_zapi(module=self.module,
                                                   vserver=results)
        netapp_utils.ems_log_event("na_ontap_autosupport", cserver)

    def apply(self):
        """
        Apply action to autosupport
        """
        current = self.get_autosupport_config()
        modify = self.na_helper.get_modified_attributes(
            current, self.parameters)
        if self.na_helper.changed:
            if self.module.check_mode:
                pass
            else:
                self.modify_autosupport_config(modify)
        self.module.exit_json(changed=self.na_helper.changed)
class NetAppontapExportRule(object):
    ''' object initialize and class methods '''
    def __init__(self):

        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
        self.argument_spec.update(
            dict(
                state=dict(required=False,
                           type='str',
                           choices=['present', 'absent'],
                           default='present'),
                name=dict(required=True, type='str', aliases=['policy_name']),
                protocol=dict(required=False,
                              type='list',
                              default=None,
                              choices=[
                                  'any', 'nfs', 'nfs3', 'nfs4', 'cifs',
                                  'flexcache'
                              ]),
                client_match=dict(required=False, type='list'),
                ro_rule=dict(required=False,
                             type='list',
                             default=None,
                             choices=[
                                 'any', 'none', 'never', 'krb5', 'krb5i',
                                 'krb5p', 'ntlm', 'sys'
                             ]),
                rw_rule=dict(required=False,
                             type='list',
                             default=None,
                             choices=[
                                 'any', 'none', 'never', 'krb5', 'krb5i',
                                 'krb5p', 'ntlm', 'sys'
                             ]),
                super_user_security=dict(required=False,
                                         type='list',
                                         default=None,
                                         choices=[
                                             'any', 'none', 'never', 'krb5',
                                             'krb5i', 'krb5p', 'ntlm', 'sys'
                                         ]),
                allow_suid=dict(required=False, type='bool'),
                rule_index=dict(required=False, type='int'),
                vserver=dict(required=True, type='str'),
            ))

        self.module = AnsibleModule(argument_spec=self.argument_spec,
                                    supports_check_mode=True)

        self.na_helper = NetAppModule()
        self.parameters = self.na_helper.set_parameters(self.module.params)
        self.set_playbook_zapi_key_map()

        if HAS_NETAPP_LIB is False:
            self.module.fail_json(
                msg="the python NetApp-Lib module is required")
        else:
            self.server = netapp_utils.setup_na_ontap_zapi(
                module=self.module, vserver=self.parameters['vserver'])

    def set_playbook_zapi_key_map(self):
        self.na_helper.zapi_string_keys = {
            'client_match': 'client-match',
            'name': 'policy-name'
        }
        self.na_helper.zapi_list_keys = {
            'protocol': ('protocol', 'access-protocol'),
            'ro_rule': ('ro-rule', 'security-flavor'),
            'rw_rule': ('rw-rule', 'security-flavor'),
            'super_user_security': ('super-user-security', 'security-flavor'),
        }
        self.na_helper.zapi_bool_keys = {
            'allow_suid': 'is-allow-set-uid-enabled'
        }
        self.na_helper.zapi_int_keys = {'rule_index': 'rule-index'}

    def set_query_parameters(self):
        """
        Return dictionary of query parameters and
        :return:
        """
        query = {
            'policy-name': self.parameters['name'],
            'vserver': self.parameters['vserver']
        }

        if self.parameters.get('rule_index'):
            query['rule-index'] = self.parameters['rule_index']
        elif self.parameters.get('client_match'):
            query['client-match'] = self.parameters['client_match']
        else:
            self.module.fail_json(
                msg=
                "Need to specify at least one of the rule_index and client_match option."
            )

        attributes = {'query': {'export-rule-info': query}}
        return attributes

    def get_export_policy_rule(self):
        """
        Return details about the export policy rule
        :param:
            name : Name of the export_policy
        :return: Details about the export_policy. None if not found.
        :rtype: dict
        """
        current, result = None, None
        rule_iter = netapp_utils.zapi.NaElement('export-rule-get-iter')
        rule_iter.translate_struct(self.set_query_parameters())
        try:
            result = self.server.invoke_successfully(rule_iter, True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(
                msg='Error getting export policy rule %s: %s' %
                (self.parameters['name'], to_native(error)),
                exception=traceback.format_exc())
        if result is not None and \
                result.get_child_by_name('num-records') and int(result.get_child_content('num-records')) >= 1:
            current = dict()
            rule_info = result.get_child_by_name(
                'attributes-list').get_child_by_name('export-rule-info')
            for item_key, zapi_key in self.na_helper.zapi_string_keys.items():
                current[item_key] = rule_info.get_child_content(zapi_key)
            for item_key, zapi_key in self.na_helper.zapi_bool_keys.items():
                current[item_key] = self.na_helper.get_value_for_bool(
                    from_zapi=True, value=rule_info[zapi_key])
            for item_key, zapi_key in self.na_helper.zapi_int_keys.items():
                current[item_key] = self.na_helper.get_value_for_int(
                    from_zapi=True, value=rule_info[zapi_key])
            for item_key, zapi_key in self.na_helper.zapi_list_keys.items():
                parent, dummy = zapi_key
                current[item_key] = self.na_helper.get_value_for_list(
                    from_zapi=True,
                    zapi_parent=rule_info.get_child_by_name(parent))
            current['num_records'] = int(
                result.get_child_content('num-records'))
            if not self.parameters.get('rule_index'):
                self.parameters['rule_index'] = current['rule_index']
        return current

    def get_export_policy(self):
        """
        Return details about the export-policy
        :param:
            name : Name of the export-policy

        :return: Details about the export-policy. None if not found.
        :rtype: dict
        """
        export_policy_iter = netapp_utils.zapi.NaElement(
            'export-policy-get-iter')
        attributes = {
            'query': {
                'export-policy-info': {
                    'policy-name': self.parameters['name'],
                    'vserver': self.parameters['vserver']
                }
            }
        }

        export_policy_iter.translate_struct(attributes)
        try:
            result = self.server.invoke_successfully(export_policy_iter, True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='Error getting export policy %s: %s' %
                                  (self.parameters['name'], to_native(error)),
                                  exception=traceback.format_exc())

        if result.get_child_by_name('num-records') and int(
                result.get_child_content('num-records')) == 1:
            return result

        return None

    def add_parameters_for_create_or_modify(self, na_element_object, values):
        """
            Add children node for create or modify NaElement object
            :param na_element_object: modify or create NaElement object
            :param values: dictionary of cron values to be added
            :return: None
        """
        for key in values:
            if key in self.na_helper.zapi_string_keys:
                zapi_key = self.na_helper.zapi_string_keys.get(key)
                na_element_object[zapi_key] = values[key]
            elif key in self.na_helper.zapi_list_keys:
                parent_key, child_key = self.na_helper.zapi_list_keys.get(key)
                na_element_object.add_child_elem(
                    self.na_helper.get_value_for_list(from_zapi=False,
                                                      zapi_parent=parent_key,
                                                      zapi_child=child_key,
                                                      data=values[key]))
            elif key in self.na_helper.zapi_int_keys:
                zapi_key = self.na_helper.zapi_int_keys.get(key)
                na_element_object[zapi_key] = self.na_helper.get_value_for_int(
                    from_zapi=False, value=values[key])
            elif key in self.na_helper.zapi_bool_keys:
                zapi_key = self.na_helper.zapi_bool_keys.get(key)
                na_element_object[
                    zapi_key] = self.na_helper.get_value_for_bool(
                        from_zapi=False, value=values[key])

    def create_export_policy_rule(self):
        """
        create rule for the export policy.
        """
        for key in ['client_match', 'ro_rule', 'rw_rule']:
            if self.parameters.get(key) is None:
                self.module.fail_json(
                    msg=
                    'Error: Missing required param for creating export policy rule %s'
                    % key)
        export_rule_create = netapp_utils.zapi.NaElement('export-rule-create')
        self.add_parameters_for_create_or_modify(export_rule_create,
                                                 self.parameters)
        try:
            self.server.invoke_successfully(export_rule_create,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(
                msg='Error creating export policy rule %s: %s' %
                (self.parameters['name'], to_native(error)),
                exception=traceback.format_exc())

    def create_export_policy(self):
        """
        Creates an export policy
        """
        export_policy_create = netapp_utils.zapi.NaElement.create_node_with_children(
            'export-policy-create', **{'policy-name': self.parameters['name']})
        try:
            self.server.invoke_successfully(export_policy_create,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='Error creating export-policy %s: %s' %
                                  (self.parameters['name'], to_native(error)),
                                  exception=traceback.format_exc())

    def delete_export_policy_rule(self, rule_index):
        """
        delete rule for the export policy.
        """
        export_rule_delete = netapp_utils.zapi.NaElement.create_node_with_children(
            'export-rule-destroy', **{
                'policy-name': self.parameters['name'],
                'rule-index': str(rule_index)
            })

        try:
            self.server.invoke_successfully(export_rule_delete,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(
                msg='Error deleting export policy rule %s: %s' %
                (self.parameters['name'], to_native(error)),
                exception=traceback.format_exc())

    def modify_export_policy_rule(self, params):
        '''
        Modify an existing export policy rule
        :param params: dict() of attributes with desired values
        :return: None
        '''
        export_rule_modify = netapp_utils.zapi.NaElement.create_node_with_children(
            'export-rule-modify', **{
                'policy-name': self.parameters['name'],
                'rule-index': str(self.parameters['rule_index'])
            })
        self.add_parameters_for_create_or_modify(export_rule_modify, params)
        try:
            self.server.invoke_successfully(export_rule_modify,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(
                msg='Error modifying allow_suid %s: %s' %
                (self.parameters['allow_suid'], to_native(error)),
                exception=traceback.format_exc())

    def autosupport_log(self):
        netapp_utils.ems_log_event("na_ontap_export_policy_rules", self.server)

    def apply(self):
        ''' Apply required action from the play'''
        self.autosupport_log()
        # convert client_match list to comma-separated string
        if self.parameters.get('client_match') is not None:
            self.parameters['client_match'] = ','.join(
                self.parameters['client_match'])
            self.parameters['client_match'] = self.parameters[
                'client_match'].replace(' ', '')

        current, modify = self.get_export_policy_rule(), None
        action = self.na_helper.get_cd_action(current, self.parameters)
        if action is None and self.parameters['state'] == 'present':
            modify = self.na_helper.get_modified_attributes(
                current, self.parameters)

        if self.na_helper.changed:
            if self.module.check_mode:
                pass
            else:
                # create export policy (if policy doesn't exist) only when changed=True
                if not self.get_export_policy():
                    self.create_export_policy()
                if action == 'create':
                    self.create_export_policy_rule()
                elif action == 'delete':
                    if current['num_records'] > 1:
                        self.module.fail_json(
                            msg='Multiple export policy rules exist.'
                            'Please specify a rule_index to delete')
                    self.delete_export_policy_rule(current['rule_index'])
                elif modify:
                    self.modify_export_policy_rule(modify)
        self.module.exit_json(changed=self.na_helper.changed)
예제 #3
0
class NetAppONTAPFirewallPolicy(object):
    def __init__(self):
        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
        self.argument_spec.update(dict(
            state=dict(required=False, choices=['present', 'absent'], default='present'),
            allow_list=dict(required=False, type="list"),
            policy=dict(required=False, type='str'),
            service=dict(required=False, type='str', choices=['dns', 'http', 'https', 'ndmp',
                                                              'ndmps', 'ntp', 'rsh', 'snmp', 'ssh', 'telnet']),
            vserver=dict(required=False, type="str"),
            enable=dict(required=False, type="str", choices=['enable', 'disable']),
            logging=dict(required=False, type="str", choices=['enable', 'disable']),
            node=dict(required=False, type="str")
        ))

        self.module = AnsibleModule(
            argument_spec=self.argument_spec,
            required_together=(['policy', 'service', 'vserver'],
                               ['enable', 'node']
                               ),
            supports_check_mode=True
        )

        self.na_helper = NetAppModule()
        self.parameters = self.na_helper.set_parameters(self.module.params)

        if HAS_NETAPP_LIB is False:
            self.module.fail_json(msg="the python NetApp-Lib module is required")
        else:
            self.server = netapp_utils.setup_na_ontap_zapi(module=self.module)

        if HAS_IPADDRESS_LIB is False:
            self.module.fail_json(msg="the python ipaddress lib is required for this module")
        return

    def validate_ip_addresses(self):
        '''
            Validate if the given IP address is a network address (i.e. it's host bits are set to 0)
            ONTAP doesn't validate if the host bits are set,
            and hence doesn't add a new address unless the IP is from a different network.
            So this validation allows the module to be idempotent.
            :return: None
        '''
        for ip in self.parameters['allow_list']:
            # create an IPv4 object for current IP address
            if sys.version_info[0] >= 3:
                ip_addr = str(ip)
            else:
                ip_addr = unicode(ip)  # pylint: disable=undefined-variable
            # get network address from netmask, throw exception if address is not a network address
            try:
                ipaddress.ip_network(ip_addr)
            except ValueError as exc:
                self.module.fail_json(msg='Error: Invalid IP address value for allow_list parameter.'
                                          'Please specify a network address without host bits set: %s'
                                      % (to_native(exc)))

    def get_firewall_policy(self):
        """
        Get a firewall policy
        :return: returns a firewall policy object, or returns False if there are none
        """
        net_firewall_policy_obj = netapp_utils.zapi.NaElement("net-firewall-policy-get-iter")
        attributes = {
            'query': {
                'net-firewall-policy-info': self.firewall_policy_attributes()
            }
        }
        net_firewall_policy_obj.translate_struct(attributes)

        try:
            result = self.server.invoke_successfully(net_firewall_policy_obj, True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error getting firewall policy %s:%s" % (self.parameters['policy'],
                                                                               to_native(error)),
                                  exception=traceback.format_exc())

        if result.get_child_by_name('num-records') and int(result.get_child_content('num-records')) >= 1:
            attributes_list = result.get_child_by_name('attributes-list')
            policy_info = attributes_list.get_child_by_name('net-firewall-policy-info')
            ips = self.na_helper.get_value_for_list(from_zapi=True,
                                                    zapi_parent=policy_info.get_child_by_name('allow-list'))
            return {
                'service': policy_info['service'],
                'allow_list': ips}
        return None

    def create_firewall_policy(self):
        """
        Create a firewall policy for given vserver
        :return: None
        """
        net_firewall_policy_obj = netapp_utils.zapi.NaElement("net-firewall-policy-create")
        net_firewall_policy_obj.translate_struct(self.firewall_policy_attributes())
        if self.parameters.get('allow_list'):
            self.validate_ip_addresses()
            net_firewall_policy_obj.add_child_elem(self.na_helper.get_value_for_list(from_zapi=False,
                                                                                     zapi_parent='allow-list',
                                                                                     zapi_child='ip-and-mask',
                                                                                     data=self.parameters['allow_list'])
                                                   )
        try:
            self.server.invoke_successfully(net_firewall_policy_obj, enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error creating Firewall Policy: %s" % (to_native(error)), exception=traceback.format_exc())

    def destroy_firewall_policy(self):
        """
        Destroy a Firewall Policy from a vserver
        :return: None
        """
        net_firewall_policy_obj = netapp_utils.zapi.NaElement("net-firewall-policy-destroy")
        net_firewall_policy_obj.translate_struct(self.firewall_policy_attributes())
        try:
            self.server.invoke_successfully(net_firewall_policy_obj, enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error destroying Firewall Policy: %s" % (to_native(error)), exception=traceback.format_exc())

    def modify_firewall_policy(self, modify):
        """
        Modify a firewall Policy on a vserver
        :return: none
        """
        self.validate_ip_addresses()
        net_firewall_policy_obj = netapp_utils.zapi.NaElement("net-firewall-policy-modify")
        net_firewall_policy_obj.translate_struct(self.firewall_policy_attributes())
        net_firewall_policy_obj.add_child_elem(self.na_helper.get_value_for_list(from_zapi=False,
                                                                                 zapi_parent='allow-list',
                                                                                 zapi_child='ip-and-mask',
                                                                                 data=modify['allow_list']))
        try:
            self.server.invoke_successfully(net_firewall_policy_obj, enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error modifying Firewall Policy: %s" % (to_native(error)), exception=traceback.format_exc())

    def firewall_policy_attributes(self):
        return {
            'policy': self.parameters['policy'],
            'service': self.parameters['service'],
            'vserver': self.parameters['vserver'],
        }

    def get_firewall_config_for_node(self):
        """
        Get firewall configuration on the node
        :return: dict() with firewall config details
        """
        if self.parameters.get('logging'):
            if self.parameters.get('node') is None:
                self.module.fail_json(msg='Error: Missing parameter \'node\' to modify firewall logging')
        net_firewall_config_obj = netapp_utils.zapi.NaElement("net-firewall-config-get")
        net_firewall_config_obj.add_new_child('node-name', self.parameters['node'])
        try:
            result = self.server.invoke_successfully(net_firewall_config_obj, True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error getting Firewall Configuration: %s" % (to_native(error)),
                                  exception=traceback.format_exc())
        if result.get_child_by_name('attributes'):
            firewall_info = result['attributes'].get_child_by_name('net-firewall-config-info')
            return {'enable': self.change_status_to_bool(firewall_info.get_child_content('is-enabled'), to_zapi=False),
                    'logging': self.change_status_to_bool(firewall_info.get_child_content('is-logging'), to_zapi=False)}
        return None

    def modify_firewall_config(self, modify):
        """
        Modify the configuration of a firewall on node
        :return: None
        """
        net_firewall_config_obj = netapp_utils.zapi.NaElement("net-firewall-config-modify")
        net_firewall_config_obj.add_new_child('node-name', self.parameters['node'])
        if modify.get('enable'):
            net_firewall_config_obj.add_new_child('is-enabled', self.change_status_to_bool(self.parameters['enable']))
        if modify.get('logging'):
            net_firewall_config_obj.add_new_child('is-logging', self.change_status_to_bool(self.parameters['logging']))
        try:
            self.server.invoke_successfully(net_firewall_config_obj, enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg="Error modifying Firewall Config: %s" % (to_native(error)),
                                  exception=traceback.format_exc())

    def change_status_to_bool(self, input, to_zapi=True):
        if to_zapi:
            return 'true' if input == 'enable' else 'false'
        else:
            return 'enable' if input == 'true' else 'disable'

    def autosupport_log(self):
        results = netapp_utils.get_cserver(self.server)
        cserver = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=results)
        netapp_utils.ems_log_event("na_ontap_firewall_policy", cserver)

    def apply(self):
        self.autosupport_log()
        cd_action, modify, modify_config = None, None, None
        if self.parameters.get('policy'):
            current = self.get_firewall_policy()
            cd_action = self.na_helper.get_cd_action(current, self.parameters)
            if cd_action is None and self.parameters['state'] == 'present':
                modify = self.na_helper.get_modified_attributes(current, self.parameters)
        if self.parameters.get('node'):
            current_config = self.get_firewall_config_for_node()
            # firewall config for a node is always present, we cannot create or delete a firewall on a node
            modify_config = self.na_helper.get_modified_attributes(current_config, self.parameters)

        if self.na_helper.changed:
            if self.module.check_mode:
                pass
            else:
                if cd_action == 'create':
                    self.create_firewall_policy()
                elif cd_action == 'delete':
                    self.destroy_firewall_policy()
                else:
                    if modify:
                        self.modify_firewall_policy(modify)
                    if modify_config:
                        self.modify_firewall_config(modify_config)
        self.module.exit_json(changed=self.na_helper.changed)
예제 #4
0
class NetAppONTAPJob(object):
    '''Class with job schedule cron methods'''

    def __init__(self):

        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
        self.argument_spec.update(dict(
            state=dict(required=False, choices=[
                       'present', 'absent'], default='present'),
            name=dict(required=True, type='str'),
            job_minutes=dict(required=False, type='list'),
            job_months=dict(required=False, type='list'),
            job_hours=dict(required=False, type='list'),
            job_days_of_month=dict(required=False, type='list'),
            job_days_of_week=dict(required=False, type='list')
        ))

        self.module = AnsibleModule(
            argument_spec=self.argument_spec,
            supports_check_mode=True
        )

        self.na_helper = NetAppModule()
        self.parameters = self.na_helper.set_parameters(self.module.params)
        self.set_playbook_zapi_key_map()

        if HAS_NETAPP_LIB is False:
            self.module.fail_json(
                msg="the python NetApp-Lib module is required")
        else:
            self.server = netapp_utils.setup_na_ontap_zapi(module=self.module)

    def set_playbook_zapi_key_map(self):
        self.na_helper.zapi_string_keys = {
            'name': 'job-schedule-name',
        }
        self.na_helper.zapi_list_keys = {
            'job_minutes': ('job-schedule-cron-minute', 'cron-minute'),
            'job_months': ('job-schedule-cron-month', 'cron-month'),
            'job_hours': ('job-schedule-cron-hour', 'cron-hour'),
            'job_days_of_month': ('job-schedule-cron-day', 'cron-day-of-month'),
            'job_days_of_week': ('job-schedule-cron-day-of-week', 'cron-day-of-week')
        }

    def get_job_schedule(self):
        """
        Return details about the job
        :param:
            name : Job name
        :return: Details about the Job. None if not found.
        :rtype: dict
        """
        job_get_iter = netapp_utils.zapi.NaElement('job-schedule-cron-get-iter')
        job_get_iter.translate_struct({
            'query': {
                'job-schedule-cron-info': {
                    'job-schedule-name': self.parameters['name']
                }
            }
        })
        result = self.server.invoke_successfully(job_get_iter, True)
        job_details = None
        # check if job exists
        if result.get_child_by_name('num-records') and int(result['num-records']) >= 1:
            job_info = result['attributes-list']['job-schedule-cron-info']
            job_details = dict()
            for item_key, zapi_key in self.na_helper.zapi_string_keys.items():
                job_details[item_key] = job_info[zapi_key]
            for item_key, zapi_key in self.na_helper.zapi_list_keys.items():
                parent, dummy = zapi_key
                job_details[item_key] = self.na_helper.get_value_for_list(from_zapi=True,
                                                                          zapi_parent=job_info.get_child_by_name(parent)
                                                                          )
                # if any of the job_hours, job_minutes, job_months, job_days are empty:
                # it means the value is -1 for ZAPI
                if not job_details[item_key]:
                    job_details[item_key] = ['-1']
        return job_details

    def add_job_details(self, na_element_object, values):
        """
        Add children node for create or modify NaElement object
        :param na_element_object: modif or create NaElement object
        :param values: dictionary of cron values to be added
        :return: None
        """
        for item_key in values:
            if item_key in self.na_helper.zapi_string_keys:
                zapi_key = self.na_helper.zapi_string_keys.get(item_key)
                na_element_object[zapi_key] = values[item_key]
            elif item_key in self.na_helper.zapi_list_keys:
                parent_key, child_key = self.na_helper.zapi_list_keys.get(item_key)
                na_element_object.add_child_elem(self.na_helper.get_value_for_list(from_zapi=False,
                                                                                   zapi_parent=parent_key,
                                                                                   zapi_child=child_key,
                                                                                   data=values.get(item_key)))

    def create_job_schedule(self):
        """
        Creates a job schedule
        """
        # job_minutes is mandatory for create
        if self.parameters.get('job_minutes') is None:
            self.module.fail_json(msg='Error: missing required parameter job_minutes for create')

        job_schedule_create = netapp_utils.zapi.NaElement('job-schedule-cron-create')
        self.add_job_details(job_schedule_create, self.parameters)
        try:
            self.server.invoke_successfully(job_schedule_create,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='Error creating job schedule %s: %s'
                                  % (self.parameters['name'], to_native(error)),
                                  exception=traceback.format_exc())

    def delete_job_schedule(self):
        """
        Delete a job schedule
        """
        job_schedule_delete = netapp_utils.zapi.NaElement('job-schedule-cron-destroy')
        self.add_job_details(job_schedule_delete, self.parameters)
        try:
            self.server.invoke_successfully(job_schedule_delete,
                                            enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='Error deleting job schedule %s: %s'
                                  % (self.parameters['name'], to_native(error)),
                                  exception=traceback.format_exc())

    def modify_job_schedule(self, params):
        """
        modify a job schedule
        """
        job_schedule_modify = netapp_utils.zapi.NaElement.create_node_with_children(
            'job-schedule-cron-modify', **{'job-schedule-name': self.parameters['name']})
        self.add_job_details(job_schedule_modify, params)
        try:
            self.server.invoke_successfully(job_schedule_modify, enable_tunneling=True)
        except netapp_utils.zapi.NaApiError as error:
            self.module.fail_json(msg='Error modifying job schedule %s: %s'
                                  % (self.parameters['name'], to_native(error)),
                                  exception=traceback.format_exc())

    def autosupport_log(self):
        """
        Autosupport log for job_schedule
        :return: None
        """
        results = netapp_utils.get_cserver(self.server)
        cserver = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=results)
        netapp_utils.ems_log_event("na_ontap_job_schedule", cserver)

    def apply(self):
        """
        Apply action to job-schedule
        """
        self.autosupport_log()
        current = self.get_job_schedule()
        action = self.na_helper.get_cd_action(current, self.parameters)
        if action is None and self.parameters['state'] == 'present':
            modify = self.na_helper.get_modified_attributes(current, self.parameters)

        if self.na_helper.changed:
            if self.module.check_mode:
                pass
            else:
                if action == 'create':
                    self.create_job_schedule()
                elif action == 'delete':
                    self.delete_job_schedule()
                elif modify:
                    self.modify_job_schedule(modify)
        self.module.exit_json(changed=self.na_helper.changed)