# coding: utf-8

# (C) Copyright IBM Corp. 2020.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
No description provided (generated by Openapi Generator
https://github.com/openapitools/openapi-generator)
"""

from datetime import datetime
from enum import Enum
from typing import BinaryIO, Dict, List
import json

from ibm_cloud_sdk_core import BaseService, DetailedResponse
from ibm_cloud_sdk_core.authenticators.authenticator import Authenticator
from ibm_cloud_sdk_core.get_authenticator import get_authenticator_from_environment
from ibm_cloud_sdk_core.utils import convert_model, datetime_to_string, string_to_datetime

from .common import get_sdk_headers

##############################################################################
# Service
##############################################################################

class DirectLinkV1(BaseService):
    """The Direct Link V1 service."""

    DEFAULT_SERVICE_URL = 'https://directlink.cloud.ibm.com/v1'
    DEFAULT_SERVICE_NAME = 'direct_link'

    @classmethod
    def new_instance(cls,
                     version: str,
                     service_name: str = DEFAULT_SERVICE_NAME,
                    ) -> 'DirectLinkV1':
        """
        Return a new client for the Direct Link service using the specified
               parameters and external configuration.

        :param str version: Requests the version of the API as a date in the format
               `YYYY-MM-DD`. Any date from 2019-12-13 up to the current date may be
               provided. Specify the current date to request the latest version.
        """
        if version is None:
            raise ValueError('version must be provided')

        authenticator = get_authenticator_from_environment(service_name)
        service = cls(
            version,
            authenticator
            )
        service.configure_service(service_name)
        return service

    def __init__(self,
                 version: str,
                 authenticator: Authenticator = None,
                ) -> None:
        """
        Construct a new client for the Direct Link service.

        :param str version: Requests the version of the API as a date in the format
               `YYYY-MM-DD`. Any date from 2019-12-13 up to the current date may be
               provided. Specify the current date to request the latest version.

        :param Authenticator authenticator: The authenticator specifies the authentication mechanism.
               Get up to date information from https://github.com/IBM/python-sdk-core/blob/master/README.md
               about initializing the authenticator of your choice.
        """
        if version is None:
            raise ValueError('version must be provided')

        BaseService.__init__(self,
                             service_url=self.DEFAULT_SERVICE_URL,
                             authenticator=authenticator)
        self.version = version


    #########################
    # gateways
    #########################


    def list_gateways(self,
        **kwargs
    ) -> DetailedResponse:
        """
        List gateways.

        List all Direct Link gateways in this account.  Gateways in other accounts with
        connections to networks in this account are also returned.

        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayCollection` object
        """

        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_gateways')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways'
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def create_gateway(self,
        gateway_template: 'GatewayTemplate',
        **kwargs
    ) -> DetailedResponse:
        """
        Create gateway.

        Creates a Direct Link gateway based on the supplied template.

        :param GatewayTemplate gateway_template: The Direct Link Gateway template.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `Gateway` object
        """

        if gateway_template is None:
            raise ValueError('gateway_template must be provided')
        if isinstance(gateway_template, GatewayTemplate):
            gateway_template = convert_model(gateway_template)
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='create_gateway')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        data = json.dumps(gateway_template)
        headers['content-type'] = 'application/json'

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways'
        request = self.prepare_request(method='POST',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       data=data)

        response = self.send(request)
        return response


    def delete_gateway(self,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Delete gateway.

        Delete a Direct Link gateway.

        :param str id: Direct Link gateway identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='delete_gateway')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='DELETE',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def get_gateway(self,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Get gateway.

        Retrieve a Direct Link gateway.

        :param str id: Direct Link gateway identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `Gateway` object
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='get_gateway')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def update_gateway(self,
        id: str,
        *,
        global_: bool = None,
        loa_reject_reason: str = None,
        macsec_config: 'GatewayMacsecConfigPatchTemplate' = None,
        metered: bool = None,
        name: str = None,
        operational_status: str = None,
        speed_mbps: int = None,
        **kwargs
    ) -> DetailedResponse:
        """
        Update gateway.

        Update a Direct Link gateway.

        :param str id: Direct Link gateway identifier.
        :param bool global_: (optional) Gateways with global routing (`true`) can
               connect to networks outside of their associated region.
        :param str loa_reject_reason: (optional) Use this field during LOA
               rejection to provide the reason for the rejection.
               Only allowed for type=dedicated gateways.
        :param GatewayMacsecConfigPatchTemplate macsec_config: (optional) MACsec
               configuration information.  When patching any macsec_config fields, no
               other fields may be specified in the patch request.  Contact IBM support
               for access to MACsec.
               A MACsec config cannot be added to a gateway created without MACsec.
        :param bool metered: (optional) Metered billing option.  When `true`
               gateway usage is billed per gigabyte.  When `false` there is no per
               gigabyte usage charge, instead a flat rate is charged for the gateway.
        :param str name: (optional) The unique user-defined name for this gateway.
        :param str operational_status: (optional) Gateway operational status.
               For gateways pending LOA approval, patch operational_status to the
               appropriate value to approve or reject its LOA.  When rejecting an LOA,
               provide reject reasoning in `loa_reject_reason`.
               Only allowed for type=dedicated gateways.
        :param int speed_mbps: (optional) Gateway speed in megabits per second.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `Gateway` object
        """

        if id is None:
            raise ValueError('id must be provided')
        if macsec_config is not None:
            macsec_config = convert_model(macsec_config)
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='update_gateway')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        data = {
            'global': global_,
            'loa_reject_reason': loa_reject_reason,
            'macsec_config': macsec_config,
            'metered': metered,
            'name': name,
            'operational_status': operational_status,
            'speed_mbps': speed_mbps
        }
        data = {k: v for (k, v) in data.items() if v is not None}
        data = json.dumps(data)
        headers['content-type'] = 'application/json'

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='PATCH',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       data=data)

        response = self.send(request)
        return response


    def create_gateway_action(self,
        id: str,
        action: str,
        *,
        global_: bool = None,
        metered: bool = None,
        resource_group: 'ResourceGroupIdentity' = None,
        updates: List[object] = None,
        **kwargs
    ) -> DetailedResponse:
        """
        Approve or reject change requests.

        Approve or reject a gateway's current oustanding change request.
        This API is only used for provider created Direct Link Connect gateways to approve
        or reject specific changes initiated from a provider portal.

        :param str id: Direct Link Connect gateway identifier.
        :param str action: Action request.
        :param bool global_: (optional) Required for create_gateway_approve
               requests to select the gateway's routing option.  Gateways with global
               routing (`true`) can connect to networks outside of their associated
               region.
        :param bool metered: (optional) Required for create_gateway_approve
               requests to select the gateway's metered billing option.  When `true`
               gateway usage is billed per gigabyte.  When `false` there is no per
               gigabyte usage charge, instead a flat rate is charged for the gateway.
        :param ResourceGroupIdentity resource_group: (optional) Set for
               create_gateway_approve requests to select the gateway's resource group.  If
               unspecified on create_gateway_approve, the account's [default resource
               group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is
               used.
        :param List[object] updates: (optional) Specify attribute updates being
               approved or rejected, update_attributes_approve and
               update_attributes_reject actions must provide an updates field that matches
               the gateway's current pending changes.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `Gateway` object
        """

        if id is None:
            raise ValueError('id must be provided')
        if action is None:
            raise ValueError('action must be provided')
        if resource_group is not None:
            resource_group = convert_model(resource_group)
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='create_gateway_action')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        data = {
            'action': action,
            'global': global_,
            'metered': metered,
            'resource_group': resource_group,
            'updates': updates
        }
        data = {k: v for (k, v) in data.items() if v is not None}
        data = json.dumps(data)
        headers['content-type'] = 'application/json'

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/actions'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='POST',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       data=data)

        response = self.send(request)
        return response


    def list_gateway_completion_notice(self,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Get completion notice.

        Retrieve a Direct Link Dedicated gateway's completion notice.

        :param str id: Direct Link Dedicated gateway identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `BinaryIO` result
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_gateway_completion_notice')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/completion_notice'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def create_gateway_completion_notice(self,
        id: str,
        *,
        upload: BinaryIO = None,
        upload_content_type: str = None,
        **kwargs
    ) -> DetailedResponse:
        """
        Create completion notice.

        Upload a Direct Link Dedicated gateway completion notice.

        :param str id: Direct Link Dedicated gateway identifier.
        :param BinaryIO upload: (optional) Completion notice PDF file.
        :param str upload_content_type: (optional) The content type of upload.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='create_gateway_completion_notice')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        form_data = []
        if upload:
            form_data.append(('upload', (None, upload, upload_content_type or 'application/octet-stream')))

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/completion_notice'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='PUT',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       files=form_data)

        response = self.send(request)
        return response


    def list_gateway_letter_of_authorization(self,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Get letter of authorization.

        Retrieve a Direct Link Dedicated gateway's Letter of Authorization.

        :param str id: Direct Link Dedicated gateway identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `BinaryIO` result
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_gateway_letter_of_authorization')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/letter_of_authorization'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def get_gateway_statistics(self,
        id: str,
        type: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Gateway statistics.

        Retrieve gateway statistics.  Specify statistic to retrieve using required `type`
        query parameter.  Currently data retrieval is only supported for MACsec
        configurations.

        :param str id: Direct Link Dedicated gateway identifier.
        :param str type: specify statistic to retrieve.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayStatisticCollection` object
        """

        if id is None:
            raise ValueError('id must be provided')
        if type is None:
            raise ValueError('type must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='get_gateway_statistics')
        headers.update(sdk_headers)

        params = {
            'type': type,
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/statistics'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response

    #########################
    # offeringInformation
    #########################


    def list_offering_type_locations(self,
        offering_type: str,
        **kwargs
    ) -> DetailedResponse:
        """
        List available locations.

        Retrieve the list of valid locations for the specified Direct Link offering.

        :param str offering_type: The Direct Link offering type.  Current supported
               values are `"dedicated"` and `"connect"`.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `LocationCollection` object
        """

        if offering_type is None:
            raise ValueError('offering_type must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_offering_type_locations')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/offering_types/{0}/locations'.format(
            *self.encode_path_vars(offering_type))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def list_offering_type_location_cross_connect_routers(self,
        offering_type: str,
        location_name: str,
        **kwargs
    ) -> DetailedResponse:
        """
        List routers.

        Retrieve location specific cross connect router information.  Only valid for
        offering_type=dedicated locations.

        :param str offering_type: The Direct Link offering type.  Only value
               `"dedicated"` is supported for this API.
        :param str location_name: The name of the Direct Link location.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `LocationCrossConnectRouterCollection` object
        """

        if offering_type is None:
            raise ValueError('offering_type must be provided')
        if location_name is None:
            raise ValueError('location_name must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_offering_type_location_cross_connect_routers')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/offering_types/{0}/locations/{1}/cross_connect_routers'.format(
            *self.encode_path_vars(offering_type, location_name))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def list_offering_type_speeds(self,
        offering_type: str,
        **kwargs
    ) -> DetailedResponse:
        """
        List speed options.

        List the available Direct Link speeds.

        :param str offering_type: The Direct Link offering type.  Current supported
               values are `"dedicated"` and `"connect"`.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `OfferingSpeedCollection` object
        """

        if offering_type is None:
            raise ValueError('offering_type must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_offering_type_speeds')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/offering_types/{0}/speeds'.format(
            *self.encode_path_vars(offering_type))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response

    #########################
    # ports
    #########################


    def list_ports(self,
        *,
        start: str = None,
        limit: int = None,
        location_name: str = None,
        **kwargs
    ) -> DetailedResponse:
        """
        List ports.

        Retrieve list of available Direct Link connect ports.  These ports can be used to
        create Direct Link connect gateways.

        :param str start: (optional) A server-supplied token determining which
               resource to start the page on.
        :param int limit: (optional) The number of resources to return on a page.
        :param str location_name: (optional) Direct Link location short name.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `PortCollection` object
        """

        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_ports')
        headers.update(sdk_headers)

        params = {
            'version': self.version,
            'start': start,
            'limit': limit,
            'location_name': location_name
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/ports'
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def get_port(self,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Get port.

        Retrieve Direct Link Connect provider port.

        :param str id: The port identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `Port` object
        """

        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='get_port')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/ports/{0}'.format(
            *self.encode_path_vars(id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response

    #########################
    # virtualConnections
    #########################


    def list_gateway_virtual_connections(self,
        gateway_id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        List virtual connections.

        List a gateway's virtual connections.   For gateway in other account with virtual
        connections that connect to network in this account.  Only virtual connections
        that connect to this account are returned.

        :param str gateway_id: Direct Link gateway identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayVirtualConnectionCollection` object
        """

        if gateway_id is None:
            raise ValueError('gateway_id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='list_gateway_virtual_connections')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/virtual_connections'.format(
            *self.encode_path_vars(gateway_id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def create_gateway_virtual_connection(self,
        gateway_id: str,
        name: str,
        type: str,
        *,
        network_id: str = None,
        **kwargs
    ) -> DetailedResponse:
        """
        Create virtual connection.

        Create a virtual connection to the specified network.

        :param str gateway_id: Direct Link gateway identifier.
        :param str name: The user-defined name for this virtual connection.
               Virtual connection names are unique within a gateway.  This is the name of
               the virtual connection itself, the network being connected may have its own
               name attribute.
        :param str type: The type of virtual connection.
        :param str network_id: (optional) Unique identifier of the target network.
               For type=vpc virtual connections this is the CRN of the target VPC.  This
               field does not apply to type=classic connections.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayVirtualConnection` object
        """

        if gateway_id is None:
            raise ValueError('gateway_id must be provided')
        if name is None:
            raise ValueError('name must be provided')
        if type is None:
            raise ValueError('type must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='create_gateway_virtual_connection')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        data = {
            'name': name,
            'type': type,
            'network_id': network_id
        }
        data = {k: v for (k, v) in data.items() if v is not None}
        data = json.dumps(data)
        headers['content-type'] = 'application/json'

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/virtual_connections'.format(
            *self.encode_path_vars(gateway_id))
        request = self.prepare_request(method='POST',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       data=data)

        response = self.send(request)
        return response


    def delete_gateway_virtual_connection(self,
        gateway_id: str,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Delete virtual connection.

        Delete the virtual connection.

        :param str gateway_id: Direct Link gateway identifier.
        :param str id: The virtual connection identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse
        """

        if gateway_id is None:
            raise ValueError('gateway_id must be provided')
        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='delete_gateway_virtual_connection')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/virtual_connections/{1}'.format(
            *self.encode_path_vars(gateway_id, id))
        request = self.prepare_request(method='DELETE',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def get_gateway_virtual_connection(self,
        gateway_id: str,
        id: str,
        **kwargs
    ) -> DetailedResponse:
        """
        Get virtual connection.

        Retrieve a virtual connection.

        :param str gateway_id: Direct Link gateway identifier.
        :param str id: The virtual connection identifier.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayVirtualConnection` object
        """

        if gateway_id is None:
            raise ValueError('gateway_id must be provided')
        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='get_gateway_virtual_connection')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/virtual_connections/{1}'.format(
            *self.encode_path_vars(gateway_id, id))
        request = self.prepare_request(method='GET',
                                       url=url,
                                       headers=headers,
                                       params=params)

        response = self.send(request)
        return response


    def update_gateway_virtual_connection(self,
        gateway_id: str,
        id: str,
        *,
        name: str = None,
        status: str = None,
        **kwargs
    ) -> DetailedResponse:
        """
        Update virtual connection.

        Update a virtual connection.

        :param str gateway_id: Direct Link gateway identifier.
        :param str id: The virtual connection identifier.
        :param str name: (optional) The user-defined name for this virtual
               connection.  Virtual connection names are unique within a gateway.  This is
               the name of the virtual connection itself, the network being connected may
               have its own name attribute.
        :param str status: (optional) Status of the virtual connection.  Virtual
               connections that span IBM Cloud Accounts are created in approval_pending
               status.  The owner of the target network can accept or reject connection
               requests by patching status to attached or rejected respectively.
        :param dict headers: A `dict` containing the request headers
        :return: A `DetailedResponse` containing the result, headers and HTTP status code.
        :rtype: DetailedResponse with `dict` result representing a `GatewayVirtualConnection` object
        """

        if gateway_id is None:
            raise ValueError('gateway_id must be provided')
        if id is None:
            raise ValueError('id must be provided')
        headers = {}
        sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
                                      service_version='V1',
                                      operation_id='update_gateway_virtual_connection')
        headers.update(sdk_headers)

        params = {
            'version': self.version
        }

        data = {
            'name': name,
            'status': status
        }
        data = {k: v for (k, v) in data.items() if v is not None}
        data = json.dumps(data)
        headers['content-type'] = 'application/json'

        if 'headers' in kwargs:
            headers.update(kwargs.get('headers'))

        url = '/gateways/{0}/virtual_connections/{1}'.format(
            *self.encode_path_vars(gateway_id, id))
        request = self.prepare_request(method='PATCH',
                                       url=url,
                                       headers=headers,
                                       params=params,
                                       data=data)

        response = self.send(request)
        return response


class GetGatewayStatisticsEnums:
    """
    Enums for get_gateway_statistics parameters.
    """

    class Type(Enum):
        """
        specify statistic to retrieve.
        """
        MACSEC_MKA = 'macsec_mka'
        MACSEC_SECURITY = 'macsec_security'


class ListOfferingTypeLocationsEnums:
    """
    Enums for list_offering_type_locations parameters.
    """

    class OfferingType(Enum):
        """
        The Direct Link offering type.  Current supported values are `"dedicated"` and
        `"connect"`.
        """
        DEDICATED = 'dedicated'
        CONNECT = 'connect'


class ListOfferingTypeLocationCrossConnectRoutersEnums:
    """
    Enums for list_offering_type_location_cross_connect_routers parameters.
    """

    class OfferingType(Enum):
        """
        The Direct Link offering type.  Only value `"dedicated"` is supported for this
        API.
        """
        DEDICATED = 'dedicated'


class ListOfferingTypeSpeedsEnums:
    """
    Enums for list_offering_type_speeds parameters.
    """

    class OfferingType(Enum):
        """
        The Direct Link offering type.  Current supported values are `"dedicated"` and
        `"connect"`.
        """
        DEDICATED = 'dedicated'
        CONNECT = 'connect'


##############################################################################
# Models
##############################################################################


class CrossConnectRouter():
    """
    Cross Connect Router details.

    :attr str router_name: (optional) The name of the Router.
    :attr int total_connections: (optional) Count of existing Direct Link Dedicated
          gateways on this router for this account.
    """

    def __init__(self,
                 *,
                 router_name: str = None,
                 total_connections: int = None) -> None:
        """
        Initialize a CrossConnectRouter object.

        :param str router_name: (optional) The name of the Router.
        :param int total_connections: (optional) Count of existing Direct Link
               Dedicated gateways on this router for this account.
        """
        self.router_name = router_name
        self.total_connections = total_connections

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'CrossConnectRouter':
        """Initialize a CrossConnectRouter object from a json dictionary."""
        args = {}
        if 'router_name' in _dict:
            args['router_name'] = _dict.get('router_name')
        if 'total_connections' in _dict:
            args['total_connections'] = _dict.get('total_connections')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a CrossConnectRouter object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'router_name') and self.router_name is not None:
            _dict['router_name'] = self.router_name
        if hasattr(self, 'total_connections') and self.total_connections is not None:
            _dict['total_connections'] = self.total_connections
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this CrossConnectRouter object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'CrossConnectRouter') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'CrossConnectRouter') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class Gateway():
    """
    gateway.

    :attr int bgp_asn: Customer BGP ASN.
    :attr str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR is deprecated and
          no longer recognized the Direct Link APIs.
          See bgp_cer_cidr and bgp_ibm_cidr fields instead for IP related information.
          Deprecated field bgp_base_cidr will be removed from the API specificiation after
          15-MAR-2021.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
    :attr int bgp_ibm_asn: (optional) IBM BGP ASN.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.
    :attr str bgp_status: (optional) Gateway BGP status. The list of enumerated
          values for this property may expand in the future. Code and processes using this
          field  must tolerate unexpected values.
    :attr str carrier_name: (optional) Carrier name.  Only set for type=dedicated
          gateways.
    :attr GatewayChangeRequest change_request: (optional) Changes pending approval
          for provider managed Direct Link Connect gateways.
    :attr str completion_notice_reject_reason: (optional) Reason for completion
          notice rejection.  Only included on type=dedicated gateways with a rejected
          completion notice.
    :attr datetime created_at: The date and time resource was created.
    :attr str crn: The CRN (Cloud Resource Name) of this gateway.
    :attr str cross_connect_router: (optional) Cross connect router.  Only included
          on type=dedicated gateways.
    :attr str customer_name: (optional) Customer name.  Only set for type=dedicated
          gateways.
    :attr bool global_: Gateways with global routing (`true`) can connect to
          networks outside their associated region.
    :attr str id: The unique identifier of this gateway.
    :attr str link_status: (optional) Gateway link status.  Only included on
          type=dedicated gateways. The list of enumerated values for this property may
          expand in the future. Code and processes using this field  must tolerate
          unexpected values.
    :attr str location_display_name: Gateway location long name.
    :attr str location_name: Gateway location.
    :attr GatewayMacsecConfig macsec_config: (optional) MACsec configuration
          information.  For Dedicated Gateways with MACsec configured, return
          configuration information.  Contact IBM support for access to MACsec.
    :attr bool metered: Metered billing option.  When `true` gateway usage is billed
          per gigabyte.  When `false` there is no per gigabyte usage charge, instead a
          flat rate is charged for the gateway.
    :attr str name: The unique user-defined name for this gateway.
    :attr str operational_status: Gateway operational status. The list of enumerated
          values for this property may expand in the future. Code and processes using this
          field  must tolerate unexpected values.
    :attr GatewayPort port: (optional) gateway port for type=connect gateways.
    :attr bool provider_api_managed: (optional) Indicates whether gateway changes
          must be made via a provider portal.
    :attr ResourceGroupReference resource_group: (optional) Resource group
          reference.
    :attr int speed_mbps: Gateway speed in megabits per second.
    :attr str type: Gateway type. The list of enumerated values for this property
          may expand in the future. Code and processes using this field  must tolerate
          unexpected values.
    :attr int vlan: (optional) VLAN allocated for this gateway.  Only set for
          type=connect gateways.
    """

    def __init__(self,
                 bgp_asn: int,
                 created_at: datetime,
                 crn: str,
                 global_: bool,
                 id: str,
                 location_display_name: str,
                 location_name: str,
                 metered: bool,
                 name: str,
                 operational_status: str,
                 speed_mbps: int,
                 type: str,
                 *,
                 bgp_base_cidr: str = None,
                 bgp_cer_cidr: str = None,
                 bgp_ibm_asn: int = None,
                 bgp_ibm_cidr: str = None,
                 bgp_status: str = None,
                 carrier_name: str = None,
                 change_request: 'GatewayChangeRequest' = None,
                 completion_notice_reject_reason: str = None,
                 cross_connect_router: str = None,
                 customer_name: str = None,
                 link_status: str = None,
                 macsec_config: 'GatewayMacsecConfig' = None,
                 port: 'GatewayPort' = None,
                 provider_api_managed: bool = None,
                 resource_group: 'ResourceGroupReference' = None,
                 vlan: int = None) -> None:
        """
        Initialize a Gateway object.

        :param int bgp_asn: Customer BGP ASN.
        :param datetime created_at: The date and time resource was created.
        :param str crn: The CRN (Cloud Resource Name) of this gateway.
        :param bool global_: Gateways with global routing (`true`) can connect to
               networks outside their associated region.
        :param str id: The unique identifier of this gateway.
        :param str location_display_name: Gateway location long name.
        :param str location_name: Gateway location.
        :param bool metered: Metered billing option.  When `true` gateway usage is
               billed per gigabyte.  When `false` there is no per gigabyte usage charge,
               instead a flat rate is charged for the gateway.
        :param str name: The unique user-defined name for this gateway.
        :param str operational_status: Gateway operational status. The list of
               enumerated values for this property may expand in the future. Code and
               processes using this field  must tolerate unexpected values.
        :param int speed_mbps: Gateway speed in megabits per second.
        :param str type: Gateway type. The list of enumerated values for this
               property may expand in the future. Code and processes using this field
               must tolerate unexpected values.
        :param str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR is
               deprecated and no longer recognized the Direct Link APIs.
               See bgp_cer_cidr and bgp_ibm_cidr fields instead for IP related
               information.
               Deprecated field bgp_base_cidr will be removed from the API specificiation
               after 15-MAR-2021.
        :param str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
        :param int bgp_ibm_asn: (optional) IBM BGP ASN.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.
        :param str bgp_status: (optional) Gateway BGP status. The list of
               enumerated values for this property may expand in the future. Code and
               processes using this field  must tolerate unexpected values.
        :param str carrier_name: (optional) Carrier name.  Only set for
               type=dedicated gateways.
        :param GatewayChangeRequest change_request: (optional) Changes pending
               approval for provider managed Direct Link Connect gateways.
        :param str completion_notice_reject_reason: (optional) Reason for
               completion notice rejection.  Only included on type=dedicated gateways with
               a rejected completion notice.
        :param str cross_connect_router: (optional) Cross connect router.  Only
               included on type=dedicated gateways.
        :param str customer_name: (optional) Customer name.  Only set for
               type=dedicated gateways.
        :param str link_status: (optional) Gateway link status.  Only included on
               type=dedicated gateways. The list of enumerated values for this property
               may expand in the future. Code and processes using this field  must
               tolerate unexpected values.
        :param GatewayMacsecConfig macsec_config: (optional) MACsec configuration
               information.  For Dedicated Gateways with MACsec configured, return
               configuration information.  Contact IBM support for access to MACsec.
        :param GatewayPort port: (optional) gateway port for type=connect gateways.
        :param bool provider_api_managed: (optional) Indicates whether gateway
               changes must be made via a provider portal.
        :param ResourceGroupReference resource_group: (optional) Resource group
               reference.
        :param int vlan: (optional) VLAN allocated for this gateway.  Only set for
               type=connect gateways.
        """
        self.bgp_asn = bgp_asn
        self.bgp_base_cidr = bgp_base_cidr
        self.bgp_cer_cidr = bgp_cer_cidr
        self.bgp_ibm_asn = bgp_ibm_asn
        self.bgp_ibm_cidr = bgp_ibm_cidr
        self.bgp_status = bgp_status
        self.carrier_name = carrier_name
        self.change_request = change_request
        self.completion_notice_reject_reason = completion_notice_reject_reason
        self.created_at = created_at
        self.crn = crn
        self.cross_connect_router = cross_connect_router
        self.customer_name = customer_name
        self.global_ = global_
        self.id = id
        self.link_status = link_status
        self.location_display_name = location_display_name
        self.location_name = location_name
        self.macsec_config = macsec_config
        self.metered = metered
        self.name = name
        self.operational_status = operational_status
        self.port = port
        self.provider_api_managed = provider_api_managed
        self.resource_group = resource_group
        self.speed_mbps = speed_mbps
        self.type = type
        self.vlan = vlan

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'Gateway':
        """Initialize a Gateway object from a json dictionary."""
        args = {}
        if 'bgp_asn' in _dict:
            args['bgp_asn'] = _dict.get('bgp_asn')
        else:
            raise ValueError('Required property \'bgp_asn\' not present in Gateway JSON')
        if 'bgp_base_cidr' in _dict:
            args['bgp_base_cidr'] = _dict.get('bgp_base_cidr')
        if 'bgp_cer_cidr' in _dict:
            args['bgp_cer_cidr'] = _dict.get('bgp_cer_cidr')
        if 'bgp_ibm_asn' in _dict:
            args['bgp_ibm_asn'] = _dict.get('bgp_ibm_asn')
        if 'bgp_ibm_cidr' in _dict:
            args['bgp_ibm_cidr'] = _dict.get('bgp_ibm_cidr')
        if 'bgp_status' in _dict:
            args['bgp_status'] = _dict.get('bgp_status')
        if 'carrier_name' in _dict:
            args['carrier_name'] = _dict.get('carrier_name')
        if 'change_request' in _dict:
            args['change_request'] = _dict.get('change_request')
        if 'completion_notice_reject_reason' in _dict:
            args['completion_notice_reject_reason'] = _dict.get('completion_notice_reject_reason')
        if 'created_at' in _dict:
            args['created_at'] = string_to_datetime(_dict.get('created_at'))
        else:
            raise ValueError('Required property \'created_at\' not present in Gateway JSON')
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in Gateway JSON')
        if 'cross_connect_router' in _dict:
            args['cross_connect_router'] = _dict.get('cross_connect_router')
        if 'customer_name' in _dict:
            args['customer_name'] = _dict.get('customer_name')
        if 'global' in _dict:
            args['global_'] = _dict.get('global')
        else:
            raise ValueError('Required property \'global\' not present in Gateway JSON')
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in Gateway JSON')
        if 'link_status' in _dict:
            args['link_status'] = _dict.get('link_status')
        if 'location_display_name' in _dict:
            args['location_display_name'] = _dict.get('location_display_name')
        else:
            raise ValueError('Required property \'location_display_name\' not present in Gateway JSON')
        if 'location_name' in _dict:
            args['location_name'] = _dict.get('location_name')
        else:
            raise ValueError('Required property \'location_name\' not present in Gateway JSON')
        if 'macsec_config' in _dict:
            args['macsec_config'] = GatewayMacsecConfig.from_dict(_dict.get('macsec_config'))
        if 'metered' in _dict:
            args['metered'] = _dict.get('metered')
        else:
            raise ValueError('Required property \'metered\' not present in Gateway JSON')
        if 'name' in _dict:
            args['name'] = _dict.get('name')
        else:
            raise ValueError('Required property \'name\' not present in Gateway JSON')
        if 'operational_status' in _dict:
            args['operational_status'] = _dict.get('operational_status')
        else:
            raise ValueError('Required property \'operational_status\' not present in Gateway JSON')
        if 'port' in _dict:
            args['port'] = GatewayPort.from_dict(_dict.get('port'))
        if 'provider_api_managed' in _dict:
            args['provider_api_managed'] = _dict.get('provider_api_managed')
        if 'resource_group' in _dict:
            args['resource_group'] = ResourceGroupReference.from_dict(_dict.get('resource_group'))
        if 'speed_mbps' in _dict:
            args['speed_mbps'] = _dict.get('speed_mbps')
        else:
            raise ValueError('Required property \'speed_mbps\' not present in Gateway JSON')
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in Gateway JSON')
        if 'vlan' in _dict:
            args['vlan'] = _dict.get('vlan')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a Gateway object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'bgp_asn') and self.bgp_asn is not None:
            _dict['bgp_asn'] = self.bgp_asn
        if hasattr(self, 'bgp_base_cidr') and self.bgp_base_cidr is not None:
            _dict['bgp_base_cidr'] = self.bgp_base_cidr
        if hasattr(self, 'bgp_cer_cidr') and self.bgp_cer_cidr is not None:
            _dict['bgp_cer_cidr'] = self.bgp_cer_cidr
        if hasattr(self, 'bgp_ibm_asn') and self.bgp_ibm_asn is not None:
            _dict['bgp_ibm_asn'] = self.bgp_ibm_asn
        if hasattr(self, 'bgp_ibm_cidr') and self.bgp_ibm_cidr is not None:
            _dict['bgp_ibm_cidr'] = self.bgp_ibm_cidr
        if hasattr(self, 'bgp_status') and self.bgp_status is not None:
            _dict['bgp_status'] = self.bgp_status
        if hasattr(self, 'carrier_name') and self.carrier_name is not None:
            _dict['carrier_name'] = self.carrier_name
        if hasattr(self, 'change_request') and self.change_request is not None:
            _dict['change_request'] = self.change_request
        if hasattr(self, 'completion_notice_reject_reason') and self.completion_notice_reject_reason is not None:
            _dict['completion_notice_reject_reason'] = self.completion_notice_reject_reason
        if hasattr(self, 'created_at') and self.created_at is not None:
            _dict['created_at'] = datetime_to_string(self.created_at)
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        if hasattr(self, 'cross_connect_router') and self.cross_connect_router is not None:
            _dict['cross_connect_router'] = self.cross_connect_router
        if hasattr(self, 'customer_name') and self.customer_name is not None:
            _dict['customer_name'] = self.customer_name
        if hasattr(self, 'global_') and self.global_ is not None:
            _dict['global'] = self.global_
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        if hasattr(self, 'link_status') and self.link_status is not None:
            _dict['link_status'] = self.link_status
        if hasattr(self, 'location_display_name') and self.location_display_name is not None:
            _dict['location_display_name'] = self.location_display_name
        if hasattr(self, 'location_name') and self.location_name is not None:
            _dict['location_name'] = self.location_name
        if hasattr(self, 'macsec_config') and self.macsec_config is not None:
            _dict['macsec_config'] = self.macsec_config.to_dict()
        if hasattr(self, 'metered') and self.metered is not None:
            _dict['metered'] = self.metered
        if hasattr(self, 'name') and self.name is not None:
            _dict['name'] = self.name
        if hasattr(self, 'operational_status') and self.operational_status is not None:
            _dict['operational_status'] = self.operational_status
        if hasattr(self, 'port') and self.port is not None:
            _dict['port'] = self.port.to_dict()
        if hasattr(self, 'provider_api_managed') and self.provider_api_managed is not None:
            _dict['provider_api_managed'] = self.provider_api_managed
        if hasattr(self, 'resource_group') and self.resource_group is not None:
            _dict['resource_group'] = self.resource_group.to_dict()
        if hasattr(self, 'speed_mbps') and self.speed_mbps is not None:
            _dict['speed_mbps'] = self.speed_mbps
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        if hasattr(self, 'vlan') and self.vlan is not None:
            _dict['vlan'] = self.vlan
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this Gateway object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'Gateway') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'Gateway') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class BgpStatusEnum(Enum):
        """
        Gateway BGP status. The list of enumerated values for this property may expand in
        the future. Code and processes using this field  must tolerate unexpected values.
        """
        ACTIVE = "active"
        CONNECT = "connect"
        ESTABLISHED = "established"
        IDLE = "idle"


    class LinkStatusEnum(Enum):
        """
        Gateway link status.  Only included on type=dedicated gateways. The list of
        enumerated values for this property may expand in the future. Code and processes
        using this field  must tolerate unexpected values.
        """
        DOWN = "down"
        UP = "up"


    class OperationalStatusEnum(Enum):
        """
        Gateway operational status. The list of enumerated values for this property may
        expand in the future. Code and processes using this field  must tolerate
        unexpected values.
        """
        AWAITING_COMPLETION_NOTICE = "awaiting_completion_notice"
        AWAITING_LOA = "awaiting_loa"
        CONFIGURING = "configuring"
        CREATE_PENDING = "create_pending"
        CREATE_REJECTED = "create_rejected"
        COMPLETION_NOTICE_APPROVED = "completion_notice_approved"
        COMPLETION_NOTICE_RECEIVED = "completion_notice_received"
        COMPLETION_NOTICE_REJECTED = "completion_notice_rejected"
        DELETE_PENDING = "delete_pending"
        LOA_ACCEPTED = "loa_accepted"
        LOA_CREATED = "loa_created"
        LOA_REJECTED = "loa_rejected"
        PROVISIONED = "provisioned"


    class TypeEnum(Enum):
        """
        Gateway type. The list of enumerated values for this property may expand in the
        future. Code and processes using this field  must tolerate unexpected values.
        """
        CONNECT = "connect"
        DEDICATED = "dedicated"


class GatewayChangeRequest():
    """
    GatewayChangeRequest.

    """

    def __init__(self) -> None:
        """
        Initialize a GatewayChangeRequest object.

        """
        msg = "Cannot instantiate base class. Instead, instantiate one of the defined subclasses: {0}".format(
                  ", ".join(['GatewayChangeRequestGatewayClientGatewayCreate', 'GatewayChangeRequestGatewayClientGatewayDelete', 'GatewayChangeRequestGatewayClientGatewayUpdateAttributes']))
        raise Exception(msg)

class GatewayCollection():
    """
    GatewayCollection.

    :attr List[Gateway] gateways: Collection of Direct Link gateways.
    """

    def __init__(self,
                 gateways: List['Gateway']) -> None:
        """
        Initialize a GatewayCollection object.

        :param List[Gateway] gateways: Collection of Direct Link gateways.
        """
        self.gateways = gateways

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayCollection':
        """Initialize a GatewayCollection object from a json dictionary."""
        args = {}
        if 'gateways' in _dict:
            args['gateways'] = [Gateway.from_dict(x) for x in _dict.get('gateways')]
        else:
            raise ValueError('Required property \'gateways\' not present in GatewayCollection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'gateways') and self.gateways is not None:
            _dict['gateways'] = [x.to_dict() for x in self.gateways]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfig():
    """
    MACsec configuration information.  For Dedicated Gateways with MACsec configured,
    return configuration information.  Contact IBM support for access to MACsec.

    :attr bool active: Indicate whether MACsec should currently be active (true) or
          inactive (false) for a MACsec enabled gateway.   To be MACsec enabled a
          `macsec_config` must be specified at gateway create time.
    :attr GatewayMacsecConfigActiveCak active_cak: (optional) Active connectivity
          association key.
          During normal operation `active_cak` will match the desired `primary_cak`.
          During CAK changes this field can be used to indicate which key is currently
          active on the gateway.
    :attr str cipher_suite: (optional) SAK cipher suite.
    :attr int confidentiality_offset: (optional) confidentiality offset.
    :attr str cryptographic_algorithm: (optional) cryptographic algorithm.
    :attr GatewayMacsecConfigFallbackCak fallback_cak: (optional) fallback
          connectivity association key.
    :attr int key_server_priority: (optional) key server priority.
    :attr GatewayMacsecConfigPrimaryCak primary_cak: desired primary connectivity
          association key.
    :attr int sak_expiry_time: (optional) Secure Association Key (SAK) expiry time
          in seconds.
    :attr str security_policy: (optional) Packets without MACsec headers are not
          dropped when security_policy is `should_secure`.
    :attr str status: Current status of MACsec on this gateway.
          Status 'unknown' is returned during gateway creation and deletion.
    :attr int window_size: (optional) replay protection window size.
    """

    def __init__(self,
                 active: bool,
                 primary_cak: 'GatewayMacsecConfigPrimaryCak',
                 status: str,
                 *,
                 active_cak: 'GatewayMacsecConfigActiveCak' = None,
                 cipher_suite: str = None,
                 confidentiality_offset: int = None,
                 cryptographic_algorithm: str = None,
                 fallback_cak: 'GatewayMacsecConfigFallbackCak' = None,
                 key_server_priority: int = None,
                 sak_expiry_time: int = None,
                 security_policy: str = None,
                 window_size: int = None) -> None:
        """
        Initialize a GatewayMacsecConfig object.

        :param bool active: Indicate whether MACsec should currently be active
               (true) or inactive (false) for a MACsec enabled gateway.   To be MACsec
               enabled a `macsec_config` must be specified at gateway create time.
        :param GatewayMacsecConfigPrimaryCak primary_cak: desired primary
               connectivity association key.
        :param str status: Current status of MACsec on this gateway.
               Status 'unknown' is returned during gateway creation and deletion.
        :param GatewayMacsecConfigActiveCak active_cak: (optional) Active
               connectivity association key.
               During normal operation `active_cak` will match the desired `primary_cak`.
               During CAK changes this field can be used to indicate which key is
               currently active on the gateway.
        :param str cipher_suite: (optional) SAK cipher suite.
        :param int confidentiality_offset: (optional) confidentiality offset.
        :param str cryptographic_algorithm: (optional) cryptographic algorithm.
        :param GatewayMacsecConfigFallbackCak fallback_cak: (optional) fallback
               connectivity association key.
        :param int key_server_priority: (optional) key server priority.
        :param int sak_expiry_time: (optional) Secure Association Key (SAK) expiry
               time in seconds.
        :param str security_policy: (optional) Packets without MACsec headers are
               not dropped when security_policy is `should_secure`.
        :param int window_size: (optional) replay protection window size.
        """
        self.active = active
        self.active_cak = active_cak
        self.cipher_suite = cipher_suite
        self.confidentiality_offset = confidentiality_offset
        self.cryptographic_algorithm = cryptographic_algorithm
        self.fallback_cak = fallback_cak
        self.key_server_priority = key_server_priority
        self.primary_cak = primary_cak
        self.sak_expiry_time = sak_expiry_time
        self.security_policy = security_policy
        self.status = status
        self.window_size = window_size

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfig':
        """Initialize a GatewayMacsecConfig object from a json dictionary."""
        args = {}
        if 'active' in _dict:
            args['active'] = _dict.get('active')
        else:
            raise ValueError('Required property \'active\' not present in GatewayMacsecConfig JSON')
        if 'active_cak' in _dict:
            args['active_cak'] = GatewayMacsecConfigActiveCak.from_dict(_dict.get('active_cak'))
        if 'cipher_suite' in _dict:
            args['cipher_suite'] = _dict.get('cipher_suite')
        if 'confidentiality_offset' in _dict:
            args['confidentiality_offset'] = _dict.get('confidentiality_offset')
        if 'cryptographic_algorithm' in _dict:
            args['cryptographic_algorithm'] = _dict.get('cryptographic_algorithm')
        if 'fallback_cak' in _dict:
            args['fallback_cak'] = GatewayMacsecConfigFallbackCak.from_dict(_dict.get('fallback_cak'))
        if 'key_server_priority' in _dict:
            args['key_server_priority'] = _dict.get('key_server_priority')
        if 'primary_cak' in _dict:
            args['primary_cak'] = GatewayMacsecConfigPrimaryCak.from_dict(_dict.get('primary_cak'))
        else:
            raise ValueError('Required property \'primary_cak\' not present in GatewayMacsecConfig JSON')
        if 'sak_expiry_time' in _dict:
            args['sak_expiry_time'] = _dict.get('sak_expiry_time')
        if 'security_policy' in _dict:
            args['security_policy'] = _dict.get('security_policy')
        if 'status' in _dict:
            args['status'] = _dict.get('status')
        else:
            raise ValueError('Required property \'status\' not present in GatewayMacsecConfig JSON')
        if 'window_size' in _dict:
            args['window_size'] = _dict.get('window_size')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfig object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'active') and self.active is not None:
            _dict['active'] = self.active
        if hasattr(self, 'active_cak') and self.active_cak is not None:
            _dict['active_cak'] = self.active_cak.to_dict()
        if hasattr(self, 'cipher_suite') and self.cipher_suite is not None:
            _dict['cipher_suite'] = self.cipher_suite
        if hasattr(self, 'confidentiality_offset') and self.confidentiality_offset is not None:
            _dict['confidentiality_offset'] = self.confidentiality_offset
        if hasattr(self, 'cryptographic_algorithm') and self.cryptographic_algorithm is not None:
            _dict['cryptographic_algorithm'] = self.cryptographic_algorithm
        if hasattr(self, 'fallback_cak') and self.fallback_cak is not None:
            _dict['fallback_cak'] = self.fallback_cak.to_dict()
        if hasattr(self, 'key_server_priority') and self.key_server_priority is not None:
            _dict['key_server_priority'] = self.key_server_priority
        if hasattr(self, 'primary_cak') and self.primary_cak is not None:
            _dict['primary_cak'] = self.primary_cak.to_dict()
        if hasattr(self, 'sak_expiry_time') and self.sak_expiry_time is not None:
            _dict['sak_expiry_time'] = self.sak_expiry_time
        if hasattr(self, 'security_policy') and self.security_policy is not None:
            _dict['security_policy'] = self.security_policy
        if hasattr(self, 'status') and self.status is not None:
            _dict['status'] = self.status
        if hasattr(self, 'window_size') and self.window_size is not None:
            _dict['window_size'] = self.window_size
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfig object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfig') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfig') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class CipherSuiteEnum(Enum):
        """
        SAK cipher suite.
        """
        GCM_AES_XPN_256 = "gcm_aes_xpn_256"


    class CryptographicAlgorithmEnum(Enum):
        """
        cryptographic algorithm.
        """
        AES_256_CMAC = "aes_256_cmac"


    class SecurityPolicyEnum(Enum):
        """
        Packets without MACsec headers are not dropped when security_policy is
        `should_secure`.
        """
        SHOULD_SECURE = "should_secure"


    class StatusEnum(Enum):
        """
        Current status of MACsec on this gateway.
        Status 'unknown' is returned during gateway creation and deletion.
        """
        INIT = "init"
        PENDING = "pending"
        SECURED = "secured"
        UNKNOWN = "unknown"


class GatewayMacsecConfigActiveCak():
    """
    Active connectivity association key.
    During normal operation `active_cak` will match the desired `primary_cak`.  During CAK
    changes this field can be used to indicate which key is currently active on the
    gateway.

    :attr str crn: connectivity association key crn.
    :attr str status: connectivity association key status.
    """

    def __init__(self,
                 crn: str,
                 status: str) -> None:
        """
        Initialize a GatewayMacsecConfigActiveCak object.

        :param str crn: connectivity association key crn.
        :param str status: connectivity association key status.
        """
        self.crn = crn
        self.status = status

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigActiveCak':
        """Initialize a GatewayMacsecConfigActiveCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigActiveCak JSON')
        if 'status' in _dict:
            args['status'] = _dict.get('status')
        else:
            raise ValueError('Required property \'status\' not present in GatewayMacsecConfigActiveCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigActiveCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        if hasattr(self, 'status') and self.status is not None:
            _dict['status'] = self.status
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigActiveCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigActiveCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigActiveCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigFallbackCak():
    """
    fallback connectivity association key.

    :attr str crn: connectivity association key crn.
    :attr str status: connectivity association key status.
    """

    def __init__(self,
                 crn: str,
                 status: str) -> None:
        """
        Initialize a GatewayMacsecConfigFallbackCak object.

        :param str crn: connectivity association key crn.
        :param str status: connectivity association key status.
        """
        self.crn = crn
        self.status = status

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigFallbackCak':
        """Initialize a GatewayMacsecConfigFallbackCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigFallbackCak JSON')
        if 'status' in _dict:
            args['status'] = _dict.get('status')
        else:
            raise ValueError('Required property \'status\' not present in GatewayMacsecConfigFallbackCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigFallbackCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        if hasattr(self, 'status') and self.status is not None:
            _dict['status'] = self.status
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigFallbackCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigFallbackCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigFallbackCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigPatchTemplate():
    """
    MACsec configuration information.  When patching any macsec_config fields, no other
    fields may be specified in the patch request.  Contact IBM support for access to
    MACsec.
    A MACsec config cannot be added to a gateway created without MACsec.

    :attr bool active: (optional) Indicate whether MACsec protection should be
          active (true) or inactive (false) for this MACsec enabled gateway.
    :attr GatewayMacsecConfigPatchTemplateFallbackCak fallback_cak: (optional)
          Fallback connectivity association key.
          MACsec keys must be type=standard with key name lengths between 2 to 64
          inclusive and contain only characters [a-fA-F0-9].
          The key material must be exactly 64 characters in length and contain only
          [a-fA-F0-9].
          To clear the optional `fallback_cak` field patch its crn to `""`.
          A gateway's `fallback_cak` crn cannot match its `primary_cak` crn.
    :attr GatewayMacsecConfigPatchTemplatePrimaryCak primary_cak: (optional) Desired
          primary connectivity association key.
          MACsec keys must be type=standard with key name lengths between 2 to 64
          inclusive and contain only characters [a-fA-F0-9].
          The key material must be exactly 64 characters in length and contain only
          [a-fA-F0-9].
          A gateway's `primary_cak` crn cannot match its `fallback_cak` crn.
    :attr int window_size: (optional) replay protection window size.
    """

    def __init__(self,
                 *,
                 active: bool = None,
                 fallback_cak: 'GatewayMacsecConfigPatchTemplateFallbackCak' = None,
                 primary_cak: 'GatewayMacsecConfigPatchTemplatePrimaryCak' = None,
                 window_size: int = None) -> None:
        """
        Initialize a GatewayMacsecConfigPatchTemplate object.

        :param bool active: (optional) Indicate whether MACsec protection should be
               active (true) or inactive (false) for this MACsec enabled gateway.
        :param GatewayMacsecConfigPatchTemplateFallbackCak fallback_cak: (optional)
               Fallback connectivity association key.
               MACsec keys must be type=standard with key name lengths between 2 to 64
               inclusive and contain only characters [a-fA-F0-9].
               The key material must be exactly 64 characters in length and contain only
               [a-fA-F0-9].
               To clear the optional `fallback_cak` field patch its crn to `""`.
               A gateway's `fallback_cak` crn cannot match its `primary_cak` crn.
        :param GatewayMacsecConfigPatchTemplatePrimaryCak primary_cak: (optional)
               Desired primary connectivity association key.
               MACsec keys must be type=standard with key name lengths between 2 to 64
               inclusive and contain only characters [a-fA-F0-9].
               The key material must be exactly 64 characters in length and contain only
               [a-fA-F0-9].
               A gateway's `primary_cak` crn cannot match its `fallback_cak` crn.
        :param int window_size: (optional) replay protection window size.
        """
        self.active = active
        self.fallback_cak = fallback_cak
        self.primary_cak = primary_cak
        self.window_size = window_size

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigPatchTemplate':
        """Initialize a GatewayMacsecConfigPatchTemplate object from a json dictionary."""
        args = {}
        if 'active' in _dict:
            args['active'] = _dict.get('active')
        if 'fallback_cak' in _dict:
            args['fallback_cak'] = GatewayMacsecConfigPatchTemplateFallbackCak.from_dict(_dict.get('fallback_cak'))
        if 'primary_cak' in _dict:
            args['primary_cak'] = GatewayMacsecConfigPatchTemplatePrimaryCak.from_dict(_dict.get('primary_cak'))
        if 'window_size' in _dict:
            args['window_size'] = _dict.get('window_size')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigPatchTemplate object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'active') and self.active is not None:
            _dict['active'] = self.active
        if hasattr(self, 'fallback_cak') and self.fallback_cak is not None:
            _dict['fallback_cak'] = self.fallback_cak.to_dict()
        if hasattr(self, 'primary_cak') and self.primary_cak is not None:
            _dict['primary_cak'] = self.primary_cak.to_dict()
        if hasattr(self, 'window_size') and self.window_size is not None:
            _dict['window_size'] = self.window_size
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigPatchTemplate object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigPatchTemplate') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigPatchTemplate') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigPatchTemplateFallbackCak():
    """
    Fallback connectivity association key.
    MACsec keys must be type=standard with key name lengths between 2 to 64 inclusive and
    contain only characters [a-fA-F0-9]. The key material must be exactly 64 characters in
    length and contain only [a-fA-F0-9].
    To clear the optional `fallback_cak` field patch its crn to `""`.
    A gateway's `fallback_cak` crn cannot match its `primary_cak` crn.

    :attr str crn: connectivity association key crn.
    """

    def __init__(self,
                 crn: str) -> None:
        """
        Initialize a GatewayMacsecConfigPatchTemplateFallbackCak object.

        :param str crn: connectivity association key crn.
        """
        self.crn = crn

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigPatchTemplateFallbackCak':
        """Initialize a GatewayMacsecConfigPatchTemplateFallbackCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigPatchTemplateFallbackCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigPatchTemplateFallbackCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigPatchTemplateFallbackCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigPatchTemplateFallbackCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigPatchTemplateFallbackCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigPatchTemplatePrimaryCak():
    """
    Desired primary connectivity association key.
    MACsec keys must be type=standard with key name lengths between 2 to 64 inclusive and
    contain only characters [a-fA-F0-9]. The key material must be exactly 64 characters in
    length and contain only [a-fA-F0-9].
    A gateway's `primary_cak` crn cannot match its `fallback_cak` crn.

    :attr str crn: connectivity association key crn.
    """

    def __init__(self,
                 crn: str) -> None:
        """
        Initialize a GatewayMacsecConfigPatchTemplatePrimaryCak object.

        :param str crn: connectivity association key crn.
        """
        self.crn = crn

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigPatchTemplatePrimaryCak':
        """Initialize a GatewayMacsecConfigPatchTemplatePrimaryCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigPatchTemplatePrimaryCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigPatchTemplatePrimaryCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigPatchTemplatePrimaryCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigPatchTemplatePrimaryCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigPatchTemplatePrimaryCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigPrimaryCak():
    """
    desired primary connectivity association key.

    :attr str crn: connectivity association key crn.
    :attr str status: connectivity association key status.
    """

    def __init__(self,
                 crn: str,
                 status: str) -> None:
        """
        Initialize a GatewayMacsecConfigPrimaryCak object.

        :param str crn: connectivity association key crn.
        :param str status: connectivity association key status.
        """
        self.crn = crn
        self.status = status

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigPrimaryCak':
        """Initialize a GatewayMacsecConfigPrimaryCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigPrimaryCak JSON')
        if 'status' in _dict:
            args['status'] = _dict.get('status')
        else:
            raise ValueError('Required property \'status\' not present in GatewayMacsecConfigPrimaryCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigPrimaryCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        if hasattr(self, 'status') and self.status is not None:
            _dict['status'] = self.status
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigPrimaryCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigPrimaryCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigPrimaryCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigTemplate():
    """
    MACsec configuration information.  Contact IBM support for access to MACsec.

    :attr bool active: Indicate whether MACsec protection should be active (true) or
          inactive (false) for this MACsec enabled gateway.
    :attr GatewayMacsecConfigTemplateFallbackCak fallback_cak: (optional) Fallback
          connectivity association key.
          The `fallback_cak` crn cannot match the `primary_cak` crn.
          MACsec keys must be type=standard with key name lengths between 2 to 64
          inclusive and contain only characters [a-fA-F0-9].
          The key material must be exactly 64 characters in length and contain only
          [a-fA-F0-9].
    :attr GatewayMacsecConfigTemplatePrimaryCak primary_cak: Desired primary
          connectivity association key.
          MACsec keys must be type=standard with key name lengths between 2 to 64
          inclusive and contain only characters [a-fA-F0-9].
          The key material must be exactly 64 characters in length and contain only
          [a-fA-F0-9].
    :attr int window_size: (optional) replay protection window size.
    """

    def __init__(self,
                 active: bool,
                 primary_cak: 'GatewayMacsecConfigTemplatePrimaryCak',
                 *,
                 fallback_cak: 'GatewayMacsecConfigTemplateFallbackCak' = None,
                 window_size: int = None) -> None:
        """
        Initialize a GatewayMacsecConfigTemplate object.

        :param bool active: Indicate whether MACsec protection should be active
               (true) or inactive (false) for this MACsec enabled gateway.
        :param GatewayMacsecConfigTemplatePrimaryCak primary_cak: Desired primary
               connectivity association key.
               MACsec keys must be type=standard with key name lengths between 2 to 64
               inclusive and contain only characters [a-fA-F0-9].
               The key material must be exactly 64 characters in length and contain only
               [a-fA-F0-9].
        :param GatewayMacsecConfigTemplateFallbackCak fallback_cak: (optional)
               Fallback connectivity association key.
               The `fallback_cak` crn cannot match the `primary_cak` crn.
               MACsec keys must be type=standard with key name lengths between 2 to 64
               inclusive and contain only characters [a-fA-F0-9].
               The key material must be exactly 64 characters in length and contain only
               [a-fA-F0-9].
        :param int window_size: (optional) replay protection window size.
        """
        self.active = active
        self.fallback_cak = fallback_cak
        self.primary_cak = primary_cak
        self.window_size = window_size

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigTemplate':
        """Initialize a GatewayMacsecConfigTemplate object from a json dictionary."""
        args = {}
        if 'active' in _dict:
            args['active'] = _dict.get('active')
        else:
            raise ValueError('Required property \'active\' not present in GatewayMacsecConfigTemplate JSON')
        if 'fallback_cak' in _dict:
            args['fallback_cak'] = GatewayMacsecConfigTemplateFallbackCak.from_dict(_dict.get('fallback_cak'))
        if 'primary_cak' in _dict:
            args['primary_cak'] = GatewayMacsecConfigTemplatePrimaryCak.from_dict(_dict.get('primary_cak'))
        else:
            raise ValueError('Required property \'primary_cak\' not present in GatewayMacsecConfigTemplate JSON')
        if 'window_size' in _dict:
            args['window_size'] = _dict.get('window_size')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigTemplate object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'active') and self.active is not None:
            _dict['active'] = self.active
        if hasattr(self, 'fallback_cak') and self.fallback_cak is not None:
            _dict['fallback_cak'] = self.fallback_cak.to_dict()
        if hasattr(self, 'primary_cak') and self.primary_cak is not None:
            _dict['primary_cak'] = self.primary_cak.to_dict()
        if hasattr(self, 'window_size') and self.window_size is not None:
            _dict['window_size'] = self.window_size
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigTemplate object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigTemplate') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigTemplate') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigTemplateFallbackCak():
    """
    Fallback connectivity association key.
    The `fallback_cak` crn cannot match the `primary_cak` crn. MACsec keys must be
    type=standard with key name lengths between 2 to 64 inclusive and contain only
    characters [a-fA-F0-9]. The key material must be exactly 64 characters in length and
    contain only [a-fA-F0-9].

    :attr str crn: connectivity association key crn.
    """

    def __init__(self,
                 crn: str) -> None:
        """
        Initialize a GatewayMacsecConfigTemplateFallbackCak object.

        :param str crn: connectivity association key crn.
        """
        self.crn = crn

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigTemplateFallbackCak':
        """Initialize a GatewayMacsecConfigTemplateFallbackCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigTemplateFallbackCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigTemplateFallbackCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigTemplateFallbackCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigTemplateFallbackCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigTemplateFallbackCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayMacsecConfigTemplatePrimaryCak():
    """
    Desired primary connectivity association key.
    MACsec keys must be type=standard with key name lengths between 2 to 64 inclusive and
    contain only characters [a-fA-F0-9]. The key material must be exactly 64 characters in
    length and contain only [a-fA-F0-9].

    :attr str crn: connectivity association key crn.
    """

    def __init__(self,
                 crn: str) -> None:
        """
        Initialize a GatewayMacsecConfigTemplatePrimaryCak object.

        :param str crn: connectivity association key crn.
        """
        self.crn = crn

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayMacsecConfigTemplatePrimaryCak':
        """Initialize a GatewayMacsecConfigTemplatePrimaryCak object from a json dictionary."""
        args = {}
        if 'crn' in _dict:
            args['crn'] = _dict.get('crn')
        else:
            raise ValueError('Required property \'crn\' not present in GatewayMacsecConfigTemplatePrimaryCak JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayMacsecConfigTemplatePrimaryCak object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'crn') and self.crn is not None:
            _dict['crn'] = self.crn
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayMacsecConfigTemplatePrimaryCak object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayMacsecConfigTemplatePrimaryCak') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayMacsecConfigTemplatePrimaryCak') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayPort():
    """
    gateway port for type=connect gateways.

    :attr str id: Port Identifier.
    """

    def __init__(self,
                 id: str) -> None:
        """
        Initialize a GatewayPort object.

        :param str id: Port Identifier.
        """
        self.id = id

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayPort':
        """Initialize a GatewayPort object from a json dictionary."""
        args = {}
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in GatewayPort JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayPort object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayPort object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayPort') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayPort') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayPortIdentity():
    """
    Select Port Label for new type=connect gateway.

    :attr str id: port id.
    """

    def __init__(self,
                 id: str) -> None:
        """
        Initialize a GatewayPortIdentity object.

        :param str id: port id.
        """
        self.id = id

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayPortIdentity':
        """Initialize a GatewayPortIdentity object from a json dictionary."""
        args = {}
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in GatewayPortIdentity JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayPortIdentity object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayPortIdentity object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayPortIdentity') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayPortIdentity') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayStatistic():
    """
    Gateway statistics.  Currently data retrieval is only supported for MACsec
    configurations.

    :attr datetime created_at: Date and time data was collected.
    :attr str data: statistics output.
    :attr str type: statistic type.
    """

    def __init__(self,
                 created_at: datetime,
                 data: str,
                 type: str) -> None:
        """
        Initialize a GatewayStatistic object.

        :param datetime created_at: Date and time data was collected.
        :param str data: statistics output.
        :param str type: statistic type.
        """
        self.created_at = created_at
        self.data = data
        self.type = type

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayStatistic':
        """Initialize a GatewayStatistic object from a json dictionary."""
        args = {}
        if 'created_at' in _dict:
            args['created_at'] = string_to_datetime(_dict.get('created_at'))
        else:
            raise ValueError('Required property \'created_at\' not present in GatewayStatistic JSON')
        if 'data' in _dict:
            args['data'] = _dict.get('data')
        else:
            raise ValueError('Required property \'data\' not present in GatewayStatistic JSON')
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayStatistic JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayStatistic object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'created_at') and self.created_at is not None:
            _dict['created_at'] = datetime_to_string(self.created_at)
        if hasattr(self, 'data') and self.data is not None:
            _dict['data'] = self.data
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayStatistic object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayStatistic') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayStatistic') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        statistic type.
        """
        MACSEC_MKA_SESSION = "macsec_mka_session"
        MACSEC_POLICY = "macsec_policy"
        MACSEC_MKA_STATISTICS = "macsec_mka_statistics"


class GatewayStatisticCollection():
    """
    gateway statistics.

    :attr List[GatewayStatistic] statistics: Collection of gateway statistics.
    """

    def __init__(self,
                 statistics: List['GatewayStatistic']) -> None:
        """
        Initialize a GatewayStatisticCollection object.

        :param List[GatewayStatistic] statistics: Collection of gateway statistics.
        """
        self.statistics = statistics

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayStatisticCollection':
        """Initialize a GatewayStatisticCollection object from a json dictionary."""
        args = {}
        if 'statistics' in _dict:
            args['statistics'] = [GatewayStatistic.from_dict(x) for x in _dict.get('statistics')]
        else:
            raise ValueError('Required property \'statistics\' not present in GatewayStatisticCollection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayStatisticCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'statistics') and self.statistics is not None:
            _dict['statistics'] = [x.to_dict() for x in self.statistics]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayStatisticCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayStatisticCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayStatisticCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayTemplate():
    """
    Create gateway template.

    :attr int bgp_asn: BGP ASN.
    :attr str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
          Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how to
          create a gateway using either automatic or explicit IP assignment.  Any
          bgp_base_cidr value set will be ignored.
          Deprecated field bgp_base_cidr will be removed from the API specificiation after
          15-MAR-2021.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr bool global_: Gateways with global routing (`true`) can connect to
          networks outside their associated region.
    :attr bool metered: Metered billing option.  When `true` gateway usage is billed
          per gigabyte.  When `false` there is no per gigabyte usage charge, instead a
          flat rate is charged for the gateway.
    :attr str name: The unique user-defined name for this gateway.
    :attr ResourceGroupIdentity resource_group: (optional) Resource group for this
          resource. If unspecified, the account's [default resource
          group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is used.
    :attr int speed_mbps: Gateway speed in megabits per second.
    :attr str type: Gateway type.
    """

    def __init__(self,
                 bgp_asn: int,
                 global_: bool,
                 metered: bool,
                 name: str,
                 speed_mbps: int,
                 type: str,
                 *,
                 bgp_base_cidr: str = None,
                 bgp_cer_cidr: str = None,
                 bgp_ibm_cidr: str = None,
                 resource_group: 'ResourceGroupIdentity' = None) -> None:
        """
        Initialize a GatewayTemplate object.

        :param int bgp_asn: BGP ASN.
        :param bool global_: Gateways with global routing (`true`) can connect to
               networks outside their associated region.
        :param bool metered: Metered billing option.  When `true` gateway usage is
               billed per gigabyte.  When `false` there is no per gigabyte usage charge,
               instead a flat rate is charged for the gateway.
        :param str name: The unique user-defined name for this gateway.
        :param int speed_mbps: Gateway speed in megabits per second.
        :param str type: Gateway type.
        :param str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
               Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how
               to create a gateway using either automatic or explicit IP assignment.  Any
               bgp_base_cidr value set will be ignored.
               Deprecated field bgp_base_cidr will be removed from the API specificiation
               after 15-MAR-2021.
        :param str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param ResourceGroupIdentity resource_group: (optional) Resource group for
               this resource. If unspecified, the account's [default resource
               group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is
               used.
        """
        msg = "Cannot instantiate base class. Instead, instantiate one of the defined subclasses: {0}".format(
                  ", ".join(['GatewayTemplateGatewayTypeDedicatedTemplate', 'GatewayTemplateGatewayTypeConnectTemplate']))
        raise Exception(msg)

    class TypeEnum(Enum):
        """
        Gateway type.
        """
        CONNECT = "connect"
        DEDICATED = "dedicated"


class GatewayVirtualConnection():
    """
    Virtual connection.

    :attr datetime created_at: The date and time resource was created.
    :attr str id: The unique identifier for this virtual connection.
    :attr str name: The user-defined name for this virtual connection.  Virtual
          connection names are unique within a gateway.  This is the name of the virtual
          connection itself, the network being connected may have its own name attribute.
    :attr str network_account: (optional) For virtual connections across two
          different IBM Cloud Accounts network_account indicates the account that owns the
          target network.
    :attr str network_id: (optional) Unique identifier of the target network.  For
          type=vpc virtual connections this is the CRN of the target VPC.  This field does
          not apply to type=classic connections.
    :attr str status: Status of the virtual connection.
          The list of enumerated values for this property may expand in the future. Code
          and processes using this field  must tolerate unexpected values.
    :attr str type: Virtual connection type.
          The list of enumerated values for this property may expand in the future. Code
          and processes using this field  must tolerate unexpected values.
    """

    def __init__(self,
                 created_at: datetime,
                 id: str,
                 name: str,
                 status: str,
                 type: str,
                 *,
                 network_account: str = None,
                 network_id: str = None) -> None:
        """
        Initialize a GatewayVirtualConnection object.

        :param datetime created_at: The date and time resource was created.
        :param str id: The unique identifier for this virtual connection.
        :param str name: The user-defined name for this virtual connection.
               Virtual connection names are unique within a gateway.  This is the name of
               the virtual connection itself, the network being connected may have its own
               name attribute.
        :param str status: Status of the virtual connection.
               The list of enumerated values for this property may expand in the future.
               Code and processes using this field  must tolerate unexpected values.
        :param str type: Virtual connection type.
               The list of enumerated values for this property may expand in the future.
               Code and processes using this field  must tolerate unexpected values.
        :param str network_account: (optional) For virtual connections across two
               different IBM Cloud Accounts network_account indicates the account that
               owns the target network.
        :param str network_id: (optional) Unique identifier of the target network.
               For type=vpc virtual connections this is the CRN of the target VPC.  This
               field does not apply to type=classic connections.
        """
        self.created_at = created_at
        self.id = id
        self.name = name
        self.network_account = network_account
        self.network_id = network_id
        self.status = status
        self.type = type

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayVirtualConnection':
        """Initialize a GatewayVirtualConnection object from a json dictionary."""
        args = {}
        if 'created_at' in _dict:
            args['created_at'] = string_to_datetime(_dict.get('created_at'))
        else:
            raise ValueError('Required property \'created_at\' not present in GatewayVirtualConnection JSON')
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in GatewayVirtualConnection JSON')
        if 'name' in _dict:
            args['name'] = _dict.get('name')
        else:
            raise ValueError('Required property \'name\' not present in GatewayVirtualConnection JSON')
        if 'network_account' in _dict:
            args['network_account'] = _dict.get('network_account')
        if 'network_id' in _dict:
            args['network_id'] = _dict.get('network_id')
        if 'status' in _dict:
            args['status'] = _dict.get('status')
        else:
            raise ValueError('Required property \'status\' not present in GatewayVirtualConnection JSON')
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayVirtualConnection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayVirtualConnection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'created_at') and self.created_at is not None:
            _dict['created_at'] = datetime_to_string(self.created_at)
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        if hasattr(self, 'name') and self.name is not None:
            _dict['name'] = self.name
        if hasattr(self, 'network_account') and self.network_account is not None:
            _dict['network_account'] = self.network_account
        if hasattr(self, 'network_id') and self.network_id is not None:
            _dict['network_id'] = self.network_id
        if hasattr(self, 'status') and self.status is not None:
            _dict['status'] = self.status
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayVirtualConnection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayVirtualConnection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayVirtualConnection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class StatusEnum(Enum):
        """
        Status of the virtual connection.
        The list of enumerated values for this property may expand in the future. Code and
        processes using this field  must tolerate unexpected values.
        """
        PENDING = "pending"
        ATTACHED = "attached"
        APPROVAL_PENDING = "approval_pending"
        REJECTED = "rejected"
        EXPIRED = "expired"
        DELETING = "deleting"
        DETACHED_BY_NETWORK_PENDING = "detached_by_network_pending"
        DETACHED_BY_NETWORK = "detached_by_network"


    class TypeEnum(Enum):
        """
        Virtual connection type.
        The list of enumerated values for this property may expand in the future. Code and
        processes using this field  must tolerate unexpected values.
        """
        CLASSIC = "classic"
        VPC = "vpc"


class GatewayVirtualConnectionCollection():
    """
    Virtual connection collection.

    :attr List[GatewayVirtualConnection] virtual_connections: virtual connection
          array.
    """

    def __init__(self,
                 virtual_connections: List['GatewayVirtualConnection']) -> None:
        """
        Initialize a GatewayVirtualConnectionCollection object.

        :param List[GatewayVirtualConnection] virtual_connections: virtual
               connection array.
        """
        self.virtual_connections = virtual_connections

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayVirtualConnectionCollection':
        """Initialize a GatewayVirtualConnectionCollection object from a json dictionary."""
        args = {}
        if 'virtual_connections' in _dict:
            args['virtual_connections'] = [GatewayVirtualConnection.from_dict(x) for x in _dict.get('virtual_connections')]
        else:
            raise ValueError('Required property \'virtual_connections\' not present in GatewayVirtualConnectionCollection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayVirtualConnectionCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'virtual_connections') and self.virtual_connections is not None:
            _dict['virtual_connections'] = [x.to_dict() for x in self.virtual_connections]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayVirtualConnectionCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayVirtualConnectionCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayVirtualConnectionCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class LocationCollection():
    """
    location collection.

    :attr List[LocationOutput] locations: Collection of Direct Link locations.
    """

    def __init__(self,
                 locations: List['LocationOutput']) -> None:
        """
        Initialize a LocationCollection object.

        :param List[LocationOutput] locations: Collection of Direct Link locations.
        """
        self.locations = locations

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'LocationCollection':
        """Initialize a LocationCollection object from a json dictionary."""
        args = {}
        if 'locations' in _dict:
            args['locations'] = [LocationOutput.from_dict(x) for x in _dict.get('locations')]
        else:
            raise ValueError('Required property \'locations\' not present in LocationCollection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a LocationCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'locations') and self.locations is not None:
            _dict['locations'] = [x.to_dict() for x in self.locations]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this LocationCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'LocationCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'LocationCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class LocationCrossConnectRouterCollection():
    """
    List of cross connect router details.

    :attr List[CrossConnectRouter] cross_connect_routers: (optional) Array of
          Routers for this location.
    """

    def __init__(self,
                 *,
                 cross_connect_routers: List['CrossConnectRouter'] = None) -> None:
        """
        Initialize a LocationCrossConnectRouterCollection object.

        :param List[CrossConnectRouter] cross_connect_routers: (optional) Array of
               Routers for this location.
        """
        self.cross_connect_routers = cross_connect_routers

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'LocationCrossConnectRouterCollection':
        """Initialize a LocationCrossConnectRouterCollection object from a json dictionary."""
        args = {}
        if 'cross_connect_routers' in _dict:
            args['cross_connect_routers'] = [CrossConnectRouter.from_dict(x) for x in _dict.get('cross_connect_routers')]
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a LocationCrossConnectRouterCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'cross_connect_routers') and self.cross_connect_routers is not None:
            _dict['cross_connect_routers'] = [x.to_dict() for x in self.cross_connect_routers]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this LocationCrossConnectRouterCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'LocationCrossConnectRouterCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'LocationCrossConnectRouterCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class LocationOutput():
    """
    location.

    :attr str billing_location: (optional) Billing location.  Only present for
          locations where provisioning is enabled.
    :attr str building_colocation_owner: (optional) Building colocation owner.  Only
          present for offering_type=dedicated locations where provisioning is enabled.
    :attr str display_name: Location long name.
    :attr str location_type: Location type.
    :attr bool macsec_enabled: (optional) Indicate whether location supports MACsec.
           Only returned for gateway type=dedicated locations.  Contact IBM support for
          access to MACsec.
    :attr str market: Location market.
    :attr str market_geography: (optional) Location geography.  Only present for
          locations where provisioning is enabled.
    :attr bool mzr: (optional) Is location a multi-zone region (MZR).  Only present
          for locations where provisioning is enabled.
    :attr str name: Location short name.
    :attr str offering_type: Location offering type.
    :attr bool provision_enabled: Indicates for the specific offering_type whether
          this location supports gateway provisioning.
    :attr str vpc_region: (optional) Location's VPC region.  Only present for
          locations where provisioning is enabled.
    """

    def __init__(self,
                 display_name: str,
                 location_type: str,
                 market: str,
                 name: str,
                 offering_type: str,
                 provision_enabled: bool,
                 *,
                 billing_location: str = None,
                 building_colocation_owner: str = None,
                 macsec_enabled: bool = None,
                 market_geography: str = None,
                 mzr: bool = None,
                 vpc_region: str = None) -> None:
        """
        Initialize a LocationOutput object.

        :param str display_name: Location long name.
        :param str location_type: Location type.
        :param str market: Location market.
        :param str name: Location short name.
        :param str offering_type: Location offering type.
        :param bool provision_enabled: Indicates for the specific offering_type
               whether this location supports gateway provisioning.
        :param str billing_location: (optional) Billing location.  Only present for
               locations where provisioning is enabled.
        :param str building_colocation_owner: (optional) Building colocation owner.
                Only present for offering_type=dedicated locations where provisioning is
               enabled.
        :param bool macsec_enabled: (optional) Indicate whether location supports
               MACsec.  Only returned for gateway type=dedicated locations.  Contact IBM
               support for access to MACsec.
        :param str market_geography: (optional) Location geography.  Only present
               for locations where provisioning is enabled.
        :param bool mzr: (optional) Is location a multi-zone region (MZR).  Only
               present for locations where provisioning is enabled.
        :param str vpc_region: (optional) Location's VPC region.  Only present for
               locations where provisioning is enabled.
        """
        self.billing_location = billing_location
        self.building_colocation_owner = building_colocation_owner
        self.display_name = display_name
        self.location_type = location_type
        self.macsec_enabled = macsec_enabled
        self.market = market
        self.market_geography = market_geography
        self.mzr = mzr
        self.name = name
        self.offering_type = offering_type
        self.provision_enabled = provision_enabled
        self.vpc_region = vpc_region

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'LocationOutput':
        """Initialize a LocationOutput object from a json dictionary."""
        args = {}
        if 'billing_location' in _dict:
            args['billing_location'] = _dict.get('billing_location')
        if 'building_colocation_owner' in _dict:
            args['building_colocation_owner'] = _dict.get('building_colocation_owner')
        if 'display_name' in _dict:
            args['display_name'] = _dict.get('display_name')
        else:
            raise ValueError('Required property \'display_name\' not present in LocationOutput JSON')
        if 'location_type' in _dict:
            args['location_type'] = _dict.get('location_type')
        else:
            raise ValueError('Required property \'location_type\' not present in LocationOutput JSON')
        if 'macsec_enabled' in _dict:
            args['macsec_enabled'] = _dict.get('macsec_enabled')
        if 'market' in _dict:
            args['market'] = _dict.get('market')
        else:
            raise ValueError('Required property \'market\' not present in LocationOutput JSON')
        if 'market_geography' in _dict:
            args['market_geography'] = _dict.get('market_geography')
        if 'mzr' in _dict:
            args['mzr'] = _dict.get('mzr')
        if 'name' in _dict:
            args['name'] = _dict.get('name')
        else:
            raise ValueError('Required property \'name\' not present in LocationOutput JSON')
        if 'offering_type' in _dict:
            args['offering_type'] = _dict.get('offering_type')
        else:
            raise ValueError('Required property \'offering_type\' not present in LocationOutput JSON')
        if 'provision_enabled' in _dict:
            args['provision_enabled'] = _dict.get('provision_enabled')
        else:
            raise ValueError('Required property \'provision_enabled\' not present in LocationOutput JSON')
        if 'vpc_region' in _dict:
            args['vpc_region'] = _dict.get('vpc_region')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a LocationOutput object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'billing_location') and self.billing_location is not None:
            _dict['billing_location'] = self.billing_location
        if hasattr(self, 'building_colocation_owner') and self.building_colocation_owner is not None:
            _dict['building_colocation_owner'] = self.building_colocation_owner
        if hasattr(self, 'display_name') and self.display_name is not None:
            _dict['display_name'] = self.display_name
        if hasattr(self, 'location_type') and self.location_type is not None:
            _dict['location_type'] = self.location_type
        if hasattr(self, 'macsec_enabled') and self.macsec_enabled is not None:
            _dict['macsec_enabled'] = self.macsec_enabled
        if hasattr(self, 'market') and self.market is not None:
            _dict['market'] = self.market
        if hasattr(self, 'market_geography') and self.market_geography is not None:
            _dict['market_geography'] = self.market_geography
        if hasattr(self, 'mzr') and self.mzr is not None:
            _dict['mzr'] = self.mzr
        if hasattr(self, 'name') and self.name is not None:
            _dict['name'] = self.name
        if hasattr(self, 'offering_type') and self.offering_type is not None:
            _dict['offering_type'] = self.offering_type
        if hasattr(self, 'provision_enabled') and self.provision_enabled is not None:
            _dict['provision_enabled'] = self.provision_enabled
        if hasattr(self, 'vpc_region') and self.vpc_region is not None:
            _dict['vpc_region'] = self.vpc_region
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this LocationOutput object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'LocationOutput') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'LocationOutput') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class OfferingSpeed():
    """
    Speed.

    :attr int link_speed: Link speed in megabits per second.
    :attr bool macsec_enabled: (optional) Indicate whether speed supports MACsec.
          Only returned for gateway type=dedicated speeds.  Contact IBM support for access
          to MACsec.
    """

    def __init__(self,
                 link_speed: int,
                 *,
                 macsec_enabled: bool = None) -> None:
        """
        Initialize a OfferingSpeed object.

        :param int link_speed: Link speed in megabits per second.
        :param bool macsec_enabled: (optional) Indicate whether speed supports
               MACsec.  Only returned for gateway type=dedicated speeds.  Contact IBM
               support for access to MACsec.
        """
        self.link_speed = link_speed
        self.macsec_enabled = macsec_enabled

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'OfferingSpeed':
        """Initialize a OfferingSpeed object from a json dictionary."""
        args = {}
        if 'link_speed' in _dict:
            args['link_speed'] = _dict.get('link_speed')
        else:
            raise ValueError('Required property \'link_speed\' not present in OfferingSpeed JSON')
        if 'macsec_enabled' in _dict:
            args['macsec_enabled'] = _dict.get('macsec_enabled')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a OfferingSpeed object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'link_speed') and self.link_speed is not None:
            _dict['link_speed'] = self.link_speed
        if hasattr(self, 'macsec_enabled') and self.macsec_enabled is not None:
            _dict['macsec_enabled'] = self.macsec_enabled
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this OfferingSpeed object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'OfferingSpeed') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'OfferingSpeed') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class OfferingSpeedCollection():
    """
    OfferingSpeedCollection.

    :attr List[OfferingSpeed] speeds: speed list.
    """

    def __init__(self,
                 speeds: List['OfferingSpeed']) -> None:
        """
        Initialize a OfferingSpeedCollection object.

        :param List[OfferingSpeed] speeds: speed list.
        """
        self.speeds = speeds

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'OfferingSpeedCollection':
        """Initialize a OfferingSpeedCollection object from a json dictionary."""
        args = {}
        if 'speeds' in _dict:
            args['speeds'] = [OfferingSpeed.from_dict(x) for x in _dict.get('speeds')]
        else:
            raise ValueError('Required property \'speeds\' not present in OfferingSpeedCollection JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a OfferingSpeedCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'speeds') and self.speeds is not None:
            _dict['speeds'] = [x.to_dict() for x in self.speeds]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this OfferingSpeedCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'OfferingSpeedCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'OfferingSpeedCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class Port():
    """
    Provider port details.

    :attr int direct_link_count: Count of existing Direct Link gateways in this
          account on this port.
    :attr str id: Port identifier.
    :attr str label: Port Label.
    :attr str location_display_name: Port location long name.
    :attr str location_name: Port location name identifier.
    :attr str provider_name: Port's provider name.
    :attr List[int] supported_link_speeds: Port's supported speeds in megabits per
          second.
    """

    def __init__(self,
                 direct_link_count: int,
                 id: str,
                 label: str,
                 location_display_name: str,
                 location_name: str,
                 provider_name: str,
                 supported_link_speeds: List[int]) -> None:
        """
        Initialize a Port object.

        :param int direct_link_count: Count of existing Direct Link gateways in
               this account on this port.
        :param str id: Port identifier.
        :param str label: Port Label.
        :param str location_display_name: Port location long name.
        :param str location_name: Port location name identifier.
        :param str provider_name: Port's provider name.
        :param List[int] supported_link_speeds: Port's supported speeds in megabits
               per second.
        """
        self.direct_link_count = direct_link_count
        self.id = id
        self.label = label
        self.location_display_name = location_display_name
        self.location_name = location_name
        self.provider_name = provider_name
        self.supported_link_speeds = supported_link_speeds

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'Port':
        """Initialize a Port object from a json dictionary."""
        args = {}
        if 'direct_link_count' in _dict:
            args['direct_link_count'] = _dict.get('direct_link_count')
        else:
            raise ValueError('Required property \'direct_link_count\' not present in Port JSON')
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in Port JSON')
        if 'label' in _dict:
            args['label'] = _dict.get('label')
        else:
            raise ValueError('Required property \'label\' not present in Port JSON')
        if 'location_display_name' in _dict:
            args['location_display_name'] = _dict.get('location_display_name')
        else:
            raise ValueError('Required property \'location_display_name\' not present in Port JSON')
        if 'location_name' in _dict:
            args['location_name'] = _dict.get('location_name')
        else:
            raise ValueError('Required property \'location_name\' not present in Port JSON')
        if 'provider_name' in _dict:
            args['provider_name'] = _dict.get('provider_name')
        else:
            raise ValueError('Required property \'provider_name\' not present in Port JSON')
        if 'supported_link_speeds' in _dict:
            args['supported_link_speeds'] = _dict.get('supported_link_speeds')
        else:
            raise ValueError('Required property \'supported_link_speeds\' not present in Port JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a Port object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'direct_link_count') and self.direct_link_count is not None:
            _dict['direct_link_count'] = self.direct_link_count
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        if hasattr(self, 'label') and self.label is not None:
            _dict['label'] = self.label
        if hasattr(self, 'location_display_name') and self.location_display_name is not None:
            _dict['location_display_name'] = self.location_display_name
        if hasattr(self, 'location_name') and self.location_name is not None:
            _dict['location_name'] = self.location_name
        if hasattr(self, 'provider_name') and self.provider_name is not None:
            _dict['provider_name'] = self.provider_name
        if hasattr(self, 'supported_link_speeds') and self.supported_link_speeds is not None:
            _dict['supported_link_speeds'] = self.supported_link_speeds
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this Port object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'Port') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'Port') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class PortCollection():
    """
    List of port label details.

    :attr PortsPaginatedCollectionFirst first: A reference to the first page of
          resources.
    :attr int limit: The maximum number of resources can be returned by the request.
    :attr PortsPaginatedCollectionNext next: (optional) A reference to the next page
          of resources; this reference is included for all pages except the last page.
    :attr int total_count: The total number of resources across all pages.
    :attr List[Port] ports: (optional) Array of ports.
    """

    def __init__(self,
                 first: 'PortsPaginatedCollectionFirst',
                 limit: int,
                 total_count: int,
                 *,
                 next: 'PortsPaginatedCollectionNext' = None,
                 ports: List['Port'] = None) -> None:
        """
        Initialize a PortCollection object.

        :param PortsPaginatedCollectionFirst first: A reference to the first page
               of resources.
        :param int limit: The maximum number of resources can be returned by the
               request.
        :param int total_count: The total number of resources across all pages.
        :param PortsPaginatedCollectionNext next: (optional) A reference to the
               next page of resources; this reference is included for all pages except the
               last page.
        :param List[Port] ports: (optional) Array of ports.
        """
        self.first = first
        self.limit = limit
        self.next = next
        self.total_count = total_count
        self.ports = ports

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'PortCollection':
        """Initialize a PortCollection object from a json dictionary."""
        args = {}
        if 'first' in _dict:
            args['first'] = PortsPaginatedCollectionFirst.from_dict(_dict.get('first'))
        else:
            raise ValueError('Required property \'first\' not present in PortCollection JSON')
        if 'limit' in _dict:
            args['limit'] = _dict.get('limit')
        else:
            raise ValueError('Required property \'limit\' not present in PortCollection JSON')
        if 'next' in _dict:
            args['next'] = PortsPaginatedCollectionNext.from_dict(_dict.get('next'))
        if 'total_count' in _dict:
            args['total_count'] = _dict.get('total_count')
        else:
            raise ValueError('Required property \'total_count\' not present in PortCollection JSON')
        if 'ports' in _dict:
            args['ports'] = [Port.from_dict(x) for x in _dict.get('ports')]
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a PortCollection object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'first') and self.first is not None:
            _dict['first'] = self.first.to_dict()
        if hasattr(self, 'limit') and self.limit is not None:
            _dict['limit'] = self.limit
        if hasattr(self, 'next') and self.next is not None:
            _dict['next'] = self.next.to_dict()
        if hasattr(self, 'total_count') and self.total_count is not None:
            _dict['total_count'] = self.total_count
        if hasattr(self, 'ports') and self.ports is not None:
            _dict['ports'] = [x.to_dict() for x in self.ports]
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this PortCollection object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'PortCollection') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'PortCollection') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class PortsPaginatedCollectionFirst():
    """
    A reference to the first page of resources.

    :attr str href: The URL for the first page of resources.
    """

    def __init__(self,
                 href: str) -> None:
        """
        Initialize a PortsPaginatedCollectionFirst object.

        :param str href: The URL for the first page of resources.
        """
        self.href = href

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'PortsPaginatedCollectionFirst':
        """Initialize a PortsPaginatedCollectionFirst object from a json dictionary."""
        args = {}
        if 'href' in _dict:
            args['href'] = _dict.get('href')
        else:
            raise ValueError('Required property \'href\' not present in PortsPaginatedCollectionFirst JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a PortsPaginatedCollectionFirst object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'href') and self.href is not None:
            _dict['href'] = self.href
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this PortsPaginatedCollectionFirst object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'PortsPaginatedCollectionFirst') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'PortsPaginatedCollectionFirst') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class PortsPaginatedCollectionNext():
    """
    A reference to the next page of resources; this reference is included for all pages
    except the last page.

    :attr str href: URL for the next page of resources.
    :attr str start: (optional) start token for the next page of resources.
    """

    def __init__(self,
                 href: str,
                 *,
                 start: str = None) -> None:
        """
        Initialize a PortsPaginatedCollectionNext object.

        :param str href: URL for the next page of resources.
        :param str start: (optional) start token for the next page of resources.
        """
        self.href = href
        self.start = start

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'PortsPaginatedCollectionNext':
        """Initialize a PortsPaginatedCollectionNext object from a json dictionary."""
        args = {}
        if 'href' in _dict:
            args['href'] = _dict.get('href')
        else:
            raise ValueError('Required property \'href\' not present in PortsPaginatedCollectionNext JSON')
        if 'start' in _dict:
            args['start'] = _dict.get('start')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a PortsPaginatedCollectionNext object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'href') and self.href is not None:
            _dict['href'] = self.href
        if hasattr(self, 'start') and self.start is not None:
            _dict['start'] = self.start
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this PortsPaginatedCollectionNext object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'PortsPaginatedCollectionNext') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'PortsPaginatedCollectionNext') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class ResourceGroupIdentity():
    """
    Resource group for this resource. If unspecified, the account's [default resource
    group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is used.

    :attr str id: Resource group identifier.
    """

    def __init__(self,
                 id: str) -> None:
        """
        Initialize a ResourceGroupIdentity object.

        :param str id: Resource group identifier.
        """
        self.id = id

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'ResourceGroupIdentity':
        """Initialize a ResourceGroupIdentity object from a json dictionary."""
        args = {}
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in ResourceGroupIdentity JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a ResourceGroupIdentity object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this ResourceGroupIdentity object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'ResourceGroupIdentity') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'ResourceGroupIdentity') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class ResourceGroupReference():
    """
    Resource group reference.

    :attr str id: Resource group identifier.
    """

    def __init__(self,
                 id: str) -> None:
        """
        Initialize a ResourceGroupReference object.

        :param str id: Resource group identifier.
        """
        self.id = id

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'ResourceGroupReference':
        """Initialize a ResourceGroupReference object from a json dictionary."""
        args = {}
        if 'id' in _dict:
            args['id'] = _dict.get('id')
        else:
            raise ValueError('Required property \'id\' not present in ResourceGroupReference JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a ResourceGroupReference object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'id') and self.id is not None:
            _dict['id'] = self.id
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this ResourceGroupReference object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'ResourceGroupReference') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'ResourceGroupReference') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

class GatewayChangeRequestGatewayClientGatewayCreate(GatewayChangeRequest):
    """
    gateway create.

    :attr str type: type of gateway change request.
    """

    def __init__(self,
                 type: str) -> None:
        """
        Initialize a GatewayChangeRequestGatewayClientGatewayCreate object.

        :param str type: type of gateway change request.
        """
        # pylint: disable=super-init-not-called
        self.type = type

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayChangeRequestGatewayClientGatewayCreate':
        """Initialize a GatewayChangeRequestGatewayClientGatewayCreate object from a json dictionary."""
        args = {}
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayChangeRequestGatewayClientGatewayCreate JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayChangeRequestGatewayClientGatewayCreate object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayChangeRequestGatewayClientGatewayCreate object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayChangeRequestGatewayClientGatewayCreate') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayChangeRequestGatewayClientGatewayCreate') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        type of gateway change request.
        """
        CREATE_GATEWAY = "create_gateway"


class GatewayChangeRequestGatewayClientGatewayDelete(GatewayChangeRequest):
    """
    gateway delete.

    :attr str type: type of gateway change request.
    """

    def __init__(self,
                 type: str) -> None:
        """
        Initialize a GatewayChangeRequestGatewayClientGatewayDelete object.

        :param str type: type of gateway change request.
        """
        # pylint: disable=super-init-not-called
        self.type = type

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayChangeRequestGatewayClientGatewayDelete':
        """Initialize a GatewayChangeRequestGatewayClientGatewayDelete object from a json dictionary."""
        args = {}
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayChangeRequestGatewayClientGatewayDelete JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayChangeRequestGatewayClientGatewayDelete object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayChangeRequestGatewayClientGatewayDelete object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayChangeRequestGatewayClientGatewayDelete') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayChangeRequestGatewayClientGatewayDelete') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        type of gateway change request.
        """
        DELETE_GATEWAY = "delete_gateway"


class GatewayChangeRequestGatewayClientGatewayUpdateAttributes(GatewayChangeRequest):
    """
    gateway attributes update.

    :attr str type: type of gateway change request.
    :attr List[object] updates: array of pending updates.
    """

    def __init__(self,
                 type: str,
                 updates: List[object]) -> None:
        """
        Initialize a GatewayChangeRequestGatewayClientGatewayUpdateAttributes object.

        :param str type: type of gateway change request.
        :param List[object] updates: array of pending updates.
        """
        # pylint: disable=super-init-not-called
        self.type = type
        self.updates = updates

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayChangeRequestGatewayClientGatewayUpdateAttributes':
        """Initialize a GatewayChangeRequestGatewayClientGatewayUpdateAttributes object from a json dictionary."""
        args = {}
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayChangeRequestGatewayClientGatewayUpdateAttributes JSON')
        if 'updates' in _dict:
            args['updates'] = _dict.get('updates')
        else:
            raise ValueError('Required property \'updates\' not present in GatewayChangeRequestGatewayClientGatewayUpdateAttributes JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayChangeRequestGatewayClientGatewayUpdateAttributes object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        if hasattr(self, 'updates') and self.updates is not None:
            _dict['updates'] = self.updates
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayChangeRequestGatewayClientGatewayUpdateAttributes object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayChangeRequestGatewayClientGatewayUpdateAttributes') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayChangeRequestGatewayClientGatewayUpdateAttributes') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        type of gateway change request.
        """
        UPDATE_ATTRIBUTES = "update_attributes"


class GatewayTemplateGatewayTypeConnectTemplate(GatewayTemplate):
    """
    Gateway fields specific to type=connect gateway create.

    :attr int bgp_asn: BGP ASN.
    :attr str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
          Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how to
          create a gateway using either automatic or explicit IP assignment.  Any
          bgp_base_cidr value set will be ignored.
          Deprecated field bgp_base_cidr will be removed from the API specificiation after
          15-MAR-2021.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr bool global_: Gateways with global routing (`true`) can connect to
          networks outside their associated region.
    :attr bool metered: Metered billing option.  When `true` gateway usage is billed
          per gigabyte.  When `false` there is no per gigabyte usage charge, instead a
          flat rate is charged for the gateway.
    :attr str name: The unique user-defined name for this gateway.
    :attr ResourceGroupIdentity resource_group: (optional) Resource group for this
          resource. If unspecified, the account's [default resource
          group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is used.
    :attr int speed_mbps: Gateway speed in megabits per second.
    :attr str type: Gateway type.
    :attr GatewayPortIdentity port: Select Port Label for new type=connect gateway.
    """

    def __init__(self,
                 bgp_asn: int,
                 global_: bool,
                 metered: bool,
                 name: str,
                 speed_mbps: int,
                 type: str,
                 port: 'GatewayPortIdentity',
                 *,
                 bgp_base_cidr: str = None,
                 bgp_cer_cidr: str = None,
                 bgp_ibm_cidr: str = None,
                 resource_group: 'ResourceGroupIdentity' = None) -> None:
        """
        Initialize a GatewayTemplateGatewayTypeConnectTemplate object.

        :param int bgp_asn: BGP ASN.
        :param bool global_: Gateways with global routing (`true`) can connect to
               networks outside their associated region.
        :param bool metered: Metered billing option.  When `true` gateway usage is
               billed per gigabyte.  When `false` there is no per gigabyte usage charge,
               instead a flat rate is charged for the gateway.
        :param str name: The unique user-defined name for this gateway.
        :param int speed_mbps: Gateway speed in megabits per second.
        :param str type: Gateway type.
        :param GatewayPortIdentity port: Select Port Label for new type=connect
               gateway.
        :param str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
               Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how
               to create a gateway using either automatic or explicit IP assignment.  Any
               bgp_base_cidr value set will be ignored.
               Deprecated field bgp_base_cidr will be removed from the API specificiation
               after 15-MAR-2021.
        :param str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param ResourceGroupIdentity resource_group: (optional) Resource group for
               this resource. If unspecified, the account's [default resource
               group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is
               used.
        """
        # pylint: disable=super-init-not-called
        self.bgp_asn = bgp_asn
        self.bgp_base_cidr = bgp_base_cidr
        self.bgp_cer_cidr = bgp_cer_cidr
        self.bgp_ibm_cidr = bgp_ibm_cidr
        self.global_ = global_
        self.metered = metered
        self.name = name
        self.resource_group = resource_group
        self.speed_mbps = speed_mbps
        self.type = type
        self.port = port

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayTemplateGatewayTypeConnectTemplate':
        """Initialize a GatewayTemplateGatewayTypeConnectTemplate object from a json dictionary."""
        args = {}
        if 'bgp_asn' in _dict:
            args['bgp_asn'] = _dict.get('bgp_asn')
        else:
            raise ValueError('Required property \'bgp_asn\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'bgp_base_cidr' in _dict:
            args['bgp_base_cidr'] = _dict.get('bgp_base_cidr')
        if 'bgp_cer_cidr' in _dict:
            args['bgp_cer_cidr'] = _dict.get('bgp_cer_cidr')
        if 'bgp_ibm_cidr' in _dict:
            args['bgp_ibm_cidr'] = _dict.get('bgp_ibm_cidr')
        if 'global' in _dict:
            args['global_'] = _dict.get('global')
        else:
            raise ValueError('Required property \'global\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'metered' in _dict:
            args['metered'] = _dict.get('metered')
        else:
            raise ValueError('Required property \'metered\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'name' in _dict:
            args['name'] = _dict.get('name')
        else:
            raise ValueError('Required property \'name\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'resource_group' in _dict:
            args['resource_group'] = ResourceGroupIdentity.from_dict(_dict.get('resource_group'))
        if 'speed_mbps' in _dict:
            args['speed_mbps'] = _dict.get('speed_mbps')
        else:
            raise ValueError('Required property \'speed_mbps\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        if 'port' in _dict:
            args['port'] = GatewayPortIdentity.from_dict(_dict.get('port'))
        else:
            raise ValueError('Required property \'port\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayTemplateGatewayTypeConnectTemplate object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'bgp_asn') and self.bgp_asn is not None:
            _dict['bgp_asn'] = self.bgp_asn
        if hasattr(self, 'bgp_base_cidr') and self.bgp_base_cidr is not None:
            _dict['bgp_base_cidr'] = self.bgp_base_cidr
        if hasattr(self, 'bgp_cer_cidr') and self.bgp_cer_cidr is not None:
            _dict['bgp_cer_cidr'] = self.bgp_cer_cidr
        if hasattr(self, 'bgp_ibm_cidr') and self.bgp_ibm_cidr is not None:
            _dict['bgp_ibm_cidr'] = self.bgp_ibm_cidr
        if hasattr(self, 'global_') and self.global_ is not None:
            _dict['global'] = self.global_
        if hasattr(self, 'metered') and self.metered is not None:
            _dict['metered'] = self.metered
        if hasattr(self, 'name') and self.name is not None:
            _dict['name'] = self.name
        if hasattr(self, 'resource_group') and self.resource_group is not None:
            _dict['resource_group'] = self.resource_group.to_dict()
        if hasattr(self, 'speed_mbps') and self.speed_mbps is not None:
            _dict['speed_mbps'] = self.speed_mbps
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        if hasattr(self, 'port') and self.port is not None:
            _dict['port'] = self.port.to_dict()
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayTemplateGatewayTypeConnectTemplate object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayTemplateGatewayTypeConnectTemplate') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayTemplateGatewayTypeConnectTemplate') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        Gateway type.
        """
        CONNECT = "connect"
        DEDICATED = "dedicated"


class GatewayTemplateGatewayTypeDedicatedTemplate(GatewayTemplate):
    """
    Gateway fields specific to type=dedicated gateway create.

    :attr int bgp_asn: BGP ASN.
    :attr str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
          Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how to
          create a gateway using either automatic or explicit IP assignment.  Any
          bgp_base_cidr value set will be ignored.
          Deprecated field bgp_base_cidr will be removed from the API specificiation after
          15-MAR-2021.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.
          For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
          automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
          For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR, the
          value must reside in one of "10.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16",
          "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr and bgp_ibm_cidr must
          have matching network and subnet mask values.
    :attr bool global_: Gateways with global routing (`true`) can connect to
          networks outside their associated region.
    :attr bool metered: Metered billing option.  When `true` gateway usage is billed
          per gigabyte.  When `false` there is no per gigabyte usage charge, instead a
          flat rate is charged for the gateway.
    :attr str name: The unique user-defined name for this gateway.
    :attr ResourceGroupIdentity resource_group: (optional) Resource group for this
          resource. If unspecified, the account's [default resource
          group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is used.
    :attr int speed_mbps: Gateway speed in megabits per second.
    :attr str type: Gateway type.
    :attr str carrier_name: Carrier name.
    :attr str cross_connect_router: Cross connect router.
    :attr str customer_name: Customer name.
    :attr str location_name: Gateway location.
    :attr GatewayMacsecConfigTemplate macsec_config: (optional) MACsec configuration
          information.  Contact IBM support for access to MACsec.
    """

    def __init__(self,
                 bgp_asn: int,
                 global_: bool,
                 metered: bool,
                 name: str,
                 speed_mbps: int,
                 type: str,
                 carrier_name: str,
                 cross_connect_router: str,
                 customer_name: str,
                 location_name: str,
                 *,
                 bgp_base_cidr: str = None,
                 bgp_cer_cidr: str = None,
                 bgp_ibm_cidr: str = None,
                 resource_group: 'ResourceGroupIdentity' = None,
                 macsec_config: 'GatewayMacsecConfigTemplate' = None) -> None:
        """
        Initialize a GatewayTemplateGatewayTypeDedicatedTemplate object.

        :param int bgp_asn: BGP ASN.
        :param bool global_: Gateways with global routing (`true`) can connect to
               networks outside their associated region.
        :param bool metered: Metered billing option.  When `true` gateway usage is
               billed per gigabyte.  When `false` there is no per gigabyte usage charge,
               instead a flat rate is charged for the gateway.
        :param str name: The unique user-defined name for this gateway.
        :param int speed_mbps: Gateway speed in megabits per second.
        :param str type: Gateway type.
        :param str carrier_name: Carrier name.
        :param str cross_connect_router: Cross connect router.
        :param str customer_name: Customer name.
        :param str location_name: Gateway location.
        :param str bgp_base_cidr: (optional) (DEPRECATED) BGP base CIDR.
               Field is deprecated.  See bgp_ibm_cidr and bgp_cer_cidr for details on how
               to create a gateway using either automatic or explicit IP assignment.  Any
               bgp_base_cidr value set will be ignored.
               Deprecated field bgp_base_cidr will be removed from the API specificiation
               after 15-MAR-2021.
        :param str bgp_cer_cidr: (optional) BGP customer edge router CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.
               For auto IP assignment, omit bgp_cer_cidr and bgp_ibm_cidr.  IBM will
               automatically select values for bgp_cer_cidr and bgp_ibm_cidr.
               For explicit IP assignment set a valid bgp_cer_cidr and bgp_ibm_cidr CIDR,
               the value must reside in one of "10.254.0.0/16", "172.16.0.0/12",
               "192.168.0.0/16", "169.254.0.0/16" or an owned public CIDR.  bgp_cer_cidr
               and bgp_ibm_cidr must have matching network and subnet mask values.
        :param ResourceGroupIdentity resource_group: (optional) Resource group for
               this resource. If unspecified, the account's [default resource
               group](https://cloud.ibm.com/apidocs/resource-manager#introduction) is
               used.
        :param GatewayMacsecConfigTemplate macsec_config: (optional) MACsec
               configuration information.  Contact IBM support for access to MACsec.
        """
        # pylint: disable=super-init-not-called
        self.bgp_asn = bgp_asn
        self.bgp_base_cidr = bgp_base_cidr
        self.bgp_cer_cidr = bgp_cer_cidr
        self.bgp_ibm_cidr = bgp_ibm_cidr
        self.global_ = global_
        self.metered = metered
        self.name = name
        self.resource_group = resource_group
        self.speed_mbps = speed_mbps
        self.type = type
        self.carrier_name = carrier_name
        self.cross_connect_router = cross_connect_router
        self.customer_name = customer_name
        self.location_name = location_name
        self.macsec_config = macsec_config

    @classmethod
    def from_dict(cls, _dict: Dict) -> 'GatewayTemplateGatewayTypeDedicatedTemplate':
        """Initialize a GatewayTemplateGatewayTypeDedicatedTemplate object from a json dictionary."""
        args = {}
        if 'bgp_asn' in _dict:
            args['bgp_asn'] = _dict.get('bgp_asn')
        else:
            raise ValueError('Required property \'bgp_asn\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'bgp_base_cidr' in _dict:
            args['bgp_base_cidr'] = _dict.get('bgp_base_cidr')
        if 'bgp_cer_cidr' in _dict:
            args['bgp_cer_cidr'] = _dict.get('bgp_cer_cidr')
        if 'bgp_ibm_cidr' in _dict:
            args['bgp_ibm_cidr'] = _dict.get('bgp_ibm_cidr')
        if 'global' in _dict:
            args['global_'] = _dict.get('global')
        else:
            raise ValueError('Required property \'global\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'metered' in _dict:
            args['metered'] = _dict.get('metered')
        else:
            raise ValueError('Required property \'metered\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'name' in _dict:
            args['name'] = _dict.get('name')
        else:
            raise ValueError('Required property \'name\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'resource_group' in _dict:
            args['resource_group'] = ResourceGroupIdentity.from_dict(_dict.get('resource_group'))
        if 'speed_mbps' in _dict:
            args['speed_mbps'] = _dict.get('speed_mbps')
        else:
            raise ValueError('Required property \'speed_mbps\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'type' in _dict:
            args['type'] = _dict.get('type')
        else:
            raise ValueError('Required property \'type\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'carrier_name' in _dict:
            args['carrier_name'] = _dict.get('carrier_name')
        else:
            raise ValueError('Required property \'carrier_name\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'cross_connect_router' in _dict:
            args['cross_connect_router'] = _dict.get('cross_connect_router')
        else:
            raise ValueError('Required property \'cross_connect_router\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'customer_name' in _dict:
            args['customer_name'] = _dict.get('customer_name')
        else:
            raise ValueError('Required property \'customer_name\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'location_name' in _dict:
            args['location_name'] = _dict.get('location_name')
        else:
            raise ValueError('Required property \'location_name\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        if 'macsec_config' in _dict:
            args['macsec_config'] = GatewayMacsecConfigTemplate.from_dict(_dict.get('macsec_config'))
        return cls(**args)

    @classmethod
    def _from_dict(cls, _dict):
        """Initialize a GatewayTemplateGatewayTypeDedicatedTemplate object from a json dictionary."""
        return cls.from_dict(_dict)

    def to_dict(self) -> Dict:
        """Return a json dictionary representing this model."""
        _dict = {}
        if hasattr(self, 'bgp_asn') and self.bgp_asn is not None:
            _dict['bgp_asn'] = self.bgp_asn
        if hasattr(self, 'bgp_base_cidr') and self.bgp_base_cidr is not None:
            _dict['bgp_base_cidr'] = self.bgp_base_cidr
        if hasattr(self, 'bgp_cer_cidr') and self.bgp_cer_cidr is not None:
            _dict['bgp_cer_cidr'] = self.bgp_cer_cidr
        if hasattr(self, 'bgp_ibm_cidr') and self.bgp_ibm_cidr is not None:
            _dict['bgp_ibm_cidr'] = self.bgp_ibm_cidr
        if hasattr(self, 'global_') and self.global_ is not None:
            _dict['global'] = self.global_
        if hasattr(self, 'metered') and self.metered is not None:
            _dict['metered'] = self.metered
        if hasattr(self, 'name') and self.name is not None:
            _dict['name'] = self.name
        if hasattr(self, 'resource_group') and self.resource_group is not None:
            _dict['resource_group'] = self.resource_group.to_dict()
        if hasattr(self, 'speed_mbps') and self.speed_mbps is not None:
            _dict['speed_mbps'] = self.speed_mbps
        if hasattr(self, 'type') and self.type is not None:
            _dict['type'] = self.type
        if hasattr(self, 'carrier_name') and self.carrier_name is not None:
            _dict['carrier_name'] = self.carrier_name
        if hasattr(self, 'cross_connect_router') and self.cross_connect_router is not None:
            _dict['cross_connect_router'] = self.cross_connect_router
        if hasattr(self, 'customer_name') and self.customer_name is not None:
            _dict['customer_name'] = self.customer_name
        if hasattr(self, 'location_name') and self.location_name is not None:
            _dict['location_name'] = self.location_name
        if hasattr(self, 'macsec_config') and self.macsec_config is not None:
            _dict['macsec_config'] = self.macsec_config.to_dict()
        return _dict

    def _to_dict(self):
        """Return a json dictionary representing this model."""
        return self.to_dict()

    def __str__(self) -> str:
        """Return a `str` version of this GatewayTemplateGatewayTypeDedicatedTemplate object."""
        return json.dumps(self.to_dict(), indent=2)

    def __eq__(self, other: 'GatewayTemplateGatewayTypeDedicatedTemplate') -> bool:
        """Return `true` when self and other are equal, false otherwise."""
        if not isinstance(other, self.__class__):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other: 'GatewayTemplateGatewayTypeDedicatedTemplate') -> bool:
        """Return `true` when self and other are not equal, false otherwise."""
        return not self == other

    class TypeEnum(Enum):
        """
        Gateway type.
        """
        CONNECT = "connect"
        DEDICATED = "dedicated"

