Merge from trunk

This commit is contained in:
Ryan Lane 2010-11-30 22:34:25 +00:00
commit 89dbaf4f26
26 changed files with 324 additions and 186 deletions

View File

@ -34,10 +34,12 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
from nova import service
from nova import twistd
from nova import utils
if __name__ == '__main__':
twistd.serve(__file__)
if __name__ == '__builtin__':
utils.default_flagfile()
application = service.Service.create() # pylint: disable=C0103

View File

@ -34,6 +34,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
from nova import utils
from nova import twistd
from nova.compute import monitor
@ -44,6 +45,7 @@ if __name__ == '__main__':
twistd.serve(__file__)
if __name__ == '__builtin__':
utils.default_flagfile()
logging.warn('Starting instance monitor')
# pylint: disable-msg=C0103
monitor = monitor.InstanceMonitor()

View File

@ -467,7 +467,7 @@ def methods_of(obj):
def main():
"""Parse options and call the appropriate class/method."""
utils.default_flagfile('/etc/nova/nova-manage.conf')
utils.default_flagfile()
argv = FLAGS(sys.argv)
if FLAGS.verbose:

View File

@ -34,10 +34,12 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
from nova import service
from nova import twistd
from nova import utils
if __name__ == '__main__':
twistd.serve(__file__)
if __name__ == '__builtin__':
utils.default_flagfile()
application = service.Service.create() # pylint: disable-msg=C0103

View File

@ -34,10 +34,12 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
from nova import service
from nova import twistd
from nova import utils
if __name__ == '__main__':
twistd.serve(__file__)
if __name__ == '__builtin__':
utils.default_flagfile()
application = service.Service.create()

View File

@ -34,10 +34,12 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
from nova import service
from nova import twistd
from nova import utils
if __name__ == '__main__':
twistd.serve(__file__)
if __name__ == '__builtin__':
utils.default_flagfile()
application = service.Service.create() # pylint: disable-msg=C0103

View File

@ -17,11 +17,17 @@ if [ ! -n "$HOST_IP" ]; then
# you should explicitly set HOST_IP in your environment
HOST_IP=`ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'`
fi
TEST=0
USE_MYSQL=0
MYSQL_PASS=nova
USE_LDAP=0
LIBVIRT_TYPE=qemu
USE_MYSQL=${USE_MYSQL:-0}
MYSQL_PASS=${MYSQL_PASS:-nova}
TEST=${TEST:-0}
USE_LDAP=${USE_LDAP:-0}
LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu}
NET_MAN=${NET_MAN:-VlanManager}
# NOTE(vish): If you are using FlatDHCP on multiple hosts, set the interface
# below but make sure that the interface doesn't already have an
# ip or you risk breaking things.
# FLAT_INTERFACE=eth0
if [ "$USE_MYSQL" == 1 ]; then
SQL_CONN=mysql://root:$MYSQL_PASS@localhost/nova
@ -36,10 +42,11 @@ else
fi
mkdir -p /etc/nova
cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF
cat >$NOVA_DIR/bin/nova.conf << NOVA_CONF_EOF
--verbose
--nodaemon
--dhcpbridge_flagfile=/etc/nova/nova-manage.conf
--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf
--network_manager=nova.network.manager.$NET_MAN
--cc_host=$HOST_IP
--routing_source_ip=$HOST_IP
--sql_connection=$SQL_CONN
@ -47,6 +54,10 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF
--libvirt_type=$LIBVIRT_TYPE
NOVA_CONF_EOF
if [ -n "$FLAT_INTERFACE" ]; then
echo "--flat_interface=$FLAT_INTERFACE" >>$NOVA_DIR/bin/nova.conf
fi
if [ "$CMD" == "branch" ]; then
sudo apt-get install -y bzr
rm -rf $NOVA_DIR
@ -61,9 +72,12 @@ if [ "$CMD" == "install" ]; then
sudo apt-get install -y python-software-properties
sudo add-apt-repository ppa:nova-core/ppa
sudo apt-get update
sudo apt-get install -y dnsmasq open-iscsi kpartx kvm gawk iptables ebtables
sudo apt-get install -y dnsmasq kpartx kvm gawk iptables ebtables
sudo apt-get install -y user-mode-linux kvm libvirt-bin
sudo apt-get install -y screen iscsitarget euca2ools vlan curl rabbitmq-server
sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server
sudo apt-get install -y lvm2 iscsitarget open-iscsi
echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget
sudo /etc/init.d/iscsitarget restart
sudo modprobe kvm
sudo /etc/init.d/libvirt-bin restart
sudo apt-get install -y python-twisted python-sqlalchemy python-mox python-greenlet python-carrot
@ -122,31 +136,32 @@ if [ "$CMD" == "run" ]; then
$NOVA_DIR/bin/nova-manage project create admin admin
# export environment variables for project 'admin' and user 'admin'
$NOVA_DIR/bin/nova-manage project environment admin admin $NOVA_DIR/novarc
# create 3 small networks
$NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 3 16
# create a small network
$NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 1 32
# nova api crashes if we start it with a regular screen command,
# so send the start command by forcing text into the window.
screen_it api "$NOVA_DIR/bin/nova-api --flagfile=/etc/nova/nova-manage.conf"
screen_it objectstore "$NOVA_DIR/bin/nova-objectstore --flagfile=/etc/nova/nova-manage.conf"
screen_it compute "$NOVA_DIR/bin/nova-compute --flagfile=/etc/nova/nova-manage.conf"
screen_it network "$NOVA_DIR/bin/nova-network --flagfile=/etc/nova/nova-manage.conf"
screen_it scheduler "$NOVA_DIR/bin/nova-scheduler --flagfile=/etc/nova/nova-manage.conf"
screen_it volume "$NOVA_DIR/bin/nova-volume --flagfile=/etc/nova/nova-manage.conf"
screen_it api "$NOVA_DIR/bin/nova-api"
screen_it objectstore "$NOVA_DIR/bin/nova-objectstore"
screen_it compute "$NOVA_DIR/bin/nova-compute"
screen_it network "$NOVA_DIR/bin/nova-network"
screen_it scheduler "$NOVA_DIR/bin/nova-scheduler"
screen_it volume "$NOVA_DIR/bin/nova-volume"
screen_it test ". $NOVA_DIR/novarc"
screen -x
screen -S nova -x
fi
if [ "$CMD" == "run" ] || [ "$CMD" == "terminate" ]; then
# shutdown instances
. $NOVA_DIR/novarc; euca-describe-instances | grep i- | cut -f2 | xargs euca-terminate-instances
sleep 2
# delete volumes
. $NOVA_DIR/novarc; euca-describe-volumes | grep vol- | cut -f2 | xargs -n1 euca-delete-volume
fi
if [ "$CMD" == "run" ] || [ "$CMD" == "clean" ]; then
screen -S nova -X quit
rm *.pid*
$NOVA_DIR/tools/setup_iptables.sh clear
fi
if [ "$CMD" == "scrub" ]; then

View File

@ -994,8 +994,11 @@ class CloudController(object):
return True
def describe_images(self, context, image_id=None, **kwargs):
imageSet = self.image_service.index(context, image_id)
return {'imagesSet': imageSet}
# Note: image_id is a list!
images = self.image_service.index(context)
if image_id:
images = filter(lambda x: x['imageId'] in image_id, images)
return {'imagesSet': images}
def deregister_image(self, context, image_id, **kwargs):
self.image_service.deregister(context, image_id)

View File

@ -23,10 +23,7 @@ class Context(object):
class BasicApiAuthManager(object):
""" Implements a somewhat rudimentary version of OpenStack Auth"""
def __init__(self, host=None, db_driver=None):
if not host:
host = FLAGS.host
self.host = host
def __init__(self, db_driver=None):
if not db_driver:
db_driver = FLAGS.db_driver
self.db = utils.import_object(db_driver)
@ -47,7 +44,7 @@ class BasicApiAuthManager(object):
except KeyError:
return faults.Fault(webob.exc.HTTPUnauthorized())
token, user = self._authorize_user(username, key)
token, user = self._authorize_user(username, key, req)
if user and token:
res = webob.Response()
res.headers['X-Auth-Token'] = token.token_hash
@ -82,8 +79,13 @@ class BasicApiAuthManager(object):
return {'id': user.id}
return None
def _authorize_user(self, username, key):
""" Generates a new token and assigns it to a user """
def _authorize_user(self, username, key, req):
"""Generates a new token and assigns it to a user.
username - string
key - string API key
req - webob.Request object
"""
user = self.auth.get_user_from_access_key(key)
if user and user.name == username:
token_hash = hashlib.sha1('%s%s%f' % (username, key,
@ -91,12 +93,10 @@ class BasicApiAuthManager(object):
token_dict = {}
token_dict['token_hash'] = token_hash
token_dict['cdn_management_url'] = ''
token_dict['server_management_url'] = self._get_server_mgmt_url()
# Same as auth url, e.g. http://foo.org:8774/baz/v1.0
token_dict['server_management_url'] = req.url
token_dict['storage_url'] = ''
token_dict['user_id'] = user.id
token = self.db.auth_create_token(self.context, token_dict)
return token, user
return None, None
def _get_server_mgmt_url(self):
return 'https://%s/v1.0/' % self.host

View File

@ -47,7 +47,7 @@ class Fault(webob.exc.HTTPException):
"""Generate a WSGI response based on the exception passed to ctor."""
# Replace the body with fault details.
code = self.wrapped_exc.status_int
fault_name = self._fault_names.get(code, "cloudServersFault")
fault_name = self._fault_names.get(code, "computeFault")
fault_data = {
fault_name: {
'code': code,

View File

@ -0,0 +1,84 @@
#
# Person object for Nova
# inetorgperson with extra attributes
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
#
#
# using internet experimental oid arc as per BP64 3.1
objectidentifier novaSchema 1.3.6.1.3.1.666.666
objectidentifier novaAttrs novaSchema:3
objectidentifier novaOCs novaSchema:4
attributetype (
novaAttrs:1
NAME 'accessKey'
DESC 'Key for accessing data'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:2
NAME 'secretKey'
DESC 'Secret key'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:3
NAME 'keyFingerprint'
DESC 'Fingerprint of private key'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:4
NAME 'isAdmin'
DESC 'Is user an administrator?'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
)
attributetype (
novaAttrs:5
NAME 'projectManager'
DESC 'Project Managers of a project'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
)
objectClass (
novaOCs:1
NAME 'novaUser'
DESC 'access and secret keys'
AUXILIARY
MUST ( uid )
MAY ( accessKey $ secretKey $ isAdmin )
)
objectClass (
novaOCs:2
NAME 'novaKeyPair'
DESC 'Key pair for User'
SUP top
STRUCTURAL
MUST ( cn $ sshPublicKey $ keyFingerprint )
)
objectClass (
novaOCs:3
NAME 'novaProject'
DESC 'Container for project'
SUP groupOfNames
STRUCTURAL
MUST ( cn $ projectManager )
)

16
nova/auth/nova_sun.schema Normal file
View File

@ -0,0 +1,16 @@
#
# Person object for Nova
# inetorgperson with extra attributes
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
# Modified for strict RFC 4512 compatibility by: Ryan Lane <ryan@ryandlane.com>
#
# using internet experimental oid arc as per BP64 3.1
dn: cn=schema
attributeTypes: ( 1.3.6.1.3.1.666.666.3.1 NAME 'accessKey' DESC 'Key for accessing data' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
attributeTypes: ( 1.3.6.1.3.1.666.666.3.2 NAME 'secretKey' DESC 'Secret key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
attributeTypes: ( 1.3.6.1.3.1.666.666.3.3 NAME 'keyFingerprint' DESC 'Fingerprint of private key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE)
attributeTypes: ( 1.3.6.1.3.1.666.666.3.4 NAME 'isAdmin' DESC 'Is user an administrator?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
attributeTypes: ( 1.3.6.1.3.1.666.666.3.5 NAME 'projectManager' DESC 'Project Managers of a project' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
objectClasses: ( 1.3.6.1.3.1.666.666.4.1 NAME 'novaUser' DESC 'access and secret keys' SUP top AUXILIARY MUST ( uid ) MAY ( accessKey $ secretKey $ isAdmin ) )
objectClasses: ( 1.3.6.1.3.1.666.666.4.2 NAME 'novaKeyPair' DESC 'Key pair for User' SUP top STRUCTURAL MUST ( cn $ sshPublicKey $ keyFingerprint ) )
objectClasses: ( 1.3.6.1.3.1.666.666.4.3 NAME 'novaProject' DESC 'Container for project' SUP groupOfNames STRUCTURAL MUST ( cn $ projectManager ) )

View File

@ -0,0 +1,19 @@
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <eau@phear.org>
#
# Based on the proposal of : Mark Ruijter
#
# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'MANDATORY: OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
DESC 'MANDATORY: OpenSSH LPK objectclass'
MAY ( sshPublicKey $ uid )
)

View File

@ -0,0 +1,10 @@
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <eau@phear.org>
#
# Schema for Sun Directory Server.
# Based on the original schema, modified by Stefan Fischer.
#
dn: cn=schema
attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) )

View File

@ -20,115 +20,9 @@
apt-get install -y slapd ldap-utils python-ldap
cat >/etc/ldap/schema/openssh-lpk_openldap.schema <<LPK_SCHEMA_EOF
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <eau@phear.org>
#
# Based on the proposal of : Mark Ruijter
#
# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'MANDATORY: OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
DESC 'MANDATORY: OpenSSH LPK objectclass'
MAY ( sshPublicKey $ uid )
)
LPK_SCHEMA_EOF
cat >/etc/ldap/schema/nova.schema <<NOVA_SCHEMA_EOF
#
# Person object for Nova
# inetorgperson with extra attributes
# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
#
#
# using internet experimental oid arc as per BP64 3.1
objectidentifier novaSchema 1.3.6.1.3.1.666.666
objectidentifier novaAttrs novaSchema:3
objectidentifier novaOCs novaSchema:4
attributetype (
novaAttrs:1
NAME 'accessKey'
DESC 'Key for accessing data'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:2
NAME 'secretKey'
DESC 'Secret key'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:3
NAME 'keyFingerprint'
DESC 'Fingerprint of private key'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
)
attributetype (
novaAttrs:4
NAME 'isAdmin'
DESC 'Is user an administrator?'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
)
attributetype (
novaAttrs:5
NAME 'projectManager'
DESC 'Project Managers of a project'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
)
objectClass (
novaOCs:1
NAME 'novaUser'
DESC 'access and secret keys'
AUXILIARY
MUST ( uid )
MAY ( accessKey $ secretKey $ isAdmin )
)
objectClass (
novaOCs:2
NAME 'novaKeyPair'
DESC 'Key pair for User'
SUP top
STRUCTURAL
MUST ( cn $ sshPublicKey $ keyFingerprint )
)
objectClass (
novaOCs:3
NAME 'novaProject'
DESC 'Container for project'
SUP groupOfNames
STRUCTURAL
MUST ( cn $ projectManager )
)
NOVA_SCHEMA_EOF
abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"`
cp $abspath/openssh-lpk_openldap.schema /etc/ldap/schema/openssh-lpk_openldap.schema
cp $abspath/nova_openldap.schema /etc/ldap/schema/nova_openldap.schema
mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf.orig
cat >/etc/ldap/slapd.conf <<SLAPD_CONF_EOF

View File

@ -47,7 +47,7 @@ from nova.compute import power_state
FLAGS = flags.FLAGS
flags.DEFINE_string('instances_path', utils.abspath('../instances'),
flags.DEFINE_string('instances_path', '$state_path/instances',
'where instances are stored on disk')
flags.DEFINE_string('compute_driver', 'nova.virt.connection.get_connection',
'Driver to use for volume creation')

View File

@ -46,7 +46,7 @@ flags.DEFINE_integer('monitoring_instances_delay', 5,
'Sleep time between updates')
flags.DEFINE_integer('monitoring_instances_step', 300,
'Interval of RRD updates')
flags.DEFINE_string('monitoring_rrd_path', '/var/nova/monitor/instances',
flags.DEFINE_string('monitoring_rrd_path', '$state_path/monitor/instances',
'Location of RRD files')

View File

@ -40,9 +40,9 @@ from nova import flags
FLAGS = flags.FLAGS
flags.DEFINE_string('ca_file', 'cacert.pem', 'Filename of root CA')
flags.DEFINE_string('keys_path', utils.abspath('../keys'),
flags.DEFINE_string('keys_path', '$state_path/keys',
'Where we keep our keys')
flags.DEFINE_string('ca_path', utils.abspath('../CA'),
flags.DEFINE_string('ca_path', '$state_path/CA',
'Where we keep our root CA')
flags.DEFINE_boolean('use_intermediate_ca', False,
'Should we use intermediate CAs for each project?')

View File

@ -24,6 +24,7 @@ where they're used.
import getopt
import os
import socket
import string
import sys
import gflags
@ -38,11 +39,12 @@ class FlagValues(gflags.FlagValues):
"""
def __init__(self):
def __init__(self, extra_context=None):
gflags.FlagValues.__init__(self)
self.__dict__['__dirty'] = []
self.__dict__['__was_already_parsed'] = False
self.__dict__['__stored_argv'] = []
self.__dict__['__extra_context'] = extra_context
def __call__(self, argv):
# We're doing some hacky stuff here so that we don't have to copy
@ -112,7 +114,7 @@ class FlagValues(gflags.FlagValues):
def ParseNewFlags(self):
if '__stored_argv' not in self.__dict__:
return
new_flags = FlagValues()
new_flags = FlagValues(self)
for k in self.__dict__['__dirty']:
new_flags[k] = gflags.FlagValues.__getitem__(self, k)
@ -134,9 +136,29 @@ class FlagValues(gflags.FlagValues):
def __getattr__(self, name):
if self.IsDirty(name):
self.ParseNewFlags()
return gflags.FlagValues.__getattr__(self, name)
val = gflags.FlagValues.__getattr__(self, name)
if type(val) is str:
tmpl = string.Template(val)
context = [self, self.__dict__['__extra_context']]
return tmpl.substitute(StrWrapper(context))
return val
class StrWrapper(object):
"""Wrapper around FlagValues objects
Wraps FlagValues objects for string.Template so that we're
sure to return strings."""
def __init__(self, context_objs):
self.context_objs = context_objs
def __getitem__(self, name):
for context in self.context_objs:
val = getattr(context, name, False)
if val:
return str(val)
raise KeyError(name)
FLAGS = FlagValues()
gflags.FLAGS = FLAGS
gflags.DEFINE_flag(gflags.HelpFlag(), FLAGS)
@ -222,8 +244,11 @@ DEFINE_string('vpn_key_suffix',
DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger')
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
"Top-level directory for maintaining nova's state")
DEFINE_string('sql_connection',
'sqlite:///%s/nova.sqlite' % os.path.abspath("./"),
'sqlite:///$state_path/nova.sqlite',
'connection string for sql database')
DEFINE_string('compute_manager', 'nova.compute.manager.ComputeManager',

View File

@ -38,12 +38,12 @@ flags.DEFINE_string('dhcpbridge_flagfile',
'/etc/nova/nova-dhcpbridge.conf',
'location of flagfile for dhcpbridge')
flags.DEFINE_string('networks_path', utils.abspath('../networks'),
flags.DEFINE_string('networks_path', '$state_path/networks',
'Location to keep network config files')
flags.DEFINE_string('public_interface', 'vlan1',
'Interface for public IP addresses')
flags.DEFINE_string('bridge_dev', 'eth0',
'network device for bridges')
flags.DEFINE_string('vlan_interface', 'eth0',
'network device for vlans')
flags.DEFINE_string('dhcpbridge', _bin_file('nova-dhcpbridge'),
'location of nova-dhcpbridge')
flags.DEFINE_string('routing_source_ip', '127.0.0.1',
@ -54,14 +54,15 @@ flags.DEFINE_bool('use_nova_chains', False,
DEFAULT_PORTS = [("tcp", 80), ("tcp", 22), ("udp", 1194), ("tcp", 443)]
def init_host():
"""Basic networking setup goes here"""
# NOTE(devcamcar): Cloud public DNAT entries, CloudPipe port
# forwarding entries and a default DNAT entry.
def metadata_forward():
"""Create forwarding rule for metadata"""
_confirm_rule("PREROUTING", "-t nat -s 0.0.0.0/0 "
"-d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT "
"--to-destination %s:%s" % (FLAGS.cc_host, FLAGS.cc_port))
def init_host():
"""Basic networking setup goes here"""
# NOTE(devcamcar): Cloud public SNAT entries and the default
# SNAT rule for outbound traffic.
_confirm_rule("POSTROUTING", "-t nat -s %s "
@ -134,7 +135,7 @@ def ensure_vlan(vlan_num):
if not _device_exists(interface):
logging.debug("Starting VLAN inteface %s", interface)
_execute("sudo vconfig set_name_type VLAN_PLUS_VID_NO_PAD")
_execute("sudo vconfig add %s %s" % (FLAGS.bridge_dev, vlan_num))
_execute("sudo vconfig add %s %s" % (FLAGS.vlan_interface, vlan_num))
_execute("sudo ifconfig %s up" % interface)
return interface
@ -142,12 +143,13 @@ def ensure_vlan(vlan_num):
def ensure_bridge(bridge, interface, net_attrs=None):
"""Create a bridge unless it already exists"""
if not _device_exists(bridge):
logging.debug("Starting Bridge inteface for %s", interface)
logging.debug("Starting Bridge interface for %s", interface)
_execute("sudo brctl addbr %s" % bridge)
_execute("sudo brctl setfd %s 0" % bridge)
# _execute("sudo brctl setageing %s 10" % bridge)
_execute("sudo brctl stp %s off" % bridge)
_execute("sudo brctl addif %s %s" % (bridge, interface))
if interface:
_execute("sudo brctl addif %s %s" % (bridge, interface))
if net_attrs:
_execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \
(bridge,

View File

@ -27,6 +27,7 @@ topologies. All of the network commands are issued to a subclass of
:network_driver: Driver to use for network creation
: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
@ -63,7 +64,11 @@ flags.DEFINE_string('flat_network_bridge', 'br100',
'Bridge for simple network instances')
flags.DEFINE_string('flat_network_dns', '8.8.4.4',
'Dns for simple network')
flags.DEFINE_string('flat_network_dhcp_start', '192.168.0.2',
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_integer('num_networks', 1000, 'Number of networks to support')
@ -175,9 +180,11 @@ class NetworkManager(manager.Manager):
if instance_ref['mac_address'] != mac:
raise exception.Error("IP %s leased to bad mac %s vs %s" %
(address, instance_ref['mac_address'], mac))
now = datetime.datetime.utcnow()
self.db.fixed_ip_update(context,
fixed_ip_ref['address'],
{'leased': True})
{'leased': True,
'updated_at': now})
if not fixed_ip_ref['allocated']:
logging.warn("IP %s leased that was already deallocated", address)
@ -246,7 +253,31 @@ class NetworkManager(manager.Manager):
class FlatManager(NetworkManager):
"""Basic network where no vlans are used."""
"""Basic network where no vlans are used.
FlatManager does not do any bridge or vlan creation. The user is
responsible for setting up whatever bridge is specified in
flat_network_bridge (br100 by default). This bridge needs to be created
on all compute hosts.
The idea is to create a single network for the host with a command like:
nova-manage network create 192.168.0.0/24 1 256. Creating multiple
networks for for one manager is currently not supported, but could be
added by modifying allocate_fixed_ip and get_network to get the a network
with new logic instead of network_get_by_bridge. Arbitrary lists of
addresses in a single network can be accomplished with manual db editing.
If flat_injected is True, the compute host will attempt to inject network
config into the guest. It attempts to modify /etc/network/interfaces and
currently only works on debian based systems. To support a wider range of
OSes, some other method may need to be devised to let the guest know which
ip it should be using so that it can configure itself. Perhaps an attached
disk or serial device with configuration info.
Metadata forwarding must be handled by the gateway, and since nova does
not do any setup in this mode, it must be done manually. Requests to
169.254.169.254 port 80 will need to be forwarded to the api server.
"""
def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):
"""Gets a fixed ip from the pool."""
@ -285,6 +316,7 @@ class FlatManager(NetworkManager):
cidr = "%s/%s" % (fixed_net[start], significant_bits)
project_net = IPy.IP(cidr)
net = {}
net['bridge'] = FLAGS.flat_network_bridge
net['cidr'] = cidr
net['netmask'] = str(project_net.netmask())
net['gateway'] = str(project_net[1])
@ -306,18 +338,36 @@ class FlatManager(NetworkManager):
def _on_set_network_host(self, context, network_id):
"""Called when this host becomes the host for a network."""
net = {}
net['injected'] = True
net['bridge'] = FLAGS.flat_network_bridge
net['injected'] = FLAGS.flat_injected
net['dns'] = FLAGS.flat_network_dns
self.db.network_update(context, network_id, net)
class FlatDHCPManager(NetworkManager):
"""Flat networking with dhcp."""
class FlatDHCPManager(FlatManager):
"""Flat networking with dhcp.
FlatDHCPManager will start up one dhcp server to give out addresses.
It never injects network settings into the guest. Otherwise it behaves
like FlatDHCPManager.
"""
def init_host(self):
"""Do any initialization that needs to be run if this is a
standalone service.
"""
super(FlatDHCPManager, self).init_host()
self.driver.metadata_forward()
def setup_compute_network(self, context, instance_id):
"""Sets up matching network for compute hosts."""
network_ref = db.network_get_by_instance(context, instance_id)
self.driver.ensure_bridge(network_ref['bridge'],
FLAGS.flat_interface,
network_ref)
def setup_fixed_ip(self, context, address):
"""Setup dhcp for this network."""
network_ref = db.fixed_ip_get_by_address(context, address)
network_ref = db.fixed_ip_get_network(context, address)
self.driver.update_dhcp(context, network_ref['id'])
def deallocate_fixed_ip(self, context, address, *args, **kwargs):
@ -326,18 +376,28 @@ class FlatDHCPManager(NetworkManager):
def _on_set_network_host(self, context, network_id):
"""Called when this host becomes the host for a project."""
super(FlatDHCPManager, self)._on_set_network_host(context, network_id)
network_ref = self.db.network_get(context, network_id)
self.db.network_update(context,
network_id,
{'dhcp_start': FLAGS.flat_network_dhcp_start})
net = {}
net['dhcp_start'] = FLAGS.flat_network_dhcp_start
self.db.network_update(context, network_id, net)
network_ref = db.network_get(context, network_id)
self.driver.ensure_bridge(network_ref['bridge'],
FLAGS.bridge_dev,
FLAGS.flat_interface,
network_ref)
class VlanManager(NetworkManager):
"""Vlan network with dhcp."""
"""Vlan network with dhcp.
VlanManager is the most complicated. It will create a host-managed
vlan for each project. Each project gets its own subnet. The networks
and associated subnets are created with nova-manage using a command like:
nova-manage network create 10.0.0.0/8 3 16. This will create 3 networks
of 16 addresses from the beginning of the 10.0.0.0 range.
A dhcp server is run for each subnet, so each project will have its own.
For this mode to be useful, each project will need a vpn to access the
instances in its subnet.
"""
@defer.inlineCallbacks
def periodic_tasks(self, context=None):
@ -357,6 +417,7 @@ class VlanManager(NetworkManager):
standalone service.
"""
super(VlanManager, self).init_host()
self.driver.metadata_forward()
self.driver.init_host()
def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):

View File

@ -33,7 +33,7 @@ from nova.objectstore import stored
FLAGS = flags.FLAGS
flags.DEFINE_string('buckets_path', utils.abspath('../buckets'),
flags.DEFINE_string('buckets_path', '$state_path/buckets',
'path to s3 buckets')

View File

@ -39,8 +39,8 @@ from nova.objectstore import bucket
FLAGS = flags.FLAGS
flags.DEFINE_string('images_path', utils.abspath('../images'),
'path to decrypted images')
flags.DEFINE_string('images_path', '$state_path/images',
'path to decrypted images')
class Image(object):

View File

@ -54,7 +54,6 @@ def fake_auth_init(self):
self.db = FakeAuthDatabase()
self.context = Context()
self.auth = FakeAuthManager()
self.host = 'foo'
@webob.dec.wsgify

View File

@ -50,12 +50,12 @@ class APITest(unittest.TestCase):
api.application = succeed
resp = Request.blank('/').get_response(api)
self.assertFalse('cloudServersFault' in resp.body, resp.body)
self.assertFalse('computeFault' in resp.body, resp.body)
self.assertEqual(resp.status_int, 200, resp.body)
api.application = raise_webob_exc
resp = Request.blank('/').get_response(api)
self.assertFalse('cloudServersFault' in resp.body, resp.body)
self.assertFalse('computeFault' in resp.body, resp.body)
self.assertEqual(resp.status_int, 404, resp.body)
api.application = raise_api_fault
@ -65,10 +65,10 @@ class APITest(unittest.TestCase):
api.application = fail
resp = Request.blank('/').get_response(api)
self.assertTrue('{"cloudServersFault' in resp.body, resp.body)
self.assertTrue('{"computeFault' in resp.body, resp.body)
self.assertEqual(resp.status_int, 500, resp.body)
api.application = fail
resp = Request.blank('/.xml').get_response(api)
self.assertTrue('<cloudServersFault' in resp.body, resp.body)
self.assertTrue('<computeFault' in resp.body, resp.body)
self.assertEqual(resp.status_int, 500, resp.body)

View File

@ -62,14 +62,14 @@ class Test(unittest.TestCase):
f = fakes.FakeAuthManager()
f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None))
req = webob.Request.blank('/v1.0/')
req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'})
req.headers['X-Auth-User'] = 'herp'
req.headers['X-Auth-Key'] = 'derp'
result = req.get_response(nova.api.API('os'))
self.assertEqual(result.status, '204 No Content')
self.assertEqual(len(result.headers['X-Auth-Token']), 40)
self.assertEqual(result.headers['X-Server-Management-Url'],
"https://foo/v1.0/")
"http://foo/v1.0/")
self.assertEqual(result.headers['X-CDN-Management-Url'],
"")
self.assertEqual(result.headers['X-Storage-Url'], "")