def build_cmdref_objects(td):
     cmd_ref[td["type"]]["ref"] = []
     saved_ids = []
     if want.get(td["name"]):
         for playvals in want[td["name"]]:
             valiate_input(playvals, td["name"], self._module)
             if playvals["id"] in saved_ids:
                 continue
             saved_ids.append(playvals["id"])
             resource_key = td["cmd"].format(playvals["id"])
             # Only build the NxosCmdRef object for the td['name'] module parameters.
             self._module.params[
                 "config"
             ] = get_module_params_subsection(
                 ALL_MP, td["type"], playvals["id"]
             )
             cmd_ref[td["type"]]["ref"].append(
                 NxosCmdRef(self._module, td["obj"])
             )
             ref = cmd_ref[td["type"]]["ref"][-1]
             ref.set_context([resource_key])
             if td["type"] == "TMS_SENSORGROUP" and get_setval_path(
                 self._module
             ):
                 # Sensor group path setting can contain optional values.
                 # Call get_setval_path helper function to process any
                 # optional setval keys.
                 ref._ref["path"]["setval"] = get_setval_path(
                     self._module
                 )
             ref.get_existing(device_cache)
             ref.get_playvals()
             if td["type"] == "TMS_DESTGROUP":
                 normalize_data(ref)
def main():
    argument_spec = dict(
        echo_interface=dict(required=False, type="str"),
        echo_rx_interval=dict(required=False, type="int"),
        interval=dict(required=False, type="dict"),
        slow_timer=dict(required=False, type="int"),
        startup_timer=dict(required=False, type="int"),
        ipv4_echo_rx_interval=dict(required=False, type="int"),
        ipv4_interval=dict(required=False, type="dict"),
        ipv4_slow_timer=dict(required=False, type="int"),
        ipv6_echo_rx_interval=dict(required=False, type="int"),
        ipv6_interval=dict(required=False, type="dict"),
        ipv6_slow_timer=dict(required=False, type="int"),
        fabricpath_interval=dict(required=False, type="dict"),
        fabricpath_slow_timer=dict(required=False, type="int"),
        fabricpath_vlan=dict(required=False, type="int"),
    )
    argument_spec.update(nxos_argument_spec)
    module = AnsibleModule(
        argument_spec=argument_spec, supports_check_mode=True
    )
    warnings = list()

    cmd_ref = NxosCmdRef(module, BFD_CMD_REF)
    cmd_ref.get_existing()
    cmd_ref.get_playvals()
    cmds = reorder_cmds(cmd_ref.get_proposed())

    result = {
        "changed": False,
        "commands": cmds,
        "warnings": warnings,
        "check_mode": module.check_mode,
    }
    if cmds:
        result["changed"] = True
        if not module.check_mode:
            load_config(module, cmds)

    module.exit_json(**result)
    def _state_replaced(want, have):
        """ The command generator when state is replaced
        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        massaged_have = massage_data(have)
        massaged_want = massage_data(want)

        ref = {}
        ref["tms_global"] = NxosCmdRef([], TMS_GLOBAL, ref_only=True)
        ref["tms_destgroup"] = NxosCmdRef([], TMS_DESTGROUP, ref_only=True)
        ref["tms_sensorgroup"] = NxosCmdRef([], TMS_SENSORGROUP, ref_only=True)
        ref["tms_subscription"] = NxosCmdRef(
            [], TMS_SUBSCRIPTION, ref_only=True
        )

        # Order matters for state replaced.
        # First remove all subscriptions, followed by sensor-groups and destination-groups.
        # Second add all destination-groups, followed by sensor-groups and subscriptions
        add = {
            "TMS_GLOBAL": [],
            "TMS_DESTGROUP": [],
            "TMS_SENSORGROUP": [],
            "TMS_SUBSCRIPTION": [],
        }
        delete = {
            "TMS_DESTGROUP": [],
            "TMS_SENSORGROUP": [],
            "TMS_SUBSCRIPTION": [],
        }

        # Process Telemetry Global Want and Have Values
        # Possible states:
        # - want and have are (set) (equal: no action, not equal: replace with want)
        # - want (set) have (not set) (add want)
        # - want (not set) have (set) (delete have)
        # - want (not set) have (not set) (no action)
        # global_ctx = ref['tms_global']._ref['_template']['context']
        # property_ctx = ref['tms_global']._ref['certificate'].get('context')
        # setval = ref['tms_global']._ref['certificate']['setval']
        #
        all_global_properties = [
            "certificate",
            "compression",
            "source_interface",
            "vrf",
        ]
        dest_profile_properties = ["compression", "source_interface", "vrf"]
        dest_profile_remote_commands = []
        for property in all_global_properties:
            cmd = None
            global_ctx = ref["tms_global"]._ref["_template"]["context"]
            property_ctx = ref["tms_global"]._ref[property].get("context")
            setval = ref["tms_global"]._ref[property]["setval"]
            kind = ref["tms_global"]._ref[property]["kind"]
            if want.get(property) is not None:
                if have.get(property) is not None:
                    if want.get(property) != have.get(property):
                        if kind == "dict":
                            cmd = [setval.format(**want.get(property))]
                        else:
                            cmd = [setval.format(want.get(property))]
                elif have.get(property) is None:
                    if kind == "dict":
                        cmd = [setval.format(**want.get(property))]
                    else:
                        cmd = [setval.format(want.get(property))]
            elif want.get(property) is None:
                if have.get(property) is not None:
                    if kind == "dict":
                        cmd = ["no " + setval.format(**have.get(property))]
                    else:
                        cmd = ["no " + setval.format(have.get(property))]
                    if property in dest_profile_properties:
                        dest_profile_remote_commands.extend(cmd)

            if cmd is not None:
                ctx = global_ctx
                if property_ctx is not None:
                    ctx.extend(property_ctx)
                add["TMS_GLOBAL"].extend(ctx)
                add["TMS_GLOBAL"].extend(cmd)

        add["TMS_GLOBAL"] = remove_duplicate_commands(add["TMS_GLOBAL"])
        # If all destination profile commands are being removed then just
        # remove the config context instead.
        if len(dest_profile_remote_commands) == 3:
            for item in dest_profile_remote_commands:
                add["TMS_GLOBAL"].remove(item)
            add["TMS_GLOBAL"].remove("destination-profile")
            add["TMS_GLOBAL"].extend(["no destination-profile"])

        # Process Telemetry destination_group, sensor_group and subscription Want and Have Values
        # Possible states:
        # - want (not set) have (set) (delete have)
        # - want and have are (set) (equal: no action, not equal: replace with want)
        # - want (set) have (not set) (add want)
        # - want (not set) have (not set) (no action)
        tms_resources = [
            "TMS_DESTGROUP",
            "TMS_SENSORGROUP",
            "TMS_SUBSCRIPTION",
        ]
        for resource in tms_resources:
            if resource == "TMS_DESTGROUP":
                name = "destination-group"
                cmd_property = "destination"
                global_ctx = ref["tms_destgroup"]._ref["_template"]["context"]
                setval = ref["tms_destgroup"]._ref["destination"]["setval"]
                want_resources = massaged_want.get("destination_groups")
                have_resources = massaged_have.get("destination_groups")
            if resource == "TMS_SENSORGROUP":
                name = "sensor-group"
                global_ctx = ref["tms_sensorgroup"]._ref["_template"][
                    "context"
                ]
                setval = {}
                setval["data_source"] = ref["tms_sensorgroup"]._ref[
                    "data_source"
                ]["setval"]
                setval["path"] = ref["tms_sensorgroup"]._ref["path"]["setval"]
                want_resources = massaged_want.get("sensor_groups")
                have_resources = massaged_have.get("sensor_groups")
            if resource == "TMS_SUBSCRIPTION":
                name = "subscription"
                global_ctx = ref["tms_subscription"]._ref["_template"][
                    "context"
                ]
                setval = {}
                setval["destination_group"] = ref["tms_subscription"]._ref[
                    "destination_group"
                ]["setval"]
                setval["sensor_group"] = ref["tms_subscription"]._ref[
                    "sensor_group"
                ]["setval"]
                want_resources = massaged_want.get("subscriptions")
                have_resources = massaged_have.get("subscriptions")

            if not want_resources and have_resources:
                # want not and have not set so delete have
                for key in have_resources.keys():
                    remove_context = ["{0} {1} {2}".format("no", name, key)]
                    delete[resource].extend(global_ctx)
                    if remove_context[0] not in delete[resource]:
                        delete[resource].extend(remove_context)
            else:
                # want and have are set.
                # process wants:
                for want_key in want_resources.keys():
                    if want_key not in have_resources.keys():
                        # Want resource key not in have resource key so add it
                        property_ctx = ["{0} {1}".format(name, want_key)]
                        for item in want_resources[want_key]:
                            if resource == "TMS_DESTGROUP":
                                cmd = [setval.format(**item[cmd_property])]
                                add[resource].extend(global_ctx)
                                if property_ctx[0] not in add[resource]:
                                    add[resource].extend(property_ctx)
                                add[resource].extend(cmd)
                            if resource == "TMS_SENSORGROUP":
                                cmd = {}
                                if item.get("data_source"):
                                    cmd["data_source"] = [
                                        setval["data_source"].format(
                                            item["data_source"]
                                        )
                                    ]
                                if item.get("path"):
                                    setval["path"] = get_setval_path(
                                        item.get("path")
                                    )
                                    cmd["path"] = [
                                        setval["path"].format(**item["path"])
                                    ]
                                add[resource].extend(global_ctx)
                                if property_ctx[0] not in add[resource]:
                                    add[resource].extend(property_ctx)
                                if cmd.get("data_source"):
                                    add[resource].extend(cmd["data_source"])
                                if cmd.get("path"):
                                    add[resource].extend(cmd["path"])
                            if resource == "TMS_SUBSCRIPTION":
                                cmd = {}
                                if item.get("destination_group"):
                                    cmd["destination_group"] = [
                                        setval["destination_group"].format(
                                            item["destination_group"]
                                        )
                                    ]
                                if item.get("sensor_group"):
                                    cmd["sensor_group"] = [
                                        setval["sensor_group"].format(
                                            **item["sensor_group"]
                                        )
                                    ]
                                add[resource].extend(global_ctx)
                                if property_ctx[0] not in add[resource]:
                                    add[resource].extend(property_ctx)
                                if cmd.get("destination_group"):
                                    add[resource].extend(
                                        cmd["destination_group"]
                                    )
                                if cmd.get("sensor_group"):
                                    add[resource].extend(cmd["sensor_group"])

                    elif want_key in have_resources.keys():
                        # Want resource key exists in have resource keys but we need to
                        # inspect the individual items under the resource key
                        # for differences
                        for item in want_resources[want_key]:
                            if item not in have_resources[want_key]:
                                if item is None:
                                    continue
                                # item wanted but does not exist so add it
                                property_ctx = [
                                    "{0} {1}".format(name, want_key)
                                ]
                                if resource == "TMS_DESTGROUP":
                                    cmd = [setval.format(**item[cmd_property])]
                                    add[resource].extend(global_ctx)
                                    if property_ctx[0] not in add[resource]:
                                        add[resource].extend(property_ctx)
                                    add[resource].extend(cmd)
                                if resource == "TMS_SENSORGROUP":
                                    cmd = {}
                                    if item.get("data_source"):
                                        cmd["data_source"] = [
                                            setval["data_source"].format(
                                                item["data_source"]
                                            )
                                        ]
                                    if item.get("path"):
                                        setval["path"] = get_setval_path(
                                            item.get("path")
                                        )
                                        cmd["path"] = [
                                            setval["path"].format(
                                                **item["path"]
                                            )
                                        ]
                                    add[resource].extend(global_ctx)
                                    if property_ctx[0] not in add[resource]:
                                        add[resource].extend(property_ctx)
                                    if cmd.get("data_source"):
                                        add[resource].extend(
                                            cmd["data_source"]
                                        )
                                    if cmd.get("path"):
                                        add[resource].extend(cmd["path"])
                                if resource == "TMS_SUBSCRIPTION":
                                    cmd = {}
                                    if item.get("destination_group"):
                                        cmd["destination_group"] = [
                                            setval["destination_group"].format(
                                                item["destination_group"]
                                            )
                                        ]
                                    if item.get("sensor_group"):
                                        cmd["sensor_group"] = [
                                            setval["sensor_group"].format(
                                                **item["sensor_group"]
                                            )
                                        ]
                                    add[resource].extend(global_ctx)
                                    if property_ctx[0] not in add[resource]:
                                        add[resource].extend(property_ctx)
                                    if cmd.get("destination_group"):
                                        add[resource].extend(
                                            cmd["destination_group"]
                                        )
                                    if cmd.get("sensor_group"):
                                        add[resource].extend(
                                            cmd["sensor_group"]
                                        )

                # process haves:
                for have_key in have_resources.keys():
                    if have_key not in want_resources.keys():
                        # Want resource key is not in have resource keys so remove it
                        cmd = ["no " + "{0} {1}".format(name, have_key)]
                        delete[resource].extend(global_ctx)
                        delete[resource].extend(cmd)
                    elif have_key in want_resources.keys():
                        # Have resource key exists in want resource keys but we need to
                        # inspect the individual items under the resource key
                        # for differences
                        for item in have_resources[have_key]:
                            if item not in want_resources[have_key]:
                                if item is None:
                                    continue
                                # have item not wanted so remove it
                                property_ctx = [
                                    "{0} {1}".format(name, have_key)
                                ]
                                if resource == "TMS_DESTGROUP":
                                    cmd = [
                                        "no "
                                        + setval.format(**item[cmd_property])
                                    ]
                                    delete[resource].extend(global_ctx)
                                    if property_ctx[0] not in delete[resource]:
                                        delete[resource].extend(property_ctx)
                                    delete[resource].extend(cmd)
                                if resource == "TMS_SENSORGROUP":
                                    cmd = {}
                                    if item.get("data_source"):
                                        cmd["data_source"] = [
                                            "no "
                                            + setval["data_source"].format(
                                                item["data_source"]
                                            )
                                        ]
                                    if item.get("path"):
                                        setval["path"] = get_setval_path(
                                            item.get("path")
                                        )
                                        cmd["path"] = [
                                            "no "
                                            + setval["path"].format(
                                                **item["path"]
                                            )
                                        ]
                                    delete[resource].extend(global_ctx)
                                    if property_ctx[0] not in delete[resource]:
                                        delete[resource].extend(property_ctx)
                                    if cmd.get("data_source"):
                                        delete[resource].extend(
                                            cmd["data_source"]
                                        )
                                    if cmd.get("path"):
                                        delete[resource].extend(cmd["path"])
                                if resource == "TMS_SUBSCRIPTION":
                                    cmd = {}
                                    if item.get("destination_group"):
                                        cmd["destination_group"] = [
                                            "no "
                                            + setval[
                                                "destination_group"
                                            ].format(item["destination_group"])
                                        ]
                                    if item.get("sensor_group"):
                                        cmd["sensor_group"] = [
                                            "no "
                                            + setval["sensor_group"].format(
                                                **item["sensor_group"]
                                            )
                                        ]
                                    delete[resource].extend(global_ctx)
                                    if property_ctx[0] not in delete[resource]:
                                        delete[resource].extend(property_ctx)
                                    if cmd.get("destination_group"):
                                        delete[resource].extend(
                                            cmd["destination_group"]
                                        )
                                    if cmd.get("sensor_group"):
                                        delete[resource].extend(
                                            cmd["sensor_group"]
                                        )

            add[resource] = remove_duplicate_context(add[resource])
            delete[resource] = remove_duplicate_context(delete[resource])

        commands.extend(delete["TMS_SUBSCRIPTION"])
        commands.extend(delete["TMS_SENSORGROUP"])
        commands.extend(delete["TMS_DESTGROUP"])
        commands.extend(add["TMS_DESTGROUP"])
        commands.extend(add["TMS_SENSORGROUP"])
        commands.extend(add["TMS_SUBSCRIPTION"])
        commands.extend(add["TMS_GLOBAL"])
        commands = remove_duplicate_context(commands)

        return commands
    def set_state(self, want, have):
        """ Select the appropriate function based on the state provided
        :param want: the desired configuration as a dictionary
        :param have: the current configuration as a dictionary
        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        state = self._module.params["state"]

        # The deleted case is very simple since we purge all telemetry config
        # and does not require any processing using NxosCmdRef objects.
        if state == "deleted":
            return self._state_deleted(want, have)
        elif state == "replaced":
            if want == have:
                return []
            return self._state_replaced(want, have)

        # Save off module params
        ALL_MP = self._module.params["config"]

        cmd_ref = {}
        cmd_ref["TMS_GLOBAL"] = {}
        cmd_ref["TMS_DESTGROUP"] = {}
        cmd_ref["TMS_SENSORGROUP"] = {}
        cmd_ref["TMS_SUBSCRIPTION"] = {}

        # Build Telemetry Global NxosCmdRef Object
        cmd_ref["TMS_GLOBAL"]["ref"] = []
        self._module.params["config"] = get_module_params_subsection(
            ALL_MP, "TMS_GLOBAL"
        )
        cmd_ref["TMS_GLOBAL"]["ref"].append(
            NxosCmdRef(self._module, TMS_GLOBAL)
        )
        ref = cmd_ref["TMS_GLOBAL"]["ref"][0]
        ref.set_context()
        ref.get_existing()
        ref.get_playvals()
        device_cache = ref.cache_existing

        def build_cmdref_objects(td):
            cmd_ref[td["type"]]["ref"] = []
            saved_ids = []
            if want.get(td["name"]):
                for playvals in want[td["name"]]:
                    valiate_input(playvals, td["name"], self._module)
                    if playvals["id"] in saved_ids:
                        continue
                    saved_ids.append(playvals["id"])
                    resource_key = td["cmd"].format(playvals["id"])
                    # Only build the NxosCmdRef object for the td['name'] module parameters.
                    self._module.params[
                        "config"
                    ] = get_module_params_subsection(
                        ALL_MP, td["type"], playvals["id"]
                    )
                    cmd_ref[td["type"]]["ref"].append(
                        NxosCmdRef(self._module, td["obj"])
                    )
                    ref = cmd_ref[td["type"]]["ref"][-1]
                    ref.set_context([resource_key])
                    if td["type"] == "TMS_SENSORGROUP" and get_setval_path(
                        self._module
                    ):
                        # Sensor group path setting can contain optional values.
                        # Call get_setval_path helper function to process any
                        # optional setval keys.
                        ref._ref["path"]["setval"] = get_setval_path(
                            self._module
                        )
                    ref.get_existing(device_cache)
                    ref.get_playvals()
                    if td["type"] == "TMS_DESTGROUP":
                        normalize_data(ref)

        # Build Telemetry Destination Group NxosCmdRef Objects
        td = {
            "name": "destination_groups",
            "type": "TMS_DESTGROUP",
            "obj": TMS_DESTGROUP,
            "cmd": "destination-group {0}",
        }
        build_cmdref_objects(td)

        # Build Telemetry Sensor Group NxosCmdRef Objects
        td = {
            "name": "sensor_groups",
            "type": "TMS_SENSORGROUP",
            "obj": TMS_SENSORGROUP,
            "cmd": "sensor-group {0}",
        }
        build_cmdref_objects(td)

        # Build Telemetry Subscription NxosCmdRef Objects
        td = {
            "name": "subscriptions",
            "type": "TMS_SUBSCRIPTION",
            "obj": TMS_SUBSCRIPTION,
            "cmd": "subscription {0}",
        }
        build_cmdref_objects(td)

        if state == "merged":
            if want == have:
                return []
            commands = self._state_merged(cmd_ref)
        return commands
예제 #5
0
    def populate_facts(self, connection, ansible_facts, data=None):
        """ Populate the facts for telemetry
        :param connection: the device connection
        :param ansible_facts: Facts dictionary
        :param data: previously collected conf
        :rtype: dictionary
        :returns: facts
        """
        if connection:  # just for linting purposes, remove
            pass

        cmd_ref = {}
        cmd_ref["TMS_GLOBAL"] = {}
        cmd_ref["TMS_DESTGROUP"] = {}
        cmd_ref["TMS_SENSORGROUP"] = {}
        cmd_ref["TMS_SUBSCRIPTION"] = {}

        # For fact gathering, module state should be 'present' when using
        # NxosCmdRef to query state
        if self._module.params.get("state"):
            saved_module_state = self._module.params["state"]
            self._module.params["state"] = "present"

        # Get Telemetry Global Data
        cmd_ref["TMS_GLOBAL"]["ref"] = []
        cmd_ref["TMS_GLOBAL"]["ref"].append(
            NxosCmdRef(self._module, TMS_GLOBAL))
        ref = cmd_ref["TMS_GLOBAL"]["ref"][0]
        ref.set_context()
        ref.get_existing()
        device_cache = ref.cache_existing

        if device_cache is None:
            device_cache_lines = []
        else:
            device_cache_lines = device_cache.split("\n")

        # Get Telemetry Destination Group Data
        cmd_ref["TMS_DESTGROUP"]["ref"] = []
        for line in device_cache_lines:
            if re.search(r"destination-group", line):
                resource_key = line.strip()
                cmd_ref["TMS_DESTGROUP"]["ref"].append(
                    NxosCmdRef(self._module, TMS_DESTGROUP))
                ref = cmd_ref["TMS_DESTGROUP"]["ref"][-1]
                ref.set_context([resource_key])
                ref.get_existing(device_cache)
                normalize_data(ref)

        # Get Telemetry Sensorgroup Group Data
        cmd_ref["TMS_SENSORGROUP"]["ref"] = []
        for line in device_cache_lines:
            if re.search(r"sensor-group", line):
                resource_key = line.strip()
                cmd_ref["TMS_SENSORGROUP"]["ref"].append(
                    NxosCmdRef(self._module, TMS_SENSORGROUP))
                ref = cmd_ref["TMS_SENSORGROUP"]["ref"][-1]
                ref.set_context([resource_key])
                ref.get_existing(device_cache)

        # Get Telemetry Subscription Data
        cmd_ref["TMS_SUBSCRIPTION"]["ref"] = []
        for line in device_cache_lines:
            if re.search(r"subscription", line):
                resource_key = line.strip()
                cmd_ref["TMS_SUBSCRIPTION"]["ref"].append(
                    NxosCmdRef(self._module, TMS_SUBSCRIPTION))
                ref = cmd_ref["TMS_SUBSCRIPTION"]["ref"][-1]
                ref.set_context([resource_key])
                ref.get_existing(device_cache)

        objs = []
        objs = self.render_config(self.generated_spec, cmd_ref)
        facts = {"telemetry": {}}
        if objs:
            # params = utils.validate_config(self.argument_spec, {'config': objs})
            facts["telemetry"] = objs

        ansible_facts["ansible_network_resources"].update(facts)
        if self._module.params.get("state"):
            self._module.params["state"] = saved_module_state
        return ansible_facts