# 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) BGP base CIDR.
    :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 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 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,
                 change_request: 'GatewayChangeRequest' = None,
                 completion_notice_reject_reason: str = None,
                 cross_connect_router: 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) BGP base CIDR.
        :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 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 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.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.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 '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 '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, '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, '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 the device for this gateway.
          Status 'unknown' is returned during gateway creation and deletion. Status
          `key_error` indicates Direct Link was unable to retrieve key materials for one
          of the specified. This usually due to inadequate service to service
          authorization.   Verify the key exists and verify a service to service policy
          exists authorization the Direct Link service to access its key material. Correct
          any problems and respecify the desired key.  If the problem persists contact IBM
          support.
    :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 the device for this gateway.
                Status 'unknown' is returned during gateway creation and deletion. Status
               `key_error` indicates Direct Link was unable to retrieve key materials for
               one of the specified. This usually due to inadequate service to service
               authorization.   Verify the key exists and verify a service to service
               policy exists authorization the Direct Link service to access its key
               material. Correct any problems and respecify the desired key.  If the
               problem persists contact IBM support.
        :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 the device for this gateway.  Status 'unknown' is
        returned during gateway creation and deletion. Status `key_error` indicates Direct
        Link was unable to retrieve key materials for one of the specified. This usually
        due to inadequate service to service authorization.   Verify the key exists and
        verify a service to service policy exists authorization the Direct Link service to
        access its key material. Correct any problems and respecify the desired key.  If
        the problem persists contact IBM support.
        """
        INIT = "init"
        KEY_ERROR = "key_error"
        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.
          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].
          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.
               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].
               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.
    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].
    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: BGP base CIDR.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.  Specify a
          value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field
          can  be ommitted and a CIDR will be selected automatically.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
          `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
          ommitted and a CIDR will be selected automatically.
    :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,
                 bgp_base_cidr: str,
                 global_: bool,
                 metered: bool,
                 name: str,
                 speed_mbps: int,
                 type: str,
                 *,
                 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 str bgp_base_cidr: BGP base CIDR.
        :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_cer_cidr: (optional) BGP customer edge router CIDR.  Specify
               a value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this
               field can  be ommitted and a CIDR will be selected automatically.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
               `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
               ommitted and a CIDR will be selected automatically.
        :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: BGP base CIDR.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.  Specify a
          value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field
          can  be ommitted and a CIDR will be selected automatically.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
          `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
          ommitted and a CIDR will be selected automatically.
    :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,
                 bgp_base_cidr: str,
                 global_: bool,
                 metered: bool,
                 name: str,
                 speed_mbps: int,
                 type: str,
                 port: 'GatewayPortIdentity',
                 *,
                 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 str bgp_base_cidr: BGP base CIDR.
        :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_cer_cidr: (optional) BGP customer edge router CIDR.  Specify
               a value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this
               field can  be ommitted and a CIDR will be selected automatically.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
               `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
               ommitted and a CIDR will be selected automatically.
        :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')
        else:
            raise ValueError('Required property \'bgp_base_cidr\' not present in GatewayTemplateGatewayTypeConnectTemplate JSON')
        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: BGP base CIDR.
    :attr str bgp_cer_cidr: (optional) BGP customer edge router CIDR.  Specify a
          value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field
          can  be ommitted and a CIDR will be selected automatically.
    :attr str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
          `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
          ommitted and a CIDR will be selected automatically.
    :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,
                 bgp_base_cidr: str,
                 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_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 str bgp_base_cidr: BGP base CIDR.
        :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_cer_cidr: (optional) BGP customer edge router CIDR.  Specify
               a value within `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this
               field can  be ommitted and a CIDR will be selected automatically.
        :param str bgp_ibm_cidr: (optional) BGP IBM CIDR.  Specify a value within
               `bgp_base_cidr`.  If `bgp_base_cidr` is 169.254.0.0/16 this field can  be
               ommitted and a CIDR will be selected automatically.
        :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')
        else:
            raise ValueError('Required property \'bgp_base_cidr\' not present in GatewayTemplateGatewayTypeDedicatedTemplate JSON')
        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"

