From 01b9d211e606ee0be221b27edae8aab1d35096ff Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 11:51:46 -0700 Subject: First round of changes for ha-flatdhcp. * added 'host' column to fixed_ips to allow associating with a host * added 'multi_host' column to network for multi_host possibility * moved extra db access from linux_net to manager * added host parameter to network calls --- nova/db/api.py | 19 ++++-- nova/db/sqlalchemy/api.py | 29 ++++++--- .../migrate_repo/versions/032_ha_network.py | 37 +++++++++++ nova/db/sqlalchemy/models.py | 1 + nova/exception.py | 5 ++ nova/network/api.py | 13 +++- nova/network/linux_net.py | 15 ++--- nova/network/manager.py | 73 +++++++++++++++------- 8 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py (limited to 'nova') diff --git a/nova/db/api.py b/nova/db/api.py index b7c5700e5..febe33374 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -332,13 +332,15 @@ def fixed_ip_associate(context, address, instance_id): return IMPL.fixed_ip_associate(context, address, instance_id) -def fixed_ip_associate_pool(context, network_id, instance_id): - """Find free ip in network and associate it to instance. +def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): + """Find free ip in network and associate it to instance or host. + If reserved is true, it will pull the ip from the reserved pool. Raises if one is not available. """ - return IMPL.fixed_ip_associate_pool(context, network_id, instance_id) + return IMPL.fixed_ip_associate_pool(context, network_id, + instance_id, host, reserved) def fixed_ip_create(context, values): @@ -361,9 +363,9 @@ def fixed_ip_get_all(context): return IMPL.fixed_ip_get_all(context) -def fixed_ip_get_all_by_host(context, host): - """Get all defined fixed ips used by a host.""" - return IMPL.fixed_ip_get_all_by_host(context, host) +def fixed_ip_get_all_by_instance_host(context, host): + """Get all allocated fixed ips filtered by instance host.""" + return IMPL.fixed_ip_get_all_instance_by_host(context, host) def fixed_ip_get_by_address(context, address): @@ -376,6 +378,11 @@ def fixed_ip_get_by_instance(context, instance_id): return IMPL.fixed_ip_get_by_instance(context, instance_id) +def fixed_ip_get_by_network_host(context, network_id, host): + """Get fixed ip for a host in a network.""" + return IMPL.fixed_ip_get_by_network_host(context, network_id, host) + + def fixed_ip_get_by_virtual_interface(context, vif_id): """Get fixed ips by virtual interface or raise if none exist.""" return IMPL.fixed_ip_get_by_virtual_interface(context, vif_id) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index ffd009513..6db142276 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -18,7 +18,6 @@ """ Implementation of SQLAlchemy backend. """ -import traceback import warnings from nova import db @@ -33,7 +32,6 @@ from sqlalchemy import or_ from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload_all -from sqlalchemy.sql import exists from sqlalchemy.sql import func from sqlalchemy.sql.expression import literal_column @@ -657,7 +655,7 @@ def fixed_ip_associate(context, address, instance_id): @require_admin_context -def fixed_ip_associate_pool(context, network_id, instance_id): +def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): session = get_session() with session.begin(): network_or_none = or_(models.FixedIp.network_id == network_id, @@ -677,9 +675,12 @@ def fixed_ip_associate_pool(context, network_id, instance_id): fixed_ip_ref.network = network_get(context, network_id, session=session) - fixed_ip_ref.instance = instance_get(context, - instance_id, - session=session) + if instance_id: + fixed_ip_ref.instance = instance_get(context, + instance_id, + session=session) + if host: + fixed_ip_ref.host = host session.add(fixed_ip_ref) return fixed_ip_ref['address'] @@ -735,7 +736,7 @@ def fixed_ip_get_all(context, session=None): @require_admin_context -def fixed_ip_get_all_by_host(context, host=None): +def fixed_ip_get_all_by_instance_host(context, host=None): session = get_session() result = session.query(models.FixedIp).\ @@ -784,6 +785,20 @@ def fixed_ip_get_by_instance(context, instance_id): return rv +@require_context +def fixed_ip_get_by_network_host(context, network_id, host): + session = get_session() + rv = session.query(models.FixedIp).\ + filter_by(network_id=network_id).\ + filter_by(host=host).\ + filter_by(deleted=False).\ + all() + if not rv: + raise exception.FixedIpNotFoundForNetworkHost(network_id=network_id, + host=host) + return rv + + @require_context def fixed_ip_get_by_virtual_interface(context, vif_id): session = get_session() diff --git a/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py b/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py new file mode 100644 index 000000000..316c36cbc --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py @@ -0,0 +1,37 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 MORITA Kazutaka. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy import Column, Table, MetaData, Boolean, String + +meta = MetaData() + +fixed_ips_host = Column('host', String(255)) + +networks_multi_host = Column('multi_host', Boolean, default=False) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + + # Add columns to existing tables + fixed_ips = Table('fixed_ips', meta, autoload=True) + fixed_ips.create_column(fixed_ips_host) + + networks = Table('networks', meta, autoload=True) + networks.create_column(networks_multi_host) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index d29d3d6f1..8c86870f0 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -543,6 +543,7 @@ class Network(BASE, NovaBase): injected = Column(Boolean, default=False) cidr = Column(String(255), unique=True) cidr_v6 = Column(String(255), unique=True) + multi_host = Column(Boolean, default=False) gateway_v6 = Column(String(255)) netmask_v6 = Column(String(255)) diff --git a/nova/exception.py b/nova/exception.py index a6776b64f..29a209c3e 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -377,6 +377,11 @@ class FixedIpNotFoundForInstance(FixedIpNotFound): message = _("Instance %(instance_id)s has zero fixed ips.") +class FixedIpNotFoundForNetworkHost(FixedIpNotFound): + message = _("Network host %(host)s has zero fixed ips " + "in network %(network_id)s.") + + class FixedIpNotFoundForVirtualInterface(FixedIpNotFound): message = _("Virtual interface %(vif_id)s has zero associated fixed ips.") diff --git a/nova/network/api.py b/nova/network/api.py index b2b96082b..c57394204 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -18,7 +18,6 @@ """Handles all requests relating to instances (guest vms).""" -from nova import db from nova import exception from nova import flags from nova import log as logging @@ -105,7 +104,10 @@ class API(base.Base): '(%(project)s)') % {'address': floating_ip['address'], 'project': context.project_id}) - host = fixed_ip['network']['host'] + if fixed_ip['network']['multi_gateway']: + host = fixed_ip['instance']['host'] + else: + host = fixed_ip['network']['host'] rpc.cast(context, self.db.queue_get_for(context, FLAGS.network_topic, host), {'method': 'associate_floating_ip', @@ -120,7 +122,10 @@ class API(base.Base): return if not floating_ip.get('fixed_ip'): raise exception.ApiError('Address is not associated.') - host = floating_ip['fixed_ip']['network']['host'] + if floating_ip['fixed_ip']['network']['multi_gateway']: + host = floating_ip['fixed_ip']['instance']['host'] + else: + host = floating_ip['fixed_ip']['network']['host'] rpc.call(context, self.db.queue_get_for(context, FLAGS.network_topic, host), {'method': 'disassociate_floating_ip', @@ -134,7 +139,9 @@ class API(base.Base): args = kwargs args['instance_id'] = instance['id'] args['project_id'] = instance['project_id'] + args['host'] = instance['host'] args['instance_type_id'] = instance['instance_type_id'] + return rpc.call(context, FLAGS.network_topic, {'method': 'allocate_for_instance', 'args': args}) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 283a5aca1..8d2bc5c0b 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -573,18 +573,16 @@ def get_dhcp_hosts(context, network_id): # configuration options (like dchp-range, vlan, ...) # aren't reloaded. @utils.synchronized('dnsmasq_start') -def update_dhcp(context, network_id): +def update_dhcp(context, network_ref): """(Re)starts a dnsmasq server for a given network. If a dnsmasq instance is already running then send a HUP signal causing it to reload, otherwise spawn a new instance. """ - network_ref = db.network_get(context, network_id) - conffile = _dhcp_file(network_ref['bridge'], 'conf') with open(conffile, 'w') as f: - f.write(get_dhcp_hosts(context, network_id)) + f.write(get_dhcp_hosts(context, network_ref['id'])) # Make sure dnsmasq can actually read it (it setuid()s to "nobody") os.chmod(conffile, 0644) @@ -612,9 +610,7 @@ def update_dhcp(context, network_id): @utils.synchronized('radvd_start') -def update_ra(context, network_id): - network_ref = db.network_get(context, network_id) - +def update_ra(context, network_ref): conffile = _ra_file(network_ref['bridge'], 'conf') with open(conffile, 'w') as f: conf_str = """ @@ -650,9 +646,6 @@ interface %s LOG.debug(_('Pid %d is stale, relaunching radvd'), pid) command = _ra_cmd(network_ref) _execute(*command) - db.network_update(context, network_id, - {'gateway_v6': - utils.get_my_linklocal(network_ref['bridge'])}) def _host_lease(fixed_ip_ref): @@ -704,7 +697,7 @@ def _dnsmasq_cmd(net): '--conf-file=%s' % FLAGS.dnsmasq_config_file, '--domain=%s' % FLAGS.dhcp_domain, '--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), - '--listen-address=%s' % net['gateway'], + '--listen-address=%s' % net['dhcp_listen'], '--except-interface=lo', '--dhcp-range=%s,static,120s' % net['dhcp_start'], '--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])), diff --git a/nova/network/manager.py b/nova/network/manager.py index d42bc8c4e..f60763eba 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -124,15 +124,17 @@ class RPCAllocateFixedIP(object): used since they share code to RPC.call allocate_fixed_ip on the correct network host to configure dnsmasq """ - def _allocate_fixed_ips(self, context, instance_id, networks): + def _allocate_fixed_ips(self, context, instance_id, host, networks): """Calls allocate_fixed_ip once for each network.""" green_pool = greenpool.GreenPool() for network in networks: - if network['host'] != self.host: + # NOTE(vish): if we are multi_gateway pass to the specified host + if not network['multi_gateway']: + host = network['host'] + if host != self.host: # need to call allocate_fixed_ip to correct network host - topic = self.db.queue_get_for(context, FLAGS.network_topic, - network['host']) + topic = self.db.queue_get_for(context, FLAGS.network_topic, host) args = {} args['instance_id'] = instance_id args['network_id'] = network['id'] @@ -298,6 +300,21 @@ class NetworkManager(manager.SchedulerDependentManager): super(NetworkManager, self).__init__(service_name='network', *args, **kwargs) + def _update_dchp(self, context, network_ref): + """Sets the listen address before sending update to the driver.""" + network_ref['dhcp_listen'] = self._get_dhcp_ip() + return self.driver.update_dhcp(context, network_ref) + + def _get_dhcp_ip(self, context, network_ref): + """Get the proper dhcp address to listen on. + + If it is a multi_host network, get the ip assigned to this host, + otherwise, assume that dhcp is listening on the gateway.""" + if network_ref['multi_host']: + return self.db.network_get_host_ip(context, FLAGS.host) + else: + return network_ref['gateway'] + def init_host(self): """Do any initialization that needs to be run if this is a standalone service. @@ -360,6 +377,7 @@ class NetworkManager(manager.SchedulerDependentManager): rpc.called by network_api """ instance_id = kwargs.pop('instance_id') + host = kwargs.pop('host') project_id = kwargs.pop('project_id') type_id = kwargs.pop('instance_type_id') admin_context = context.elevated() @@ -368,7 +386,7 @@ class NetworkManager(manager.SchedulerDependentManager): networks = self._get_networks_for_instance(admin_context, instance_id, project_id) self._allocate_mac_addresses(context, instance_id, networks) - self._allocate_fixed_ips(admin_context, instance_id, networks) + self._allocate_fixed_ips(admin_context, instance_id, host, networks) return self.get_instance_nw_info(context, instance_id, type_id) def deallocate_for_instance(self, context, **kwargs): @@ -475,10 +493,10 @@ class NetworkManager(manager.SchedulerDependentManager): random.randint(0x00, 0xff)] return ':'.join(map(lambda x: "%02x" % x, mac)) - def add_fixed_ip_to_instance(self, context, instance_id, network_id): + def add_fixed_ip_to_instance(self, context, instance_id, host, network_id): """Adds a fixed ip to an instance from specified network.""" networks = [self.db.network_get(context, network_id)] - self._allocate_fixed_ips(context, instance_id, networks) + self._allocate_fixed_ips(context, instance_id, host, networks) def allocate_fixed_ip(self, context, instance_id, network, **kwargs): """Gets a fixed ip from the pool.""" @@ -540,8 +558,9 @@ class NetworkManager(manager.SchedulerDependentManager): # means there will stale entries in the conf file # the code below will update the file if necessary if FLAGS.update_dhcp_on_disassociate: - network = self.db.fixed_ip_get_network(context, address) - self.driver.update_dhcp(context, network['id']) + network_ref = self.db.fixed_ip_get_network(context, address) + network_ref['dhcp_listen'] = self._get_dhcp_ip(context, network_ref) + self._update_dhcp(context, network_ref) def create_networks(self, context, label, cidr, num_networks, network_size, cidr_v6, gateway_v6, bridge, @@ -637,7 +656,7 @@ class NetworkManager(manager.SchedulerDependentManager): 'address': address, 'reserved': reserved}) - def _allocate_fixed_ips(self, context, instance_id, networks): + def _allocate_fixed_ips(self, context, instance_id, host, networks): """Calls allocate_fixed_ip once for each network.""" raise NotImplementedError() @@ -684,7 +703,7 @@ class FlatManager(NetworkManager): timeout_fixed_ips = False - def _allocate_fixed_ips(self, context, instance_id, networks): + def _allocate_fixed_ips(self, context, instance_id, host, networks): """Calls allocate_fixed_ip once for each network.""" for network in networks: self.allocate_fixed_ip(context, instance_id, network) @@ -738,8 +757,9 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): """ networks = db.network_get_all_by_instance(context, instance_id) for network in networks: - self.driver.ensure_bridge(network['bridge'], - network['bridge_interface']) + if not network['multi_host']: + self.driver.ensure_bridge(network['bridge'], + network['bridge_interface']) def allocate_fixed_ip(self, context, instance_id, network): """Allocate flat_network fixed_ip, then setup dhcp for this network.""" @@ -747,7 +767,7 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): instance_id, network) if not FLAGS.fake_network: - self.driver.update_dhcp(context, network['id']) + self._update_dhcp(context, network) def _on_set_network_host(self, context, network_id): """Called when this host becomes the host for a project.""" @@ -759,9 +779,13 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): network['bridge_interface'], network) if not FLAGS.fake_network: - self.driver.update_dhcp(context, network_id) + network_ref = self.db.network_get(context, network_id) + self._update_dhcp(context, network_ref) if(FLAGS.use_ipv6): - self.driver.update_ra(context, network_id) + self.driver.update_ra(context, network_ref) + gateway = utils.get_my_linklocal(network_ref['bridge']) + self.db.network_update(context, network_id, + {'gateway_v6': gateway}) class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): @@ -810,7 +834,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): 'virtual_interface_id': vif['id']} self.db.fixed_ip_update(context, address, values) if not FLAGS.fake_network: - self.driver.update_dhcp(context, network['id']) + self._update_dhcp(context, network) def add_network_to_project(self, context, project_id): """Force adds another network to a project.""" @@ -822,9 +846,10 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): """ networks = self.db.network_get_all_by_instance(context, instance_id) for network in networks: - self.driver.ensure_vlan_bridge(network['vlan'], - network['bridge'], - network['bridge_interface']) + if not network['multi_host']: + self.driver.ensure_vlan_bridge(network['vlan'], + network['bridge'], + network['bridge_interface']) def _get_networks_for_instance(self, context, instance_id, project_id): """Determine which networks an instance should connect to.""" @@ -874,9 +899,13 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): network['vpn_public_port'], network['vpn_private_address']) if not FLAGS.fake_network: - self.driver.update_dhcp(context, network_id) + network_ref = self.db.network_get(context, network_id) + self._update_dhcp(context, network_ref) if(FLAGS.use_ipv6): - self.driver.update_ra(context, network_id) + self.driver.update_ra(context, network_ref) + gateway = utils.get_my_linklocal(network_ref['bridge']) + self.db.network_update(context, network_id, + {'gateway_v6': gateway}) @property def _bottom_reserved_ips(self): -- cgit From 9a8254ef2751e1b7502107a9c6afe05ea1e2efd4 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 12:00:11 -0700 Subject: it is multi_host not multi_gateway --- nova/network/api.py | 6 ++++-- nova/network/manager.py | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'nova') diff --git a/nova/network/api.py b/nova/network/api.py index c57394204..c0f0fb8eb 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -104,7 +104,8 @@ class API(base.Base): '(%(project)s)') % {'address': floating_ip['address'], 'project': context.project_id}) - if fixed_ip['network']['multi_gateway']: + # NOTE(vish): if we are multi_host, send to the instances host + if fixed_ip['network']['multi_host']: host = fixed_ip['instance']['host'] else: host = fixed_ip['network']['host'] @@ -122,7 +123,8 @@ class API(base.Base): return if not floating_ip.get('fixed_ip'): raise exception.ApiError('Address is not associated.') - if floating_ip['fixed_ip']['network']['multi_gateway']: + # NOTE(vish): if we are multi_host, send to the instances host + if floating_ip['fixed_ip']['network']['multi_host']: host = floating_ip['fixed_ip']['instance']['host'] else: host = floating_ip['fixed_ip']['network']['host'] diff --git a/nova/network/manager.py b/nova/network/manager.py index f60763eba..84d2cbbcb 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -49,7 +49,6 @@ import datetime import math import netaddr import socket -import pickle from eventlet import greenpool from nova import context @@ -129,8 +128,8 @@ class RPCAllocateFixedIP(object): green_pool = greenpool.GreenPool() for network in networks: - # NOTE(vish): if we are multi_gateway pass to the specified host - if not network['multi_gateway']: + # NOTE(vish): if we are not multi_host pass to the network host + if not network['multi_host']: host = network['host'] if host != self.host: # need to call allocate_fixed_ip to correct network host -- cgit From 8d2f3f26e8089020616312334689f1c594a67b4f Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 12:16:46 -0700 Subject: make sure to filter out ips associated by host and add some sync for allocating ip to host --- nova/db/sqlalchemy/api.py | 1 + nova/network/manager.py | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 6db142276..7065de00f 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -665,6 +665,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): filter_by(reserved=False).\ filter_by(deleted=False).\ filter_by(instance=None).\ + filter_by(host=None).\ with_lockmode('update').\ first() # NOTE(vish): if with_lockmode isn't supported, as in sqlite, diff --git a/nova/network/manager.py b/nova/network/manager.py index 84d2cbbcb..55f81da9e 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -310,7 +310,18 @@ class NetworkManager(manager.SchedulerDependentManager): If it is a multi_host network, get the ip assigned to this host, otherwise, assume that dhcp is listening on the gateway.""" if network_ref['multi_host']: - return self.db.network_get_host_ip(context, FLAGS.host) + + @utils.synchronized('get_dhcp') + def _sync_get_dhcp_ip(): + try: + return self.db.fixed_ip_get_by_network_host(context, + FLAGS.host) + except exception.FixedIpNotFoundForNetworkHost: + return self.db.fixed_ip_associate_pool(context.elevated(), + network_ref['id'], + host=FLAGS.host) + return _sync_get_dhcp_ip() + else: return network_ref['gateway'] -- cgit From 9b5adcbe92a4f7e0f9b1592be123c58f743def34 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 15:55:16 -0700 Subject: pass in dhcp server address, fix a bunch of bugs --- nova/compute/manager.py | 17 ++++++++------- nova/db/api.py | 2 +- nova/db/sqlalchemy/api.py | 3 ++- nova/db/sqlalchemy/models.py | 1 + nova/network/linux_net.py | 4 ++-- nova/network/manager.py | 47 ++++++++++++++++++++++++++++------------- nova/virt/libvirt/connection.py | 3 +-- 7 files changed, 48 insertions(+), 29 deletions(-) (limited to 'nova') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index bbbddde0a..b198adc97 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -77,8 +77,6 @@ flags.DEFINE_integer('live_migration_retry_count', 30, flags.DEFINE_integer("rescue_timeout", 0, "Automatically unrescue an instance after N seconds." " Set to 0 to disable.") -flags.DEFINE_bool('auto_assign_floating_ip', False, - 'Autoassigning floating ip to VM') flags.DEFINE_integer('host_state_interval', 120, 'Interval in seconds for querying the host status') @@ -268,16 +266,19 @@ class ComputeManager(manager.SchedulerDependentManager): """Launch a new instance with specified options.""" context = context.elevated() instance = self.db.instance_get(context, instance_id) - instance.injected_files = kwargs.get('injected_files', []) - instance.admin_pass = kwargs.get('admin_password', None) if instance['name'] in self.driver.list_instances(): raise exception.Error(_("Instance has already been created")) LOG.audit(_("instance %s: starting..."), instance_id, context=context) - self.db.instance_update(context, - instance_id, - {'host': self.host, 'launched_on': self.host}) - + updates = {} + updates['host'] = self.host + updates['launched_on'] = self.host + # NOTE(vish): used by virt but not in database + updates['injected_files'] = kwargs.get('injected_files', []) + updates['admin_pass'] = kwargs.get('admin_password', None) + instance = self.db.instance_update(context, + instance_id, + updates) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, diff --git a/nova/db/api.py b/nova/db/api.py index febe33374..ee4cbad57 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -340,7 +340,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): """ return IMPL.fixed_ip_associate_pool(context, network_id, - instance_id, host, reserved) + instance_id, host) def fixed_ip_create(context, values): diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 7065de00f..9c138d2fd 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -683,6 +683,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): if host: fixed_ip_ref.host = host session.add(fixed_ip_ref) + LOG.warn("gave address %s to %s, %s", fixed_ip_ref['address'], instance_id, host) return fixed_ip_ref['address'] @@ -793,7 +794,7 @@ def fixed_ip_get_by_network_host(context, network_id, host): filter_by(network_id=network_id).\ filter_by(host=host).\ filter_by(deleted=False).\ - all() + first() if not rv: raise exception.FixedIpNotFoundForNetworkHost(network_id=network_id, host=host) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 8c86870f0..639941dc8 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -602,6 +602,7 @@ class FixedIp(BASE, NovaBase): # leased means dhcp bridge has leased the ip leased = Column(Boolean, default=False) reserved = Column(Boolean, default=False) + host = Column(String(255)) class FloatingIp(BASE, NovaBase): diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 8d2bc5c0b..0a7a62510 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -497,7 +497,7 @@ def ensure_bridge(bridge, interface, net_attrs=None): suffix = net_attrs['cidr'].rpartition('/')[2] out, err = _execute('sudo', 'ip', 'addr', 'add', '%s/%s' % - (net_attrs['gateway'], suffix), + (net_attrs['dhcp_server'], suffix), 'brd', net_attrs['broadcast'], 'dev', @@ -697,7 +697,7 @@ def _dnsmasq_cmd(net): '--conf-file=%s' % FLAGS.dnsmasq_config_file, '--domain=%s' % FLAGS.dhcp_domain, '--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), - '--listen-address=%s' % net['dhcp_listen'], + '--listen-address=%s' % net['dhcp_server'], '--except-interface=lo', '--dhcp-range=%s,static,120s' % net['dhcp_start'], '--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])), diff --git a/nova/network/manager.py b/nova/network/manager.py index 55f81da9e..ce631ce75 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -103,7 +103,8 @@ flags.DEFINE_integer('fixed_ip_disassociate_timeout', 600, 'Seconds after which a deallocated ip is disassociated') flags.DEFINE_integer('create_unique_mac_address_attempts', 5, 'Number of attempts to create unique mac address') - +flags.DEFINE_bool('auto_assign_floating_ip', False, + 'Autoassigning floating ip to VM') flags.DEFINE_bool('use_ipv6', False, 'use the ipv6') flags.DEFINE_string('network_host', socket.gethostname(), @@ -192,7 +193,7 @@ class FloatingIP(object): # which is currently the NetworkManager version # do this first so fixed ip is already allocated ips = super(FloatingIP, self).allocate_for_instance(context, **kwargs) - if hasattr(FLAGS, 'auto_assign_floating_ip'): + if FLAGS.auto_assign_floating_ip: # allocate a floating ip (public_ip is just the address string) public_ip = self.allocate_floating_ip(context, project_id) # set auto_assigned column to true for the floating ip @@ -299,9 +300,9 @@ class NetworkManager(manager.SchedulerDependentManager): super(NetworkManager, self).__init__(service_name='network', *args, **kwargs) - def _update_dchp(self, context, network_ref): + def _update_dhcp(self, context, network_ref): """Sets the listen address before sending update to the driver.""" - network_ref['dhcp_listen'] = self._get_dhcp_ip() + network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) return self.driver.update_dhcp(context, network_ref) def _get_dhcp_ip(self, context, network_ref): @@ -313,13 +314,18 @@ class NetworkManager(manager.SchedulerDependentManager): @utils.synchronized('get_dhcp') def _sync_get_dhcp_ip(): + network_id = network_ref['id'] try: - return self.db.fixed_ip_get_by_network_host(context, - FLAGS.host) + fip = self.db.fixed_ip_get_by_network_host(context, + network_id, + self.host) + return fip['address'] except exception.FixedIpNotFoundForNetworkHost: - return self.db.fixed_ip_associate_pool(context.elevated(), - network_ref['id'], - host=FLAGS.host) + addr = self.db.fixed_ip_associate_pool(context.elevated(), + network_id, + host=self.host) + return addr + return _sync_get_dhcp_ip() else: @@ -334,6 +340,11 @@ class NetworkManager(manager.SchedulerDependentManager): ctxt = context.get_admin_context() for network in self.db.network_get_all_by_host(ctxt, self.host): self._on_set_network_host(ctxt, network['id']) + for network in self.db.network_get_all(ctxt): + # NOTE(vish): multi_host networks need to be set on all boxes + if network['multi_host']: + self._on_set_network_host(ctxt, network['id']) + def periodic_tasks(self, context=None): """Tasks to be run at a periodic interval.""" @@ -349,7 +360,7 @@ class NetworkManager(manager.SchedulerDependentManager): LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num) # setup any new networks which have been created - self.set_network_hosts(context) + #self.set_network_hosts(context) def set_network_host(self, context, network_id): """Safely sets the host of the network.""" @@ -378,8 +389,8 @@ class NetworkManager(manager.SchedulerDependentManager): networks = self.db.network_get_all(context) # return only networks which are not vlan networks and have host set - return [network for network in networks if - not network['vlan'] and network['host']] + return [network for network in networks if not network['vlan'] + and network['host'] or network['multi_host']] def allocate_for_instance(self, context, **kwargs): """Handles allocating the various network resources for an instance. @@ -395,6 +406,7 @@ class NetworkManager(manager.SchedulerDependentManager): context=context) networks = self._get_networks_for_instance(admin_context, instance_id, project_id) + LOG.warn(networks) self._allocate_mac_addresses(context, instance_id, networks) self._allocate_fixed_ips(admin_context, instance_id, host, networks) return self.get_instance_nw_info(context, instance_id, type_id) @@ -464,6 +476,7 @@ class NetworkManager(manager.SchedulerDependentManager): info = { 'label': network['label'], 'gateway': network['gateway'], + 'dhcp_server': self._get_dhcp_ip(context, network), 'broadcast': network['broadcast'], 'mac': vif['address'], 'rxtx_cap': flavor['rxtx_cap'], @@ -569,7 +582,7 @@ class NetworkManager(manager.SchedulerDependentManager): # the code below will update the file if necessary if FLAGS.update_dhcp_on_disassociate: network_ref = self.db.fixed_ip_get_network(context, address) - network_ref['dhcp_listen'] = self._get_dhcp_ip(context, network_ref) + network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) self._update_dhcp(context, network_ref) def create_networks(self, context, label, cidr, num_networks, @@ -628,6 +641,7 @@ class NetworkManager(manager.SchedulerDependentManager): # robust solution would be to make them uniq per ip net['vpn_public_port'] = kwargs['vpn_start'] + index + net['multi_host'] = True # None if network with cidr or cidr_v6 already exists network = self.db.network_create_safe(context, net) @@ -785,6 +799,7 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): net['dhcp_start'] = FLAGS.flat_network_dhcp_start self.db.network_update(context, network_id, net) network = db.network_get(context, network_id) + network['dhcp_server'] = self._get_dhcp_ip(context, network) self.driver.ensure_bridge(network['bridge'], network['bridge_interface'], network) @@ -866,8 +881,9 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): # get networks associated with project networks = self.db.project_get_networks(context, project_id) - # return only networks which have host set - return [network for network in networks if network['host']] + # return only networks which have host set or are multi_host + return [network for network in networks + if network['host'] or network['multi_host']] def create_networks(self, context, **kwargs): """Create networks based on parameters.""" @@ -896,6 +912,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): db.network_update(context, network_id, net) else: address = network['vpn_public_address'] + network['dhcp_server'] = self._get_dhcp_ip(context, network) self.driver.ensure_vlan_bridge(network['vlan'], network['bridge'], network['bridge_interface'], diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 0c6eaab84..5e8fcdd2f 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -928,7 +928,6 @@ class LibvirtConnection(driver.ComputeDriver): def _get_nic_for_xml(self, network, mapping): # Assume that the gateway also acts as the dhcp server. - dhcp_server = mapping['gateway'] gateway6 = mapping.get('gateway6') mac_id = mapping['mac'].replace(':', '') @@ -951,7 +950,7 @@ class LibvirtConnection(driver.ComputeDriver): 'bridge_name': network['bridge'], 'mac_address': mapping['mac'], 'ip_address': mapping['ips'][0]['ip'], - 'dhcp_server': dhcp_server, + 'dhcp_server': mapping['dhcp_server'], 'extra_params': extra_params, } -- cgit From 8e1a74e5604e1569e314af67b72966122940330b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 16:06:20 -0700 Subject: filter the dhcp to only respond to requests from this host --- nova/network/linux_net.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'nova') diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 0a7a62510..848e40643 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -551,21 +551,27 @@ def ensure_bridge(bridge, interface, net_attrs=None): bridge) -def get_dhcp_leases(context, network_id): +def get_dhcp_leases(context, network_ref): """Return a network's hosts config in dnsmasq leasefile format.""" hosts = [] - for fixed_ip_ref in db.network_get_associated_fixed_ips(context, - network_id): - hosts.append(_host_lease(fixed_ip_ref)) + for fixed_ref in db.network_get_associated_fixed_ips(context, + network_ref['id']): + host = fixed_ref['instance']['host'] + if network_ref['multi_host'] and FLAGS.host != host: + continue + hosts.append(_host_lease(fixed_ref)) return '\n'.join(hosts) -def get_dhcp_hosts(context, network_id): +def get_dhcp_hosts(context, network_ref): """Get network's hosts config in dhcp-host format.""" hosts = [] - for fixed_ip_ref in db.network_get_associated_fixed_ips(context, - network_id): - hosts.append(_host_dhcp(fixed_ip_ref)) + for fixed_ref in db.network_get_associated_fixed_ips(context, + network_ref['id']): + host = fixed_ref['instance']['host'] + if network_ref['multi_host'] and FLAGS.host != host: + continue + hosts.append(_host_dhcp(fixed_ref)) return '\n'.join(hosts) @@ -582,7 +588,7 @@ def update_dhcp(context, network_ref): """ conffile = _dhcp_file(network_ref['bridge'], 'conf') with open(conffile, 'w') as f: - f.write(get_dhcp_hosts(context, network_ref['id'])) + f.write(get_dhcp_hosts(context, network_ref)) # Make sure dnsmasq can actually read it (it setuid()s to "nobody") os.chmod(conffile, 0644) -- cgit From 53213dc4cd0f6f940d707c5d5932f4af7e5f988a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 16:22:41 -0700 Subject: add ability to set multi_host in nova-manage and remove debugging issues --- nova/db/sqlalchemy/api.py | 1 - nova/network/manager.py | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 9c138d2fd..472513329 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -683,7 +683,6 @@ def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): if host: fixed_ip_ref.host = host session.add(fixed_ip_ref) - LOG.warn("gave address %s to %s, %s", fixed_ip_ref['address'], instance_id, host) return fixed_ip_ref['address'] diff --git a/nova/network/manager.py b/nova/network/manager.py index ce631ce75..d799d5346 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -86,6 +86,8 @@ flags.DEFINE_integer('num_networks', 1, 'Number of networks to support') flags.DEFINE_string('vpn_ip', '$my_ip', 'Public IP for the cloudpipe VPN servers') flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks') +flags.DEFINE_bool('multi_host', False, + 'Default value for multi_host in networks') flags.DEFINE_integer('network_size', 256, 'Number of addresses in each private subnet') flags.DEFINE_string('floating_range', '4.4.4.0/24', @@ -360,7 +362,7 @@ class NetworkManager(manager.SchedulerDependentManager): LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num) # setup any new networks which have been created - #self.set_network_hosts(context) + self.set_network_hosts(context) def set_network_host(self, context, network_id): """Safely sets the host of the network.""" @@ -585,7 +587,7 @@ class NetworkManager(manager.SchedulerDependentManager): network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) self._update_dhcp(context, network_ref) - def create_networks(self, context, label, cidr, num_networks, + def create_networks(self, context, label, cidr, multi_host, num_networks, network_size, cidr_v6, gateway_v6, bridge, bridge_interface, **kwargs): """Create networks based on parameters.""" @@ -604,6 +606,7 @@ class NetworkManager(manager.SchedulerDependentManager): net['bridge_interface'] = bridge_interface net['dns'] = FLAGS.flat_network_dns net['cidr'] = cidr + net['multi_host'] = multi_host net['netmask'] = str(project_net.netmask) net['gateway'] = str(project_net[1]) net['broadcast'] = str(project_net.broadcast) @@ -641,7 +644,6 @@ class NetworkManager(manager.SchedulerDependentManager): # robust solution would be to make them uniq per ip net['vpn_public_port'] = kwargs['vpn_start'] + index - net['multi_host'] = True # None if network with cidr or cidr_v6 already exists network = self.db.network_create_safe(context, net) -- cgit From 11dfe937bcfa542c985a977e9ff855f717e80e69 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 16:24:43 -0700 Subject: don't set network host for multi_host networks --- nova/network/manager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index d799d5346..83ab4dd72 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -378,8 +378,7 @@ class NetworkManager(manager.SchedulerDependentManager): """Set the network hosts for any networks which are unset.""" networks = self.db.network_get_all(context) for network in networks: - host = network['host'] - if not host: + if not network['multi_host'] and not network['host']: # return so worker will only grab 1 (to help scale flatter) return self.set_network_host(context, network['id']) -- cgit From 77b655cd16a265eb2b8fc369941d19890766e712 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 17:01:19 -0700 Subject: update tests --- nova/tests/__init__.py | 1 + nova/tests/test_network.py | 3 +++ 2 files changed, 4 insertions(+) (limited to 'nova') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index e4ed75d37..b885000e1 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -59,6 +59,7 @@ def setup(): network.create_networks(ctxt, label='test', cidr=FLAGS.fixed_range, + multi_host=FLAGS.multi_host, num_networks=FLAGS.num_networks, network_size=FLAGS.network_size, cidr_v6=FLAGS.fixed_range_v6, diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 6d5166019..390cdc003 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -44,6 +44,7 @@ class FakeModel(dict): networks = [{'id': 0, 'label': 'test0', 'injected': False, + 'multi_host': False, 'cidr': '192.168.0.0/24', 'cidr_v6': '2001:db8::/64', 'gateway_v6': '2001:db8::1', @@ -61,6 +62,7 @@ networks = [{'id': 0, {'id': 1, 'label': 'test1', 'injected': False, + 'multi_host': False, 'cidr': '192.168.1.0/24', 'cidr_v6': '2001:db9::/64', 'gateway_v6': '2001:db9::1', @@ -163,6 +165,7 @@ class FlatNetworkTestCase(test.TestCase): self.assertDictMatch(nw[0], check) check = {'broadcast': '192.168.%s.255' % i, + 'dhcp_server': '192.168.%s.1' % i, 'dns': 'DONTCARE', 'gateway': '192.168.%s.1' % i, 'gateway6': '2001:db%s::1' % i8, -- cgit From e24c1d998331444235480be241484b0408cdaf9e Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Jul 2011 17:07:44 -0700 Subject: fix libvirt test --- nova/tests/test_libvirt.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova') diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index f99e1713d..6e2ec7ed6 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -58,6 +58,7 @@ def _create_network_info(count=1, ipv6=None): 'cidr': fake_ip, 'cidr_v6': fake_ip} mapping = {'mac': fake, + 'dhcp_server': fake, 'gateway': fake, 'gateway6': fake, 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]} -- cgit From 0af41b8c50631252f0dfe0b11268beb3d5e49508 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 6 Jul 2011 12:58:04 -0700 Subject: removed extra comment --- nova/db/api.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova') diff --git a/nova/db/api.py b/nova/db/api.py index ee4cbad57..c9d5bc72b 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -335,7 +335,6 @@ def fixed_ip_associate(context, address, instance_id): def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None): """Find free ip in network and associate it to instance or host. - If reserved is true, it will pull the ip from the reserved pool. Raises if one is not available. """ -- cgit From 5ef4e6e318caa038f2af31a930f6b2b952176661 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 8 Jul 2011 18:28:25 -0700 Subject: cleaned up on set network host to _setup_network and made networks allocate ips dynamically --- nova/db/sqlalchemy/api.py | 2 + nova/network/api.py | 3 +- nova/network/linux_net.py | 1 + nova/network/manager.py | 184 ++++++++++++++++++---------------------------- 4 files changed, 75 insertions(+), 115 deletions(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 472513329..c22ece068 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1706,7 +1706,9 @@ def network_get_all_by_host(context, host): with session.begin(): return session.query(models.Network).\ filter_by(deleted=False).\ + join(models.Network.fixed_ips).\ filter_by(host=host).\ + filter_by(deleted=False).\ all() diff --git a/nova/network/api.py b/nova/network/api.py index c0f0fb8eb..38560b037 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -174,7 +174,8 @@ class API(base.Base): def get_instance_nw_info(self, context, instance): """Returns all network info related to an instance.""" args = {'instance_id': instance['id'], - 'instance_type_id': instance['instance_type_id']} + 'instance_type_id': instance['instance_type_id'], + 'host': instance['host']} return rpc.call(context, FLAGS.network_topic, {'method': 'get_instance_nw_info', 'args': args}) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 848e40643..a8ce1c16a 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -700,6 +700,7 @@ def _dnsmasq_cmd(net): cmd = ['sudo', '-E', 'dnsmasq', '--strict-order', '--bind-interfaces', + '--interface=%s' % net['bridge'], '--conf-file=%s' % FLAGS.dnsmasq_config_file, '--domain=%s' % FLAGS.dhcp_domain, '--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), diff --git a/nova/network/manager.py b/nova/network/manager.py index 83ab4dd72..8ef9c9a33 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -28,7 +28,6 @@ topologies. All of the network commands are issued to a subclass of :flat_network_bridge: Bridge device for simple network instances :flat_interface: FlatDhcp will bridge into this interface if set :flat_network_dns: Dns for simple network -:flat_network_dhcp_start: Dhcp start for FlatDhcp :vlan_start: First VLAN for private networks :vpn_ip: Public IP for the cloudpipe VPN servers :vpn_start: First Vpn port for private networks @@ -77,8 +76,6 @@ flags.DEFINE_bool('flat_injected', True, 'Whether to attempt to inject network setup into guest') flags.DEFINE_string('flat_interface', None, 'FlatDhcp will bridge into this interface if set') -flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2', - 'Dhcp start for FlatDhcp') flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') flags.DEFINE_string('vlan_interface', None, 'vlans will bridge into this interface if set') @@ -134,6 +131,11 @@ class RPCAllocateFixedIP(object): # NOTE(vish): if we are not multi_host pass to the network host if not network['multi_host']: host = network['host'] + # NOTE(vish): if there is no network host, set one + if host == None: + host = rpc.call(context, FLAGS.network_topic, + {'method': 'set_network_host', + 'args': {'network_ref': network}}) if host != self.host: # need to call allocate_fixed_ip to correct network host topic = self.db.queue_get_for(context, FLAGS.network_topic, host) @@ -302,51 +304,34 @@ class NetworkManager(manager.SchedulerDependentManager): super(NetworkManager, self).__init__(service_name='network', *args, **kwargs) - def _update_dhcp(self, context, network_ref): - """Sets the listen address before sending update to the driver.""" - network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) - return self.driver.update_dhcp(context, network_ref) - - def _get_dhcp_ip(self, context, network_ref): - """Get the proper dhcp address to listen on. - - If it is a multi_host network, get the ip assigned to this host, - otherwise, assume that dhcp is listening on the gateway.""" - if network_ref['multi_host']: - - @utils.synchronized('get_dhcp') - def _sync_get_dhcp_ip(): - network_id = network_ref['id'] - try: - fip = self.db.fixed_ip_get_by_network_host(context, - network_id, - self.host) - return fip['address'] - except exception.FixedIpNotFoundForNetworkHost: - addr = self.db.fixed_ip_associate_pool(context.elevated(), - network_id, - host=self.host) - return addr - - return _sync_get_dhcp_ip() + @utils.synchronized('get_dhcp') + def _get_dhcp_ip(self, context, network_ref, host=None): + """Get the proper dhcp address to listen on.""" + if not host: + host = self.host + network_id = network_ref['id'] + try: + fip = self.db.fixed_ip_get_by_network_host(context, + network_id, + host) + return fip['address'] + except exception.FixedIpNotFoundForNetworkHost: + elevated = context.elevated() + addr = self.db.fixed_ip_associate_pool(elevated, + network_id, + host=host) + return addr - else: - return network_ref['gateway'] def init_host(self): """Do any initialization that needs to be run if this is a standalone service. """ - # Set up this host for networks in which it's already - # the designated network host. + # NOTE(vish): Set up networks for which this host already has + # an ip address. ctxt = context.get_admin_context() for network in self.db.network_get_all_by_host(ctxt, self.host): - self._on_set_network_host(ctxt, network['id']) - for network in self.db.network_get_all(ctxt): - # NOTE(vish): multi_host networks need to be set on all boxes - if network['multi_host']: - self._on_set_network_host(ctxt, network['id']) - + self._setup_network(ctxt, network) def periodic_tasks(self, context=None): """Tasks to be run at a periodic interval.""" @@ -361,37 +346,21 @@ class NetworkManager(manager.SchedulerDependentManager): if num: LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num) - # setup any new networks which have been created - self.set_network_hosts(context) - - def set_network_host(self, context, network_id): + def set_network_host(self, context, network_ref): """Safely sets the host of the network.""" LOG.debug(_('setting network host'), context=context) host = self.db.network_set_host(context, - network_id, + network_ref['id'], self.host) - if host == self.host: - self._on_set_network_host(context, network_id) return host - def set_network_hosts(self, context): - """Set the network hosts for any networks which are unset.""" - networks = self.db.network_get_all(context) - for network in networks: - if not network['multi_host'] and not network['host']: - # return so worker will only grab 1 (to help scale flatter) - return self.set_network_host(context, network['id']) - def _get_networks_for_instance(self, context, instance_id, project_id): """Determine & return which networks an instance should connect to.""" # TODO(tr3buchet) maybe this needs to be updated in the future if # there is a better way to determine which networks # a non-vlan instance should connect to - networks = self.db.network_get_all(context) - - # return only networks which are not vlan networks and have host set - return [network for network in networks if not network['vlan'] - and network['host'] or network['multi_host']] + return [network for network in self.db.network_get_all(context) + if not network['vlan']] def allocate_for_instance(self, context, **kwargs): """Handles allocating the various network resources for an instance. @@ -410,7 +379,7 @@ class NetworkManager(manager.SchedulerDependentManager): LOG.warn(networks) self._allocate_mac_addresses(context, instance_id, networks) self._allocate_fixed_ips(admin_context, instance_id, host, networks) - return self.get_instance_nw_info(context, instance_id, type_id) + return self.get_instance_nw_info(context, instance_id, type_id, host) def deallocate_for_instance(self, context, **kwargs): """Handles deallocating various network resources for an instance. @@ -430,7 +399,7 @@ class NetworkManager(manager.SchedulerDependentManager): # deallocate vifs (mac addresses) self.db.virtual_interface_delete_by_instance(context, instance_id) - def get_instance_nw_info(self, context, instance_id, instance_type_id): + def get_instance_nw_info(self, context, instance_id, instance_type_id, host): """Creates network info list for instance. called by allocate_for_instance and netowrk_api @@ -474,10 +443,16 @@ class NetworkManager(manager.SchedulerDependentManager): 'cidr': network['cidr'], 'cidr_v6': network['cidr_v6'], 'injected': network['injected']} + if network['multi_host']: + dhcp_server = self._get_dhcp_ip(context, network, host) + else: + dhcp_server = self._get_dhcp_ip(context, + network, + network['host']) info = { 'label': network['label'], 'gateway': network['gateway'], - 'dhcp_server': self._get_dhcp_ip(context, network), + 'dhcp_server': dhcp_server, 'broadcast': network['broadcast'], 'mac': vif['address'], 'rxtx_cap': flavor['rxtx_cap'], @@ -537,6 +512,7 @@ class NetworkManager(manager.SchedulerDependentManager): values = {'allocated': True, 'virtual_interface_id': vif['id']} self.db.fixed_ip_update(context, address, values) + self._setup_network(context, network) return address def deallocate_fixed_ip(self, context, address, **kwargs): @@ -583,8 +559,7 @@ class NetworkManager(manager.SchedulerDependentManager): # the code below will update the file if necessary if FLAGS.update_dhcp_on_disassociate: network_ref = self.db.fixed_ip_get_network(context, address) - network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) - self._update_dhcp(context, network_ref) + self._setup_network(context, network_ref) def create_networks(self, context, label, cidr, multi_host, num_networks, network_size, cidr_v6, gateway_v6, bridge, @@ -685,8 +660,8 @@ class NetworkManager(manager.SchedulerDependentManager): """Calls allocate_fixed_ip once for each network.""" raise NotImplementedError() - def _on_set_network_host(self, context, network_id): - """Called when this host becomes the host for a network.""" + def _setup_network(self, context, network_ref): + """Sets up network on this host.""" raise NotImplementedError() def setup_compute_network(self, context, instance_id): @@ -746,12 +721,12 @@ class FlatManager(NetworkManager): """ pass - def _on_set_network_host(self, context, network_id): - """Called when this host becomes the host for a network.""" + def _setup_network(self, context, network_ref): + """Setup Network on this host.""" net = {} net['injected'] = FLAGS.flat_injected net['dns'] = FLAGS.flat_network_dns - self.db.network_update(context, network_id, net) + self.db.network_update(context, network_ref['id'], net) class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): @@ -786,31 +761,18 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): self.driver.ensure_bridge(network['bridge'], network['bridge_interface']) - def allocate_fixed_ip(self, context, instance_id, network): - """Allocate flat_network fixed_ip, then setup dhcp for this network.""" - address = super(FlatDHCPManager, self).allocate_fixed_ip(context, - instance_id, - network) - if not FLAGS.fake_network: - self._update_dhcp(context, network) - - def _on_set_network_host(self, context, network_id): - """Called when this host becomes the host for a project.""" - net = {} - net['dhcp_start'] = FLAGS.flat_network_dhcp_start - self.db.network_update(context, network_id, net) - network = db.network_get(context, network_id) - network['dhcp_server'] = self._get_dhcp_ip(context, network) - self.driver.ensure_bridge(network['bridge'], - network['bridge_interface'], - network) + def _setup_network(self, context, network_ref): + """Sets up network on this host.""" + network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) + self.driver.ensure_bridge(network_ref['bridge'], + network_ref['bridge_interface'], + network_ref) if not FLAGS.fake_network: - network_ref = self.db.network_get(context, network_id) - self._update_dhcp(context, network_ref) + self.driver.update_dhcp(context, network_ref) if(FLAGS.use_ipv6): self.driver.update_ra(context, network_ref) gateway = utils.get_my_linklocal(network_ref['bridge']) - self.db.network_update(context, network_id, + self.db.network_update(context, network_ref['id'], {'gateway_v6': gateway}) @@ -859,8 +821,8 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): values = {'allocated': True, 'virtual_interface_id': vif['id']} self.db.fixed_ip_update(context, address, values) - if not FLAGS.fake_network: - self._update_dhcp(context, network) + self._setup_network(context, network) + return address def add_network_to_project(self, context, project_id): """Force adds another network to a project.""" @@ -880,11 +842,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): def _get_networks_for_instance(self, context, instance_id, project_id): """Determine which networks an instance should connect to.""" # get networks associated with project - networks = self.db.project_get_networks(context, project_id) - - # return only networks which have host set or are multi_host - return [network for network in networks - if network['host'] or network['multi_host']] + return self.db.project_get_networks(context, project_id) def create_networks(self, context, **kwargs): """Create networks based on parameters.""" @@ -903,36 +861,34 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): NetworkManager.create_networks(self, context, vpn=True, **kwargs) - def _on_set_network_host(self, context, network_id): - """Called when this host becomes the host for a network.""" - network = self.db.network_get(context, network_id) - if not network['vpn_public_address']: + def _setup_network(self, context, network_ref): + """Sets up network on this host.""" + network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) + if not network_ref['vpn_public_address']: net = {} address = FLAGS.vpn_ip net['vpn_public_address'] = address - db.network_update(context, network_id, net) + network_ref = db.network_update(context, network_ref, net) else: - address = network['vpn_public_address'] - network['dhcp_server'] = self._get_dhcp_ip(context, network) - self.driver.ensure_vlan_bridge(network['vlan'], - network['bridge'], - network['bridge_interface'], - network) + address = network_ref['vpn_public_address'] + self.driver.ensure_vlan_bridge(network_ref['vlan'], + network_ref['bridge'], + network_ref['bridge_interface'], + network_ref) # NOTE(vish): only ensure this forward if the address hasn't been set # manually. if address == FLAGS.vpn_ip and hasattr(self.driver, "ensure_vlan_forward"): self.driver.ensure_vlan_forward(FLAGS.vpn_ip, - network['vpn_public_port'], - network['vpn_private_address']) + network_ref['vpn_public_port'], + network_ref['vpn_private_address']) if not FLAGS.fake_network: - network_ref = self.db.network_get(context, network_id) - self._update_dhcp(context, network_ref) + self.driver.update_dhcp(context, network_ref) if(FLAGS.use_ipv6): self.driver.update_ra(context, network_ref) gateway = utils.get_my_linklocal(network_ref['bridge']) - self.db.network_update(context, network_id, + self.db.network_update(context, network_ref['id'], {'gateway_v6': gateway}) @property -- cgit From 71cbb30cfaf9b38786949fbf6314f0284e9a7efc Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 8 Jul 2011 18:45:13 -0700 Subject: make sure that old networks get the same dhcp ip so we don't break existing deployments --- nova/db/sqlalchemy/api.py | 7 ++++++- nova/network/manager.py | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index c22ece068..8b7ab8cbd 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1704,10 +1704,15 @@ def network_get_all_by_instance(_context, instance_id): def network_get_all_by_host(context, host): session = get_session() with session.begin(): + # NOTE(vish): return networks that have host set + # or that have a fixed ip with host set + host_filter = or_(models.Network.host == host, + models.FixedIp.host == host) + return session.query(models.Network).\ filter_by(deleted=False).\ join(models.Network.fixed_ips).\ - filter_by(host=host).\ + filter(host_filter).\ filter_by(deleted=False).\ all() diff --git a/nova/network/manager.py b/nova/network/manager.py index 8ef9c9a33..dac42e7ec 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -307,6 +307,10 @@ class NetworkManager(manager.SchedulerDependentManager): @utils.synchronized('get_dhcp') def _get_dhcp_ip(self, context, network_ref, host=None): """Get the proper dhcp address to listen on.""" + # NOTE(vish): this is for compatibility + if not network_ref['multi_host']: + return network_ref['gateway'] + if not host: host = self.host network_id = network_ref['id'] @@ -317,11 +321,9 @@ class NetworkManager(manager.SchedulerDependentManager): return fip['address'] except exception.FixedIpNotFoundForNetworkHost: elevated = context.elevated() - addr = self.db.fixed_ip_associate_pool(elevated, + return self.db.fixed_ip_associate_pool(elevated, network_id, host=host) - return addr - def init_host(self): """Do any initialization that needs to be run if this is a -- cgit From 4858a276a4cb779de55d987f2b3c37db5bf24492 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 8 Jul 2011 18:58:24 -0700 Subject: fix tests --- nova/tests/__init__.py | 2 +- nova/tests/test_network.py | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) (limited to 'nova') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index b885000e1..7df6c06eb 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -69,7 +69,7 @@ def setup(): vpn_start=FLAGS.vpn_start, vlan_start=FLAGS.vlan_start) for net in db.network_get_all(ctxt): - network.set_network_host(ctxt, net['id']) + network.set_network_host(ctxt, net) cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db) shutil.copyfile(testdb, cleandb) diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 390cdc003..1740d4f54 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -123,20 +123,6 @@ class FlatNetworkTestCase(test.TestCase): self.network = network_manager.FlatManager(host=HOST) self.network.db = db - def test_set_network_hosts(self): - self.mox.StubOutWithMock(db, 'network_get_all') - self.mox.StubOutWithMock(db, 'network_set_host') - self.mox.StubOutWithMock(db, 'network_update') - - db.network_get_all(mox.IgnoreArg()).AndReturn([networks[0]]) - db.network_set_host(mox.IgnoreArg(), - networks[0]['id'], - mox.IgnoreArg()).AndReturn(HOST) - db.network_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) - self.mox.ReplayAll() - - self.network.set_network_hosts(None) - def test_get_instance_nw_info(self): self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance') self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') @@ -150,7 +136,7 @@ class FlatNetworkTestCase(test.TestCase): mox.IgnoreArg()).AndReturn(flavor) self.mox.ReplayAll() - nw_info = self.network.get_instance_nw_info(None, 0, 0) + nw_info = self.network.get_instance_nw_info(None, 0, 0, None) self.assertTrue(nw_info) -- cgit From 67e5492d6723a00b0ad5d7e8c44f5762a9b0a206 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 18 Jul 2011 12:16:10 -0700 Subject: fix issues that were breaking vlan mode --- nova/db/sqlalchemy/api.py | 4 +--- nova/network/manager.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 8b7ab8cbd..a90b61e39 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1480,8 +1480,6 @@ def network_associate(context, project_id, force=False): called by project_get_networks under certain conditions and network manager add_network_to_project() - only associates projects with networks that have configured hosts - only associate if the project doesn't already have a network or if force is True @@ -1497,7 +1495,6 @@ def network_associate(context, project_id, force=False): def network_query(project_filter): return session.query(models.Network).\ filter_by(deleted=False).\ - filter(models.Network.host != None).\ filter_by(project_id=project_filter).\ with_lockmode('update').\ first() @@ -1745,6 +1742,7 @@ def network_update(context, network_id, values): network_ref = network_get(context, network_id, session=session) network_ref.update(values) network_ref.save(session=session) + return network_ref ################### diff --git a/nova/network/manager.py b/nova/network/manager.py index dac42e7ec..4568d0fa7 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -870,7 +870,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): net = {} address = FLAGS.vpn_ip net['vpn_public_address'] = address - network_ref = db.network_update(context, network_ref, net) + network_ref = db.network_update(context, network_ref['id'], net) else: address = network_ref['vpn_public_address'] self.driver.ensure_vlan_bridge(network_ref['vlan'], -- cgit From 87434352e7dc165d269b5831af8ff690fcdbdb5b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 18 Jul 2011 17:17:30 -0700 Subject: change migration number --- .../migrate_repo/versions/032_ha_network.py | 37 ---------------------- .../migrate_repo/versions/033_ha_network.py | 37 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py (limited to 'nova') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py b/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py deleted file mode 100644 index 316c36cbc..000000000 --- a/nova/db/sqlalchemy/migrate_repo/versions/032_ha_network.py +++ /dev/null @@ -1,37 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 MORITA Kazutaka. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from sqlalchemy import Column, Table, MetaData, Boolean, String - -meta = MetaData() - -fixed_ips_host = Column('host', String(255)) - -networks_multi_host = Column('multi_host', Boolean, default=False) - - -def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; - # bind migrate_engine to your metadata - meta.bind = migrate_engine - - # Add columns to existing tables - fixed_ips = Table('fixed_ips', meta, autoload=True) - fixed_ips.create_column(fixed_ips_host) - - networks = Table('networks', meta, autoload=True) - networks.create_column(networks_multi_host) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py new file mode 100644 index 000000000..316c36cbc --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py @@ -0,0 +1,37 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 MORITA Kazutaka. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy import Column, Table, MetaData, Boolean, String + +meta = MetaData() + +fixed_ips_host = Column('host', String(255)) + +networks_multi_host = Column('multi_host', Boolean, default=False) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + + # Add columns to existing tables + fixed_ips = Table('fixed_ips', meta, autoload=True) + fixed_ips.create_column(fixed_ips_host) + + networks = Table('networks', meta, autoload=True) + networks.create_column(networks_multi_host) -- cgit From 89ead61d521c8f585732d50b8d3d31361d7c1d82 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 18 Jul 2011 17:26:38 -0700 Subject: fix bad merge --- nova/network/manager.py | 8 -------- 1 file changed, 8 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index a411ad9ff..360e08ceb 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -776,14 +776,6 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): self.driver.metadata_forward() - def allocate_fixed_ip(self, context, instance_id, network, **kwargs): - """Allocate flat_network fixed_ip, then setup dhcp for this network.""" - address = super(FlatDHCPManager, self).allocate_fixed_ip(context, - instance_id, - network) - if not FLAGS.fake_network: - self.driver.update_dhcp(context, network['id']) - def setup_compute_network(self, context, instance_id): """Sets up matching networks for compute hosts. -- cgit From 39701e13188275fc2f798a790e2edc4488ecb3e4 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 18 Jul 2011 17:35:14 -0700 Subject: missed the vpn kwarg in rpc --- nova/network/manager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index 360e08ceb..7a7520f5d 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -156,12 +156,13 @@ class RPCAllocateFixedIP(object): # wait for all of the allocates (if any) to finish green_pool.waitall() - def _rpc_allocate_fixed_ip(self, context, instance_id, network_id): + def _rpc_allocate_fixed_ip(self, context, instance_id, network_id, + **kwargs): """Sits in between _allocate_fixed_ips and allocate_fixed_ip to perform network lookup on the far side of rpc. """ network = self.db.network_get(context, network_id) - self.allocate_fixed_ip(context, instance_id, network) + self.allocate_fixed_ip(context, instance_id, network, **kwargs) class FloatingIP(object): -- cgit From cfa755c6f3bbcc3dd376d66b3722021ad4b4ec62 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 19 Jul 2011 10:00:00 -0700 Subject: add downgrade --- .../db/sqlalchemy/migrate_repo/versions/033_ha_network.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'nova') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py index 316c36cbc..3a5f7eba8 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 MORITA Kazutaka. +# Copyright (c) 2011 OpenStack, LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -25,13 +25,20 @@ networks_multi_host = Column('multi_host', Boolean, default=False) def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; - # bind migrate_engine to your metadata meta.bind = migrate_engine - # Add columns to existing tables fixed_ips = Table('fixed_ips', meta, autoload=True) fixed_ips.create_column(fixed_ips_host) networks = Table('networks', meta, autoload=True) networks.create_column(networks_multi_host) + + +def downgrade(migrate_engine): + meta.bind = migrate_engine + + fixed_ips = Table('fixed_ips', meta, autoload=True) + fixed_ips.drop_column(fixed_ips_host) + + networks = Table('networks', meta, autoload=True) + networks.drop_column(networks_multi_host) -- cgit From 36f8bd801bc8a7696e7850613747a5f7ae8c487a Mon Sep 17 00:00:00 2001 From: Adam Gandelman Date: Tue, 19 Jul 2011 10:19:10 -0700 Subject: Fix unchecked key reference to mappings['gateway6']. Fixes LP #807764. --- nova/virt/libvirt/connection.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 977bb7dfe..572be38d8 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -881,9 +881,12 @@ class LibvirtConnection(driver.ComputeDriver): address = mapping['ips'][0]['ip'] netmask = mapping['ips'][0]['netmask'] address_v6 = None + gateway_v6 = None + netmask_v6 = None if FLAGS.use_ipv6: address_v6 = mapping['ip6s'][0]['ip'] netmask_v6 = mapping['ip6s'][0]['netmask'] + gateway_v6 = mapping['gateway6'] net_info = {'name': 'eth%d' % ifc_num, 'address': address, 'netmask': netmask, @@ -891,7 +894,7 @@ class LibvirtConnection(driver.ComputeDriver): 'broadcast': mapping['broadcast'], 'dns': mapping['dns'], 'address_v6': address_v6, - 'gateway6': mapping['gateway6'], + 'gateway6': gateway_v6, 'netmask_v6': netmask_v6} nets.append(net_info) -- cgit From 1b423b464e0dd849d1a6dafde08b3c4420217151 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 20 Jul 2011 13:52:22 -0400 Subject: Set the status_int on fault wrapped exceptions. Fixes WSGI logging issues when faults are returned. Updated so that webob exceptions aren't used for the happy path (HTTP 200 responses). We now return a proper webob object response in these cases. This fixes issues where HTML/XML would get returned with the old style happy path exceptions. --- nova/api/openstack/consoles.py | 3 +- nova/api/openstack/contrib/multinic.py | 5 ++-- nova/api/openstack/contrib/volumes.py | 5 ++-- nova/api/openstack/faults.py | 1 + nova/api/openstack/servers.py | 49 ++++++++++++++++----------------- nova/tests/api/openstack/test_faults.py | 5 ++++ 6 files changed, 37 insertions(+), 31 deletions(-) (limited to 'nova') diff --git a/nova/api/openstack/consoles.py b/nova/api/openstack/consoles.py index 7a43fba96..9c7b37f0d 100644 --- a/nova/api/openstack/consoles.py +++ b/nova/api/openstack/consoles.py @@ -16,6 +16,7 @@ # under the License. from webob import exc +import webob from nova import console from nova import exception @@ -86,7 +87,7 @@ class Controller(object): int(id)) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def create_resource(): diff --git a/nova/api/openstack/contrib/multinic.py b/nova/api/openstack/contrib/multinic.py index 841061721..da8dcee5d 100644 --- a/nova/api/openstack/contrib/multinic.py +++ b/nova/api/openstack/contrib/multinic.py @@ -16,6 +16,7 @@ """The multinic extension.""" from webob import exc +import webob from nova import compute from nova import log as logging @@ -103,7 +104,7 @@ class Multinic(extensions.ExtensionDescriptor): except Exception, e: LOG.exception(_("Error in addFixedIp %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _remove_fixed_ip(self, input_dict, req, id): """Removes an IP from an instance.""" @@ -122,4 +123,4 @@ class Multinic(extensions.ExtensionDescriptor): except Exception, e: LOG.exception(_("Error in removeFixedIp %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) diff --git a/nova/api/openstack/contrib/volumes.py b/nova/api/openstack/contrib/volumes.py index e5e2c5b50..827e36097 100644 --- a/nova/api/openstack/contrib/volumes.py +++ b/nova/api/openstack/contrib/volumes.py @@ -16,6 +16,7 @@ """The volumes extension.""" from webob import exc +import webob from nova import compute from nova import exception @@ -104,7 +105,7 @@ class VolumeController(object): self.volume_api.delete(context, volume_id=id) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def index(self, req): """Returns a summary list of volumes.""" @@ -279,7 +280,7 @@ class VolumeAttachmentController(object): self.compute_api.detach_volume(context, volume_id=volume_id) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _items(self, req, server_id, entity_maker): """Returns a list of attachments, transformed through entity_maker.""" diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py index b9a23c126..24cde69e4 100644 --- a/nova/api/openstack/faults.py +++ b/nova/api/openstack/faults.py @@ -40,6 +40,7 @@ class Fault(webob.exc.HTTPException): def __init__(self, exception): """Create a Fault for the given webob.exc.exception.""" self.wrapped_exc = exception + self.status_int = exception.status_int @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 93f8e832c..3b3d0685d 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -17,6 +17,7 @@ import base64 import traceback from webob import exc +import webob from nova import compute from nova import db @@ -189,7 +190,7 @@ class Controller(object): except Exception, e: LOG.exception(_("Error in revert-resize %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _action_resize(self, input_dict, req, id): return exc.HTTPNotImplemented() @@ -207,7 +208,7 @@ class Controller(object): except Exception, e: LOG.exception(_("Error in reboot %s"), e) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _action_migrate(self, input_dict, req, id): try: @@ -215,7 +216,7 @@ class Controller(object): except Exception, e: LOG.exception(_("Error in migrate %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def lock(self, req, id): @@ -231,7 +232,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::lock %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def unlock(self, req, id): @@ -247,7 +248,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::unlock %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def get_lock(self, req, id): @@ -262,7 +263,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::get_lock %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def reset_network(self, req, id, body): @@ -277,7 +278,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::reset_network %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def inject_network_info(self, req, id, body): @@ -292,7 +293,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::inject_network_info %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def pause(self, req, id, body): @@ -304,7 +305,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::pause %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def unpause(self, req, id, body): @@ -316,7 +317,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("Compute.api::unpause %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def suspend(self, req, id, body): @@ -328,7 +329,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("compute.api::suspend %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def resume(self, req, id, body): @@ -340,7 +341,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("compute.api::resume %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def rescue(self, req, id): @@ -352,7 +353,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("compute.api::rescue %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def unrescue(self, req, id): @@ -364,7 +365,7 @@ class Controller(object): readable = traceback.format_exc() LOG.exception(_("compute.api::unrescue %s"), readable) return faults.Fault(exc.HTTPUnprocessableEntity()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def get_ajax_console(self, req, id): @@ -374,7 +375,7 @@ class Controller(object): int(id)) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def get_vnc_console(self, req, id): @@ -384,7 +385,7 @@ class Controller(object): int(id)) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) @scheduler_api.redirect_handler def diagnostics(self, req, id): @@ -416,7 +417,7 @@ class ControllerV10(Controller): self.compute_api.delete(req.environ['nova.context'], id) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _image_ref_from_req_data(self, data): return data['server']['imageId'] @@ -450,7 +451,7 @@ class ControllerV10(Controller): except Exception, e: LOG.exception(_("Error in resize %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _action_rebuild(self, info, request, instance_id): context = request.environ['nova.context'] @@ -470,9 +471,7 @@ class ControllerV10(Controller): LOG.debug(msg) return faults.Fault(exc.HTTPConflict(explanation=msg)) - response = exc.HTTPAccepted() - response.empty_body = True - return response + return webob.Response(status_int=202) def _get_server_admin_password(self, server): """ Determine the admin password for a server on creation """ @@ -519,7 +518,7 @@ class ControllerV11(Controller): msg = _("Invalid adminPass") return exc.HTTPBadRequest(explanation=msg) self.compute_api.set_admin_password(context, id, password) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _limit_items(self, items, req): return common.limited_by_marker(items, req) @@ -565,7 +564,7 @@ class ControllerV11(Controller): except Exception, e: LOG.exception(_("Error in resize %s"), e) return faults.Fault(exc.HTTPBadRequest()) - return exc.HTTPAccepted() + return webob.Response(status_int=202) def _action_rebuild(self, info, request, instance_id): context = request.environ['nova.context'] @@ -594,9 +593,7 @@ class ControllerV11(Controller): LOG.debug(msg) return faults.Fault(exc.HTTPConflict(explanation=msg)) - response = exc.HTTPAccepted() - response.empty_body = True - return response + return webob.Response(status_int=202) def get_default_xmlns(self, req): return common.XML_NS_V11 diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index 4d86ffb26..927009e77 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -139,3 +139,8 @@ class TestFaults(test.TestCase): self.assertEqual(resp.content_type, "application/xml") self.assertEqual(resp.status_int, 404) self.assertTrue('whut?' in resp.body) + + def test_fault_has_status_int(self): + """Ensure the status_int is set correctly on faults""" + fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='what?')) + self.assertEqual(fault.status_int, 400) -- cgit From a01afcd449d7f1f6ffd74d9ca314edcdbb9b155d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 20 Jul 2011 18:27:15 +0000 Subject: pep8 --- nova/network/manager.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index 7a7520f5d..34001657b 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -140,7 +140,9 @@ class RPCAllocateFixedIP(object): 'args': {'network_ref': network}}) if host != self.host: # need to call allocate_fixed_ip to correct network host - topic = self.db.queue_get_for(context, FLAGS.network_topic, host) + topic = self.db.queue_get_for(context, + FLAGS.network_topic, + host) args = {} args['instance_id'] = instance_id args['network_id'] = network['id'] @@ -414,7 +416,8 @@ class NetworkManager(manager.SchedulerDependentManager): # deallocate vifs (mac addresses) self.db.virtual_interface_delete_by_instance(context, instance_id) - def get_instance_nw_info(self, context, instance_id, instance_type_id, host): + def get_instance_nw_info(self, context, instance_id, + instance_type_id, host): """Creates network info list for instance. called by allocate_for_instance and netowrk_api -- cgit From 58a76cede01b6bb141d060636c21318db1712527 Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Wed, 20 Jul 2011 18:46:29 +0000 Subject: Make sure reset_network() call happens after we've determined the agent is running. --- nova/virt/xenapi/vmops.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index bade23889..419685a6f 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -311,6 +311,7 @@ class VMOps(object): _check_agent_version() _inject_files() _set_admin_password() + self.reset_network(instance, vm_ref) return True except Exception, exc: LOG.warn(exc) @@ -320,9 +321,6 @@ class VMOps(object): timer.f = _wait_for_boot - # call to reset network to configure network from xenstore - self.reset_network(instance, vm_ref) - return timer.start(interval=0.5, now=True) def _get_vm_opaque_ref(self, instance_or_vm): -- cgit From e3abccb611345d61584569114a4929e751de14ae Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 16:17:23 +0900 Subject: Combined bridige and vlan VIF driver to allow better transition for current Nova users --- nova/network/manager.py | 29 ++++++++++++++++++++++++++++- nova/virt/libvirt/vif.py | 46 +++++++++++++++++++++------------------------- 2 files changed, 49 insertions(+), 26 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index d11aa4135..25490bf39 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -478,7 +478,9 @@ class NetworkManager(manager.SchedulerDependentManager): 'mac': vif['address'], 'rxtx_cap': flavor['rxtx_cap'], 'dns': [network['dns']], - 'ips': [ip_dict(ip) for ip in network_IPs]} + 'ips': [ip_dict(ip) for ip in network_IPs], + 'create_bridge': self._create_bridge, + 'create_vlan': self._create_vlan} if network['cidr_v6']: info['ip6s'] = [ip6_dict()] # TODO(tr3buchet): handle ip6 routes here as well @@ -696,6 +698,16 @@ class NetworkManager(manager.SchedulerDependentManager): """Sets up network on this host.""" raise NotImplementedError() + @property + def _create_bridge(self): + """Indicate whether this manager requires VIF to create a bridge.""" + return False + + @property + def _create_vlan(self): + """Indicate whether this manager requires VIF to create a VLAN tag.""" + return False + class FlatManager(NetworkManager): """Basic network where no vlans are used. @@ -783,6 +795,11 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): self.db.network_update(context, network_ref['id'], {'gateway_v6': gateway}) + @property + def _create_bridge(self): + """Indicate whether this manager requires VIF to create a bridge.""" + return True + class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): """Vlan network with dhcp. @@ -899,3 +916,13 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): """Number of reserved ips at the top of the range.""" parent_reserved = super(VlanManager, self)._top_reserved_ips return parent_reserved + FLAGS.cnt_vpn_clients + + @property + def _create_bridge(self): + """Indicate whether this manager requires VIF to create a bridge.""" + return True + + @property + def _create_vlan(self): + """Indicate whether this manager requires VIF to create a VLAN tag.""" + return True diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index c43ce14e3..24634d7d2 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -19,20 +19,24 @@ """VIF drivers for libvirt.""" from nova import flags +from nova import log as logging from nova.network import linux_net from nova.virt.libvirt import netutils from nova import utils from nova.virt.vif import VIFDriver +LOG = logging.getLogger('nova.virt.libvirt.vif') + FLAGS = flags.FLAGS flags.DEFINE_string('libvirt_ovs_integration_bridge', 'br-int', 'Name of Integration Bridge used by Open vSwitch') -class LibvirtBridge(object): - """Linux bridge VIF for Libvirt.""" - def get_configurations(self, network, mapping): +class LibvirtBridgeDriver(VIFDriver): + """VIF driver for Linux bridge.""" + + def _get_configurations(self, network, mapping): """Get a dictionary of VIF configurations for bridge type.""" # Assume that the gateway also acts as the dhcp server. gateway6 = mapping.get('gateway6') @@ -66,32 +70,24 @@ class LibvirtBridge(object): return result - -class LibvirtBridgeDriver(VIFDriver, LibvirtBridge): - """VIF driver for Linux bridge.""" - def plug(self, instance, network, mapping): """Ensure that the bridge exists, and add VIF to it.""" - if not network.get('multi_host'): - linux_net.ensure_bridge(network['bridge'], - network['bridge_interface']) - return self.get_configurations(network, mapping) - - def unplug(self, instance, network, mapping): - pass - - -class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge): - """VIF driver for Linux bridge with VLAN.""" - - def plug(self, instance, network, mapping): - """Ensure that VLAN and bridge exist and add VIF to the bridge.""" - if not network.get('multi_host'): - linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'], - network['bridge_interface']) - return self.get_configurations(network, mapping) + if not network.get('multi_host') and mapping.get('create_bridge'): + if mapping.get('create_vlan'): + LOG.debug(_("Ensuring vlan %s and bridge %s") % + (network['vlan'], network['bridge'])) + linux_net.ensure_vlan_bridge(network['vlan'], + network['bridge'], + network['bridge_interface']) + else: + LOG.debug(_("Ensuring bridge %s") % network['bridge']) + linux_net.ensure_bridge(network['bridge'], + network['bridge_interface']) + + return self._get_configurations(network, mapping) def unplug(self, instance, network, mapping): + """No manual unplugging required.""" pass -- cgit From 3b32c0270d6f61e0164185757ed97c82bda25600 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 16:31:14 +0900 Subject: Fixed PEP8 issues --- nova/network/manager.py | 1 - nova/virt/driver.py | 1 - nova/virt/libvirt/vif.py | 2 +- nova/virt/vmwareapi/vif.py | 26 ++++++++++++++------------ nova/virt/vmwareapi/vmops.py | 1 - nova/virt/vmwareapi_conn.py | 1 + nova/virt/xenapi/vm_utils.py | 2 +- nova/virt/xenapi/vmops.py | 1 - 8 files changed, 17 insertions(+), 18 deletions(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index 25490bf39..ef96d48a7 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -780,7 +780,6 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager): self.driver.metadata_forward() - def _setup_network(self, context, network_ref): """Sets up network on this host.""" network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index e8dcf138b..2faff0a1e 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -257,4 +257,3 @@ class ComputeDriver(object): def plug_vifs(self, instance, network_info): """Plugs in VIFs to networks.""" raise NotImplementedError() - diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 24634d7d2..fdd12d2f4 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -30,7 +30,7 @@ LOG = logging.getLogger('nova.virt.libvirt.vif') FLAGS = flags.FLAGS flags.DEFINE_string('libvirt_ovs_integration_bridge', 'br-int', - 'Name of Integration Bridge used by Open vSwitch') + 'Name of Integration Bridge used by Open vSwitch') class LibvirtBridgeDriver(VIFDriver): diff --git a/nova/virt/vmwareapi/vif.py b/nova/virt/vmwareapi/vif.py index 902699089..281565bbc 100644 --- a/nova/virt/vmwareapi/vif.py +++ b/nova/virt/vmwareapi/vif.py @@ -53,7 +53,8 @@ class VMWareVlanBridgeDriver(VIFDriver): session = VMWareAPISession(host_ip, host_username, host_password, FLAGS.vmwareapi_api_retry_count) vlan_interface = bridge_interface - # Check if the vlan_interface physical network adapter exists on the host + # Check if the vlan_interface physical network adapter exists on the + # host. if not network_utils.check_if_vlan_interface_exists(session, vlan_interface): raise exception.NetworkAdapterNotFound(adapter=vlan_interface) @@ -62,32 +63,33 @@ class VMWareVlanBridgeDriver(VIFDriver): vswitch_associated = network_utils.get_vswitch_for_vlan_interface( session, vlan_interface) if vswitch_associated is None: - raise exception.SwicthNotFoundForNetworkAdapter(adapter=vlan_interface) + raise exception.SwicthNotFoundForNetworkAdapter( + adapter=vlan_interface) # Check whether bridge already exists and retrieve the the ref of the # network whose name_label is "bridge" network_ref = network_utils.get_network_with_the_name(session, bridge) if network_ref is None: - # Create a port group on the vSwitch associated with the vlan_interface - # corresponding physical network adapter on the ESX host - network_utils.create_port_group(session, bridge, vswitch_associated, - vlan_num) + # Create a port group on the vSwitch associated with the + # vlan_interface corresponding physical network adapter on the ESX + # host. + network_utils.create_port_group(session, bridge, + vswitch_associated, vlan_num) else: # Get the vlan id and vswitch corresponding to the port group pg_vlanid, pg_vswitch = \ - network_utils.get_vlanid_and_vswitch_for_portgroup(session, bridge) + network_utils.get_vlanid_and_vswitch_for_portgroup(session, + bridge) # Check if the vswitch associated is proper if pg_vswitch != vswitch_associated: - raise exception.InvalidVLANPortGroup(bridge=bridge, - expected=vswitch_associated, - actual=pg_vswitch) + raise exception.InvalidVLANPortGroup( + bridge=bridge, expected=vswitch_associated, + actual=pg_vswitch) # Check if the vlan id is proper for the port group if pg_vlanid != vlan_num: raise exception.InvalidVLANTag(bridge=bridge, tag=vlan_num, pgroup=pg_vlanid) - def unplug(self, instance, network, mapping): pass - diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index eded4391e..6cc130809 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -806,4 +806,3 @@ class VMWareVMOps(object): """Unplug VIFs from networks.""" for (network, mapping) in network_info: self._vif_driver.unplug(instance, network, mapping) - diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py index 2492c9951..ce57847b2 100644 --- a/nova/virt/vmwareapi_conn.py +++ b/nova/virt/vmwareapi_conn.py @@ -198,6 +198,7 @@ class VMWareESXConnection(driver.ComputeDriver): """Plugs in VIFs to networks.""" self._vmops.plug_vifs(instance, network_info) + class VMWareAPISession(object): """ Sets up a session with the ESX host and handles all diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index e63582b54..62863c6d8 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -282,7 +282,6 @@ class VMHelper(HelperBase): LOG.exception(exc) raise StorageError(_('Unable to destroy VDI %s') % vdi_ref) - @classmethod def create_vdi(cls, session, sr_ref, name_label, virtual_size, read_only): """Create a VDI record and returns its reference.""" @@ -1095,6 +1094,7 @@ def _stream_disk(dev, image_type, virtual_size, image_file): for chunk in image_file: f.write(chunk) + def _write_partition(virtual_size, dev): dest = '/dev/%s' % dev primary_first = MBR_SIZE_SECTORS diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ad90e38e9..4fa59b6b7 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -884,7 +884,6 @@ class VMOps(object): instance['name']) raise - def _wait_with_callback(self, instance_id, task, callback): ret = None try: -- cgit From b2b378748aa859bab63c65fe88aa45081945b3c6 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 18:41:32 +0900 Subject: Changed the default of VIF driver --- nova/virt/libvirt/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 7b2ff49b2..585cd74a3 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -126,7 +126,7 @@ flags.DEFINE_bool('start_guests_on_host_boot', False, flags.DEFINE_string('libvirt_vif_type', 'bridge', 'Type of VIF to create.') flags.DEFINE_string('libvirt_vif_driver', - 'nova.virt.libvirt.vif.LibvirtVlanBridgeDriver', + 'nova.virt.libvirt.vif.LibvirtBridgeDriver', 'The libvirt VIF driver to configure the VIFs.') -- cgit From 68134f862e8c3eaa571791d9675fd0f8dbc3b906 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 22:00:20 +0900 Subject: Added create_vlan/bridge in network unit test --- nova/tests/test_network.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 340313405..57aa04ece 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -147,6 +147,7 @@ class FlatNetworkTestCase(test.TestCase): 'cidr': '192.168.%s.0/24' % i, 'cidr_v6': '2001:db%s::/64' % i8, 'id': i, + 'multi_host': False, 'injected': 'DONTCARE', 'bridge_interface': 'fake_fa%s' % i, 'vlan': None} @@ -162,7 +163,9 @@ class FlatNetworkTestCase(test.TestCase): 'ips': 'DONTCARE', 'label': 'test%s' % i, 'mac': 'DE:AD:BE:EF:00:0%s' % i, - 'rxtx_cap': 'DONTCARE'} + 'rxtx_cap': 'DONTCARE', + 'create_vlan': False, + 'create_bridge': False} self.assertDictMatch(nw[1], check) check = [{'enabled': 'DONTCARE', -- cgit From 337c1ae31b348f3103db09e81af6f27d5290b79e Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 23:55:10 +0900 Subject: Fixed Xenapi unit test error of test_rescue --- nova/tests/test_xenapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 4cb7447d3..199a8bc52 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -647,7 +647,7 @@ class XenAPIVMTestCase(test.TestCase): self.flags(xenapi_inject_image=False) instance = self._create_instance() conn = xenapi_conn.get_connection(False) - conn.rescue(instance, None) + conn.rescue(instance, None, []) def test_unrescue(self): instance = self._create_instance() -- cgit From d79ad70cf9ad959ea91b13a2724450cbadcdc0c4 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Thu, 21 Jul 2011 23:58:25 +0900 Subject: removed vif API extension --- nova/api/openstack/contrib/vifs.py | 85 -------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 nova/api/openstack/contrib/vifs.py (limited to 'nova') diff --git a/nova/api/openstack/contrib/vifs.py b/nova/api/openstack/contrib/vifs.py deleted file mode 100644 index a54f412a6..000000000 --- a/nova/api/openstack/contrib/vifs.py +++ /dev/null @@ -1,85 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (C) 2011 Midokura KK -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License -from webob import exc - -from nova import exception -from nova import network -from nova.api.openstack import extensions - - -def _translate_vif_view(vif): - result = {'id': vif['id'], - 'mac': vif['address'], - 'network_id': vif['network_id']} - return {'vif': result} - - -def _translate_vifs_view(vifs): - return {'vifs': [_translate_vif_view(vif) for vif in vifs]} - - -class ServerVIFController(object): - """The controller for VIFs attached to servers. - - A child resource of the server. - """ - - _serialization_metadata = { - 'application/xml': { - "attributes": { - "vif": [ - "id", - "mac", - "network_id", - ]}}} - - def __init__(self): - self.network_api = network.API() - super(ServerVIFController, self).__init__() - - def index(self, req, server_id): - """Return data about the vifs of the server.""" - context = req.environ['nova.context'] - - vifs = self.network_api.get_vifs_by_instance(context, server_id) - - return _translate_vifs_view(vifs) - - -class VIFs(extensions.ExtensionDescriptor): - def get_name(self): - return "VIFs" - - def get_alias(self): - return "os-vifs" - - def get_description(self): - return "VIF support" - - def get_namespace(self): - return "http://docs.openstack.org/ext/vifs/api/v1.1" - - def get_updated(self): - return "2011-07-11T00:00:00+00:00" - - def get_resources(self): - resources = [] - - res = extensions.ResourceExtension('os-server_vifs', - ServerVIFController()) - resources.append(res) - - return resources -- cgit From 7aca24e8463c38c4e051a59788de1c0c0b15cd0c Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Fri, 22 Jul 2011 00:27:45 +0900 Subject: Fixed the localization unit test error in the vif driver logging --- nova/virt/libvirt/vif.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'nova') diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index fdd12d2f4..bf3579608 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -74,13 +74,14 @@ class LibvirtBridgeDriver(VIFDriver): """Ensure that the bridge exists, and add VIF to it.""" if not network.get('multi_host') and mapping.get('create_bridge'): if mapping.get('create_vlan'): - LOG.debug(_("Ensuring vlan %s and bridge %s") % - (network['vlan'], network['bridge'])) + LOG.debug(_('Ensuring vlan %(vlan)s and bridge %(bridge)s'), + {'vlan': network['vlan'], + 'bridge': network['bridge']}) linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'], network['bridge_interface']) else: - LOG.debug(_("Ensuring bridge %s") % network['bridge']) + LOG.debug(_("Ensuring bridge %s"), network['bridge']) linux_net.ensure_bridge(network['bridge'], network['bridge_interface']) -- cgit From 87403c1e8b27b52e9e84856490ea7a0dc51f5bb6 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Fri, 22 Jul 2011 01:13:34 +0900 Subject: Changed test_live_migration_raises_exception to use mock for compte manager method --- nova/tests/test_libvirt.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'nova') diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 01a37fe47..ad0931a89 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -722,6 +722,9 @@ class LibvirtConnTestCase(test.TestCase): return vdmock self.create_fake_libvirt_mock(lookupByName=fake_lookup) + self.mox.StubOutWithMock(self.compute, "recover_live_migration") + self.compute.recover_live_migration(self.context, instance_ref, + dest='dest') # Start test self.mox.ReplayAll() -- cgit From 6e3c492ae878335ea7ef7e00cc9e9abc55b0a0b4 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Fri, 22 Jul 2011 05:23:44 +0900 Subject: Catch the FixedIpNotFoundForInstance exception when no fixed IP is mapped to instance --- nova/network/manager.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'nova') diff --git a/nova/network/manager.py b/nova/network/manager.py index ef96d48a7..83d0519c9 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -427,7 +427,12 @@ class NetworkManager(manager.SchedulerDependentManager): and info = dict containing pertinent networking data """ # TODO(tr3buchet) should handle floating IPs as well? - fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id) + try: + fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id) + except exception.FixedIpNotFoundForInstance, ex: + LOG.warn(_('No fixed IPs for instance %s'), instance_id) + fixed_ips = [] + vifs = self.db.virtual_interface_get_by_instance(context, instance_id) flavor = self.db.instance_type_get_by_id(context, instance_type_id) -- cgit