def execute(self, loadbalancer, amphora, availability_zone, vrrp_port=None): LOG.debug("Calculating network delta for amphora id: %s", amphora.get(constants.ID)) if vrrp_port is None: vrrp_port = self.network_driver.get_port( amphora[constants.VRRP_PORT_ID]) vrrp_port_network_id = vrrp_port.network_id else: vrrp_port_network_id = vrrp_port[constants.NETWORK_ID] # Figure out what networks we want # seed with lb network(s) if availability_zone: management_nets = ( [availability_zone.get(constants.MANAGEMENT_NETWORK)] or CONF.controller_worker.amp_boot_network_list) else: management_nets = CONF.controller_worker.amp_boot_network_list desired_network_ids = {vrrp_port_network_id}.union(management_nets) db_lb = self.loadbalancer_repo.get( db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID]) for pool in db_lb.pools: member_networks = [ self.network_driver.get_subnet(member.subnet_id).network_id for member in pool.members if member.subnet_id ] desired_network_ids.update(member_networks) nics = self.network_driver.get_plugged_networks( amphora[constants.COMPUTE_ID]) # assume we don't have two nics in the same network actual_network_nics = dict((nic.network_id, nic) for nic in nics) del_ids = set(actual_network_nics) - desired_network_ids delete_nics = list( n_data_models.Interface(network_id=net_id) for net_id in del_ids) add_ids = desired_network_ids - set(actual_network_nics) add_nics = list( n_data_models.Interface(network_id=net_id) for net_id in add_ids) delta = n_data_models.Delta(amphora_id=amphora[constants.ID], compute_id=amphora[constants.COMPUTE_ID], add_nics=add_nics, delete_nics=delete_nics) return delta.to_dict(recurse=True)
def execute(self, loadbalancer, amphora): LOG.debug("Calculating network delta for amphora id: %s", amphora.id) # Figure out what networks we want # seed with lb network(s) vrrp_port = self.network_driver.get_port(amphora.vrrp_port_id) desired_network_ids = {vrrp_port.network_id}.union( CONF.controller_worker.amp_boot_network_list) for pool in loadbalancer.pools: member_networks = [ self.network_driver.get_subnet(member.subnet_id).network_id for member in pool.members if member.subnet_id ] desired_network_ids.update(member_networks) nics = self.network_driver.get_plugged_networks(amphora.compute_id) # assume we don't have two nics in the same network actual_network_nics = dict((nic.network_id, nic) for nic in nics) del_ids = set(actual_network_nics) - desired_network_ids delete_nics = list(actual_network_nics[net_id] for net_id in del_ids) add_ids = desired_network_ids - set(actual_network_nics) add_nics = list( n_data_models.Interface(network_id=net_id) for net_id in add_ids) delta = n_data_models.Delta(amphora_id=amphora.id, compute_id=amphora.compute_id, add_nics=add_nics, delete_nics=delete_nics) return delta
def plug_port(self, amphora, port): try: interface = self.nova_client.servers.interface_attach( server=amphora.compute_id, net_id=None, fixed_ip=None, port_id=port.id) plugged_interface = self._nova_interface_to_octavia_interface( amphora.compute_id, interface) except nova_client_exceptions.NotFound as e: if 'Instance' in str(e): raise base.AmphoraNotFound(str(e)) elif 'Network' in str(e): raise base.NetworkNotFound(str(e)) else: raise base.PlugNetworkException(str(e)) except nova_client_exceptions.Conflict: LOG.info('Port %(portid)s is already plugged, ' 'skipping', {'portid': port.id}) plugged_interface = n_data_models.Interface( compute_id=amphora.compute_id, network_id=port.network_id, port_id=port.id, fixed_ips=port.fixed_ips) except Exception: message = _('Error plugging amphora (compute_id: ' '{compute_id}) into port ' '{port_id}.').format(compute_id=amphora.compute_id, port_id=port.id) LOG.exception(message) raise base.PlugNetworkException(message) return plugged_interface
def _port_to_octavia_interface(self, compute_id, port): fixed_ips = [utils.convert_fixed_ip_dict_to_model(fixed_ip) for fixed_ip in port.get('fixed_ips', [])] return network_models.Interface(compute_id=compute_id, network_id=port['network_id'], port_id=port['id'], fixed_ips=fixed_ips)
def _nova_interface_to_octavia_interface(self, compute_id, nova_interface): fixed_ips = [utils.convert_fixed_ip_dict_to_model(fixed_ip) for fixed_ip in nova_interface.fixed_ips] return network_models.Interface(compute_id=compute_id, network_id=nova_interface.net_id, port_id=nova_interface.port_id, fixed_ips=fixed_ips)
def test_get_interfaces_to_unplug(self): if1 = network_models.Interface() if1.network_id = 'if1-net' if1.port_id = 'if1-port' if1.fixed_ips = [network_models.FixedIP(ip_address='10.0.0.1')] if2 = network_models.Interface() if2.network_id = 'if2-net' if2.port_id = 'if2-port' if2.fixed_ips = [network_models.FixedIP(ip_address='11.0.0.1')] interfaces = [if1, if2] unpluggers = self.driver._get_interfaces_to_unplug( interfaces, 'if1-net') self.assertEqual([if1], unpluggers) unpluggers = self.driver._get_interfaces_to_unplug( interfaces, 'if1-net', ip_address='10.0.0.1') self.assertEqual([if1], unpluggers) unpluggers = self.driver._get_interfaces_to_unplug( interfaces, 'if1-net', ip_address='11.0.0.1') self.assertEqual([], unpluggers) unpluggers = self.driver._get_interfaces_to_unplug( interfaces, 'if3-net') self.assertEqual([], unpluggers)
def plug_network(self, compute_id, network_id, ip_address=None): LOG.debug( "Network %s no-op, plug_network compute_id %s, network_id " "%s, ip_address %s", self.__class__.__name__, compute_id, network_id, ip_address) self.networkconfigconfig[(compute_id, network_id, ip_address)] = (compute_id, network_id, ip_address, 'plug_network') return network_models.Interface(id=uuidutils.generate_uuid(), compute_id=compute_id, network_id=network_id, fixed_ips=[], port_id=uuidutils.generate_uuid())
def attach_network_or_port(self, compute_id, network_id, ip_address=None, port_id=None): LOG.debug("Compute %s no-op, attach_network_or_port compute_id %s," "network_id %s, ip_address %s, port_id %s", self.__class__.__name__, compute_id, network_id, ip_address, port_id) self.computeconfig[(compute_id, network_id, ip_address, port_id)] = ( compute_id, network_id, ip_address, port_id, 'attach_network_or_port') return network_models.Interface( id=uuidutils.generate_uuid(), compute_id=compute_id, network_id=network_id, fixed_ips=[], port_id=uuidutils.generate_uuid() )
def execute(self, loadbalancers_list, amphora, member_list): LOG.debug("Calculating network delta for amphora id: %s", amphora.id) # Figure out what networks we want # seed with lb network(s) desired_network_ids = set( CONF.a10_controller_worker.amp_boot_network_list[:]) member_networks = [] for loadbalancer in loadbalancers_list: for pool in loadbalancer.pools: member_networks = [ self.network_driver.get_subnet(member.subnet_id).network_id for member in pool.members if member.subnet_id and member in member_list ] desired_network_ids.update(member_networks) loadbalancer_networks = [ self.network_driver.get_subnet( loadbalancer.vip.subnet_id).network_id for loadbalancer in loadbalancers_list if loadbalancer.vip.subnet_id ] desired_network_ids.update(loadbalancer_networks) LOG.debug("[NetIF] desired_network_ids.update{0}".format( desired_network_ids)) nics = self.network_driver.get_plugged_networks(amphora.compute_id) # assume we don't have two nics in the same network actual_network_nics = dict((nic.network_id, nic) for nic in nics) LOG.debug( "[NetIF] actual_network_nics {0}".format(actual_network_nics)) del_ids = set(actual_network_nics) - desired_network_ids delete_nics = list(actual_network_nics[net_id] for net_id in del_ids) add_ids = desired_network_ids - set(actual_network_nics) add_nics = list( n_data_models.Interface(network_id=net_id) for net_id in add_ids) delta = n_data_models.Delta(amphora_id=amphora.id, compute_id=amphora.compute_id, add_nics=add_nics, delete_nics=delete_nics) return delta
def execute(self, loadbalancer, amphora, availability_zone, vrrp_port=None): LOG.debug("Calculating network delta for amphora id: %s", amphora.id) if vrrp_port is None: vrrp_port = self.network_driver.get_port(amphora.vrrp_port_id) if availability_zone: management_nets = ( [availability_zone.get(constants.MANAGEMENT_NETWORK)] or CONF.controller_worker.amp_boot_network_list) else: management_nets = CONF.controller_worker.amp_boot_network_list desired_network_ids = {vrrp_port.network_id}.union(management_nets) for pool in loadbalancer.pools: member_networks = [ self.network_driver.get_subnet(member.subnet_id).network_id for member in pool.members if member.subnet_id ] desired_network_ids.update(member_networks) nics = self.network_driver.get_plugged_networks(amphora.compute_id) # assume we don't have two nics in the same network actual_network_nics = dict((nic.network_id, nic) for nic in nics) del_ids = set(actual_network_nics) - desired_network_ids delete_nics = list(actual_network_nics[net_id] for net_id in del_ids) add_ids = desired_network_ids - set(actual_network_nics) add_nics = list( n_data_models.Interface(network_id=net_id) for net_id in add_ids) delta = n_data_models.Delta(amphora_id=amphora.id, compute_id=amphora.compute_id, add_nics=add_nics, delete_nics=delete_nics) return delta
def execute(self, loadbalancer, amphora): LOG.debug("Calculating network delta for amphora id: %s", amphora.id) # Figure out what networks we want # seed with lb network(s) subnet = self.network_driver.get_subnet(loadbalancer.vip.subnet_id) desired_network_ids = { CONF.controller_worker.amp_network, subnet.network_id } if not loadbalancer.listeners: return None for listener in loadbalancer.listeners: if (not listener.default_pool) or ( not listener.default_pool.members): continue member_networks = [ self.network_driver.get_subnet(member.subnet_id).network_id for member in listener.default_pool.members if member.subnet_id ] desired_network_ids.update(member_networks) nics = self.network_driver.get_plugged_networks(amphora.compute_id) # assume we don't have two nics in the same network actual_network_nics = dict((nic.network_id, nic) for nic in nics) del_ids = set(actual_network_nics) - desired_network_ids delete_nics = list(actual_network_nics[net_id] for net_id in del_ids) add_ids = desired_network_ids - set(actual_network_nics) add_nics = list( n_data_models.Interface(network_id=net_id) for net_id in add_ids) delta = n_data_models.Delta(amphora_id=amphora.id, compute_id=amphora.compute_id, add_nics=add_nics, delete_nics=delete_nics) return delta
def _interface(port_id): return [data_models.Interface(port_id=port_id)]
def _interface(network_id): return [data_models.Interface(network_id=network_id)]
def test_handle_network_delta(self, mock_get_net_driver): mock_net_driver = mock.MagicMock() self.db_amphora_mock.to_dict.return_value = { constants.ID: AMPHORA_ID, constants.COMPUTE_ID: COMPUTE_ID} mock_get_net_driver.return_value = mock_net_driver nic1 = data_models.Interface() nic1.network_id = uuidutils.generate_uuid() nic2 = data_models.Interface() nic2.network_id = uuidutils.generate_uuid() interface1 = mock.MagicMock() interface1.port_id = uuidutils.generate_uuid() port1 = mock.MagicMock() port1.network_id = uuidutils.generate_uuid() fixed_ip = mock.MagicMock() fixed_ip.subnet_id = uuidutils.generate_uuid() port1.fixed_ips = [fixed_ip] subnet = mock.MagicMock() network = mock.MagicMock() delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[nic1], delete_nics=[nic2, nic2, nic2] ).to_dict(recurse=True) mock_net_driver.plug_network.return_value = interface1 mock_net_driver.get_port.return_value = port1 mock_net_driver.get_network.return_value = network mock_net_driver.get_subnet.return_value = subnet mock_net_driver.unplug_network.side_effect = [ None, net_base.NetworkNotFound, Exception] handle_net_delta_obj = network_tasks.HandleNetworkDelta() result = handle_net_delta_obj.execute(self.amphora_mock, delta) mock_net_driver.plug_network.assert_called_once_with( self.db_amphora_mock.compute_id, nic1.network_id) mock_net_driver.get_port.assert_called_once_with(interface1.port_id) mock_net_driver.get_network.assert_called_once_with(port1.network_id) mock_net_driver.get_subnet.assert_called_once_with(fixed_ip.subnet_id) self.assertEqual({self.db_amphora_mock.id: [port1.to_dict()]}, result) mock_net_driver.unplug_network.assert_called_with( self.db_amphora_mock.compute_id, nic2.network_id) # Revert delta2 = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[nic1, nic1], delete_nics=[nic2, nic2, nic2] ).to_dict(recurse=True) mock_net_driver.unplug_network.reset_mock() handle_net_delta_obj.revert( failure.Failure.from_exception(Exception('boom')), None, None) mock_net_driver.unplug_network.assert_not_called() mock_net_driver.unplug_network.reset_mock() handle_net_delta_obj.revert(None, None, None) mock_net_driver.unplug_network.assert_not_called() mock_net_driver.unplug_network.reset_mock() handle_net_delta_obj.revert(None, None, delta2)
def test_calculate_delta(self, mock_get_session, mock_get_lb, mock_get_net_driver): mock_driver = mock.MagicMock() mock_get_lb.return_value = self.db_load_balancer_mock self.db_amphora_mock.to_dict.return_value = { constants.ID: AMPHORA_ID, constants.COMPUTE_ID: COMPUTE_ID, constants.VRRP_PORT_ID: PORT_ID} mock_get_net_driver.return_value = mock_driver mock_driver.get_plugged_networks.return_value = [ data_models.Interface(network_id='netid')] mock_driver.get_port.return_value = data_models.Port( network_id='netid') EMPTY = {} empty_deltas = {self.db_amphora_mock.id: data_models.Delta( amphora_id=AMPHORA_ID, compute_id=COMPUTE_ID, add_nics=[], delete_nics=[]).to_dict(recurse=True)} calc_delta = network_tasks.CalculateDelta() self.assertEqual(EMPTY, calc_delta.execute(self.load_balancer_mock, {})) # Test with one amp and no pools, nothing plugged # Delta should be empty mock_driver.reset_mock() self.db_amphora_mock.load_balancer = self.db_load_balancer_mock self.db_load_balancer_mock.amphorae = [self.db_amphora_mock] self.db_load_balancer_mock.pools = [] self.assertEqual(empty_deltas, calc_delta.execute(self.load_balancer_mock, {})) mock_driver.get_plugged_networks.assert_called_once_with(COMPUTE_ID) # Pool mock should be configured explicitly for each test pool_mock = mock.MagicMock() self.db_load_balancer_mock.pools = [pool_mock] # Test with one amp and one pool but no members, nothing plugged # Delta should be empty pool_mock.members = [] self.assertEqual(empty_deltas, calc_delta.execute(self.load_balancer_mock, {})) # Test with one amp and one pool and one member, nothing plugged # Delta should be one additional subnet to plug mock_driver.reset_mock() member_mock = mock.MagicMock() member_mock.subnet_id = 1 pool_mock.members = [member_mock] mock_driver.get_subnet.return_value = data_models.Subnet(id=2, network_id=3) ndm = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[ data_models.Interface(network_id=3)], delete_nics=[]).to_dict(recurse=True) self.assertEqual({self.db_amphora_mock.id: ndm}, calc_delta.execute(self.load_balancer_mock, {})) vrrp_port_call = mock.call(PORT_ID) mock_driver.get_port.assert_has_calls([vrrp_port_call]) self.assertEqual(1, mock_driver.get_port.call_count) member_subnet_call = mock.call(member_mock.subnet_id) mock_driver.get_subnet.assert_has_calls([member_subnet_call]) self.assertEqual(1, mock_driver.get_subnet.call_count) # Test with one amp and one pool and one member, already plugged # Delta should be empty mock_driver.reset_mock() member_mock = mock.MagicMock() member_mock.subnet_id = 1 pool_mock.members = [member_mock] mock_driver.get_plugged_networks.return_value = [ data_models.Interface(network_id=3), data_models.Interface(network_id='netid')] self.assertEqual(empty_deltas, calc_delta.execute(self.load_balancer_mock, {})) # Test with one amp and one pool and one member, wrong network plugged # Delta should be one network to add and one to remove mock_driver.reset_mock() member_mock = mock.MagicMock() member_mock.subnet_id = 1 pool_mock.members = [member_mock] mock_driver.get_plugged_networks.return_value = [ data_models.Interface(network_id=2), data_models.Interface(network_id='netid')] ndm = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[ data_models.Interface(network_id=3)], delete_nics=[ data_models.Interface(network_id=2)] ).to_dict(recurse=True) self.assertEqual({self.db_amphora_mock.id: ndm}, calc_delta.execute(self.load_balancer_mock, {})) # Test with one amp and one pool and no members, one network plugged # Delta should be one network to remove mock_driver.reset_mock() pool_mock.members = [] mock_driver.get_plugged_networks.return_value = [ data_models.Interface(network_id=2), data_models.Interface(network_id='netid') ] ndm = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[], delete_nics=[ data_models.Interface(network_id=2)] ).to_dict(recurse=True) self.assertEqual({self.db_amphora_mock.id: ndm}, calc_delta.execute(self.load_balancer_mock, {}))
PORT_ID = uuidutils.generate_uuid() SUBNET_ID = uuidutils.generate_uuid() NETWORK_ID = uuidutils.generate_uuid() IP_ADDRESS = "172.24.41.1" VIP = o_data_models.Vip(port_id=t_constants.MOCK_PORT_ID, subnet_id=t_constants.MOCK_SUBNET_ID, qos_policy_id=t_constants.MOCK_QOS_POLICY_ID1) VIP2 = o_data_models.Vip(port_id=t_constants.MOCK_PORT_ID2, subnet_id=t_constants.MOCK_SUBNET_ID2, qos_policy_id=t_constants.MOCK_QOS_POLICY_ID2) LB = o_data_models.LoadBalancer(vip=VIP) LB2 = o_data_models.LoadBalancer(vip=VIP2) FIRST_IP = {"ip_address": IP_ADDRESS, "subnet_id": SUBNET_ID} FIXED_IPS = [FIRST_IP] INTERFACE = data_models.Interface(id=uuidutils.generate_uuid(), compute_id=COMPUTE_ID, fixed_ips=FIXED_IPS, port_id=PORT_ID) AMPS_DATA = [o_data_models.Amphora(id=t_constants.MOCK_AMP_ID1, vrrp_port_id=t_constants.MOCK_VRRP_PORT_ID1, vrrp_ip=t_constants.MOCK_VRRP_IP1), o_data_models.Amphora(id=t_constants.MOCK_AMP_ID2, vrrp_port_id=t_constants.MOCK_VRRP_PORT_ID2, vrrp_ip=t_constants.MOCK_VRRP_IP2) ] UPDATE_DICT = {constants.TOPOLOGY: None} _session_mock = mock.MagicMock() class TestException(Exception): def __init__(self, value):