# Copyright 2014 Mellanox Technologies, Ltd
#
# 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.


import socket
import sys
import time

import eventlet
eventlet.monkey_patch()

from oslo.config import cfg
from oslo import messaging

from neutron.agent import rpc as agent_rpc
from neutron.agent import securitygroups_rpc as sg_rpc
from neutron.common import config as common_config
from neutron.common import constants as q_constants
from neutron.common import topics
from neutron.common import utils as q_utils
from neutron import context
from neutron.i18n import _LE, _LI
from neutron.openstack.common import log as logging
from neutron.openstack.common import loopingcall
from neutron.plugins.sriovnicagent.common import config  # noqa
from neutron.plugins.sriovnicagent.common import exceptions as exc
from neutron.plugins.sriovnicagent import eswitch_manager as esm


LOG = logging.getLogger(__name__)


class SriovNicSwitchRpcCallbacks(sg_rpc.SecurityGroupAgentRpcCallbackMixin):

    # Set RPC API version to 1.0 by default.
    # history
    #   1.1 Support Security Group RPC
    target = messaging.Target(version='1.1')

    def __init__(self, context, agent):
        super(SriovNicSwitchRpcCallbacks, self).__init__()
        self.context = context
        self.agent = agent
        self.sg_agent = agent

    def port_update(self, context, **kwargs):
        LOG.debug("port_update received")
        port = kwargs.get('port')
        # Put the port mac address in the updated_devices set.
        # Do not store port details, as if they're used for processing
        # notifications there is no guarantee the notifications are
        # processed in the same order as the relevant API requests.
        self.agent.updated_devices.add(port['mac_address'])
        LOG.debug("port_update RPC received for port: %s", port['id'])


class SriovNicSwitchPluginApi(agent_rpc.PluginApi,
                              sg_rpc.SecurityGroupServerRpcApiMixin):
    pass


class SriovNicSwitchAgent(sg_rpc.SecurityGroupAgentRpcMixin):
    def __init__(self, physical_devices_mappings, exclude_devices,
                 polling_interval, root_helper):

        self.polling_interval = polling_interval
        self.root_helper = root_helper
        self.setup_eswitch_mgr(physical_devices_mappings,
                               exclude_devices)
        configurations = {'device_mappings': physical_devices_mappings}
        self.agent_state = {
            'binary': 'neutron-sriov-nic-agent',
            'host': cfg.CONF.host,
            'topic': q_constants.L2_AGENT_TOPIC,