Merged trunk

This commit is contained in:
Ryu Ishimoto
2011-07-21 15:38:13 +09:00
24 changed files with 321 additions and 208 deletions

View File

@@ -1,3 +1,4 @@
Adam Gandelman <adamg@canonical.com>
Alex Meade <alex.meade@rackspace.com>
Alexander Sakhnov <asakhnov@mirantis.com>
Andrey Brindeyev <abrindeyev@griddynamics.com>

View File

@@ -91,7 +91,7 @@ def init_leases(interface):
"""Get the list of hosts for an interface."""
ctxt = context.get_admin_context()
network_ref = db.network_get_by_bridge(ctxt, interface)
return linux_net.get_dhcp_leases(ctxt, network_ref['id'])
return linux_net.get_dhcp_leases(ctxt, network_ref)
def main():

View File

@@ -479,7 +479,7 @@ class ProjectCommands(object):
except db.api.NoMoreNetworks:
print _('No more networks available. If this is a new '
'installation, you need\nto call something like this:\n\n'
' nova-manage network create 10.0.0.0/8 10 64\n\n')
' nova-manage network create pvt 10.0.0.0/8 10 64\n\n')
except exception.ProcessExecutionError, e:
print e
print _("The above error may show that the certificate db has not "
@@ -500,7 +500,7 @@ class FixedIpCommands(object):
if host is None:
fixed_ips = db.fixed_ip_get_all(ctxt)
else:
fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host)
fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host)
except exception.NotFound as ex:
print "error: %s" % ex
sys.exit(2)
@@ -564,17 +564,17 @@ class NetworkCommands(object):
"""Class for managing networks."""
def create(self, label=None, fixed_range=None, num_networks=None,
network_size=None, vlan_start=None,
network_size=None, multi_host=None, vlan_start=None,
vpn_start=None, fixed_range_v6=None, gateway_v6=None,
flat_network_bridge=None, bridge_interface=None):
"""Creates fixed ips for host by range
arguments: label, fixed_range, [num_networks=FLAG],
[network_size=FLAG], [vlan_start=FLAG],
[network_size=FLAG], [multi_host=FLAG], [vlan_start=FLAG],
[vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG],
[flat_network_bridge=FLAG], [bridge_interface=FLAG]
If you wish to use a later argument fill in the gaps with 0s
Ex: network create private 10.0.0.0/8 1 15 0 0 0 0 xenbr1 eth1
network create private 10.0.0.0/8 1 15
If you wish to use a later argument fill in the gaps with ""s
Ex: network create private 10.0.0.0/8 1 16 T "" "" "" "" xenbr1 eth1
network create private 10.0.0.0/8 1 16
"""
if not label:
msg = _('a label (ex: public) is required to create networks.')
@@ -589,6 +589,10 @@ class NetworkCommands(object):
num_networks = FLAGS.num_networks
if not network_size:
network_size = FLAGS.network_size
if not multi_host:
multi_host = FLAGS.multi_host
else:
multi_host = multi_host == 'T'
if not vlan_start:
vlan_start = FLAGS.vlan_start
if not vpn_start:
@@ -607,6 +611,7 @@ class NetworkCommands(object):
net_manager.create_networks(context.get_admin_context(),
label=label,
cidr=fixed_range,
multi_host=multi_host,
num_networks=int(num_networks),
network_size=int(network_size),
vlan_start=int(vlan_start),

View File

@@ -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():

View File

@@ -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)

View File

@@ -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."""

View File

@@ -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):

View File

@@ -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

View File

@@ -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')
@@ -283,16 +281,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,

View File

@@ -332,13 +332,14 @@ 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.
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)
def fixed_ip_create(context, values):
@@ -361,9 +362,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 +377,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)

View File

@@ -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
@@ -672,7 +670,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,
@@ -682,6 +680,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id):
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,
@@ -692,9 +691,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']
@@ -750,7 +752,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).\
@@ -799,6 +801,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).\
first()
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()
@@ -1480,8 +1496,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 +1511,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()
@@ -1704,9 +1717,16 @@ 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).\
filter_by(host=host).\
join(models.Network.fixed_ips).\
filter(host_filter).\
filter_by(deleted=False).\
all()
@@ -1738,6 +1758,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
###################

View File

@@ -0,0 +1,44 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 OpenStack, LLC.
# 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):
meta.bind = migrate_engine
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)

View File

@@ -545,6 +545,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))
@@ -603,6 +604,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):

View File

@@ -408,6 +408,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 FixedIpNotFoundForSpecificInstance(FixedIpNotFound):
message = _("Instance %(instance_id)s doesn't have fixed ip '%(ip)s'.")

View File

@@ -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
@@ -112,7 +111,11 @@ class API(base.Base):
'(%(project)s)') %
{'address': floating_ip['address'],
'project': context.project_id})
host = fixed_ip['network']['host']
# 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']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.network_topic, host),
{'method': 'associate_floating_ip',
@@ -127,7 +130,11 @@ 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']
# 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']
rpc.call(context,
self.db.queue_get_for(context, FLAGS.network_topic, host),
{'method': 'disassociate_floating_ip',
@@ -141,7 +148,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})
@@ -180,7 +189,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})

View File

@@ -498,7 +498,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',
@@ -552,21 +552,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)
@@ -574,18 +580,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))
# Make sure dnsmasq can actually read it (it setuid()s to "nobody")
os.chmod(conffile, 0644)
@@ -613,9 +617,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 = """
@@ -651,9 +653,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):
@@ -702,10 +701,11 @@ 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'),
'--listen-address=%s' % net['gateway'],
'--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'])),

View File

@@ -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
@@ -49,7 +48,6 @@ import datetime
import math
import netaddr
import socket
import pickle
from eventlet import greenpool
from nova import context
@@ -78,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')
@@ -87,6 +83,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',
@@ -104,7 +102,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(),
@@ -124,16 +123,26 @@ 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, **kwargs):
def _allocate_fixed_ips(self, context, instance_id, host, networks,
**kwargs):
"""Calls allocate_fixed_ip once for each network."""
green_pool = greenpool.GreenPool()
vpn = kwargs.pop('vpn')
for network in networks:
if network['host'] != self.host:
# 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,
network['host'])
topic = self.db.queue_get_for(context,
FLAGS.network_topic,
host)
args = {}
args['instance_id'] = instance_id
args['network_id'] = network['id']
@@ -149,12 +158,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):
@@ -193,7 +203,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
@@ -300,15 +310,36 @@ class NetworkManager(manager.SchedulerDependentManager):
super(NetworkManager, self).__init__(service_name='network',
*args, **kwargs)
@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']
try:
fip = self.db.fixed_ip_get_by_network_host(context,
network_id,
host)
return fip['address']
except exception.FixedIpNotFoundForNetworkHost:
elevated = context.elevated()
return self.db.fixed_ip_associate_pool(elevated,
network_id,
host=host)
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'])
self._setup_network(ctxt, network)
def periodic_tasks(self, context=None):
"""Tasks to be run at a periodic interval."""
@@ -323,32 +354,13 @@ 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)
def set_network_hosts(self, context):
"""Set the network hosts for any networks which are unset."""
try:
networks = self.db.network_get_all(context)
except exception.NoNetworksFound:
# no networks found, nothing to do
return
for network in networks:
host = network['host']
if not host:
# break so worker will only grab 1 (to help scale flatter)
self.set_network_host(context, network['id'])
break
return host
def _get_networks_for_instance(self, context, instance_id, project_id):
"""Determine & return which networks an instance should connect to."""
@@ -361,9 +373,9 @@ class NetworkManager(manager.SchedulerDependentManager):
# we don't care if no networks are found
pass
# return only networks which are not vlan networks and have host set
# return only networks which are not vlan networks
return [network for network in networks if
not network['vlan'] and network['host']]
not network['vlan']]
def allocate_for_instance(self, context, **kwargs):
"""Handles allocating the various network resources for an instance.
@@ -371,6 +383,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')
vpn = kwargs.pop('vpn')
@@ -379,9 +392,11 @@ 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, networks, vpn=vpn)
return self.get_instance_nw_info(context, instance_id, type_id)
self._allocate_fixed_ips(admin_context, instance_id, host, networks,
vpn=vpn)
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.
@@ -401,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):
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
@@ -446,10 +462,18 @@ class NetworkManager(manager.SchedulerDependentManager):
'cidr_v6': network['cidr_v6'],
'injected': network['injected'],
'vlan': network['vlan'],
'bridge_interface': network['bridge_interface']}
'bridge_interface': network['bridge_interface'],
'multi_host': network['multi_host']}
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': dhcp_server,
'broadcast': network['broadcast'],
'mac': vif['address'],
'rxtx_cap': flavor['rxtx_cap'],
@@ -489,10 +513,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 remove_fixed_ip_from_instance(self, context, instance_id, address):
"""Removes a fixed ip from an instance from specified network."""
@@ -519,6 +543,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):
@@ -564,10 +589,10 @@ 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)
self._setup_network(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."""
@@ -586,6 +611,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)
@@ -661,12 +687,13 @@ class NetworkManager(manager.SchedulerDependentManager):
'address': address,
'reserved': reserved})
def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
def _allocate_fixed_ips(self, context, instance_id, host, networks,
**kwargs):
"""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()
@@ -700,7 +727,8 @@ class FlatManager(NetworkManager):
timeout_fixed_ips = False
def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
def _allocate_fixed_ips(self, context, instance_id, host, networks,
**kwargs):
"""Calls allocate_fixed_ip once for each network."""
for network in networks:
self.allocate_fixed_ip(context, instance_id, network)
@@ -711,12 +739,12 @@ class FlatManager(NetworkManager):
**kwargs)
self.db.fixed_ip_disassociate(context, address)
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):
@@ -740,27 +768,20 @@ 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 _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)
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:
self.driver.update_dhcp(context, network_id)
self.driver.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_ref['id'],
{'gateway_v6': gateway})
class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
@@ -809,8 +830,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.driver.update_dhcp(context, network['id'])
self._setup_network(context, network)
return address
def add_network_to_project(self, context, project_id):
"""Force adds another network to a project."""
@@ -819,10 +840,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
return [network for network in networks if network['host']]
return self.db.project_get_networks(context, project_id)
def create_networks(self, context, **kwargs):
"""Create networks based on parameters."""
@@ -841,33 +859,35 @@ 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['id'], net)
else:
address = network['vpn_public_address']
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:
self.driver.update_dhcp(context, network_id)
self.driver.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_ref['id'],
{'gateway_v6': gateway})
@property
def _bottom_reserved_ips(self):

View File

@@ -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,
@@ -68,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)

View File

@@ -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)

View File

@@ -62,6 +62,7 @@ def _create_network_info(count=1, ipv6=None):
'vlan': fake_vlan,
'bridge_interface': fake_bridge_interface}
mapping = {'mac': fake,
'dhcp_server': fake,
'gateway': fake,
'gateway6': fake,
'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}

View File

@@ -45,6 +45,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',
@@ -62,6 +63,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',
@@ -122,20 +124,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')
@@ -149,7 +137,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)
@@ -166,6 +154,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,

View File

@@ -35,7 +35,6 @@ class LibvirtBridge(object):
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.
dhcp_server = mapping['gateway']
gateway6 = mapping.get('gateway6')
mac_id = mapping['mac'].replace(':', '')
@@ -58,7 +57,7 @@ class LibvirtBridge(object):
'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,
}
@@ -73,8 +72,9 @@ class LibvirtBridgeDriver(VIFDriver, LibvirtBridge):
def plug(self, instance, network, mapping):
"""Ensure that the bridge exists, and add VIF to it."""
linux_net.ensure_bridge(network['bridge'],
network['bridge_interface'])
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):
@@ -86,8 +86,9 @@ class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge):
def plug(self, instance, network, mapping):
"""Ensure that VLAN and bridge exist and add VIF to the bridge."""
linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'],
network['bridge_interface'])
if not network.get('multi_host'):
linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'],
network['bridge_interface'])
return self.get_configurations(network, mapping)
def unplug(self, instance, network, mapping):

View File

@@ -344,6 +344,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)
@@ -353,9 +354,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 _handle_spawn_error(self, vdis, spawn_error):

View File

@@ -72,7 +72,9 @@ def key_init(self, arg_dict):
info to be passed, such as passwords. Returns the shared
secret key value.
"""
pub = int(arg_dict["pub"])
# WARNING: Some older Windows agents will crash if the public key isn't
# a string
pub = arg_dict["pub"]
arg_dict["value"] = json.dumps({"name": "keyinit", "value": pub})
request_id = arg_dict["id"]
arg_dict["path"] = "data/host/%s" % request_id