# 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
                assert len(pol['listeners']) == 1
            except AssertionError:
                msg = 'A policy should have only one listener, but found ' \
                    '{0} for policy {1}'.format(
                        len(pol['listeners']), pol['id'])
                raise f5_exc.PolicyHasMoreThanOneListener(msg)
            else:
                listener = pol.pop('listeners')[0]
                l7policies[index]['listener_id'] = listener['id']

        return l7policies

    @log_helpers.log_method_call
    def _get_l7policy_rules(self, context, l7policies):
        """Get l7 policy rules filtered by l7 policies."""
        l7policy_rules = []
        if l7policies:
            policy_ids = [p['id'] for p in l7policies]
            for pol_id in policy_ids:
                rules = self.plugin.db.get_l7policy_rules(context, pol_id)
                l7policy_rules.extend(
                    self._l7rule_to_dict(rule) for rule in rules)

        for index, rule in enumerate(l7policy_rules):
            try:
                assert len(rule['policies']) == 1
            except AssertionError:
                msg = 'A rule should have only one policy, but found ' \
                    '{0} for rule {1}'.format(
                        len(rule['policies']), rule['id'])

# 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

                assert len(pol['listeners']) == 1
            except AssertionError:
                msg = 'A policy should have only one listener, but found ' \
                    '{0} for policy {1}'.format(
                        len(pol['listeners']), pol['id'])
                raise f5_exc.PolicyHasMoreThanOneListener(msg)
            else:
                listener = pol.pop('listeners')[0]
                l7policies[index]['listener_id'] = listener['id']

        return l7policies

    @log_helpers.log_method_call
    def _get_l7policy_rules(self, context, l7policies):
        """Get l7 policy rules filtered by l7 policies."""
        l7policy_rules = []
        if l7policies:
            policy_ids = [p['id'] for p in l7policies]
            for pol_id in policy_ids:
                rules = self.plugin.db.get_l7policy_rules(context, pol_id)
                l7policy_rules.extend(
                    self._l7rule_to_dict(rule) for rule in rules)

        for index, rule in enumerate(l7policy_rules):
            try:
                assert len(rule['policies']) == 1
            except AssertionError:
                msg = 'A rule should have only one policy, but found ' \
                    '{0} for rule {1}'.format(
                        len(rule['policies']), rule['id'])

                raise f5_exc.RuleHasMoreThanOnePolicy(msg)