23 |
23 |
24 import errno |
24 import errno |
25 import netaddr |
25 import netaddr |
26 |
26 |
27 from oslo.config import cfg |
27 from oslo.config import cfg |
28 |
28 from oslo_log import log as logging |
29 from neutron.agent.common import config |
29 |
30 from neutron.agent import l3_agent |
30 from neutron.agent.l3 import agent as l3_agent |
31 from neutron.agent.linux import external_process |
31 from neutron.agent.l3 import router_info as router |
32 from neutron.agent.linux import utils |
32 from neutron.agent.linux import utils |
33 from neutron.agent.solaris import interface |
33 from neutron.agent.solaris import interface |
|
34 from neutron.agent.solaris import ipfilters_manager |
34 from neutron.agent.solaris import net_lib |
35 from neutron.agent.solaris import net_lib |
35 from neutron.agent.solaris import ra |
36 from neutron.agent.solaris import ra |
|
37 from neutron.callbacks import events |
|
38 from neutron.callbacks import registry |
|
39 from neutron.callbacks import resources |
36 from neutron.common import constants as l3_constants |
40 from neutron.common import constants as l3_constants |
|
41 from neutron.common import exceptions as n_exc |
37 from neutron.common import utils as common_utils |
42 from neutron.common import utils as common_utils |
38 from neutron.openstack.common import log as logging |
43 from oslo_utils import importutils |
39 |
44 from oslo_log import log as logging |
|
45 |
|
46 import neutron_vpnaas.services.vpn.agent as neutron_vpnaas |
|
47 from neutron_vpnaas.extensions import vpnaas |
|
48 from neutron_vpnaas.services.vpn import vpn_service |
40 |
49 |
41 LOG = logging.getLogger(__name__) |
50 LOG = logging.getLogger(__name__) |
42 INTERNAL_DEV_PREFIX = 'l3i' |
51 INTERNAL_DEV_PREFIX = 'l3i' |
43 EXTERNAL_DEV_PREFIX = 'l3e' |
52 EXTERNAL_DEV_PREFIX = 'l3e' |
44 FLOATING_IP_CIDR_SUFFIX = '/32' |
53 FLOATING_IP_CIDR_SUFFIX = '/32' |
45 |
54 |
46 |
55 |
47 class EVSL3NATAgent(l3_agent.L3NATAgentWithStateReport): |
56 class SolarisRouterInfo(router.RouterInfo): |
48 OPTS = [ |
57 |
49 cfg.StrOpt('external_network_datalink', default='net0', |
58 def __init__(self, router_id, router, agent_conf, interface_driver, |
50 help=_("Name of the datalink that connects to " |
59 use_ipv6=False): |
51 "an external network.")), |
60 super(SolarisRouterInfo, self).__init__(router_id, router, agent_conf, |
52 cfg.BoolOpt('allow_forwarding_between_networks', default=False, |
61 interface_driver, use_ipv6) |
53 help=_("Allow forwarding of packets between tenant's " |
62 self.ipfilters_manager = ipfilters_manager.IPfiltersManager() |
54 "networks")), |
63 self.iptables_manager = None |
55 ] |
64 self.remove_route = False |
56 |
65 |
57 def __init__(self, host, conf=None): |
66 def initialize(self, process_monitor): |
58 cfg.CONF.register_opts(self.OPTS) |
67 """Initialize the router on the system. |
59 cfg.CONF.register_opts(interface.OPTS) |
68 |
60 super(EVSL3NATAgent, self).__init__(host=host, conf=conf) |
69 This differs from __init__ in that this method actually affects the |
61 |
70 system creating namespaces, starting processes, etc. The other merely |
62 def _router_added(self, router_id, router): |
71 initializes the python object. This separates in-memory object |
63 ri = l3_agent.RouterInfo(router_id, None, |
72 initialization from methods that actually go do stuff to the system. |
64 self.conf.use_namespaces, router) |
73 |
65 self.router_info[router_id] = ri |
74 :param process_monitor: The agent's process monitor instance. |
66 |
|
67 if self.conf.enable_metadata_proxy: |
|
68 self._spawn_metadata_proxy(ri.router_id, ri.ns_name) |
|
69 |
|
70 def _router_removed(self, router_id): |
|
71 ri = self.router_info.get(router_id) |
|
72 if ri is None: |
|
73 LOG.warn(_("Info for router %s were not found. " |
|
74 "Skipping router removal"), router_id) |
|
75 return |
|
76 ri.router['gw_port'] = None |
|
77 ri.router[l3_constants.INTERFACE_KEY] = [] |
|
78 ri.router[l3_constants.FLOATINGIP_KEY] = [] |
|
79 self.process_router(ri) |
|
80 if self.conf.enable_metadata_proxy: |
|
81 self._destroy_metadata_proxy(ri.router_id, ri.ns_name) |
|
82 |
|
83 del self.router_info[router_id] |
|
84 |
|
85 def _get_metadata_proxy_process_manager(self, router_id, ns_name): |
|
86 return external_process.ProcessManager( |
|
87 self.conf, |
|
88 router_id, |
|
89 root_helper=None, |
|
90 namespace=ns_name) |
|
91 |
|
92 def _get_metadata_proxy_callback(self, router_id): |
|
93 """Need to override this since we need to pass the absolute |
|
94 path to neutron-ns-metadata-proxy binary. |
|
95 """ |
75 """ |
96 def callback(pid_file): |
76 self.process_monitor = process_monitor |
97 metadata_proxy_socket = cfg.CONF.metadata_proxy_socket |
77 self.radvd = ra.NDPD(self.router_id, self.get_internal_device_name) |
98 proxy_cmd = ['/usr/lib/neutron/neutron-ns-metadata-proxy', |
78 |
99 '--pid_file=%s' % pid_file, |
79 def get_internal_device_name(self, port_id): |
100 '--metadata_proxy_socket=%s' % metadata_proxy_socket, |
80 # Because of the way how dnsmasq works on Solaris, the length |
101 '--router_id=%s' % router_id, |
81 # of datalink name cannot exceed 16 (includes terminating nul |
102 '--state_path=%s' % self.conf.state_path, |
82 # character). So, the linkname can only have 15 characters and |
103 '--metadata_port=%s' % self.conf.metadata_port] |
83 # the last two characters are set aside for '_0'. So, we only |
104 proxy_cmd.extend(config.get_log_args( |
84 # have 13 characters left. |
105 cfg.CONF, 'neutron-ns-metadata-proxy-%s.log' % |
85 dname = (INTERNAL_DEV_PREFIX + port_id)[:13] |
106 router_id)) |
86 dname += '_0' |
107 return proxy_cmd |
87 return dname.replace('-', '_') |
108 |
88 |
109 return callback |
89 def get_external_device_name(self, port_id): |
110 |
90 # please see the comment above |
111 def external_gateway_snat_rules(self, ex_gw_ip, internal_cidrs, |
91 dname = (EXTERNAL_DEV_PREFIX + port_id)[:13] |
112 interface_name): |
92 dname += '_0' |
113 rules = [] |
93 return dname.replace('-', '_') |
114 for cidr in internal_cidrs: |
94 |
115 rules.append('map %s %s -> %s/32' % |
95 def routes_updated(self): |
116 (interface_name, cidr, ex_gw_ip)) |
96 pass |
117 return rules |
97 |
118 |
98 def _get_existing_devices(self): |
119 def _handle_router_snat_rules(self, ri, ex_gw_port, internal_cidrs, |
99 return net_lib.Datalink.show_link() |
120 interface_name, action): |
100 |
121 assert not ri.router['distributed'] |
101 def internal_network_added(self, port): |
122 |
102 internal_dlname = self.get_internal_device_name(port['id']) |
123 # Remove all the old SNAT rules |
103 # driver just returns if datalink and IP interface already exists |
124 # This is safe because if use_namespaces is set as False |
104 self.driver.plug(port['tenant_id'], port['network_id'], port['id'], |
125 # then the agent can only configure one router, otherwise |
105 internal_dlname) |
126 # each router's SNAT rules will be in their own namespace |
106 ip_cidrs = common_utils.fixed_ip_cidrs(port['fixed_ips']) |
127 |
107 self.driver.init_l3(internal_dlname, ip_cidrs) |
128 # get only the SNAT rules |
108 |
129 old_snat_rules = [rule for rule in ri.ipfilters_manager.ipv4['nat'] |
109 # Since we support shared router model, we need to block the new |
130 if rule.startswith('map')] |
110 # internal port from reaching other tenant's ports |
131 ri.ipfilters_manager.remove_nat_rules(old_snat_rules) |
111 block_pname = self._get_ippool_name(port['mac_address']) |
132 |
112 self.ipfilters_manager.add_ippool(block_pname, None) |
133 # And add them back if the action is add_rules |
113 if self.agent_conf.allow_forwarding_between_networks: |
134 if action == 'add_rules' and ex_gw_port: |
114 # If allow_forwarding_between_networks is set, then we need to |
135 # NAT rules are added only if ex_gw_port has an IPv4 address |
115 # allow forwarding of packets between same tenant's ports. |
136 for ip_addr in ex_gw_port['fixed_ips']: |
116 allow_pname = self._get_ippool_name(port['mac_address'], '0') |
137 ex_gw_ip = ip_addr['ip_address'] |
117 self.ipfilters_manager.add_ippool(allow_pname, None) |
138 if netaddr.IPAddress(ex_gw_ip).version == 4: |
118 |
139 rules = self.external_gateway_snat_rules(ex_gw_ip, |
119 # walk through the other internal ports and retrieve their |
140 internal_cidrs, |
120 # cidrs and at the same time add the new internal port's |
141 interface_name) |
121 # cidr to them |
142 ri.ipfilters_manager.add_nat_rules(rules) |
122 port_subnet = port['subnets'][0]['cidr'] |
143 break |
123 block_subnets = [] |
144 |
124 allow_subnets = [] |
145 @common_utils.exception_logger() |
125 for internal_port in self.internal_ports: |
146 def process_router(self, ri): |
126 if internal_port['mac_address'] == port['mac_address']: |
147 # TODO(mrsmith) - we shouldn't need to check here |
127 continue |
148 if 'distributed' not in ri.router: |
128 if (self.agent_conf.allow_forwarding_between_networks and |
149 ri.router['distributed'] = False |
129 internal_port['tenant_id'] == port['tenant_id']): |
150 ex_gw_port = self._get_ex_gw_port(ri) |
130 allow_subnets.append(internal_port['subnets'][0]['cidr']) |
151 internal_ports = ri.router.get(l3_constants.INTERFACE_KEY, []) |
131 # we need to add the port's subnet to this internal_port's |
152 existing_port_ids = set([p['id'] for p in ri.internal_ports]) |
132 # allowed_subnet_pool |
|
133 iport_allow_pname = \ |
|
134 self._get_ippool_name(internal_port['mac_address'], '0') |
|
135 self.ipfilters_manager.add_ippool(iport_allow_pname, |
|
136 [port_subnet]) |
|
137 else: |
|
138 block_subnets.append(internal_port['subnets'][0]['cidr']) |
|
139 iport_block_pname = \ |
|
140 self._get_ippool_name(internal_port['mac_address']) |
|
141 self.ipfilters_manager.add_ippool(iport_block_pname, |
|
142 [port_subnet]) |
|
143 # update the new port's pool with other ports' subnet |
|
144 self.ipfilters_manager.add_ippool(block_pname, block_subnets) |
|
145 if self.agent_conf.allow_forwarding_between_networks: |
|
146 self.ipfilters_manager.add_ippool(allow_pname, allow_subnets) |
|
147 |
|
148 # now setup the IPF rules |
|
149 rules = ['block in quick on %s from %s to pool/%d' % |
|
150 (internal_dlname, port_subnet, block_pname)] |
|
151 # pass in packets between networks that belong to same tenant |
|
152 if self.agent_conf.allow_forwarding_between_networks: |
|
153 rules.append('pass in quick on %s from %s to pool/%d' % |
|
154 (internal_dlname, port_subnet, allow_pname)) |
|
155 # if the external gateway is already setup for the shared router, |
|
156 # then we need to add Policy Based Routing (PBR) for this internal |
|
157 # network |
|
158 ex_gw_port = self.ex_gw_port |
|
159 ex_gw_ip = (ex_gw_port['subnets'][0]['gateway_ip'] |
|
160 if ex_gw_port else None) |
|
161 if ex_gw_ip: |
|
162 external_dlname = self.get_external_device_name(ex_gw_port['id']) |
|
163 rules.append('pass in on %s to %s:%s from any to !%s' % |
|
164 (internal_dlname, external_dlname, ex_gw_ip, |
|
165 port_subnet)) |
|
166 |
|
167 ipversion = netaddr.IPNetwork(port_subnet).version |
|
168 self.ipfilters_manager.add_ipf_rules(rules, ipversion) |
|
169 if self.agent_conf.enable_metadata_proxy and ipversion == 4: |
|
170 rdr_rule = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' % |
|
171 (internal_dlname, port['fixed_ips'][0]['ip_address'], |
|
172 self.agent_conf.metadata_port)] |
|
173 self.ipfilters_manager.add_nat_rules(rdr_rule) |
|
174 |
|
175 def internal_network_removed(self, port): |
|
176 internal_dlname = self.get_internal_device_name(port['id']) |
|
177 port_subnet = port['subnets'][0]['cidr'] |
|
178 # remove all the IP filter rules that we added during |
|
179 # internal network addition |
|
180 block_pname = self._get_ippool_name(port['mac_address']) |
|
181 rules = ['block in quick on %s from %s to pool/%d' % |
|
182 (internal_dlname, port_subnet, block_pname)] |
|
183 if self.agent_conf.allow_forwarding_between_networks: |
|
184 allow_pname = self._get_ippool_name(port['mac_address'], '0') |
|
185 rules.append('pass in quick on %s from %s to pool/%d' % |
|
186 (internal_dlname, port_subnet, allow_pname)) |
|
187 |
|
188 # remove all the IP filter rules that we added during |
|
189 # external network addition |
|
190 ex_gw_port = self.ex_gw_port |
|
191 ex_gw_ip = (ex_gw_port['subnets'][0]['gateway_ip'] |
|
192 if ex_gw_port else None) |
|
193 if ex_gw_ip: |
|
194 external_dlname = self.get_external_device_name(ex_gw_port['id']) |
|
195 rules.append('pass in on %s to %s:%s from any to !%s' % |
|
196 (internal_dlname, external_dlname, ex_gw_ip, |
|
197 port_subnet)) |
|
198 ipversion = netaddr.IPNetwork(port['subnets'][0]['cidr']).version |
|
199 self.ipfilters_manager.remove_ipf_rules(rules, ipversion) |
|
200 |
|
201 # remove the ippool |
|
202 self.ipfilters_manager.remove_ippool(block_pname, None) |
|
203 if self.agent_conf.allow_forwarding_between_networks: |
|
204 self.ipfilters_manager.remove_ippool(allow_pname, None) |
|
205 |
|
206 for internal_port in self.internal_ports: |
|
207 if (self.agent_conf.allow_forwarding_between_networks and |
|
208 internal_port['tenant_id'] == port['tenant_id']): |
|
209 iport_allow_pname = \ |
|
210 self._get_ippool_name(internal_port['mac_address'], '0') |
|
211 self.ipfilters_manager.remove_ippool(iport_allow_pname, |
|
212 [port_subnet]) |
|
213 else: |
|
214 iport_block_pname = \ |
|
215 self._get_ippool_name(internal_port['mac_address']) |
|
216 self.ipfilters_manager.remove_ippool(iport_block_pname, |
|
217 [port_subnet]) |
|
218 if self.agent_conf.enable_metadata_proxy and ipversion == 4: |
|
219 rdr_rule = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' % |
|
220 (internal_dlname, port['fixed_ips'][0]['ip_address'], |
|
221 self.agent_conf.metadata_port)] |
|
222 self.ipfilters_manager.remove_nat_rules(rdr_rule) |
|
223 |
|
224 if net_lib.Datalink.datalink_exists(internal_dlname): |
|
225 self.driver.fini_l3(internal_dlname) |
|
226 self.driver.unplug(internal_dlname) |
|
227 |
|
228 def _process_internal_ports(self): |
|
229 existing_port_ids = set([p['id'] for p in self.internal_ports]) |
|
230 |
|
231 internal_ports = self.router.get(l3_constants.INTERFACE_KEY, []) |
153 current_port_ids = set([p['id'] for p in internal_ports |
232 current_port_ids = set([p['id'] for p in internal_ports |
154 if p['admin_state_up']]) |
233 if p['admin_state_up']]) |
155 new_ports = [p for p in internal_ports if |
234 |
156 p['id'] in current_port_ids and |
235 new_port_ids = current_port_ids - existing_port_ids |
157 p['id'] not in existing_port_ids] |
236 new_ports = [p for p in internal_ports if p['id'] in new_port_ids] |
158 old_ports = [p for p in ri.internal_ports if |
237 old_ports = [p for p in self.internal_ports if |
159 p['id'] not in current_port_ids] |
238 p['id'] not in current_port_ids] |
160 new_ipv6_port = False |
239 # updated_ports = self._get_updated_ports(self.internal_ports, |
161 old_ipv6_port = False |
240 # internal_ports) |
|
241 |
|
242 enable_ra = False |
162 for p in new_ports: |
243 for p in new_ports: |
163 self._set_subnet_info(p) |
244 self.internal_network_added(p) |
164 self.internal_network_added(ri, p) |
245 self.internal_ports.append(p) |
165 ri.internal_ports.append(p) |
246 enable_ra = enable_ra or self._port_has_ipv6_subnet(p) |
166 if (not new_ipv6_port and |
|
167 netaddr.IPNetwork(p['subnet']['cidr']).version == 6): |
|
168 new_ipv6_port = True |
|
169 |
247 |
170 for p in old_ports: |
248 for p in old_ports: |
171 self.internal_network_removed(ri, p) |
249 self.internal_network_removed(p) |
172 ri.internal_ports.remove(p) |
250 self.internal_ports.remove(p) |
173 if (not old_ipv6_port and |
251 enable_ra = enable_ra or self._port_has_ipv6_subnet(p) |
174 netaddr.IPNetwork(p['subnet']['cidr']).version == 6): |
252 |
175 old_ipv6_port = True |
253 # if updated_ports: |
176 |
254 # for index, p in enumerate(internal_ports): |
177 if new_ipv6_port or old_ipv6_port: |
255 # if not updated_ports.get(p['id']): |
178 # refresh ndpd daemon after filling in ndpd.conf |
256 # continue |
179 # with the right entries |
257 # self.internal_ports[index] = updated_ports[p['id']] |
180 ra.enable_ipv6_ra(ri.router_id, |
258 # interface_name = self.get_internal_device_name(p['id']) |
181 internal_ports, |
259 # ip_cidrs = common_utils.fixed_ip_cidrs(p['fixed_ips']) |
182 self.get_internal_device_name) |
260 # self.driver.init_l3(interface_name, ip_cidrs=ip_cidrs, |
|
261 # namespace=self.ns_name) |
|
262 # enable_ra = enable_ra or self._port_has_ipv6_subnet(p) |
|
263 |
|
264 # Enable RA |
|
265 if enable_ra: |
|
266 self.radvd.enable(internal_ports) |
183 |
267 |
184 # remove any internal stale router interfaces (i.e., l3i.. VNICs) |
268 # remove any internal stale router interfaces (i.e., l3i.. VNICs) |
185 existing_devices = net_lib.Datalink.show_vnic() |
269 existing_devices = self._get_existing_devices() |
186 current_internal_devs = set([n for n in existing_devices |
270 current_internal_devs = set(n for n in existing_devices |
187 if n.startswith(INTERNAL_DEV_PREFIX)]) |
271 if n.startswith(INTERNAL_DEV_PREFIX)) |
188 current_port_devs = set([self.get_internal_device_name(id) for |
272 current_port_devs = set(self.get_internal_device_name(port_id) |
189 id in current_port_ids]) |
273 for port_id in current_port_ids) |
190 stale_devs = current_internal_devs - current_port_devs |
274 stale_devs = current_internal_devs - current_port_devs |
191 for stale_dev in stale_devs: |
275 for stale_dev in stale_devs: |
192 LOG.debug(_('Deleting stale internal router device: %s'), |
276 LOG.debug(_('Deleting stale internal router device: %s'), |
193 stale_dev) |
277 stale_dev) |
194 self.driver.fini_l3(stale_dev) |
278 self.driver.fini_l3(stale_dev) |
195 self.driver.unplug(stale_dev) |
279 self.driver.unplug(stale_dev) |
196 |
280 |
197 # TODO(salv-orlando): RouterInfo would be a better place for |
281 def _get_ippool_name(self, mac_address, suffix=None): |
198 # this logic too |
282 # Generate a unique-name for ippool(1m) from that last 3 |
199 ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or |
283 # bytes of mac-address. It is called pool name, but it is |
200 ri.ex_gw_port and ri.ex_gw_port['id']) |
284 # actually a 32 bit integer |
201 |
285 name = mac_address.split(':')[3:] |
202 interface_name = None |
286 if suffix: |
203 if ex_gw_port_id: |
287 name.append(suffix) |
204 interface_name = self.get_external_device_name(ex_gw_port_id) |
288 return int("".join(name), 16) |
205 if ex_gw_port: |
289 |
206 def _gateway_ports_equal(port1, port2): |
290 def process_floating_ip_addresses(self, interface_name): |
207 def _get_filtered_dict(d, ignore): |
291 """Configure IP addresses on router's external gateway interface. |
208 return dict((k, v) for k, v in d.iteritems() |
292 |
209 if k not in ignore) |
293 Ensures addresses for existing floating IPs and cleans up |
210 |
294 those that should not longer be configured. |
211 keys_to_ignore = set(['binding:host_id']) |
295 """ |
212 port1_filtered = _get_filtered_dict(port1, keys_to_ignore) |
296 |
213 port2_filtered = _get_filtered_dict(port2, keys_to_ignore) |
|
214 return port1_filtered == port2_filtered |
|
215 |
|
216 self._set_subnet_info(ex_gw_port) |
|
217 if not ri.ex_gw_port: |
|
218 self.external_gateway_added(ri, ex_gw_port, interface_name) |
|
219 elif not _gateway_ports_equal(ex_gw_port, ri.ex_gw_port): |
|
220 self.external_gateway_updated(ri, ex_gw_port, interface_name) |
|
221 elif not ex_gw_port and ri.ex_gw_port: |
|
222 self.external_gateway_removed(ri, ri.ex_gw_port, interface_name) |
|
223 |
|
224 # Remove any external stale router interfaces (i.e., l3e.. VNICs) |
|
225 stale_devs = [dev for dev in existing_devices |
|
226 if dev.startswith(EXTERNAL_DEV_PREFIX) |
|
227 and dev != interface_name] |
|
228 for stale_dev in stale_devs: |
|
229 LOG.debug(_('Deleting stale external router device: %s'), |
|
230 stale_dev) |
|
231 self.driver.fini_l3(stale_dev) |
|
232 self.driver.unplug(stale_dev) |
|
233 |
|
234 # Process static routes for router |
|
235 self.routes_updated(ri) |
|
236 |
|
237 # Process SNAT rules for external gateway |
|
238 if (not ri.router['distributed'] or |
|
239 ex_gw_port and self.get_gw_port_host(ri.router) == self.host): |
|
240 # Get IPv4 only internal CIDRs |
|
241 internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports |
|
242 if netaddr.IPNetwork(p['ip_cidr']).version == 4] |
|
243 ri.perform_snat_action(self._handle_router_snat_rules, |
|
244 internal_cidrs, interface_name) |
|
245 |
|
246 # Process SNAT/DNAT rules for floating IPs |
|
247 fip_statuses = {} |
297 fip_statuses = {} |
248 if ex_gw_port: |
298 if interface_name is None: |
249 existing_floating_ips = ri.floating_ips |
299 LOG.debug('No Interface for floating IPs router: %s', |
250 fip_statuses = self.process_router_floating_ips(ri, ex_gw_port) |
300 self.router['id']) |
251 # Identify floating IPs which were disabled |
301 return fip_statuses |
252 ri.floating_ips = set(fip_statuses.keys()) |
302 |
253 for fip_id in existing_floating_ips - ri.floating_ips: |
303 ipintf = net_lib.IPInterface(interface_name) |
254 fip_statuses[fip_id] = l3_constants.FLOATINGIP_STATUS_DOWN |
|
255 # Update floating IP status on the neutron server |
|
256 self.plugin_rpc.update_floatingip_statuses( |
|
257 self.context, ri.router_id, fip_statuses) |
|
258 |
|
259 # Update ex_gw_port and enable_snat on the router info cache |
|
260 ri.ex_gw_port = ex_gw_port |
|
261 ri.enable_snat = ri.router.get('enable_snat') |
|
262 |
|
263 def process_router_floating_ips(self, ri, ex_gw_port): |
|
264 """Configure the router's floating IPs |
|
265 Configures floating ips using ipnat(1m) on the router's gateway device. |
|
266 |
|
267 Cleans up floating ips that should not longer be configured. |
|
268 """ |
|
269 ifname = self.get_external_device_name(ex_gw_port['id']) |
|
270 ipintf = net_lib.IPInterface(ifname) |
|
271 ipaddr_list = ipintf.ipaddr_list()['static'] |
304 ipaddr_list = ipintf.ipaddr_list()['static'] |
272 |
305 |
273 existing_cidrs = set(ipaddr_list) |
306 existing_cidrs = set(ipaddr_list) |
274 new_cidrs = set() |
307 new_cidrs = set() |
275 |
308 |
276 existing_nat_rules = [nat_rule for nat_rule in |
309 existing_nat_rules = [nat_rule for nat_rule in |
277 ri.ipfilters_manager.ipv4['nat']] |
310 self.ipfilters_manager.ipv4['nat']] |
278 new_nat_rules = [] |
311 new_nat_rules = [] |
279 |
312 |
|
313 floating_ips = self.get_floating_ips() |
280 # Loop once to ensure that floating ips are configured. |
314 # Loop once to ensure that floating ips are configured. |
281 fip_statuses = {} |
315 for fip in floating_ips: |
282 for fip in ri.router.get(l3_constants.FLOATINGIP_KEY, []): |
|
283 fip_ip = fip['floating_ip_address'] |
316 fip_ip = fip['floating_ip_address'] |
284 fip_cidr = str(fip_ip) + FLOATING_IP_CIDR_SUFFIX |
317 fip_cidr = str(fip_ip) + FLOATING_IP_CIDR_SUFFIX |
285 new_cidrs.add(fip_cidr) |
318 new_cidrs.add(fip_cidr) |
286 fixed_cidr = str(fip['fixed_ip_address']) + '/32' |
319 fixed_cidr = str(fip['fixed_ip_address']) + '/32' |
287 nat_rule = 'bimap %s %s -> %s' % (ifname, fixed_cidr, fip_cidr) |
320 nat_rule = 'bimap %s %s -> %s' % (interface_name, fixed_cidr, |
|
321 fip_cidr) |
288 |
322 |
289 if fip_cidr not in existing_cidrs: |
323 if fip_cidr not in existing_cidrs: |
290 try: |
324 try: |
291 ipintf.create_address(fip_cidr) |
325 ipintf.create_address(fip_cidr) |
292 ri.ipfilters_manager.add_nat_rules([nat_rule]) |
326 self.ipfilters_manager.add_nat_rules([nat_rule]) |
293 except Exception as err: |
327 except Exception as err: |
294 # TODO(gmoodalb): If we fail in add_nat_rules(), then |
328 # TODO(gmoodalb): If we fail in add_nat_rules(), then |
295 # we need to remove the fip_cidr address |
329 # we need to remove the fip_cidr address |
296 |
330 |
297 # any exception occurred here should cause the floating IP |
331 # any exception occurred here should cause the floating IP |
355 LOG.error(_("External network should be either Flat or " |
378 LOG.error(_("External network should be either Flat or " |
356 "VLAN based, and it is required to " |
379 "VLAN based, and it is required to " |
357 "create an external gateway port")) |
380 "create an external gateway port")) |
358 return |
381 return |
359 elif (l2type == 'vlan' and |
382 elif (l2type == 'vlan' and |
360 self.conf.get("external_network_datalink", None)): |
383 self.agent_conf.get("external_network_datalink", None)): |
361 LOG.warning(_("external_network_datalink is deprecated in " |
384 LOG.warning(_("external_network_datalink is deprecated in " |
362 "Juno and will be removed in the next release " |
385 "Juno and will be removed in the next release " |
363 "of Solaris OpenStack. Please use the evsadm " |
386 "of Solaris OpenStack. Please use the evsadm " |
364 "set-controlprop subcommand to setup the " |
387 "set-controlprop subcommand to setup the " |
365 "uplink-port for an external network")) |
388 "uplink-port for an external network")) |
366 # proceed with the old-style of doing things |
389 # proceed with the old-style of doing things |
367 mac_address = ex_gw_port['mac_address'] |
390 mac_address = ex_gw_port['mac_address'] |
368 dl.create_vnic(self.conf.external_network_datalink, |
391 dl.create_vnic(self.agent_conf.external_network_datalink, |
369 mac_address=mac_address, vid=vid) |
392 mac_address=mac_address, vid=vid) |
370 else: |
393 else: |
371 # This is to handle HA by Solaris Cluster and is similar to |
394 self.driver.plug(ex_gw_port['tenant_id'], |
372 # the code we already have for the DHCP Agent. So, when |
395 ex_gw_port['network_id'], |
373 # the 1st L3 agent is down and the second L3 agent tries to |
396 ex_gw_port['id'], external_dlname) |
374 # connect its VNIC to EVS, we will end up in "vport in use" |
397 |
375 # error. So, we need to reset the vport before we connect |
398 ip_cidrs = common_utils.fixed_ip_cidrs(ex_gw_port['fixed_ips']) |
376 # the VNIC to EVS. |
399 self.driver.init_l3(external_dlname, ip_cidrs) |
377 cmd = ['/usr/sbin/evsadm', 'show-vport', '-f', |
400 |
378 'vport=%s' % ex_gw_port['id'], '-co', |
401 gw_ip = ex_gw_port['subnets'][0]['gateway_ip'] |
379 'evs,vport,status'] |
|
380 stdout = utils.execute(cmd) |
|
381 evsname, vportname, status = stdout.strip().split(':') |
|
382 tenant_id = ex_gw_port['tenant_id'] |
|
383 if status == 'used': |
|
384 cmd = ['/usr/sbin/evsadm', 'reset-vport', '-T', tenant_id, |
|
385 '%s/%s' % (evsname, vportname)] |
|
386 utils.execute(cmd) |
|
387 |
|
388 # next remove protection setting on the VPort to allow |
|
389 # multiple floating IPs to be configured on the l3e* |
|
390 # interface |
|
391 evsvport = "%s/%s" % (ex_gw_port['network_id'], |
|
392 ex_gw_port['id']) |
|
393 cmd = ['/usr/sbin/evsadm', 'set-vportprop', '-T', |
|
394 tenant_id, '-p', 'protection=none', evsvport] |
|
395 utils.execute(cmd) |
|
396 dl.connect_vnic(evsvport, tenant_id) |
|
397 |
|
398 self.driver.init_l3(external_dlname, [ex_gw_port['ip_cidr']]) |
|
399 |
|
400 # TODO(gmoodalb): wrap route(1m) command within a class in net_lib.py |
|
401 gw_ip = ex_gw_port['subnet']['gateway_ip'] |
|
402 if gw_ip: |
402 if gw_ip: |
403 cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'add', 'default', |
403 cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'add', 'default', |
404 gw_ip] |
404 gw_ip] |
405 stdout = utils.execute(cmd, extra_ok_codes=[errno.EEXIST]) |
405 stdout = utils.execute(cmd, extra_ok_codes=[errno.EEXIST]) |
406 ri.remove_route = True |
406 if 'entry exists' not in stdout: |
407 if 'entry exists' in stdout: |
407 self.remove_route = True |
408 ri.remove_route = False |
|
409 |
408 |
410 # for each of the internal ports, add Policy Based |
409 # for each of the internal ports, add Policy Based |
411 # Routing (PBR) rule |
410 # Routing (PBR) rule |
412 for port in ri.internal_ports: |
411 for port in self.internal_ports: |
413 internal_dlname = self.get_internal_device_name(port['id']) |
412 internal_dlname = self.get_internal_device_name(port['id']) |
414 rules = ['pass in on %s to %s:%s from any to !%s' % |
413 rules = ['pass in on %s to %s:%s from any to !%s' % |
415 (internal_dlname, external_dlname, gw_ip, |
414 (internal_dlname, external_dlname, gw_ip, |
416 port['subnet']['cidr'])] |
415 port['subnets'][0]['cidr'])] |
417 ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version |
416 ipversion = \ |
418 ri.ipfilters_manager.add_ipf_rules(rules, ipversion) |
417 netaddr.IPNetwork(port['subnets'][0]['cidr']).version |
419 |
418 self.ipfilters_manager.add_ipf_rules(rules, ipversion) |
420 def external_gateway_updated(self, ri, ex_gw_port, external_dlname): |
419 |
|
420 def external_gateway_updated(self, ex_gw_port, external_dlname): |
421 # There is nothing to do on Solaris |
421 # There is nothing to do on Solaris |
422 pass |
422 pass |
423 |
423 |
424 def external_gateway_removed(self, ri, ex_gw_port, external_dlname): |
424 def external_gateway_removed(self, ex_gw_port, external_dlname): |
425 gw_ip = ex_gw_port['subnet']['gateway_ip'] |
425 gw_ip = ex_gw_port['subnets'][0]['gateway_ip'] |
426 if gw_ip: |
426 if gw_ip: |
427 # remove PBR rules |
427 # remove PBR rules |
428 for port in ri.internal_ports: |
428 for port in self.internal_ports: |
429 internal_dlname = self.get_internal_device_name(port['id']) |
429 internal_dlname = self.get_internal_device_name(port['id']) |
430 rules = ['pass in on %s to %s:%s from any to !%s' % |
430 rules = ['pass in on %s to %s:%s from any to !%s' % |
431 (internal_dlname, external_dlname, gw_ip, |
431 (internal_dlname, external_dlname, gw_ip, |
432 port['subnet']['cidr'])] |
432 port['subnets'][0]['cidr'])] |
433 ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version |
433 ipversion = \ |
434 ri.ipfilters_manager.remove_ipf_rules(rules, ipversion) |
434 netaddr.IPNetwork(port['subnets'][0]['cidr']).version |
435 |
435 self.ipfilters_manager.remove_ipf_rules(rules, ipversion) |
436 if ri.remove_route: |
436 |
|
437 if self.remove_route: |
437 cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'delete', |
438 cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'delete', |
438 'default', gw_ip] |
439 'default', gw_ip] |
439 utils.execute(cmd, check_exit_code=False) |
440 utils.execute(cmd, check_exit_code=False) |
440 |
441 |
441 if net_lib.Datalink.datalink_exists(external_dlname): |
442 if net_lib.Datalink.datalink_exists(external_dlname): |
442 self.driver.fini_l3(external_dlname) |
443 self.driver.fini_l3(external_dlname) |
443 self.driver.unplug(external_dlname) |
444 self.driver.unplug(external_dlname) |
444 |
445 |
445 # remove the EVS VPort associated with external network |
446 def _process_external_gateway(self, ex_gw_port): |
446 cmd = ['/usr/sbin/evsadm', 'remove-vport', |
447 # TODO(Carl) Refactor to clarify roles of ex_gw_port vs self.ex_gw_port |
447 '-T', ex_gw_port['tenant_id'], |
448 ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or |
448 '%s/%s' % (ex_gw_port['network_id'], ex_gw_port['id'])] |
449 self.ex_gw_port and self.ex_gw_port['id']) |
|
450 |
|
451 interface_name = None |
|
452 if ex_gw_port_id: |
|
453 interface_name = self.get_external_device_name(ex_gw_port_id) |
|
454 if ex_gw_port: |
|
455 def _gateway_ports_equal(port1, port2): |
|
456 def _get_filtered_dict(d, ignore): |
|
457 return dict((k, v) for k, v in d.iteritems() |
|
458 if k not in ignore) |
|
459 |
|
460 keys_to_ignore = set(['binding:host_id']) |
|
461 port1_filtered = _get_filtered_dict(port1, keys_to_ignore) |
|
462 port2_filtered = _get_filtered_dict(port2, keys_to_ignore) |
|
463 return port1_filtered == port2_filtered |
|
464 |
|
465 if not self.ex_gw_port: |
|
466 self.external_gateway_added(ex_gw_port, interface_name) |
|
467 elif not _gateway_ports_equal(ex_gw_port, self.ex_gw_port): |
|
468 self.external_gateway_updated(ex_gw_port, interface_name) |
|
469 elif not ex_gw_port and self.ex_gw_port: |
|
470 self.external_gateway_removed(self.ex_gw_port, interface_name) |
|
471 |
|
472 # Remove any external stale router interfaces (i.e., l3e.. VNICs) |
|
473 existing_devices = self._get_existing_devices() |
|
474 stale_devs = [dev for dev in existing_devices |
|
475 if dev.startswith(EXTERNAL_DEV_PREFIX) and |
|
476 dev != interface_name] |
|
477 for stale_dev in stale_devs: |
|
478 LOG.debug(_('Deleting stale external router device: %s'), |
|
479 stale_dev) |
|
480 self.driver.fini_l3(stale_dev) |
|
481 self.driver.unplug(stale_dev) |
|
482 |
|
483 # Process SNAT rules for external gateway |
|
484 self.perform_snat_action(self._handle_router_snat_rules, |
|
485 interface_name) |
|
486 |
|
487 def external_gateway_snat_rules(self, ex_gw_ip, interface_name): |
|
488 rules = [] |
|
489 ip_cidrs = [] |
|
490 for port in self.internal_ports: |
|
491 if netaddr.IPNetwork(port['subnets'][0]['cidr']).version == 4: |
|
492 ip_cidrs.extend(common_utils.fixed_ip_cidrs(port['fixed_ips'])) |
|
493 |
|
494 for ip_cidr in ip_cidrs: |
|
495 rules.append('map %s %s -> %s/32' % |
|
496 (interface_name, ip_cidr, ex_gw_ip)) |
|
497 return rules |
|
498 |
|
499 def _handle_router_snat_rules(self, ex_gw_port, interface_name, action): |
|
500 # Remove all the old SNAT rules |
|
501 # This is safe because if use_namespaces is set as False |
|
502 # then the agent can only configure one router, otherwise |
|
503 # each router's SNAT rules will be in their own namespace |
|
504 |
|
505 # get only the SNAT rules |
|
506 old_snat_rules = [rule for rule in self.ipfilters_manager.ipv4['nat'] |
|
507 if rule.startswith('map')] |
|
508 self.ipfilters_manager.remove_nat_rules(old_snat_rules) |
|
509 |
|
510 # And add them back if the action is add_rules |
|
511 if action == 'add_rules' and ex_gw_port: |
|
512 # NAT rules are added only if ex_gw_port has an IPv4 address |
|
513 for ip_addr in ex_gw_port['fixed_ips']: |
|
514 ex_gw_ip = ip_addr['ip_address'] |
|
515 if netaddr.IPAddress(ex_gw_ip).version == 4: |
|
516 rules = self.external_gateway_snat_rules(ex_gw_ip, |
|
517 interface_name) |
|
518 self.ipfilters_manager.add_nat_rules(rules) |
|
519 break |
|
520 |
|
521 def process_external(self, agent): |
|
522 existing_floating_ips = self.floating_ips |
449 try: |
523 try: |
450 utils.execute(cmd) |
524 ex_gw_port = self.get_ex_gw_port() |
451 except Exception as err: |
525 self._process_external_gateway(ex_gw_port) |
452 LOG.error(_("Failed to delete the EVS VPort associated with " |
526 # TODO(Carl) Return after setting existing_floating_ips and |
453 "external network: %s") % err) |
527 # still call update_fip_statuses? |
454 |
528 if not ex_gw_port: |
455 def _get_ippool_name(self, mac_address, suffix=None): |
529 return |
456 # Generate a unique-name for ippool(1m) from that last 3 |
530 |
457 # bytes of mac-address. It is called pool name, but it is |
531 # Once NAT rules for floating IPs are safely in place |
458 # actually a 32 bit integer |
532 # configure their addresses on the external gateway port |
459 name = mac_address.split(':')[3:] |
533 interface_name = self.get_external_device_name(ex_gw_port['id']) |
460 if suffix: |
534 fip_statuses = self.configure_fip_addresses(interface_name) |
461 name.append(suffix) |
535 except (n_exc.FloatingIpSetupException, |
462 return int("".join(name), 16) |
536 n_exc.IpTablesApplyException) as e: |
463 |
537 # All floating IPs must be put in error state |
464 def internal_network_added(self, ri, port): |
538 LOG.exception(e) |
465 internal_dlname = self.get_internal_device_name(port['id']) |
539 fip_statuses = self.put_fips_in_error_state() |
466 # driver just returns if datalink and IP interface already exists |
540 |
467 self.driver.plug(port['tenant_id'], port['network_id'], port['id'], |
541 agent.update_fip_statuses(self, existing_floating_ips, fip_statuses) |
468 internal_dlname) |
542 |
469 self.driver.init_l3(internal_dlname, [port['ip_cidr']]) |
543 |
470 |
544 class EVSL3NATAgent(l3_agent.L3NATAgentWithStateReport): |
471 # Since we support shared router model, we need to block the new |
545 OPTS = [ |
472 # internal port from reaching other tenant's ports |
546 cfg.StrOpt('external_network_datalink', default='net0', |
473 block_pname = self._get_ippool_name(port['mac_address']) |
547 help=_("Name of the datalink that connects to " |
474 ri.ipfilters_manager.add_ippool(block_pname, None) |
548 "an external network.")), |
475 if self.conf.allow_forwarding_between_networks: |
549 cfg.BoolOpt('allow_forwarding_between_networks', default=False, |
476 # If allow_forwarding_between_networks is set, then we need to |
550 help=_("Allow forwarding of packets between tenant's " |
477 # allow forwarding of packets between same tenant's ports. |
551 "networks")), |
478 allow_pname = self._get_ippool_name(port['mac_address'], '0') |
552 ] |
479 ri.ipfilters_manager.add_ippool(allow_pname, None) |
553 |
480 |
554 def __init__(self, host, conf=None): |
481 # walk through the other internal ports and retrieve their |
555 cfg.CONF.register_opts(self.OPTS) |
482 # cidrs and at the same time add the new internal port's |
556 cfg.CONF.register_opts(interface.OPTS) |
483 # cidr to them |
557 super(EVSL3NATAgent, self).__init__(host=host, conf=conf) |
484 port_subnet = port['subnet']['cidr'] |
558 cfg.CONF.register_opts(neutron_vpnaas.vpn_agent_opts, 'vpnagent') |
485 block_subnets = [] |
559 self.service = vpn_service.VPNService(self) |
486 allow_subnets = [] |
560 self.device_drivers = self.service.load_device_drivers(host) |
487 for internal_port in ri.internal_ports: |
561 |
488 if internal_port['mac_address'] == port['mac_address']: |
562 def _router_added(self, router_id, router): |
489 continue |
563 args = [] |
490 if (self.conf.allow_forwarding_between_networks and |
564 kwargs = { |
491 internal_port['tenant_id'] == port['tenant_id']): |
565 'router_id': router_id, |
492 allow_subnets.append(internal_port['subnet']['cidr']) |
566 'router': router, |
493 # we need to add the port's subnet to this internal_port's |
567 'use_ipv6': self.use_ipv6, |
494 # allowed_subnet_pool |
568 'agent_conf': self.conf, |
495 iport_allow_pname = \ |
569 'interface_driver': self.driver, |
496 self._get_ippool_name(internal_port['mac_address'], '0') |
570 } |
497 ri.ipfilters_manager.add_ippool(iport_allow_pname, |
571 ri = SolarisRouterInfo(*args, **kwargs) |
498 [port_subnet]) |
572 registry.notify(resources.ROUTER, events.BEFORE_CREATE, |
499 else: |
573 self, router=ri) |
500 block_subnets.append(internal_port['subnet']['cidr']) |
574 |
501 iport_block_pname = \ |
575 self.router_info[router_id] = ri |
502 self._get_ippool_name(internal_port['mac_address']) |
576 |
503 ri.ipfilters_manager.add_ippool(iport_block_pname, |
577 ri.initialize(self.process_monitor) |
504 [port_subnet]) |
|
505 # update the new port's pool with other ports' subnet |
|
506 ri.ipfilters_manager.add_ippool(block_pname, block_subnets) |
|
507 if self.conf.allow_forwarding_between_networks: |
|
508 ri.ipfilters_manager.add_ippool(allow_pname, allow_subnets) |
|
509 |
|
510 # now setup the IPF rules |
|
511 rules = ['block in quick on %s from %s to pool/%d' % |
|
512 (internal_dlname, port_subnet, block_pname)] |
|
513 # pass in packets between networks that belong to same tenant |
|
514 if self.conf.allow_forwarding_between_networks: |
|
515 rules.append('pass in quick on %s from %s to pool/%d' % |
|
516 (internal_dlname, port_subnet, allow_pname)) |
|
517 # if the external gateway is already setup for the shared router, |
|
518 # then we need to add Policy Based Routing (PBR) for this internal |
|
519 # network |
|
520 ex_gw_port = ri.ex_gw_port |
|
521 ex_gw_ip = (ex_gw_port['subnet']['gateway_ip'] if ex_gw_port else None) |
|
522 if ex_gw_ip: |
|
523 external_dlname = self.get_external_device_name(ex_gw_port['id']) |
|
524 rules.append('pass in on %s to %s:%s from any to !%s' % |
|
525 (internal_dlname, external_dlname, ex_gw_ip, |
|
526 port_subnet)) |
|
527 |
|
528 ipversion = netaddr.IPNetwork(port_subnet).version |
|
529 ri.ipfilters_manager.add_ipf_rules(rules, ipversion) |
|
530 |
|
531 # if metadata proxy is enabled, then add the necessary |
|
532 # IP NAT rules to forward the metadata requests to the |
|
533 # metadata proxy server |
|
534 if self.conf.enable_metadata_proxy and ipversion == 4: |
|
535 # TODO(gmoodalb): when IP Filter allows redirection of packets |
|
536 # to loopback IP address, then we need to add an IPF rule allowing |
|
537 # only packets destined to 127.0.0.1:9697 to |
|
538 # neutron-ns-metadata-proxy server |
|
539 rules = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' % |
|
540 (internal_dlname, port['fixed_ips'][0]['ip_address'], |
|
541 self.conf.metadata_port)] |
|
542 ri.ipfilters_manager.add_nat_rules(rules) |
|
543 |
|
544 def internal_network_removed(self, ri, port): |
|
545 internal_dlname = self.get_internal_device_name(port['id']) |
|
546 port_subnet = port['subnet']['cidr'] |
|
547 # remove all the IP filter rules that we added during |
|
548 # internal network addition |
|
549 block_pname = self._get_ippool_name(port['mac_address']) |
|
550 rules = ['block in quick on %s from %s to pool/%d' % |
|
551 (internal_dlname, port_subnet, block_pname)] |
|
552 if self.conf.allow_forwarding_between_networks: |
|
553 allow_pname = self._get_ippool_name(port['mac_address'], '0') |
|
554 rules.append('pass in quick on %s from %s to pool/%d' % |
|
555 (internal_dlname, port_subnet, allow_pname)) |
|
556 |
|
557 # remove all the IP filter rules that we added during |
|
558 # external network addition |
|
559 ex_gw_port = ri.ex_gw_port |
|
560 ex_gw_ip = (ex_gw_port['subnet']['gateway_ip'] if ex_gw_port else None) |
|
561 if ex_gw_ip: |
|
562 external_dlname = self.get_external_device_name(ex_gw_port['id']) |
|
563 rules.append('pass in on %s to %s:%s from any to !%s' % |
|
564 (internal_dlname, external_dlname, ex_gw_ip, |
|
565 port_subnet)) |
|
566 ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version |
|
567 ri.ipfilters_manager.remove_ipf_rules(rules, ipversion) |
|
568 |
|
569 # remove the ippool |
|
570 ri.ipfilters_manager.remove_ippool(block_pname, None) |
|
571 if self.conf.allow_forwarding_between_networks: |
|
572 ri.ipfilters_manager.remove_ippool(allow_pname, None) |
|
573 |
|
574 for internal_port in ri.internal_ports: |
|
575 if (self.conf.allow_forwarding_between_networks and |
|
576 internal_port['tenant_id'] == port['tenant_id']): |
|
577 iport_allow_pname = \ |
|
578 self._get_ippool_name(internal_port['mac_address'], '0') |
|
579 ri.ipfilters_manager.remove_ippool(iport_allow_pname, |
|
580 [port_subnet]) |
|
581 else: |
|
582 iport_block_pname = \ |
|
583 self._get_ippool_name(internal_port['mac_address']) |
|
584 ri.ipfilters_manager.remove_ippool(iport_block_pname, |
|
585 [port_subnet]) |
|
586 |
|
587 # if metadata proxy is enabled, then remove the IP NAT rules that |
|
588 # were added while adding the internal network |
|
589 if self.conf.enable_metadata_proxy and ipversion == 4: |
|
590 rules = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' % |
|
591 (internal_dlname, port['fixed_ips'][0]['ip_address'], |
|
592 self.conf.metadata_port)] |
|
593 ri.ipfilters_manager.remove_nat_rules(rules) |
|
594 |
|
595 if net_lib.Datalink.datalink_exists(internal_dlname): |
|
596 self.driver.fini_l3(internal_dlname) |
|
597 self.driver.unplug(internal_dlname) |
|
598 |
|
599 # remove the EVS VPort associated with internal network |
|
600 cmd = ['/usr/sbin/evsadm', 'remove-vport', '-T', port['tenant_id'], |
|
601 '%s/%s' % (port['network_id'], port['id'])] |
|
602 try: |
|
603 utils.execute(cmd) |
|
604 except Exception as err: |
|
605 LOG.error(_("Failed to delete the EVS VPort associated with " |
|
606 "internal network: %s") % err) |
|
607 |
|
608 def routes_updated(self, ri): |
|
609 pass |
|