def get_expected_keepalive_configuration(self, router): ha_device_name = router.get_ha_device_name() external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) ex_device_name = router.get_external_device_name(external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr') return textwrap.dedent("""\ global_defs { notification_email_from %(email_from)s router_id %(router_id)s } vrrp_instance VR_1 { state BACKUP interface %(ha_device_name)s virtual_router_id 1 priority 50 garp_master_delay 60 nopreempt advert_int 2 track_interface { %(ha_device_name)s } virtual_ipaddress { 169.254.0.1/24 dev %(ha_device_name)s } virtual_ipaddress_excluded { %(floating_ip_cidr)s dev %(ex_device_name)s %(external_device_cidr)s dev %(ex_device_name)s %(internal_device_cidr)s dev %(internal_device_name)s %(ex_port_ipv6)s dev %(ex_device_name)s scope link %(int_port_ipv6)s dev %(internal_device_name)s scope link } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(ex_device_name)s 8.8.8.0/24 via 19.4.4.4 %(extra_subnet_cidr)s dev %(ex_device_name)s scope link } }""") % { 'email_from': keepalived.KEEPALIVED_EMAIL_FROM, 'router_id': keepalived.KEEPALIVED_ROUTER_ID, 'ha_device_name': ha_device_name, 'ex_device_name': ex_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6, 'extra_subnet_cidr': extra_subnet_cidr, }
def get_expected_keepalive_configuration(self, router): ha_device_name = router.get_ha_device_name() external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) ex_device_name = router.get_external_device_name(external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr') return KEEPALIVED_CONFIG % { 'email_from': keepalived.KEEPALIVED_EMAIL_FROM, 'router_id': keepalived.KEEPALIVED_ROUTER_ID, 'ha_device_name': ha_device_name, 'ex_device_name': ex_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6, 'extra_subnet_cidr': extra_subnet_cidr, }
def get_expected_keepalive_configuration(self, router): router_id = router.router_id ha_device_name = router.get_ha_device_name() ha_device_cidr = self._port_first_ip_cidr(router.ha_port) external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) external_device_name = router.get_external_device_name( external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[l3_constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') return """vrrp_instance VR_1 { state BACKUP interface %(ha_device_name)s virtual_router_id 1 priority 50 nopreempt advert_int 2 track_interface { %(ha_device_name)s } virtual_ipaddress { 169.254.0.1/24 dev %(ha_device_name)s } virtual_ipaddress_excluded { %(floating_ip_cidr)s dev %(external_device_name)s %(external_device_cidr)s dev %(external_device_name)s %(internal_device_cidr)s dev %(internal_device_name)s %(ex_port_ipv6)s dev %(external_device_name)s scope link %(int_port_ipv6)s dev %(internal_device_name)s scope link } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(external_device_name)s 8.8.8.0/24 via 19.4.4.4 } }""" % { 'router_id': router_id, 'ha_device_name': ha_device_name, 'ha_device_cidr': ha_device_cidr, 'external_device_name': external_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6 }
def init_l3(self, device_name, ip_cidrs, namespace=None, preserve_ips=None, clean_connections=False): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings preserve_ips: list of ip cidrs that should not be removed from device clean_connections: Boolean to indicate if we should cleanup connections associated to removed ips """ preserve_ips = preserve_ips or [] device = ip_lib.IPDevice(device_name, namespace=namespace) # The LLA generated by the operating system is not known to # Neutron, so it would be deleted if we added it to the 'previous' # list here default_ipv6_lla = ip_lib.get_ipv6_lladdr(device.link.address) cidrs = set() remove_ips = set() # normalize all the IP addresses first for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) # Convert to compact IPv6 address because the return values of # "ip addr list" are compact. if net.version == 6: ip_cidr = str(net) cidrs.add(ip_cidr) # Determine the addresses that must be added and removed for address in device.addr.list(): cidr = address['cidr'] dynamic = address['dynamic'] # skip the IPv6 link-local if cidr == default_ipv6_lla: continue if cidr in preserve_ips: continue # Statically created addresses are OK, dynamically created # addresses must be removed and replaced if cidr in cidrs and not dynamic: cidrs.remove(cidr) continue remove_ips.add(cidr) # Clean up any old addresses. This must be done first since there # could be a dynamic address being replaced with a static one. for ip_cidr in remove_ips: if clean_connections: device.delete_addr_and_conntrack_state(ip_cidr) else: device.addr.delete(ip_cidr) # add any new addresses for ip_cidr in cidrs: device.addr.add(ip_cidr)
def check_gw_lla_status(expected): lladdr = ip_lib.get_ipv6_lladdr( external_port['mac_address']) exists = ip_lib.device_exists_with_ips_and_mac( external_device_name, [lladdr], external_port['mac_address'], router.ns_name) self.assertEqual(expected, exists)
def _check_lla_status(router, expected): internal_devices = router.router[l3_constants.INTERFACE_KEY] for device in internal_devices: lladdr = ip_lib.get_ipv6_lladdr(device['mac_address']) exists = ip_lib.device_exists_with_ips_and_mac( router.get_internal_device_name(device['id']), [lladdr], device['mac_address'], router.ns_name) self.assertEqual(expected, exists)
def _check_lla_status(router, expected): internal_devices = router.router[constants.INTERFACE_KEY] for device in internal_devices: lladdr = ip_lib.get_ipv6_lladdr(device['mac_address']) exists = ip_lib.device_exists_with_ips_and_mac( router.get_internal_device_name(device['id']), [lladdr], device['mac_address'], router.ns_name) self.assertEqual(expected, exists)
def init_l3(self, device_name, ip_cidrs, namespace=None, preserve_ips=[], gateway_ips=None, extra_subnets=[], enable_ra_on_gw=False, clean_connections=False): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings preserve_ips: list of ip cidrs that should not be removed from device gateway_ips: For gateway ports, list of external gateway ip addresses enable_ra_on_gw: Boolean to indicate configuring acceptance of IPv6 RA clean_connections: Boolean to indicate if we should cleanup connections associated to removed ips """ device = ip_lib.IPDevice(device_name, namespace=namespace) # The LLA generated by the operating system is not known to # Neutron, so it would be deleted if we added it to the 'previous' # list here default_ipv6_lla = ip_lib.get_ipv6_lladdr(device.link.address) previous = {addr['cidr'] for addr in device.addr.list( filters=['permanent'])} - {default_ipv6_lla} # add new addresses for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) # Convert to compact IPv6 address because the return values of # "ip addr list" are compact. if net.version == 6: ip_cidr = str(net) if ip_cidr in previous: previous.remove(ip_cidr) continue device.addr.add(ip_cidr) # clean up any old addresses for ip_cidr in previous: if ip_cidr not in preserve_ips: if clean_connections: device.delete_addr_and_conntrack_state(ip_cidr) else: device.addr.delete(ip_cidr) for gateway_ip in gateway_ips or []: device.route.add_gateway(gateway_ip) if enable_ra_on_gw: self.configure_ipv6_ra(namespace, device_name) new_onlink_routes = set(s['cidr'] for s in extra_subnets) existing_onlink_routes = set( device.route.list_onlink_routes(n_const.IP_VERSION_4) + device.route.list_onlink_routes(n_const.IP_VERSION_6)) for route in new_onlink_routes - existing_onlink_routes: device.route.add_onlink_route(route) for route in existing_onlink_routes - new_onlink_routes: device.route.delete_onlink_route(route)
def init_l3(self, device_name, ip_cidrs, namespace=None, preserve_ips=[], gateway_ips=None, extra_subnets=[], enable_ra_on_gw=False): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings preserve_ips: list of ip cidrs that should not be removed from device gateway_ips: For gateway ports, list of external gateway ip addresses enable_ra_on_gw: Boolean to indicate configuring acceptance of IPv6 RA """ device = ip_lib.IPDevice(device_name, namespace=namespace) # The LLA generated by the operating system is not known to # Neutron, so it would be deleted if we added it to the 'previous' # list here default_ipv6_lla = ip_lib.get_ipv6_lladdr(device.link.address) previous = {addr['cidr'] for addr in device.addr.list( filters=['permanent'])} - {default_ipv6_lla} # add new addresses for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) # Convert to compact IPv6 address because the return values of # "ip addr list" are compact. if net.version == 6: ip_cidr = str(net) if ip_cidr in previous: previous.remove(ip_cidr) continue device.addr.add(ip_cidr) # clean up any old addresses for ip_cidr in previous: if ip_cidr not in preserve_ips: device.addr.delete(ip_cidr) self.delete_conntrack_state(namespace=namespace, ip=ip_cidr) for gateway_ip in gateway_ips or []: device.route.add_gateway(gateway_ip) if enable_ra_on_gw: self.configure_ipv6_ra(namespace, device_name) new_onlink_routes = set(s['cidr'] for s in extra_subnets) existing_onlink_routes = set( device.route.list_onlink_routes(n_const.IP_VERSION_4) + device.route.list_onlink_routes(n_const.IP_VERSION_6)) for route in new_onlink_routes - existing_onlink_routes: device.route.add_onlink_route(route) for route in existing_onlink_routes - new_onlink_routes: device.route.delete_onlink_route(route)
def _disable_ipv6_addressing_on_interface(self, interface_name): """Disable IPv6 link local addressing on the device and add it as a VIP to keepalived. This means that the IPv6 link local address will only be present on the master. """ device = ip_lib.IPDevice(interface_name, namespace=self.ns_name) ipv6_lladdr = ip_lib.get_ipv6_lladdr(device.link.address) if self._should_delete_ipv6_lladdr(ipv6_lladdr): device.addr.flush(n_consts.IP_VERSION_6) self._remove_vip(ipv6_lladdr) self._add_vip(ipv6_lladdr, interface_name, scope='link')
def init_l3(self, device_name, ip_cidrs, namespace=None, preserve_ips=[], gateway_ips=None, clean_connections=False): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings preserve_ips: list of ip cidrs that should not be removed from device gateway_ips: For gateway ports, list of external gateway ip addresses clean_connections: Boolean to indicate if we should cleanup connections associated to removed ips """ device = ip_lib.IPDevice(device_name, namespace=namespace) # The LLA generated by the operating system is not known to # Neutron, so it would be deleted if we added it to the 'previous' # list here default_ipv6_lla = ip_lib.get_ipv6_lladdr(device.link.address) previous = { addr['cidr'] for addr in device.addr.list(filters=['permanent']) } - {default_ipv6_lla} # add new addresses for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) # Convert to compact IPv6 address because the return values of # "ip addr list" are compact. if net.version == 6: ip_cidr = str(net) if ip_cidr in previous: previous.remove(ip_cidr) continue device.addr.add(ip_cidr) # clean up any old addresses for ip_cidr in previous: if ip_cidr not in preserve_ips: if clean_connections: device.delete_addr_and_conntrack_state(ip_cidr) else: device.addr.delete(ip_cidr) for gateway_ip in gateway_ips or []: device.route.add_gateway(gateway_ip)
def _disable_ipv6_addressing_on_interface(self, interface_name): """Disable IPv6 link local addressing on the device and add it as a VIP to keepalived. This means that the IPv6 link local address will only be present on the master. """ device = ip_lib.IPDevice(interface_name, namespace=self.ha_namespace) ipv6_lladdr = ip_lib.get_ipv6_lladdr(device.link.address) if self._should_delete_ipv6_lladdr(ipv6_lladdr): self.driver.configure_ipv6_ra(self.ha_namespace, interface_name, const.ACCEPT_RA_DISABLED) device.addr.flush(n_consts.IP_VERSION_6) else: self.driver.configure_ipv6_ra(self.ha_namespace, interface_name, const.ACCEPT_RA_WITHOUT_FORWARDING) self._remove_vip(ipv6_lladdr) self._add_vip(ipv6_lladdr, interface_name, scope='link')
def init_l3( self, device_name, ip_cidrs, namespace=None, preserve_ips=[], gateway_ips=None, clean_connections=False ): """Set the L3 settings for the interface using data from the port. ip_cidrs: list of 'X.X.X.X/YY' strings preserve_ips: list of ip cidrs that should not be removed from device gateway_ips: For gateway ports, list of external gateway ip addresses clean_connections: Boolean to indicate if we should cleanup connections associated to removed ips """ device = ip_lib.IPDevice(device_name, namespace=namespace) # The LLA generated by the operating system is not known to # Neutron, so it would be deleted if we added it to the 'previous' # list here default_ipv6_lla = ip_lib.get_ipv6_lladdr(device.link.address) previous = {addr["cidr"] for addr in device.addr.list(filters=["permanent"])} - {default_ipv6_lla} # add new addresses for ip_cidr in ip_cidrs: net = netaddr.IPNetwork(ip_cidr) # Convert to compact IPv6 address because the return values of # "ip addr list" are compact. if net.version == 6: ip_cidr = str(net) if ip_cidr in previous: previous.remove(ip_cidr) continue device.addr.add(ip_cidr) # clean up any old addresses for ip_cidr in previous: if ip_cidr not in preserve_ips: if clean_connections: device.delete_addr_and_conntrack_state(ip_cidr) else: device.addr.delete(ip_cidr) for gateway_ip in gateway_ips or []: device.route.add_gateway(gateway_ip)
def create_rtr_2_fip_link(self, ri): """Create interface between router and Floating IP namespace.""" LOG.debug("Create FIP link interfaces for router %s", ri.router_id) fip_ns_name = self.get_name() # add link local IP to interface if ri.rtr_fip_subnet is None: ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id) rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair() rtr_2_fip_dev = self.get_rtr_2_fip_device(ri) fip_2_rtr_dev = self.get_fip_2_rtr_device(ri) if not rtr_2_fip_dev.exists(): ip_wrapper = ip_lib.IPWrapper(namespace=ri.ns_name) rtr_2_fip_dev, fip_2_rtr_dev = ip_wrapper.add_veth( rtr_2_fip_dev.name, fip_2_rtr_dev.name, fip_ns_name) rtr_2_fip_dev.link.set_up() fip_2_rtr_dev.link.set_up() mtu = ri.get_ex_gw_port().get('mtu') if mtu: rtr_2_fip_dev.link.set_mtu(mtu) fip_2_rtr_dev.link.set_mtu(mtu) self._add_cidr_to_device(rtr_2_fip_dev, str(rtr_2_fip)) self._add_cidr_to_device(fip_2_rtr_dev, str(fip_2_rtr)) # Add permanant ARP entries on each side of veth pair rtr_2_fip_dev.neigh.add(common_utils.cidr_to_ip(fip_2_rtr), fip_2_rtr_dev.link.address) fip_2_rtr_dev.neigh.add(common_utils.cidr_to_ip(rtr_2_fip), rtr_2_fip_dev.link.address) self._add_rtr_ext_route_rule_to_route_table(ri, fip_2_rtr, fip_2_rtr_dev.name) # add default route for the link local interface rtr_2_fip_dev.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL) v6_gateway = common_utils.cidr_to_ip( ip_lib.get_ipv6_lladdr(fip_2_rtr_dev.link.address)) rtr_2_fip_dev.route.add_gateway(v6_gateway)
def _get_device_ipv6_lladdr(self, device): lladdr_cidr = ip_lib.get_ipv6_lladdr(device.link.address) return utils.cidr_to_ip(lladdr_cidr)
def get_expected_keepalive_configuration(self, router): ha_device_name = router.get_ha_device_name() external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) ex_device_name = router.get_external_device_name( external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr') return textwrap.dedent("""\ global_defs { notification_email_from %(email_from)s router_id %(router_id)s } vrrp_instance VR_1 { state BACKUP interface %(ha_device_name)s virtual_router_id 1 priority 50 garp_master_delay 60 nopreempt advert_int 2 track_interface { %(ha_device_name)s } virtual_ipaddress { 169.254.0.1/24 dev %(ha_device_name)s } virtual_ipaddress_excluded { %(floating_ip_cidr)s dev %(ex_device_name)s %(external_device_cidr)s dev %(ex_device_name)s %(internal_device_cidr)s dev %(internal_device_name)s %(ex_port_ipv6)s dev %(ex_device_name)s scope link %(int_port_ipv6)s dev %(internal_device_name)s scope link } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(ex_device_name)s 8.8.8.0/24 via 19.4.4.4 %(extra_subnet_cidr)s dev %(ex_device_name)s scope link } }""") % { 'email_from': keepalived.KEEPALIVED_EMAIL_FROM, 'router_id': keepalived.KEEPALIVED_ROUTER_ID, 'ha_device_name': ha_device_name, 'ex_device_name': ex_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6, 'extra_subnet_cidr': extra_subnet_cidr, }