# Path: f5lbaasdriver/v2/bigip/disconnected_service.py
# class DisconnectedService(object):
#     def __init__(self):
#         self.supported_encapsulations = ['vlan']
# 
#     # Retain this method for future use in case a particular ML2 implementation
#     # decouples network_id from physical_network name.  The implementation in
#     # neutron db.py requires a network_id.
#     def get_network_segments(self, session):
#         with session.begin(subtransactions=True):
#             query = (session.query(models.NetworkSegment).
#                      order_by(models.NetworkSegment.segment_index))
#             records = query.all()
#             result = {}
#             for record in records:
#                 if record.network_id not in result:
#                     result[record.network_id] = []
#                 result[record.network_id].append(db._make_segment_dict(record))
#             return result
# 
#     def get_network_segment(self, context, agent_configuration, network):
#         data = None
# 
#         network_segment_physical_network = \
#             agent_configuration.get('network_segment_physical_network', None)
# 
#         supported_encapsulations = [
#             x.lower() for x in self.supported_encapsulations +
#             agent_configuration.get('tunnel_types', [])
#         ]
#         # look up segment details in the ml2_network_segments table
#         segments = segments_db.get_network_segments(context, network['id'],
#                                                     filter_dynamic=None)
# 
#         for segment in segments:
#             LOG.debug("F5 disconnected service check segment: %s" % segment)
#             if ((network_segment_physical_network ==
#                  segment['physical_network']) and
#                 (segment['network_type'].lower() in
#                  supported_encapsulations)):
#                 data = segment
#                 break
#             elif (network['provider:network_type'] == 'opflex' and
#                   segment['network_type'] == 'vlan'):
#                 data = segment
#                 LOG.debug("Got OPFLEX segment: %s" % segment)
#                 break
# 
#         if not data:
#             LOG.debug('Using default segment for network %s' %
#                       (network['id']))
# 
#             # neutron is expected to provide this data immediately
#             data = {
#                 'segmentation_id': network['provider:segmentation_id']
#             }
#             if 'provider:network_type' in network:
#                 data['network_type'] = network['provider:network_type']
#             if 'provider:physical_network' in network:
#                 data['physical_network'] = network['provider:physical_network']
# 
#         return data
# 
#     def get_segment_id(self, context, port_id, agent_hosts):
#         try:
#             segment = None
#             if agent_hosts:
#                 for host_id in agent_hosts:
#                     levels = db.get_binding_levels(
#                         context, port_id, host_id
#                     )
#                     if levels:
#                         LOG.debug('levels: %s binding host_id: %s' % (
#                             levels, host_id))
#                         for level in levels:
#                             if level.driver in ('f5networks', 'huawei_ac_ml2'):
#                                 LOG.debug('level with driver f5networks')
#                                 segment = segments_db.get_segment_by_id(
#                                     context, level.segment_id
#                                 )
#                                 LOG.debug(
#                                     'vxlan 2 vlan seg id %s: segment %s'
#                                     % (level.segment_id, segment)
#                                 )
#                                 if segment:
#                                     break
#             return segment
#         except Exception as exc:
#             LOG.error(
#                 "could not get segment id by port %s and host %s, %s" % (
#                     port_id, agent_hosts, exc.message))
# 
# Path: f5lbaasdriver/v2/bigip/exceptions.py
# class F5LBaaSv2DriverException(q_exc.NeutronException):
# class F5MismatchedTenants(F5LBaaSv2DriverException):
# class F5DeleteListenerWithAttachedPool(F5LBaaSv2DriverException):
# class PolicyHasMoreThanOneListener(F5LBaaSv2DriverException):
# class RuleHasMoreThanOnePolicy(F5LBaaSv2DriverException):
#     def __init__(self, message=None):
#     def __str__(self):
#     def __str__(self):
# 
# Path: f5lbaasdriver/v2/bigip/neutron_client.py
# LOG = logging.getLogger(__name__)
# class F5NetworksNeutronClient(object):
#     def __init__(self, plugin):
#     def create_port_on_subnet(self, context, subnet_id=None,
#                               mac_address=None, ip_address=None,
#                               name="", fixed_address_count=1, host=""):
#     def delete_port(self, context, port_id=None, mac_address=None):


import datetime
import json
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
from f5lbaasdriver.v2.bigip import constants_v2
from f5lbaasdriver.v2.bigip.disconnected_service import DisconnectedService
from f5lbaasdriver.v2.bigip import exceptions as f5_exc
from f5lbaasdriver.v2.bigip import neutron_client as q_client
# limitations under the License.
#



LOG = logging.getLogger(__name__)


class LBaaSv2ServiceBuilder(object):
    """The class creates a service definition from neutron database.

    A service definition represents all the information required to
    construct a load-balancing service on BigIP.

    Requests come in to agent as full service definitions, not incremental
    changes. The driver looks up networks, mac entries, segmentation info,
    etc and places all information in a service object (which is a python
    dictionary variable) and passes that to the agent.

    """

    def __init__(self, driver):
        """Get full service definition from loadbalancer id."""
        self.driver = driver

        self.net_cache = {}
        self.subnet_cache = {}
        self.last_cache_update = datetime.datetime.fromtimestamp(0)
        self.plugin = self.driver.plugin
        self.disconnected_service = DisconnectedService()

# Path: f5lbaasdriver/v2/bigip/disconnected_service.py
# class DisconnectedService(object):
#     def __init__(self):
#         self.supported_encapsulations = ['vlan']
# 
#     # Retain this method for future use in case a particular ML2 implementation
#     # decouples network_id from physical_network name.  The implementation in
#     # neutron db.py requires a network_id.
#     def get_network_segments(self, session):
#         with session.begin(subtransactions=True):
#             query = (session.query(models.NetworkSegment).
#                      order_by(models.NetworkSegment.segment_index))
#             records = query.all()
#             result = {}
#             for record in records:
#                 if record.network_id not in result:
#                     result[record.network_id] = []
#                 result[record.network_id].append(db._make_segment_dict(record))
#             return result
# 
#     def get_network_segment(self, context, agent_configuration, network):
#         data = None
# 
#         network_segment_physical_network = \
#             agent_configuration.get('network_segment_physical_network', None)
# 
#         supported_encapsulations = [
#             x.lower() for x in self.supported_encapsulations +
#             agent_configuration.get('tunnel_types', [])
#         ]
#         # look up segment details in the ml2_network_segments table
#         segments = segments_db.get_network_segments(context, network['id'],
#                                                     filter_dynamic=None)
# 
#         for segment in segments:
#             LOG.debug("F5 disconnected service check segment: %s" % segment)
#             if ((network_segment_physical_network ==
#                  segment['physical_network']) and
#                 (segment['network_type'].lower() in
#                  supported_encapsulations)):
#                 data = segment
#                 break
#             elif (network['provider:network_type'] == 'opflex' and
#                   segment['network_type'] == 'vlan'):
#                 data = segment
#                 LOG.debug("Got OPFLEX segment: %s" % segment)
#                 break
# 
#         if not data:
#             LOG.debug('Using default segment for network %s' %
#                       (network['id']))
# 
#             # neutron is expected to provide this data immediately
#             data = {
#                 'segmentation_id': network['provider:segmentation_id']
#             }
#             if 'provider:network_type' in network:
#                 data['network_type'] = network['provider:network_type']
#             if 'provider:physical_network' in network:
#                 data['physical_network'] = network['provider:physical_network']
# 
#         return data
# 
#     def get_segment_id(self, context, port_id, agent_hosts):
#         try:
#             segment = None
#             if agent_hosts:
#                 for host_id in agent_hosts:
#                     levels = db.get_binding_levels(
#                         context, port_id, host_id
#                     )
#                     if levels:
#                         LOG.debug('levels: %s binding host_id: %s' % (
#                             levels, host_id))
#                         for level in levels:
#                             if level.driver in ('f5networks', 'huawei_ac_ml2'):
#                                 LOG.debug('level with driver f5networks')
#                                 segment = segments_db.get_segment_by_id(
#                                     context, level.segment_id
#                                 )
#                                 LOG.debug(
#                                     'vxlan 2 vlan seg id %s: segment %s'
#                                     % (level.segment_id, segment)
#                                 )
#                                 if segment:
#                                     break
#             return segment
#         except Exception as exc:
#             LOG.error(
#                 "could not get segment id by port %s and host %s, %s" % (
#                     port_id, agent_hosts, exc.message))
# 
# Path: f5lbaasdriver/v2/bigip/exceptions.py
# class F5LBaaSv2DriverException(q_exc.NeutronException):
# class F5MismatchedTenants(F5LBaaSv2DriverException):
# class F5DeleteListenerWithAttachedPool(F5LBaaSv2DriverException):
# class PolicyHasMoreThanOneListener(F5LBaaSv2DriverException):
# class RuleHasMoreThanOnePolicy(F5LBaaSv2DriverException):
#     def __init__(self, message=None):
#     def __str__(self):
#     def __str__(self):
# 
# Path: f5lbaasdriver/v2/bigip/neutron_client.py
# LOG = logging.getLogger(__name__)
# class F5NetworksNeutronClient(object):
#     def __init__(self, plugin):
#     def create_port_on_subnet(self, context, subnet_id=None,
#                               mac_address=None, ip_address=None,
#                               name="", fixed_address_count=1, host=""):
#     def delete_port(self, context, port_id=None, mac_address=None):


# Path: f5lbaasdriver/v2/bigip/service_builder.py
import datetime
import json
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
from f5lbaasdriver.v2.bigip import constants_v2
from f5lbaasdriver.v2.bigip.disconnected_service import DisconnectedService
from f5lbaasdriver.v2.bigip import exceptions as f5_exc
from f5lbaasdriver.v2.bigip import neutron_client as q_client

# limitations under the License.
#



LOG = logging.getLogger(__name__)


class LBaaSv2ServiceBuilder(object):
    """The class creates a service definition from neutron database.

    A service definition represents all the information required to
    construct a load-balancing service on BigIP.

    Requests come in to agent as full service definitions, not incremental
    changes. The driver looks up networks, mac entries, segmentation info,
    etc and places all information in a service object (which is a python
    dictionary variable) and passes that to the agent.

    """

    def __init__(self, driver):
        """Get full service definition from loadbalancer id."""
        self.driver = driver

        self.net_cache = {}
        self.subnet_cache = {}
        self.last_cache_update = datetime.datetime.fromtimestamp(0)
        self.plugin = self.driver.plugin
        self.disconnected_service = DisconnectedService()

        self.q_client = q_client.F5NetworksNeutronClient(self.plugin)