def ensure_mesh(self): with db.get_object_lock(self, ttl=120, op='Network ensure mesh'): # Ensure network was not deleted whilst waiting for the lock. if self.is_dead(): raise DeadNetwork('network=%s' % self) removed = [] added = [] instances = [] for iface in db.get_network_interfaces(self.db_entry['uuid']): if not iface['instance_uuid'] in instances: instances.append(iface['instance_uuid']) node_fqdns = [] for inst in instances: i = db.get_instance(inst) if not i: continue if not i['node']: continue if not i['node'] in node_fqdns: node_fqdns.append(i['node']) # NOTE(mikal): why not use DNS here? Well, DNS might be outside # the control of the deployer if we're running in a public cloud # as an overlay cloud... node_ips = [config.NETWORK_NODE_IP] for fqdn in node_fqdns: ip = db.get_node(fqdn)['ip'] if ip not in node_ips: node_ips.append(ip) discovered = list(self.discover_mesh()) LOG.withObj(self).withField( 'discovered', discovered).debug('Discovered mesh elements') for node in discovered: if node in node_ips: node_ips.remove(node) else: self._remove_mesh_element(node) removed.append(node) for node in node_ips: self._add_mesh_element(node) added.append(node) if removed: db.add_event('network', self.db_entry['uuid'], 'remove mesh elements', None, None, ' '.join(removed)) if added: db.add_event('network', self.db_entry['uuid'], 'add mesh elements', None, None, ' '.join(added))
def remove_dhcp(self): if util.is_network_node(): subst = self.subst_dict() with util.RecordedOperation('remove dhcp', self): with db.get_object_lock(self, ttl=120, op='Network remove DHCP'): d = dhcp.DHCP(self, subst['vx_veth_inner']) d.remove_dhcpd() else: db.enqueue('networknode', RemoveDHCPNetworkTask(self.db_entry['uuid'])) db.add_event('network', self.db_entry['uuid'], 'remove dhcp', 'enqueued', None, None)
def update_dhcp(self): if not self.db_entry['provide_dhcp']: return if util.is_network_node(): subst = self.subst_dict() with util.RecordedOperation('update dhcp', self): with db.get_object_lock(self, ttl=120, op='Network update DHCP'): d = dhcp.DHCP(self, subst['vx_veth_inner']) d.restart_dhcpd() else: db.enqueue('networknode', UpdateDHCPNetworkTask(self.db_entry['uuid'])) db.add_event('network', self.db_entry['uuid'], 'update dhcp', 'enqueued', None, None)
def delete(self): subst = self.subst_dict() LOG.withFields(subst).debug('net.delete()') # Cleanup local node with db.get_object_lock(self, ttl=120, op='Network delete'): if util.check_for_interface(subst['vx_bridge']): with util.RecordedOperation('delete vxlan bridge', self): util.execute(None, 'ip link delete %(vx_bridge)s' % subst) if util.check_for_interface(subst['vx_interface']): with util.RecordedOperation('delete vxlan interface', self): util.execute(None, 'ip link delete %(vx_interface)s' % subst) # If this is the network node do additional cleanup if util.is_network_node(): if util.check_for_interface(subst['vx_veth_outer']): with util.RecordedOperation('delete router veth', self): util.execute( None, 'ip link delete %(vx_veth_outer)s' % subst) if util.check_for_interface(subst['physical_veth_outer']): with util.RecordedOperation('delete physical veth', self): util.execute( None, 'ip link delete %(physical_veth_outer)s' % subst) if os.path.exists('/var/run/netns/%(netns)s' % subst): with util.RecordedOperation('delete netns', self): util.execute(None, 'ip netns del %(netns)s' % subst) if self.db_entry['floating_gateway']: with db.get_lock('ipmanager', None, 'floating', ttl=120, op='Network delete'): ipm = db.get_ipmanager('floating') ipm.release(self.db_entry['floating_gateway']) db.persist_ipmanager('floating', ipm.save())
def deploy_nat(self): if not self.db_entry['provide_nat']: return subst = self.subst_dict() if not self.db_entry['floating_gateway']: with db.get_lock('ipmanager', None, 'floating', ttl=120, op='Network deploy NAT'): ipm = db.get_ipmanager('floating') self.db_entry[ 'floating_gateway'] = ipm.get_random_free_address() db.persist_ipmanager('floating', ipm.save()) self.persist_floating_gateway() # No lock because no data changing ipm = db.get_ipmanager('floating') subst['floating_router'] = ipm.get_address_at_index(1) subst['floating_gateway'] = self.db_entry['floating_gateway'] subst['floating_netmask'] = ipm.netmask with db.get_object_lock(self, ttl=120, op='Network deploy NAT'): # Ensure network was not deleted whilst waiting for the lock. if self.is_dead(): raise DeadNetwork('network=%s' % self) with util.RecordedOperation('enable virtual routing', self): addresses = util.get_interface_addresses( subst['netns'], subst['physical_veth_inner']) if not subst['floating_gateway'] in list(addresses): util.execute( None, '%(in_netns)s ip addr add ' '%(floating_gateway)s/%(floating_netmask)s ' 'dev %(physical_veth_inner)s' % subst) util.execute( None, '%(in_netns)s ip link set ' '%(physical_veth_inner)s up' % subst) default_routes = util.get_default_routes(subst['netns']) if default_routes != [subst['floating_router']]: if default_routes: for default_route in default_routes: util.execute( None, '%s route del default gw %s' % (subst['in_netns'], default_route)) util.execute( None, '%(in_netns)s route add default ' 'gw %(floating_router)s' % subst) if not util.nat_rules_for_ipblock(self.network_address): with util.RecordedOperation('enable nat', self): util.execute(None, 'echo 1 > /proc/sys/net/ipv4/ip_forward') util.execute( None, '%(in_netns)s iptables -A FORWARD ' '-o %(physical_veth_inner)s ' '-i %(vx_veth_inner)s -j ACCEPT' % subst) util.execute( None, '%(in_netns)s iptables -A FORWARD ' '-i %(physical_veth_inner)s ' '-o %(vx_veth_inner)s -j ACCEPT' % subst) util.execute( None, '%(in_netns)s iptables -t nat -A POSTROUTING ' '-s %(ipblock)s/%(netmask)s ' '-o %(physical_veth_inner)s ' '-j MASQUERADE' % subst)
def create(self): subst = self.subst_dict() with db.get_object_lock(self, ttl=120, op='Network create'): # Ensure network was not deleted whilst waiting for the lock. if self.is_dead(): raise DeadNetwork('network=%s' % self) if not util.check_for_interface(subst['vx_interface']): with util.RecordedOperation('create vxlan interface', self): util.create_interface( subst['vx_interface'], 'vxlan', 'id %(vx_id)s dev %(physical_interface)s dstport 0' % subst) util.execute( None, 'sysctl -w net.ipv4.conf.' '%(vx_interface)s.arp_notify=1' % subst) if not util.check_for_interface(subst['vx_bridge']): with util.RecordedOperation('create vxlan bridge', self): util.create_interface(subst['vx_bridge'], 'bridge', '') util.execute( None, 'ip link set %(vx_interface)s ' 'master %(vx_bridge)s' % subst) util.execute(None, 'ip link set %(vx_interface)s up' % subst) util.execute(None, 'ip link set %(vx_bridge)s up' % subst) util.execute( None, 'sysctl -w net.ipv4.conf.' '%(vx_bridge)s.arp_notify=1' % subst) util.execute(None, 'brctl setfd %(vx_bridge)s 0' % subst) util.execute(None, 'brctl stp %(vx_bridge)s off' % subst) util.execute(None, 'brctl setageing %(vx_bridge)s 0' % subst) if util.is_network_node(): if not os.path.exists('/var/run/netns/%(netns)s' % subst): with util.RecordedOperation('create netns', self): util.execute(None, 'ip netns add %(netns)s' % subst) if not util.check_for_interface(subst['vx_veth_outer']): with util.RecordedOperation('create router veth', self): util.create_interface( subst['vx_veth_outer'], 'veth', 'peer name %(vx_veth_inner)s' % subst) util.execute( None, 'ip link set %(vx_veth_inner)s netns %(netns)s' % subst) util.execute( None, 'brctl addif %(vx_bridge)s %(vx_veth_outer)s' % subst) util.execute(None, 'ip link set %(vx_veth_outer)s up' % subst) util.execute( None, '%(in_netns)s ip link set %(vx_veth_inner)s up' % subst) util.execute( None, '%(in_netns)s ip addr add %(router)s/%(netmask)s ' 'dev %(vx_veth_inner)s' % subst) if not util.check_for_interface(subst['physical_veth_outer']): with util.RecordedOperation('create physical veth', self): util.create_interface( subst['physical_veth_outer'], 'veth', 'peer name %(physical_veth_inner)s' % subst) util.execute( None, 'brctl addif %(physical_bridge)s ' '%(physical_veth_outer)s' % subst) util.execute( None, 'ip link set %(physical_veth_outer)s up' % subst) util.execute( None, 'ip link set %(physical_veth_inner)s ' 'netns %(netns)s' % subst) self.deploy_nat() self.update_dhcp() else: db.enqueue('networknode', DeployNetworkTask(self.db_entry['uuid'])) db.add_event('network', self.db_entry['uuid'], 'deploy', 'enqueued', None, None)