"""ActionBatchAppliance API endpoints.

This file is automatically @generated from the Meraki API specification.
Do not edit this file manually.

"""

import urllib.parse
from typing import Any

from meraki_client.schemas import (
    BulkOrganizationApplianceDnsLocalProfilesAssignmentsCreateItemsItem,
    CreateNetworkAppliancePrefixesDelegatedStaticOrigin,
    CreateNetworkApplianceRfProfileFiveGhzSettings,
    CreateNetworkApplianceRfProfilePerSsidSettings,
    CreateNetworkApplianceRfProfileTwoFourGhzSettings,
    CreateNetworkApplianceVlanDhcpOptionsItem,
    CreateNetworkApplianceVlanIpv6,
    CreateNetworkApplianceVlanMandatoryDhcp,
    CreateOrganizationActionBatchActionsItem,
    CreateOrganizationApplianceDnsLocalProfilesAssignmentsBulkDeleteItemsItem,
    CreateOrganizationApplianceDnsLocalRecordProfile,
    CreateOrganizationApplianceDnsSplitProfileNameservers,
    CreateOrganizationApplianceDnsSplitProfilesAssignmentsBulkCreateItemsItem,
    CreateOrganizationApplianceDnsSplitProfilesAssignmentsBulkDeleteItemsItem,
    UpdateDeviceApplianceRadioSettingsFiveGhzSettings,
    UpdateDeviceApplianceRadioSettingsTwoFourGhzSettings,
    UpdateDeviceApplianceUplinksSettingsInterfaces,
    UpdateNetworkApplianceConnectivityMonitoringDestinationsDestinationsItem,
    UpdateNetworkApplianceFirewallL7FirewallRulesRulesItem,
    UpdateNetworkApplianceFirewallMulticastForwardingRulesItem,
    UpdateNetworkAppliancePrefixesDelegatedStaticOrigin,
    UpdateNetworkApplianceRfProfileFiveGhzSettings,
    UpdateNetworkApplianceRfProfilePerSsidSettings,
    UpdateNetworkApplianceRfProfileTwoFourGhzSettings,
    UpdateNetworkApplianceSdwanInternetPoliciesWanTrafficUplinkPreferencesItem,
    UpdateNetworkApplianceSettingsDynamicDns,
    UpdateNetworkApplianceSingleLanIpv6,
    UpdateNetworkApplianceSingleLanMandatoryDhcp,
    UpdateNetworkApplianceSsidDhcpEnforcedDeauthentication,
    UpdateNetworkApplianceSsidDot11w,
    UpdateNetworkApplianceSsidRadiusServersItem,
    UpdateNetworkApplianceTrafficShapingRulesRulesItem,
    UpdateNetworkApplianceTrafficShapingUplinkBandwidthBandwidthLimits,
    UpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback,
    UpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesItem,
    UpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesItem,
    UpdateNetworkApplianceTrafficShapingVpnExclusionsCustomItem,
    UpdateNetworkApplianceTrafficShapingVpnExclusionsMajorApplicationsItem,
    UpdateNetworkApplianceVlanDhcpOptionsItem,
    UpdateNetworkApplianceVlanIpv6,
    UpdateNetworkApplianceVlanMandatoryDhcp,
    UpdateNetworkApplianceVlanReservedIpRangesItem,
    UpdateNetworkApplianceVpnBgpNeighborsItem,
    UpdateNetworkApplianceVpnSiteToSiteVpnHubsItem,
    UpdateNetworkApplianceVpnSiteToSiteVpnSubnet,
    UpdateNetworkApplianceVpnSiteToSiteVpnSubnetsItem,
    UpdateOrganizationApplianceDnsLocalRecordProfile,
    UpdateOrganizationApplianceDnsSplitProfileNameservers,
    UpdateOrganizationApplianceVpnSiteToSiteIpsecPeersSlasItemsItem,
    UpdateOrganizationApplianceVpnThirdPartyVPNPeersPeersItem,
)
from meraki_client.types import (
    CreateNetworkApplianceVlanDhcpHandling,
    CreateNetworkApplianceVlanDhcpLeaseTime,
    CreateNetworkApplianceVlanTemplateVlanType,
    UpdateNetworkApplianceSettingsClientTrackingMethod,
    UpdateNetworkApplianceSettingsDeploymentMode,
    UpdateNetworkApplianceSsidAuthMode,
    UpdateNetworkApplianceSsidEncryptionMode,
    UpdateNetworkApplianceSsidWpaEncryptionMode,
    UpdateNetworkApplianceVlanDhcpHandling,
    UpdateNetworkApplianceVlanDhcpLeaseTime,
    UpdateNetworkApplianceVlanTemplateVlanType,
    UpdateNetworkApplianceVpnSiteToSiteVpnMode,
)


class ActionBatchAppliance:
    """ActionBatchAppliance class."""

    def __init__(self) -> None:
        pass

    def update_device_appliance_radio_settings(
        self,
        serial: str,
        *,
        rf_profile_id: str | None = None,
        two_four_ghz_settings: UpdateDeviceApplianceRadioSettingsTwoFourGhzSettings | None = None,
        five_ghz_settings: UpdateDeviceApplianceRadioSettingsFiveGhzSettings | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the radio settings of an appliance.

        [API documentation: updateDeviceApplianceRadioSettings](https://developer.cisco.com/meraki/api-v1/#!update-device-appliance-radio-settings)

        Args:
            serial: Serial.
            rf_profile_id: The ID of an RF profile to assign to the device. If the value of this
                parameter is null, the appropriate basic RF profile (indoor or outdoor)
                will be assigned to the device. Assigning an RF profile will clear ALL
                manually configured overrides on the device (channel width, channel,
                power).
            two_four_ghz_settings: Manual radio settings for 2.4 GHz.
            five_ghz_settings: Manual radio settings for 5 GHz.

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/appliance/radio/settings"

        payload: dict[str, Any] = {}
        if rf_profile_id is not None:
            payload["rfProfileId"] = rf_profile_id
        if two_four_ghz_settings is not None:
            payload["twoFourGhzSettings"] = two_four_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )
        if five_ghz_settings is not None:
            payload["fiveGhzSettings"] = five_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_device_appliance_uplinks_settings(
        self, *, serial: str, interfaces: UpdateDeviceApplianceUplinksSettingsInterfaces
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the uplink settings for an MX appliance.

        [API documentation: updateDeviceApplianceUplinksSettings](https://developer.cisco.com/meraki/api-v1/#!update-device-appliance-uplinks-settings)

        Args:
            serial: Serial.
            interfaces: Interface settings.

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/appliance/uplinks/settings"

        payload: dict[str, Any] = {}
        if interfaces is not None:
            payload["interfaces"] = interfaces.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def create_device_appliance_vmx_authentication_token(
        self, serial: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Generate a new vMX authentication token.

        [API documentation: createDeviceApplianceVmxAuthenticationToken](https://developer.cisco.com/meraki/api-v1/#!create-device-appliance-vmx-authentication-token)

        Args:
            serial: Serial.

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/appliance/vmx/authenticationToken"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
        )

    def update_network_appliance_connectivity_monitoring_destinations(
        self,
        network_id: str,
        *,
        destinations: list[UpdateNetworkApplianceConnectivityMonitoringDestinationsDestinationsItem]
        | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the connectivity testing destinations for an MX network.

        [API documentation: updateNetworkApplianceConnectivityMonitoringDestinations](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-connectivity-monitoring-destinations)

        Args:
            network_id: Network ID.
            destinations: The list of connectivity monitoring destinations.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/connectivityMonitoringDestinations"

        payload: dict[str, Any] = {}
        if destinations is not None:
            payload["destinations"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in destinations
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_firewall_l7_firewall_rules(
        self,
        network_id: str,
        *,
        rules: list[UpdateNetworkApplianceFirewallL7FirewallRulesRulesItem] | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the MX L7 firewall rules for an MX network.

        [API documentation: updateNetworkApplianceFirewallL7FirewallRules](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-firewall-l-7-firewall-rules)

        Args:
            network_id: Network ID.
            rules: An ordered array of the MX L7 firewall rules.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/firewall/l7FirewallRules"

        payload: dict[str, Any] = {}
        if rules is not None:
            payload["rules"] = [item.model_dump(by_alias=True, exclude_none=True) for item in rules]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_firewall_multicast_forwarding(
        self,
        *,
        network_id: str,
        rules: list[UpdateNetworkApplianceFirewallMulticastForwardingRulesItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update static multicast forward rules for a network.

        [API documentation: updateNetworkApplianceFirewallMulticastForwarding](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-firewall-multicast-forwarding)

        Args:
            network_id: Network ID.
            rules: Static multicast forwarding rules. Pass an empty array to clear all rules.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/firewall/multicastForwarding"

        payload: dict[str, Any] = {}
        if rules is not None:
            payload["rules"] = [item.model_dump(by_alias=True, exclude_none=True) for item in rules]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_port(
        self,
        *,
        network_id: str,
        port_id: str,
        enabled: bool | None = None,
        drop_untagged_traffic: bool | None = None,
        type_: str | None = None,
        vlan: int | None = None,
        allowed_vlans: str | None = None,
        access_policy: str | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the per-port VLAN settings for a single MX port.

        [API documentation: updateNetworkAppliancePort](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-port)

        Args:
            network_id: Network ID.
            port_id: Port ID.
            enabled: The status of the port.
            drop_untagged_traffic: Trunk port can Drop all Untagged traffic. When true, no VLAN is
                required. Access ports cannot have dropUntaggedTraffic set to true.
            type_: The type of the port: 'access' or 'trunk'.
            vlan: Native VLAN when the port is in Trunk mode. Access VLAN when the port is in Access
                mode.
            allowed_vlans: Comma-delimited list of the VLAN ID's allowed on the port, or 'all' to
                permit all VLAN's on the port.
            access_policy: The name of the policy. Only applicable to Access ports. Valid values
                are: 'open', '8021x-radius', 'mac-radius', 'hybris-radius' for MX64 or
                Z3 or any MX supporting the per port authentication feature. Otherwise,
                'open' is the only valid value and 'open' is the default value if the
                field is missing.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        port_id = urllib.parse.quote(str(port_id), safe="")
        path = f"/networks/{network_id}/appliance/ports/{port_id}"

        payload: dict[str, Any] = {}
        if enabled is not None:
            payload["enabled"] = enabled
        if drop_untagged_traffic is not None:
            payload["dropUntaggedTraffic"] = drop_untagged_traffic
        if type_ is not None:
            payload["type"] = type_
        if vlan is not None:
            payload["vlan"] = vlan
        if allowed_vlans is not None:
            payload["allowedVlans"] = allowed_vlans
        if access_policy is not None:
            payload["accessPolicy"] = access_policy

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def create_network_appliance_prefixes_delegated_static(
        self,
        *,
        network_id: str,
        prefix: str,
        origin: CreateNetworkAppliancePrefixesDelegatedStaticOrigin,
        description: str | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Add a static delegated prefix from a network.

        [API documentation: createNetworkAppliancePrefixesDelegatedStatic](https://developer.cisco.com/meraki/api-v1/#!create-network-appliance-prefixes-delegated-static)

        Args:
            network_id: Network ID.
            prefix: A static IPv6 prefix.
            origin: The origin of the prefix.
            description: A name or description for the prefix.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/prefixes/delegated/statics"

        payload: dict[str, Any] = {}
        if prefix is not None:
            payload["prefix"] = prefix
        if origin is not None:
            payload["origin"] = origin.model_dump(by_alias=True, exclude_none=True)
        if description is not None:
            payload["description"] = description

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def update_network_appliance_prefixes_delegated_static(
        self,
        *,
        network_id: str,
        static_delegated_prefix_id: str,
        prefix: str | None = None,
        origin: UpdateNetworkAppliancePrefixesDelegatedStaticOrigin | None = None,
        description: str | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a static delegated prefix from a network.

        [API documentation: updateNetworkAppliancePrefixesDelegatedStatic](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-prefixes-delegated-static)

        Args:
            network_id: Network ID.
            static_delegated_prefix_id: Static delegated prefix ID.
            prefix: A static IPv6 prefix.
            origin: The origin of the prefix.
            description: A name or description for the prefix.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        static_delegated_prefix_id = urllib.parse.quote(str(static_delegated_prefix_id), safe="")
        path = f"/networks/{network_id}/appliance/prefixes/delegated/statics/{static_delegated_prefix_id}"

        payload: dict[str, Any] = {}
        if prefix is not None:
            payload["prefix"] = prefix
        if origin is not None:
            payload["origin"] = origin.model_dump(by_alias=True, exclude_none=True)
        if description is not None:
            payload["description"] = description

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_network_appliance_prefixes_delegated_static(
        self, *, network_id: str, static_delegated_prefix_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Delete a static delegated prefix from a network.

        [API documentation: deleteNetworkAppliancePrefixesDelegatedStatic](https://developer.cisco.com/meraki/api-v1/#!delete-network-appliance-prefixes-delegated-static)

        Args:
            network_id: Network ID.
            static_delegated_prefix_id: Static delegated prefix ID.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        static_delegated_prefix_id = urllib.parse.quote(str(static_delegated_prefix_id), safe="")
        path = f"/networks/{network_id}/appliance/prefixes/delegated/statics/{static_delegated_prefix_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def create_network_appliance_rf_profile(
        self,
        *,
        network_id: str,
        name: str,
        two_four_ghz_settings: CreateNetworkApplianceRfProfileTwoFourGhzSettings | None = None,
        five_ghz_settings: CreateNetworkApplianceRfProfileFiveGhzSettings | None = None,
        per_ssid_settings: CreateNetworkApplianceRfProfilePerSsidSettings | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Creates new RF profile for this network.

        [API documentation: createNetworkApplianceRfProfile](https://developer.cisco.com/meraki/api-v1/#!create-network-appliance-rf-profile)

        Args:
            network_id: Network ID.
            name: The name of the new profile. Must be unique. This param is required on creation.
            two_four_ghz_settings: Settings related to 2.4Ghz band.
            five_ghz_settings: Settings related to 5Ghz band.
            per_ssid_settings: Per-SSID radio settings by number.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/rfProfiles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if two_four_ghz_settings is not None:
            payload["twoFourGhzSettings"] = two_four_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )
        if five_ghz_settings is not None:
            payload["fiveGhzSettings"] = five_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )
        if per_ssid_settings is not None:
            payload["perSsidSettings"] = per_ssid_settings.model_dump(
                by_alias=True, exclude_none=True
            )

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def update_network_appliance_rf_profile(
        self,
        *,
        network_id: str,
        rf_profile_id: str,
        name: str | None = None,
        two_four_ghz_settings: UpdateNetworkApplianceRfProfileTwoFourGhzSettings | None = None,
        five_ghz_settings: UpdateNetworkApplianceRfProfileFiveGhzSettings | None = None,
        per_ssid_settings: UpdateNetworkApplianceRfProfilePerSsidSettings | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Updates specified RF profile for this network.

        [API documentation: updateNetworkApplianceRfProfile](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-rf-profile)

        Args:
            network_id: Network ID.
            rf_profile_id: Rf profile ID.
            name: The name of the new profile. Must be unique.
            two_four_ghz_settings: Settings related to 2.4Ghz band.
            five_ghz_settings: Settings related to 5Ghz band.
            per_ssid_settings: Per-SSID radio settings by number.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        rf_profile_id = urllib.parse.quote(str(rf_profile_id), safe="")
        path = f"/networks/{network_id}/appliance/rfProfiles/{rf_profile_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if two_four_ghz_settings is not None:
            payload["twoFourGhzSettings"] = two_four_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )
        if five_ghz_settings is not None:
            payload["fiveGhzSettings"] = five_ghz_settings.model_dump(
                by_alias=True, exclude_none=True
            )
        if per_ssid_settings is not None:
            payload["perSsidSettings"] = per_ssid_settings.model_dump(
                by_alias=True, exclude_none=True
            )

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_network_appliance_rf_profile(
        self, *, network_id: str, rf_profile_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Delete a RF Profile.

        [API documentation: deleteNetworkApplianceRfProfile](https://developer.cisco.com/meraki/api-v1/#!delete-network-appliance-rf-profile)

        Args:
            network_id: Network ID.
            rf_profile_id: Rf profile ID.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        rf_profile_id = urllib.parse.quote(str(rf_profile_id), safe="")
        path = f"/networks/{network_id}/appliance/rfProfiles/{rf_profile_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def update_network_appliance_sdwan_internet_policies(
        self,
        network_id: str,
        *,
        wan_traffic_uplink_preferences: list[
            UpdateNetworkApplianceSdwanInternetPoliciesWanTrafficUplinkPreferencesItem
        ]
        | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update SDWAN internet traffic preferences for an MX network.

        [API documentation: updateNetworkApplianceSdwanInternetPolicies](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-sdwan-internet-policies)

        Args:
            network_id: Network ID.
            wan_traffic_uplink_preferences: policies with respective traffic filters for an MX
                network.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/sdwan/internetPolicies"

        payload: dict[str, Any] = {}
        if wan_traffic_uplink_preferences is not None:
            payload["wanTrafficUplinkPreferences"] = [
                item.model_dump(by_alias=True, exclude_none=True)
                for item in wan_traffic_uplink_preferences
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_settings(
        self,
        network_id: str,
        *,
        client_tracking_method: UpdateNetworkApplianceSettingsClientTrackingMethod | None = None,
        deployment_mode: UpdateNetworkApplianceSettingsDeploymentMode | None = None,
        dynamic_dns: UpdateNetworkApplianceSettingsDynamicDns | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the appliance settings for a network.

        [API documentation: updateNetworkApplianceSettings](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-settings)

        Args:
            network_id: Network ID.
            client_tracking_method: Client tracking method of a network.
            deployment_mode: Deployment mode of a network.
            dynamic_dns: Dynamic DNS settings for a network.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/settings"

        payload: dict[str, Any] = {}
        if client_tracking_method is not None:
            payload["clientTrackingMethod"] = client_tracking_method
        if deployment_mode is not None:
            payload["deploymentMode"] = deployment_mode
        if dynamic_dns is not None:
            payload["dynamicDns"] = dynamic_dns.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_single_lan(
        self,
        network_id: str,
        *,
        subnet: str | None = None,
        appliance_ip: str | None = None,
        ipv6: UpdateNetworkApplianceSingleLanIpv6 | None = None,
        mandatory_dhcp: UpdateNetworkApplianceSingleLanMandatoryDhcp | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update single LAN configuration.

        [API documentation: updateNetworkApplianceSingleLan](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-single-lan)

        Args:
            network_id: Network ID.
            subnet: The subnet of the single LAN configuration.
            appliance_ip: The appliance IP address of the single LAN.
            ipv6: IPv6 configuration on the VLAN.
            mandatory_dhcp: Mandatory DHCP will enforce that clients connecting to this LAN must use
                the IP address assigned by the DHCP server. Clients who use a static IP
                address won't be able to associate. Only available on firmware versions
                17.0 and above.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/singleLan"

        payload: dict[str, Any] = {}
        if subnet is not None:
            payload["subnet"] = subnet
        if appliance_ip is not None:
            payload["applianceIp"] = appliance_ip
        if ipv6 is not None:
            payload["ipv6"] = ipv6.model_dump(by_alias=True, exclude_none=True)
        if mandatory_dhcp is not None:
            payload["mandatoryDhcp"] = mandatory_dhcp.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_ssid(
        self,
        *,
        network_id: str,
        number: str,
        name: str | None = None,
        enabled: bool | None = None,
        default_vlan_id: int | None = None,
        auth_mode: UpdateNetworkApplianceSsidAuthMode | None = None,
        psk: str | None = None,
        radius_servers: list[UpdateNetworkApplianceSsidRadiusServersItem] | None = None,
        encryption_mode: UpdateNetworkApplianceSsidEncryptionMode | None = None,
        wpa_encryption_mode: UpdateNetworkApplianceSsidWpaEncryptionMode | None = None,
        visible: bool | None = None,
        dhcp_enforced_deauthentication: UpdateNetworkApplianceSsidDhcpEnforcedDeauthentication
        | None = None,
        dot11w: UpdateNetworkApplianceSsidDot11w | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the attributes of an MX SSID.

        [API documentation: updateNetworkApplianceSsid](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-ssid)

        Args:
            network_id: Network ID.
            number: Number.
            name: The name of the SSID.
            enabled: Whether or not the SSID is enabled.
            default_vlan_id: The VLAN ID of the VLAN associated to this SSID. This parameter is only
                valid if the network is in routed mode.
            auth_mode: The association control method for the SSID ('open', 'psk', '8021x-meraki' or
                '8021x-radius').
            psk: The passkey for the SSID. This param is only valid if the authMode is 'psk'.
            radius_servers: The RADIUS 802.1x servers to be used for authentication. This param is
                only valid if the authMode is '8021x-radius'.
            encryption_mode: The psk encryption mode for the SSID ('wep' or 'wpa'). This param is
                only valid if the authMode is 'psk'.
            wpa_encryption_mode: The types of WPA encryption. ('WPA1 and WPA2', 'WPA2 only', 'WPA3
                Transition Mode' or 'WPA3 only'). This param is only valid if (1) the
                authMode is 'psk' & the encryptionMode is 'wpa' OR (2) the authMode is
                '8021x-meraki' OR (3) the authMode is '8021x-radius'.
            visible: Boolean indicating whether the MX should advertise or hide this SSID.
            dhcp_enforced_deauthentication: DHCP Enforced Deauthentication enables the
                disassociation of wireless clients in addition to Mandatory DHCP. This
                param is only valid on firmware versions >= MX 17.0 where the associated
                LAN has Mandatory DHCP Enabled.
            dot11w: The current setting for Protected Management Frames (802.11w).

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        number = urllib.parse.quote(str(number), safe="")
        path = f"/networks/{network_id}/appliance/ssids/{number}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if enabled is not None:
            payload["enabled"] = enabled
        if default_vlan_id is not None:
            payload["defaultVlanId"] = default_vlan_id
        if auth_mode is not None:
            payload["authMode"] = auth_mode
        if psk is not None:
            payload["psk"] = psk
        if radius_servers is not None:
            payload["radiusServers"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in radius_servers
            ]
        if encryption_mode is not None:
            payload["encryptionMode"] = encryption_mode
        if wpa_encryption_mode is not None:
            payload["wpaEncryptionMode"] = wpa_encryption_mode
        if visible is not None:
            payload["visible"] = visible
        if dhcp_enforced_deauthentication is not None:
            payload["dhcpEnforcedDeauthentication"] = dhcp_enforced_deauthentication.model_dump(
                by_alias=True, exclude_none=True
            )
        if dot11w is not None:
            payload["dot11w"] = dot11w.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def create_network_appliance_traffic_shaping_custom_performance_class(
        self,
        *,
        network_id: str,
        name: str,
        max_latency: int | None = None,
        max_jitter: int | None = None,
        max_loss_percentage: int | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Add a custom performance class for an MX network.

        [API documentation: createNetworkApplianceTrafficShapingCustomPerformanceClass](https://developer.cisco.com/meraki/api-v1/#!create-network-appliance-traffic-shaping-custom-performance-class)

        Args:
            network_id: Network ID.
            name: Name of the custom performance class.
            max_latency: Maximum latency in milliseconds.
            max_jitter: Maximum jitter in milliseconds.
            max_loss_percentage: Maximum percentage of packet loss.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/customPerformanceClasses"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if max_latency is not None:
            payload["maxLatency"] = max_latency
        if max_jitter is not None:
            payload["maxJitter"] = max_jitter
        if max_loss_percentage is not None:
            payload["maxLossPercentage"] = max_loss_percentage

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def update_network_appliance_traffic_shaping_custom_performance_class(
        self,
        *,
        network_id: str,
        custom_performance_class_id: str,
        name: str | None = None,
        max_latency: int | None = None,
        max_jitter: int | None = None,
        max_loss_percentage: int | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a custom performance class for an MX network.

        [API documentation: updateNetworkApplianceTrafficShapingCustomPerformanceClass](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-traffic-shaping-custom-performance-class)

        Args:
            network_id: Network ID.
            custom_performance_class_id: Custom performance class ID.
            name: Name of the custom performance class.
            max_latency: Maximum latency in milliseconds.
            max_jitter: Maximum jitter in milliseconds.
            max_loss_percentage: Maximum percentage of packet loss.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        custom_performance_class_id = urllib.parse.quote(str(custom_performance_class_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/customPerformanceClasses/{custom_performance_class_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if max_latency is not None:
            payload["maxLatency"] = max_latency
        if max_jitter is not None:
            payload["maxJitter"] = max_jitter
        if max_loss_percentage is not None:
            payload["maxLossPercentage"] = max_loss_percentage

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_network_appliance_traffic_shaping_custom_performance_class(
        self, *, network_id: str, custom_performance_class_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Delete a custom performance class from an MX network.

        [API documentation: deleteNetworkApplianceTrafficShapingCustomPerformanceClass](https://developer.cisco.com/meraki/api-v1/#!delete-network-appliance-traffic-shaping-custom-performance-class)

        Args:
            network_id: Network ID.
            custom_performance_class_id: Custom performance class ID.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        custom_performance_class_id = urllib.parse.quote(str(custom_performance_class_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/customPerformanceClasses/{custom_performance_class_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def update_network_appliance_traffic_shaping_rules(
        self,
        network_id: str,
        *,
        default_rules_enabled: bool | None = None,
        rules: list[UpdateNetworkApplianceTrafficShapingRulesRulesItem] | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the traffic shaping settings rules for an MX network.

        [API documentation: updateNetworkApplianceTrafficShapingRules](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-traffic-shaping-rules)

        Args:
            network_id: Network ID.
            default_rules_enabled: Whether default traffic shaping rules are enabled (true) or
                disabled (false). There are 4 default rules, which can be seen on your
                network's traffic shaping page. Note that default rules count against
                the rule limit of 8.
            rules: An array of traffic shaping rules. Rules are applied in the order that they are
                specified in. An empty list (or null) means no rules. Note that you are
                allowed a maximum of 8 rules.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/rules"

        payload: dict[str, Any] = {}
        if default_rules_enabled is not None:
            payload["defaultRulesEnabled"] = default_rules_enabled
        if rules is not None:
            payload["rules"] = [item.model_dump(by_alias=True, exclude_none=True) for item in rules]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_traffic_shaping_uplink_bandwidth(
        self,
        network_id: str,
        *,
        bandwidth_limits: UpdateNetworkApplianceTrafficShapingUplinkBandwidthBandwidthLimits
        | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Updates the uplink bandwidth settings for your MX network.

        [API documentation: updateNetworkApplianceTrafficShapingUplinkBandwidth](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-traffic-shaping-uplink-bandwidth)

        Args:
            network_id: Network ID.
            bandwidth_limits: A mapping of uplinks to their bandwidth settings (be sure to check
                which uplinks are supported for your network).

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/uplinkBandwidth"

        payload: dict[str, Any] = {}
        if bandwidth_limits is not None:
            payload["bandwidthLimits"] = bandwidth_limits.model_dump(
                by_alias=True, exclude_none=True
            )

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_traffic_shaping_uplink_selection(
        self,
        network_id: str,
        *,
        active_active_auto_vpn_enabled: bool | None = None,
        default_uplink: str | None = None,
        load_balancing_enabled: bool | None = None,
        failover_and_failback: UpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback
        | None = None,
        wan_traffic_uplink_preferences: list[
            UpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesItem
        ]
        | None = None,
        vpn_traffic_uplink_preferences: list[
            UpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesItem
        ]
        | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update uplink selection settings for an MX network.

        [API documentation: updateNetworkApplianceTrafficShapingUplinkSelection](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-traffic-shaping-uplink-selection)

        Args:
            network_id: Network ID.
            active_active_auto_vpn_enabled: Toggle for enabling or disabling active-active AutoVPN.
            default_uplink: The default uplink. Must be a WAN interface 'wanX'.
            load_balancing_enabled: Toggle for enabling or disabling load balancing.
            failover_and_failback: WAN failover and failback behavior.
            wan_traffic_uplink_preferences: Array of uplink preference rules for WAN traffic.
            vpn_traffic_uplink_preferences: Array of uplink preference rules for VPN traffic.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/uplinkSelection"

        payload: dict[str, Any] = {}
        if active_active_auto_vpn_enabled is not None:
            payload["activeActiveAutoVpnEnabled"] = active_active_auto_vpn_enabled
        if default_uplink is not None:
            payload["defaultUplink"] = default_uplink
        if load_balancing_enabled is not None:
            payload["loadBalancingEnabled"] = load_balancing_enabled
        if failover_and_failback is not None:
            payload["failoverAndFailback"] = failover_and_failback.model_dump(
                by_alias=True, exclude_none=True
            )
        if wan_traffic_uplink_preferences is not None:
            payload["wanTrafficUplinkPreferences"] = [
                item.model_dump(by_alias=True, exclude_none=True)
                for item in wan_traffic_uplink_preferences
            ]
        if vpn_traffic_uplink_preferences is not None:
            payload["vpnTrafficUplinkPreferences"] = [
                item.model_dump(by_alias=True, exclude_none=True)
                for item in vpn_traffic_uplink_preferences
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_traffic_shaping_vpn_exclusions(
        self,
        network_id: str,
        *,
        custom: list[UpdateNetworkApplianceTrafficShapingVpnExclusionsCustomItem] | None = None,
        major_applications: list[
            UpdateNetworkApplianceTrafficShapingVpnExclusionsMajorApplicationsItem
        ]
        | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update VPN exclusion rules for an MX network.

        [API documentation: updateNetworkApplianceTrafficShapingVpnExclusions](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-traffic-shaping-vpn-exclusions)

        Args:
            network_id: Network ID.
            custom: Custom VPN exclusion rules. Pass an empty array to clear existing rules.
            major_applications: Major Application based VPN exclusion rules. Pass an empty array to
                clear existing rules.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/trafficShaping/vpnExclusions"

        payload: dict[str, Any] = {}
        if custom is not None:
            payload["custom"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in custom
            ]
        if major_applications is not None:
            payload["majorApplications"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in major_applications
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def create_network_appliance_vlan(
        self,
        *,
        network_id: str,
        id: str,
        name: str,
        subnet: str | None = None,
        appliance_ip: str | None = None,
        group_policy_id: str | None = None,
        template_vlan_type: CreateNetworkApplianceVlanTemplateVlanType | None = None,
        cidr: str | None = None,
        mask: int | None = None,
        ipv6: CreateNetworkApplianceVlanIpv6 | None = None,
        dhcp_handling: CreateNetworkApplianceVlanDhcpHandling | None = None,
        dhcp_relay_server_ips: list[str] | None = None,
        dhcp_lease_time: CreateNetworkApplianceVlanDhcpLeaseTime | None = None,
        mandatory_dhcp: CreateNetworkApplianceVlanMandatoryDhcp | None = None,
        dhcp_boot_options_enabled: bool | None = None,
        dhcp_boot_next_server: str | None = None,
        dhcp_boot_filename: str | None = None,
        dhcp_options: list[CreateNetworkApplianceVlanDhcpOptionsItem] | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Add a VLAN.

        [API documentation: createNetworkApplianceVlan](https://developer.cisco.com/meraki/api-v1/#!create-network-appliance-vlan)

        Args:
            network_id: Network ID.
            id: The VLAN ID of the new VLAN (must be between 1 and 4094).
            name: The name of the new VLAN.
            subnet: The subnet of the VLAN.
            appliance_ip: The local IP of the appliance on the VLAN.
            group_policy_id: The id of the desired group policy to apply to the VLAN.
            template_vlan_type: Type of subnetting of the VLAN. Applicable only for template
                network.
            cidr: CIDR of the pool of subnets. Applicable only for template network. Each network
                bound to the template will automatically pick a subnet from this pool to
                build its own VLAN.
            mask: Mask used for the subnet of all bound to the template networks. Applicable only
                for template network.
            ipv6: IPv6 configuration on the VLAN.
            dhcp_handling: The appliance's handling of DHCP requests on this VLAN. One of: 'Run a
                DHCP server', 'Relay DHCP to another server' or 'Do not respond to DHCP
                requests'.
            dhcp_relay_server_ips: The IPs (IPv4) of the DHCP servers that DHCP requests should be
                relayed to. CIDR/subnet notation and hostnames are not supported.
            dhcp_lease_time: The term of DHCP leases if the appliance is running a DHCP server on
                this VLAN. One of: '30 minutes', '1 hour', '4 hours', '12 hours', '1
                day' or '1 week'.
            mandatory_dhcp: Mandatory DHCP will enforce that clients connecting to this VLAN must
                use the IP address assigned by the DHCP server. Clients who use a static
                IP address won't be able to associate. Only available on firmware
                versions 17.0 and above.
            dhcp_boot_options_enabled: Use DHCP boot options specified in other properties.
            dhcp_boot_next_server: DHCP boot option to direct boot clients to the server to load the
                boot file from.
            dhcp_boot_filename: DHCP boot option for boot filename.
            dhcp_options: The list of DHCP options that will be included in DHCP responses. Each
                object in the list should have "code", "type", and "value" properties.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/vlans"

        payload: dict[str, Any] = {}
        if id is not None:
            payload["id"] = id
        if name is not None:
            payload["name"] = name
        if subnet is not None:
            payload["subnet"] = subnet
        if appliance_ip is not None:
            payload["applianceIp"] = appliance_ip
        if group_policy_id is not None:
            payload["groupPolicyId"] = group_policy_id
        if template_vlan_type is not None:
            payload["templateVlanType"] = template_vlan_type
        if cidr is not None:
            payload["cidr"] = cidr
        if mask is not None:
            payload["mask"] = mask
        if ipv6 is not None:
            payload["ipv6"] = ipv6.model_dump(by_alias=True, exclude_none=True)
        if dhcp_handling is not None:
            payload["dhcpHandling"] = dhcp_handling
        if dhcp_relay_server_ips is not None:
            payload["dhcpRelayServerIps"] = dhcp_relay_server_ips
        if dhcp_lease_time is not None:
            payload["dhcpLeaseTime"] = dhcp_lease_time
        if mandatory_dhcp is not None:
            payload["mandatoryDhcp"] = mandatory_dhcp.model_dump(by_alias=True, exclude_none=True)
        if dhcp_boot_options_enabled is not None:
            payload["dhcpBootOptionsEnabled"] = dhcp_boot_options_enabled
        if dhcp_boot_next_server is not None:
            payload["dhcpBootNextServer"] = dhcp_boot_next_server
        if dhcp_boot_filename is not None:
            payload["dhcpBootFilename"] = dhcp_boot_filename
        if dhcp_options is not None:
            payload["dhcpOptions"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in dhcp_options
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def update_network_appliance_vlans_settings(
        self, network_id: str, *, vlans_enabled: bool | None = None
    ) -> CreateOrganizationActionBatchActionsItem:
        """Enable/Disable VLANs for the given network.

        [API documentation: updateNetworkApplianceVlansSettings](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-vlans-settings)

        Args:
            network_id: Network ID.
            vlans_enabled: Boolean indicating whether to enable (true) or disable (false) VLANs for
                the network.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/vlans/settings"

        payload: dict[str, Any] = {}
        if vlans_enabled is not None:
            payload["vlansEnabled"] = vlans_enabled

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_vlan(
        self,
        *,
        network_id: str,
        vlan_id: str,
        name: str | None = None,
        subnet: str | None = None,
        appliance_ip: str | None = None,
        group_policy_id: str | None = None,
        vpn_nat_subnet: str | None = None,
        dhcp_handling: UpdateNetworkApplianceVlanDhcpHandling | None = None,
        dhcp_relay_server_ips: list[str] | None = None,
        dhcp_lease_time: UpdateNetworkApplianceVlanDhcpLeaseTime | None = None,
        dhcp_boot_options_enabled: bool | None = None,
        dhcp_boot_next_server: str | None = None,
        dhcp_boot_filename: str | None = None,
        fixed_ip_assignments: dict[str, Any] | None = None,
        reserved_ip_ranges: list[UpdateNetworkApplianceVlanReservedIpRangesItem] | None = None,
        dns_nameservers: str | None = None,
        dhcp_options: list[UpdateNetworkApplianceVlanDhcpOptionsItem] | None = None,
        template_vlan_type: UpdateNetworkApplianceVlanTemplateVlanType | None = None,
        cidr: str | None = None,
        mask: int | None = None,
        ipv6: UpdateNetworkApplianceVlanIpv6 | None = None,
        mandatory_dhcp: UpdateNetworkApplianceVlanMandatoryDhcp | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a VLAN.

        [API documentation: updateNetworkApplianceVlan](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-vlan)

        Args:
            network_id: Network ID.
            vlan_id: Vlan ID.
            name: The name of the VLAN.
            subnet: The subnet of the VLAN.
            appliance_ip: The local IP of the appliance on the VLAN.
            group_policy_id: The id of the desired group policy to apply to the VLAN.
            vpn_nat_subnet: The translated VPN subnet if VPN and VPN subnet translation are enabled
                on the VLAN.
            dhcp_handling: The appliance's handling of DHCP requests on this VLAN. One of: 'Run a
                DHCP server', 'Relay DHCP to another server' or 'Do not respond to DHCP
                requests'.
            dhcp_relay_server_ips: The IPs (IPv4) of the DHCP servers that DHCP requests should be
                relayed to. CIDR/subnet notation and hostnames are not supported.
            dhcp_lease_time: The term of DHCP leases if the appliance is running a DHCP server on
                this VLAN. One of: '30 minutes', '1 hour', '4 hours', '12 hours', '1
                day' or '1 week'.
            dhcp_boot_options_enabled: Use DHCP boot options specified in other properties.
            dhcp_boot_next_server: DHCP boot option to direct boot clients to the server to load the
                boot file from.
            dhcp_boot_filename: DHCP boot option for boot filename.
            fixed_ip_assignments: The DHCP fixed IP assignments on the VLAN. This should be an
                object that contains mappings from MAC addresses to objects that
                themselves each contain "ip" and "name" string fields. See the sample
                request/response for more details.
            reserved_ip_ranges: The DHCP reserved IP ranges on the VLAN.
            dns_nameservers: The DNS nameservers used for DHCP responses, either "upstream_dns",
                "google_dns", "opendns", or a newline seperated string of IP addresses
                or domain names.
            dhcp_options: The list of DHCP options that will be included in DHCP responses. Each
                object in the list should have "code", "type", and "value" properties.
            template_vlan_type: Type of subnetting of the VLAN. Applicable only for template
                network.
            cidr: CIDR of the pool of subnets. Applicable only for template network. Each network
                bound to the template will automatically pick a subnet from this pool to
                build its own VLAN.
            mask: Mask used for the subnet of all bound to the template networks. Applicable only
                for template network.
            ipv6: IPv6 configuration on the VLAN.
            mandatory_dhcp: Mandatory DHCP will enforce that clients connecting to this VLAN must
                use the IP address assigned by the DHCP server. Clients who use a static
                IP address won't be able to associate. Only available on firmware
                versions 17.0 and above.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        vlan_id = urllib.parse.quote(str(vlan_id), safe="")
        path = f"/networks/{network_id}/appliance/vlans/{vlan_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if subnet is not None:
            payload["subnet"] = subnet
        if appliance_ip is not None:
            payload["applianceIp"] = appliance_ip
        if group_policy_id is not None:
            payload["groupPolicyId"] = group_policy_id
        if vpn_nat_subnet is not None:
            payload["vpnNatSubnet"] = vpn_nat_subnet
        if dhcp_handling is not None:
            payload["dhcpHandling"] = dhcp_handling
        if dhcp_relay_server_ips is not None:
            payload["dhcpRelayServerIps"] = dhcp_relay_server_ips
        if dhcp_lease_time is not None:
            payload["dhcpLeaseTime"] = dhcp_lease_time
        if dhcp_boot_options_enabled is not None:
            payload["dhcpBootOptionsEnabled"] = dhcp_boot_options_enabled
        if dhcp_boot_next_server is not None:
            payload["dhcpBootNextServer"] = dhcp_boot_next_server
        if dhcp_boot_filename is not None:
            payload["dhcpBootFilename"] = dhcp_boot_filename
        if fixed_ip_assignments is not None:
            payload["fixedIpAssignments"] = fixed_ip_assignments
        if reserved_ip_ranges is not None:
            payload["reservedIpRanges"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in reserved_ip_ranges
            ]
        if dns_nameservers is not None:
            payload["dnsNameservers"] = dns_nameservers
        if dhcp_options is not None:
            payload["dhcpOptions"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in dhcp_options
            ]
        if template_vlan_type is not None:
            payload["templateVlanType"] = template_vlan_type
        if cidr is not None:
            payload["cidr"] = cidr
        if mask is not None:
            payload["mask"] = mask
        if ipv6 is not None:
            payload["ipv6"] = ipv6.model_dump(by_alias=True, exclude_none=True)
        if mandatory_dhcp is not None:
            payload["mandatoryDhcp"] = mandatory_dhcp.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_network_appliance_vlan(
        self, *, network_id: str, vlan_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Delete a VLAN from a network.

        [API documentation: deleteNetworkApplianceVlan](https://developer.cisco.com/meraki/api-v1/#!delete-network-appliance-vlan)

        Args:
            network_id: Network ID.
            vlan_id: Vlan ID.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        vlan_id = urllib.parse.quote(str(vlan_id), safe="")
        path = f"/networks/{network_id}/appliance/vlans/{vlan_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def update_network_appliance_vpn_bgp(
        self,
        *,
        network_id: str,
        enabled: bool,
        as_number: int | None = None,
        ibgp_hold_timer: int | None = None,
        neighbors: list[UpdateNetworkApplianceVpnBgpNeighborsItem] | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a Hub BGP Configuration.

        [API documentation: updateNetworkApplianceVpnBgp](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-vpn-bgp)

        Args:
            network_id: Network ID.
            enabled: Boolean value to enable or disable the BGP configuration. When BGP is enabled,
                the asNumber (ASN) will be autopopulated with the preconfigured ASN at
                other Hubs or a default value if there is no ASN configured.
            as_number: An Autonomous System Number (ASN) is required if you are to run BGP and peer
                with another BGP Speaker outside of the Auto VPN domain. This ASN will
                be applied to the entire Auto VPN domain. The entire 4-byte ASN range is
                supported. So, the ASN must be an integer between 1 and 4294967295. When
                absent, this field is not updated. If no value exists then it defaults
                to 64512.
            ibgp_hold_timer: The iBGP holdtimer in seconds. The iBGP holdtimer must be an integer
                between 12 and 240. When absent, this field is not updated. If no value
                exists then it defaults to 240.
            neighbors: List of BGP neighbors. This list replaces the existing set of neighbors. When
                absent, this field is not updated.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/vpn/bgp"

        payload: dict[str, Any] = {}
        if enabled is not None:
            payload["enabled"] = enabled
        if as_number is not None:
            payload["asNumber"] = as_number
        if ibgp_hold_timer is not None:
            payload["ibgpHoldTimer"] = ibgp_hold_timer
        if neighbors is not None:
            payload["neighbors"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in neighbors
            ]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="settings/update",
            body=payload,
        )

    def update_network_appliance_vpn_site_to_site_vpn(
        self,
        *,
        network_id: str,
        mode: UpdateNetworkApplianceVpnSiteToSiteVpnMode,
        hubs: list[UpdateNetworkApplianceVpnSiteToSiteVpnHubsItem] | None = None,
        subnets: list[UpdateNetworkApplianceVpnSiteToSiteVpnSubnetsItem] | None = None,
        subnet: UpdateNetworkApplianceVpnSiteToSiteVpnSubnet | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the site-to-site VPN settings of a network.

        [API documentation: updateNetworkApplianceVpnSiteToSiteVpn](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-vpn-site-to-site-vpn)

        Args:
            network_id: Network ID.
            mode: The site-to-site VPN mode. Can be one of 'none', 'spoke' or 'hub'.
            hubs: The list of VPN hubs, in order of preference. In spoke mode, at least 1 hub is
                required.
            subnets: The list of subnets and their VPN presence.
            subnet: Configuration of subnet features.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/vpn/siteToSiteVpn"

        payload: dict[str, Any] = {}
        if mode is not None:
            payload["mode"] = mode
        if hubs is not None:
            payload["hubs"] = [item.model_dump(by_alias=True, exclude_none=True) for item in hubs]
        if subnets is not None:
            payload["subnets"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in subnets
            ]
        if subnet is not None:
            payload["subnet"] = subnet.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_network_appliance_warm_spare(
        self,
        *,
        network_id: str,
        enabled: bool,
        spare_serial: str | None = None,
        uplink_mode: str | None = None,
        virtual_ip1: str | None = None,
        virtual_ip2: str | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update MX warm spare settings.

        [API documentation: updateNetworkApplianceWarmSpare](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-warm-spare)

        Args:
            network_id: Network ID.
            enabled: Enable warm spare.
            spare_serial: Serial number of the warm spare appliance.
            uplink_mode: Uplink mode, either virtual or public.
            virtual_ip1: The WAN 1 shared IP.
            virtual_ip2: The WAN 2 shared IP.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/warmSpare"

        payload: dict[str, Any] = {}
        if enabled is not None:
            payload["enabled"] = enabled
        if spare_serial is not None:
            payload["spareSerial"] = spare_serial
        if uplink_mode is not None:
            payload["uplinkMode"] = uplink_mode
        if virtual_ip1 is not None:
            payload["virtualIp1"] = virtual_ip1
        if virtual_ip2 is not None:
            payload["virtualIp2"] = virtual_ip2

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def swap_network_appliance_warm_spare(
        self, network_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Swap MX primary and warm spare appliances.

        [API documentation: swapNetworkApplianceWarmSpare](https://developer.cisco.com/meraki/api-v1/#!swap-network-appliance-warm-spare)

        Args:
            network_id: Network ID.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/appliance/warmSpare/swap"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="swap",
        )

    def create_organization_appliance_dns_local_profile(
        self, *, organization_id: str, name: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Create a new local DNS profile.

        [API documentation: createOrganizationApplianceDnsLocalProfile](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-local-profile)

        Args:
            organization_id: Organization ID.
            name: Name of profile.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/profiles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def bulk_organization_appliance_dns_local_profiles_assignments_create(
        self,
        *,
        organization_id: str,
        items: list[BulkOrganizationApplianceDnsLocalProfilesAssignmentsCreateItemsItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Assign the local DNS profile to networks in the organization.

        [API documentation: bulkOrganizationApplianceDnsLocalProfilesAssignmentsCreate](https://developer.cisco.com/meraki/api-v1/#!bulk-organization-appliance-dns-local-profiles-assignments-create)

        Args:
            organization_id: Organization ID.
            items: List containing the network ID and Profile ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = (
            f"/organizations/{organization_id}/appliance/dns/local/profiles/assignments/bulkCreate"
        )

        payload: dict[str, Any] = {}
        if items is not None:
            payload["items"] = [item.model_dump(by_alias=True, exclude_none=True) for item in items]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="bulk_create",
            body=payload,
        )

    def create_organization_appliance_dns_local_profiles_assignments_bulk_delete(
        self,
        *,
        organization_id: str,
        items: list[CreateOrganizationApplianceDnsLocalProfilesAssignmentsBulkDeleteItemsItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Unassign the local DNS profile to networks in the organization.

        [API documentation: createOrganizationApplianceDnsLocalProfilesAssignmentsBulkDelete](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-local-profiles-assignments-bulk-delete)

        Args:
            organization_id: Organization ID.
            items: List containing the assignment ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = (
            f"/organizations/{organization_id}/appliance/dns/local/profiles/assignments/bulkDelete"
        )

        payload: dict[str, Any] = {}
        if items is not None:
            payload["items"] = [item.model_dump(by_alias=True, exclude_none=True) for item in items]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="bulk_delete",
            body=payload,
        )

    def update_organization_appliance_dns_local_profile(
        self, *, organization_id: str, profile_id: str, name: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a local DNS profile.

        [API documentation: updateOrganizationApplianceDnsLocalProfile](https://developer.cisco.com/meraki/api-v1/#!update-organization-appliance-dns-local-profile)

        Args:
            organization_id: Organization ID.
            profile_id: Profile ID.
            name: Name of profile.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        profile_id = urllib.parse.quote(str(profile_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/profiles/{profile_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_organization_appliance_dns_local_profile(
        self, *, organization_id: str, profile_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Deletes a local DNS profile.

        [API documentation: deleteOrganizationApplianceDnsLocalProfile](https://developer.cisco.com/meraki/api-v1/#!delete-organization-appliance-dns-local-profile)

        Args:
            organization_id: Organization ID.
            profile_id: Profile ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        profile_id = urllib.parse.quote(str(profile_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/profiles/{profile_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def create_organization_appliance_dns_local_record(
        self,
        *,
        organization_id: str,
        hostname: str,
        address: str,
        profile: CreateOrganizationApplianceDnsLocalRecordProfile,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Create a new local DNS record.

        [API documentation: createOrganizationApplianceDnsLocalRecord](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-local-record)

        Args:
            organization_id: Organization ID.
            hostname: Hostname for the DNS record.
            address: IP for the DNS record.
            profile: The profile the DNS record is associated with.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/records"

        payload: dict[str, Any] = {}
        if hostname is not None:
            payload["hostname"] = hostname
        if address is not None:
            payload["address"] = address
        if profile is not None:
            payload["profile"] = profile.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def update_organization_appliance_dns_local_record(
        self,
        *,
        organization_id: str,
        record_id: str,
        hostname: str | None = None,
        address: str | None = None,
        profile: UpdateOrganizationApplianceDnsLocalRecordProfile | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Updates a local DNS record.

        [API documentation: updateOrganizationApplianceDnsLocalRecord](https://developer.cisco.com/meraki/api-v1/#!update-organization-appliance-dns-local-record)

        Args:
            organization_id: Organization ID.
            record_id: Record ID.
            hostname: Hostname for the DNS record.
            address: IP for the DNS record.
            profile: The profile the DNS record is associated with.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        record_id = urllib.parse.quote(str(record_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/records/{record_id}"

        payload: dict[str, Any] = {}
        if hostname is not None:
            payload["hostname"] = hostname
        if address is not None:
            payload["address"] = address
        if profile is not None:
            payload["profile"] = profile.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_organization_appliance_dns_local_record(
        self, *, organization_id: str, record_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Deletes a local DNS record.

        [API documentation: deleteOrganizationApplianceDnsLocalRecord](https://developer.cisco.com/meraki/api-v1/#!delete-organization-appliance-dns-local-record)

        Args:
            organization_id: Organization ID.
            record_id: Record ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        record_id = urllib.parse.quote(str(record_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/local/records/{record_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def create_organization_appliance_dns_split_profile(
        self,
        *,
        organization_id: str,
        name: str,
        hostnames: list[str],
        nameservers: CreateOrganizationApplianceDnsSplitProfileNameservers,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Create a new split DNS profile.

        [API documentation: createOrganizationApplianceDnsSplitProfile](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-split-profile)

        Args:
            organization_id: Organization ID.
            name: Name of profile.
            hostnames: The hostname patterns to match for redirection. For more information on Split
                DNS hostname pattern formatting, please consult the Split DNS KB.
            nameservers: Contains the nameserver information for redirection.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/split/profiles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if hostnames is not None:
            payload["hostnames"] = hostnames
        if nameservers is not None:
            payload["nameservers"] = nameservers.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="create",
            body=payload,
        )

    def create_organization_appliance_dns_split_profiles_assignments_bulk_create(
        self,
        *,
        organization_id: str,
        items: list[CreateOrganizationApplianceDnsSplitProfilesAssignmentsBulkCreateItemsItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Assign the split DNS profile to networks in the organization.

        [API documentation: createOrganizationApplianceDnsSplitProfilesAssignmentsBulkCreate](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-split-profiles-assignments-bulk-create)

        Args:
            organization_id: Organization ID.
            items: List containing the network ID and Profile ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = (
            f"/organizations/{organization_id}/appliance/dns/split/profiles/assignments/bulkCreate"
        )

        payload: dict[str, Any] = {}
        if items is not None:
            payload["items"] = [item.model_dump(by_alias=True, exclude_none=True) for item in items]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="bulk_create",
            body=payload,
        )

    def create_organization_appliance_dns_split_profiles_assignments_bulk_delete(
        self,
        *,
        organization_id: str,
        items: list[CreateOrganizationApplianceDnsSplitProfilesAssignmentsBulkDeleteItemsItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Unassign the split DNS profile to networks in the organization.

        [API documentation: createOrganizationApplianceDnsSplitProfilesAssignmentsBulkDelete](https://developer.cisco.com/meraki/api-v1/#!create-organization-appliance-dns-split-profiles-assignments-bulk-delete)

        Args:
            organization_id: Organization ID.
            items: List containing the assignment ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = (
            f"/organizations/{organization_id}/appliance/dns/split/profiles/assignments/bulkDelete"
        )

        payload: dict[str, Any] = {}
        if items is not None:
            payload["items"] = [item.model_dump(by_alias=True, exclude_none=True) for item in items]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="bulk_delete",
            body=payload,
        )

    def update_organization_appliance_dns_split_profile(
        self,
        *,
        organization_id: str,
        profile_id: str,
        name: str | None = None,
        hostnames: list[str] | None = None,
        nameservers: UpdateOrganizationApplianceDnsSplitProfileNameservers | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update a split DNS profile.

        [API documentation: updateOrganizationApplianceDnsSplitProfile](https://developer.cisco.com/meraki/api-v1/#!update-organization-appliance-dns-split-profile)

        Args:
            organization_id: Organization ID.
            profile_id: Profile ID.
            name: Name of profile.
            hostnames: The hostname patterns to match for redirection. For more information on Split
                DNS hostname pattern formatting, please consult the Split DNS KB.
            nameservers: Contains the nameserver information for redirection.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        profile_id = urllib.parse.quote(str(profile_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/split/profiles/{profile_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if hostnames is not None:
            payload["hostnames"] = hostnames
        if nameservers is not None:
            payload["nameservers"] = nameservers.model_dump(by_alias=True, exclude_none=True)

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def delete_organization_appliance_dns_split_profile(
        self, *, organization_id: str, profile_id: str
    ) -> CreateOrganizationActionBatchActionsItem:
        """Deletes a split DNS profile.

        [API documentation: deleteOrganizationApplianceDnsSplitProfile](https://developer.cisco.com/meraki/api-v1/#!delete-organization-appliance-dns-split-profile)

        Args:
            organization_id: Organization ID.
            profile_id: Profile ID.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        profile_id = urllib.parse.quote(str(profile_id), safe="")
        path = f"/organizations/{organization_id}/appliance/dns/split/profiles/{profile_id}"

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="destroy",
        )

    def update_organization_appliance_vpn_site_to_site_ipsec_peers_slas(
        self,
        organization_id: str,
        *,
        items: list[UpdateOrganizationApplianceVpnSiteToSiteIpsecPeersSlasItemsItem] | None = None,
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the IPsec SLA policies for an organization.

        [API documentation: updateOrganizationApplianceVpnSiteToSiteIpsecPeersSlas](https://developer.cisco.com/meraki/api-v1/#!update-organization-appliance-vpn-site-to-site-ipsec-peers-slas)

        Args:
            organization_id: Organization ID.
            items: List of IPsec SLA policies.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/appliance/vpn/siteToSite/ipsec/peers/slas"

        payload: dict[str, Any] = {}
        if items is not None:
            payload["items"] = [item.model_dump(by_alias=True, exclude_none=True) for item in items]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )

    def update_organization_appliance_vpn_third_party_vpn_peers(
        self,
        *,
        organization_id: str,
        peers: list[UpdateOrganizationApplianceVpnThirdPartyVPNPeersPeersItem],
    ) -> CreateOrganizationActionBatchActionsItem:
        """Update the third party VPN peers for an organization.

        [API documentation: updateOrganizationApplianceVpnThirdPartyVPNPeers](https://developer.cisco.com/meraki/api-v1/#!update-organization-appliance-vpn-third-party-vpn-peers)

        Args:
            organization_id: Organization ID.
            peers: The list of VPN peers.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/appliance/vpn/thirdPartyVPNPeers"

        payload: dict[str, Any] = {}
        if peers is not None:
            payload["peers"] = [item.model_dump(by_alias=True, exclude_none=True) for item in peers]

        return CreateOrganizationActionBatchActionsItem(
            resource=path,
            operation="update",
            body=payload,
        )
