From ab2bed9ed60c5333a0f9ba3e679df9893781b72f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 10:39:52 +0200 Subject: Apply IP configuration to bridge regardless of whether it existed before. The fixes a race condition on hosts running both compute and network where, if compute got there first, it would set up the bridge, but not do IP configuration (because that's meant to happen on the network host), and when network came around, it would see the interface already there and not configure it further. --- nova/network/linux_net.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 41aeb5da7..9d5bd8495 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -118,15 +118,16 @@ def ensure_bridge(bridge, interface, net_attrs=None): # _execute("sudo brctl setageing %s 10" % bridge) _execute("sudo brctl stp %s off" % bridge) _execute("sudo brctl addif %s %s" % (bridge, interface)) - if net_attrs: - _execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \ - (bridge, - net_attrs['gateway'], - net_attrs['broadcast'], - net_attrs['netmask'])) - _confirm_rule("FORWARD --in-interface %s -j ACCEPT" % bridge) - else: - _execute("sudo ifconfig %s up" % bridge) + + if net_attrs: + _execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \ + (bridge, + net_attrs['gateway'], + net_attrs['broadcast'], + net_attrs['netmask'])) + _confirm_rule("FORWARD --in-interface %s -j ACCEPT" % bridge) + else: + _execute("sudo ifconfig %s up" % bridge) def get_dhcp_hosts(context, network_id): -- cgit From b4dbc4efa576af61ddc26d1c277237ad4bcdfcfa Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 12:07:55 +0200 Subject: Add db api methods for retrieving the networks for which a host is the designated network host. --- nova/db/api.py | 12 ++++++++++++ nova/db/sqlalchemy/api.py | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/nova/db/api.py b/nova/db/api.py index c1cb1953a..4657408db 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -554,3 +554,15 @@ def volume_update(context, volume_id, values): """ return IMPL.volume_update(context, volume_id, values) + + +################### + + +def host_get_networks(context, host): + """Return all networks for which the given host is the designated + network host + """ + return IMPL.host_get_networks(context, host) + + diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 2b0dd6ea6..6e6b0e3fc 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -848,3 +848,15 @@ def volume_update(_context, volume_id, values): for (key, value) in values.iteritems(): volume_ref[key] = value volume_ref.save(session=session) + + +################### + + +def host_get_networks(context, host): + session = get_session() + with session.begin(): + return session.query(models.Network + ).filter_by(deleted=False + ).filter_by(host=host + ).all() -- cgit From e70948dbec0b21664739b2b7cdb1cc3da92bd01b Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 12:08:40 +0200 Subject: Set up network at manager instantiation time to ensure we're ready to handle the networks we're already supposed to handle. --- nova/network/manager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nova/network/manager.py b/nova/network/manager.py index 191c1d364..c17823f1e 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -80,6 +80,10 @@ class NetworkManager(manager.Manager): network_driver = FLAGS.network_driver self.driver = utils.import_object(network_driver) super(NetworkManager, self).__init__(*args, **kwargs) + # Set up networking for the projects for which we're already + # the designated network host. + for network in self.db.host_get_networks(None, host=kwargs['host']): + self._on_set_network_host(None, network['id']) def set_network_host(self, context, project_id): """Safely sets the host of the projects network""" -- cgit From 47cccfc21dfd4c1acf74b6d84ced8abba8c40e76 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 12:14:20 +0200 Subject: Ensure dnsmasq can read updates to dnsmasq conffile. --- nova/network/linux_net.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 9d5bd8495..7d708968c 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -150,9 +150,14 @@ def update_dhcp(context, network_id): signal causing it to reload, otherwise spawn a new instance """ network_ref = db.network_get(context, network_id) - with open(_dhcp_file(network_ref['vlan'], 'conf'), 'w') as f: + + conffile = _dhcp_file(network_ref['vlan'], 'conf') + with open(conffile, 'w') as f: f.write(get_dhcp_hosts(context, network_id)) + # Make sure dnsmasq can actually read it (it setuid()s to "nobody") + os.chmod(conffile, 0644) + pid = _dnsmasq_pid_for(network_ref['vlan']) # if dnsmasq is already running, then tell it to reload -- cgit From 928df580e5973bc1fd3871a0aa31886302bb9268 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 13:03:29 +0200 Subject: Add a flag the specifies where to find nova-dhcpbridge. --- nova/network/linux_net.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7d708968c..bfa73dca0 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -28,6 +28,11 @@ from nova import flags from nova import utils +def _bin_file(script): + """Return the absolute path to scipt in the bin directory""" + return os.path.abspath(os.path.join(__file__, "../../../bin", script)) + + FLAGS = flags.FLAGS flags.DEFINE_string('dhcpbridge_flagfile', '/etc/nova/nova-dhcpbridge.conf', @@ -39,6 +44,8 @@ flags.DEFINE_string('public_interface', 'vlan1', 'Interface for public IP addresses') flags.DEFINE_string('bridge_dev', 'eth0', 'network device for bridges') +flags.DEFINE_string('dhcpbridge', _bin_file('nova-dhcpbridge'), + 'location of nova-dhcpbridge') DEFAULT_PORTS = [("tcp", 80), ("tcp", 22), ("udp", 1194), ("tcp", 443)] @@ -222,7 +229,7 @@ def _dnsmasq_cmd(net): ' --except-interface=lo', ' --dhcp-range=%s,static,120s' % net['dhcp_start'], ' --dhcp-hostsfile=%s' % _dhcp_file(net['vlan'], 'conf'), - ' --dhcp-script=%s' % _bin_file('nova-dhcpbridge'), + ' --dhcp-script=%s' % FLAGS.dhcpbridge, ' --leasefile-ro'] return ''.join(cmd) @@ -244,11 +251,6 @@ def _dhcp_file(vlan, kind): return os.path.abspath("%s/nova-%s.%s" % (FLAGS.networks_path, vlan, kind)) -def _bin_file(script): - """Return the absolute path to scipt in the bin directory""" - return os.path.abspath(os.path.join(__file__, "../../../bin", script)) - - def _dnsmasq_pid_for(vlan): """Returns he pid for prior dnsmasq instance for a vlan -- cgit From 04fa25e63bf37222d2b1cf88837f1c85cf944f54 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 27 Sep 2010 13:23:39 +0200 Subject: Only call _on_set_network_host on nova-network hosts. --- nova/network/manager.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index c17823f1e..2530f04b7 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -80,10 +80,13 @@ class NetworkManager(manager.Manager): network_driver = FLAGS.network_driver self.driver = utils.import_object(network_driver) super(NetworkManager, self).__init__(*args, **kwargs) - # Set up networking for the projects for which we're already - # the designated network host. - for network in self.db.host_get_networks(None, host=kwargs['host']): - self._on_set_network_host(None, network['id']) + # Host only gets passed if being instantiated as part of the network + # service. + if 'host' in kwargs: + # Set up networking for the projects for which we're already + # the designated network host. + for network in self.db.host_get_networks(None, host=kwargs['host']): + self._on_set_network_host(None, network['id']) def set_network_host(self, context, project_id): """Safely sets the host of the projects network""" -- cgit From afc782e0e80a71ac8d1eb2f1d70e67375ba62aca Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 28 Sep 2010 10:59:55 +0200 Subject: Make sure we also start dnsmasq on startup if we're managing networks. --- nova/network/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/network/manager.py b/nova/network/manager.py index 2530f04b7..20d4fe0f7 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -358,6 +358,7 @@ class VlanManager(NetworkManager): self.driver.ensure_vlan_bridge(network_ref['vlan'], network_ref['bridge'], network_ref) + self.driver.update_dhcp(context, network_id) @property def _bottom_reserved_ips(self): -- cgit From 687a90d6a7ad947c4a5851b1766a19209bb5e46f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 28 Sep 2010 11:09:40 +0200 Subject: Call out to 'sudo kill' instead of using os.kill. dnsmasq runs as root or nobody, nova may or may not be running as root, so os.kill won't work. --- nova/network/linux_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index bfa73dca0..50d2831c3 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -172,7 +172,7 @@ def update_dhcp(context, network_id): # TODO(ja): use "/proc/%d/cmdline" % (pid) to determine if pid refers # correct dnsmasq process try: - os.kill(pid, signal.SIGHUP) + _execute('sudo kill -HUP %d' % pid) return except Exception as exc: # pylint: disable-msg=W0703 logging.debug("Hupping dnsmasq threw %s", exc) @@ -240,7 +240,7 @@ def _stop_dnsmasq(network): if pid: try: - os.kill(pid, signal.SIGTERM) + _execute('sudo kill -TERM %d' % pid) except Exception as exc: # pylint: disable-msg=W0703 logging.debug("Killing dnsmasq threw %s", exc) -- cgit From 033c464882c3d74ecd863abde767f37e7ad6a956 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Sat, 2 Oct 2010 12:39:47 +0200 Subject: Make _dhcp_file ensure the existence of the directory containing the files it returns. --- nova/network/linux_net.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 95f7fe2d0..37f9c8253 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -274,6 +274,9 @@ def _stop_dnsmasq(network): def _dhcp_file(vlan, kind): """Return path to a pid, leases or conf file for a vlan""" + if not os.path.exists(FLAGS.networks_path): + os.makedirs(FLAGS.networks_path) + return os.path.abspath("%s/nova-%s.%s" % (FLAGS.networks_path, vlan, kind)) -- cgit From 5945291281f239bd928cea1833ee5a5b6c3df523 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 2 Oct 2010 12:42:09 +0100 Subject: Bug #653534: NameError on session_get in sqlalchemy.api.service_update Fix function call: session_get was meant to be service_get. --- nova/db/sqlalchemy/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 7f72f66b9..9a7c71a70 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -240,7 +240,7 @@ def service_create(context, values): def service_update(context, service_id, values): session = get_session() with session.begin(): - service_ref = session_get(context, service_id, session=session) + service_ref = service_get(context, service_id, session=session) for (key, value) in values.iteritems(): service_ref[key] = value service_ref.save(session=session) -- cgit From c66d550d208544799fdaf4646a846e9f9c0b6bc5 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 2 Oct 2010 13:11:33 +0100 Subject: Bug #653560: AttributeError in VlanManager.periodic_tasks Pass the correct context to db.fixed_ip_disassociate_all_by_timeout. --- nova/network/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index ef1d01138..9580479e5 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -230,7 +230,7 @@ class VlanManager(NetworkManager): now = datetime.datetime.utcnow() timeout = FLAGS.fixed_ip_disassociate_timeout time = now - datetime.timedelta(seconds=timeout) - num = self.db.fixed_ip_disassociate_all_by_timeout(self, + num = self.db.fixed_ip_disassociate_all_by_timeout(context, self.host, time) if num: -- cgit From 4e45f9472a95207153d32c88df8396c633c67a5d Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Sun, 3 Oct 2010 20:22:35 +0200 Subject: s/APIRequestContext/get_admin_context/ <-- sudo for request contexts. --- nova/tests/network_unittest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/tests/network_unittest.py b/nova/tests/network_unittest.py index 5370966d2..59b0a36e4 100644 --- a/nova/tests/network_unittest.py +++ b/nova/tests/network_unittest.py @@ -56,8 +56,8 @@ class NetworkTestCase(test.TrialTestCase): 'netuser', name)) # create the necessary network data for the project - user_context = context.APIRequestContext(project=self.projects[i], - user=self.user) + user_context = context.get_admin_context(user=self.user) + self.network.set_network_host(user_context, self.projects[i].id) instance_ref = self._create_instance(0) self.instance_id = instance_ref['id'] -- cgit