Merge from trunk
This commit is contained in:
3
Authors
3
Authors
@@ -8,6 +8,7 @@ Chmouel Boudjnah <chmouel@chmouel.com>
|
||||
Chris Behrens <cbehrens@codestud.com>
|
||||
Cory Wright <corywright@gmail.com>
|
||||
David Pravec <David.Pravec@danix.org>
|
||||
Dan Prince <dan.prince@rackspace.com>
|
||||
Dean Troyer <dtroyer@gmail.com>
|
||||
Devin Carlen <devin.carlen@gmail.com>
|
||||
Ed Leafe <ed@leafe.com>
|
||||
@@ -23,6 +24,7 @@ Joe Heck <heckj@mac.com>
|
||||
Joel Moore <joelbm24@gmail.com>
|
||||
John Dewey <john@dewey.ws>
|
||||
Jonathan Bryce <jbryce@jbryce.com>
|
||||
Jordan Rinke <jordan@openstack.org>
|
||||
Josh Durgin <joshd@hq.newdream.net>
|
||||
Josh Kearney <josh.kearney@rackspace.com>
|
||||
Joshua McKenty <jmckenty@gmail.com>
|
||||
@@ -50,6 +52,7 @@ Soren Hansen <soren.hansen@rackspace.com>
|
||||
Thierry Carrez <thierry@openstack.org>
|
||||
Todd Willey <todd@ansolabs.com>
|
||||
Trey Morris <trey.morris@rackspace.com>
|
||||
Tushar Patil <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||
Zhixue Wu <Zhixue.Wu@citrix.com>
|
||||
|
||||
@@ -267,6 +267,14 @@ class RoleCommands(object):
|
||||
self.manager.remove_role(user, role, project)
|
||||
|
||||
|
||||
def _db_error(caught_exception):
|
||||
print caught_exception
|
||||
print _("The above error may show that the database has not "
|
||||
"been created.\nPlease create a database using "
|
||||
"nova-manage sync db before running this command.")
|
||||
exit(1)
|
||||
|
||||
|
||||
class UserCommands(object):
|
||||
"""Class for managing users."""
|
||||
|
||||
@@ -282,13 +290,19 @@ class UserCommands(object):
|
||||
def admin(self, name, access=None, secret=None):
|
||||
"""creates a new admin and prints exports
|
||||
arguments: name [access] [secret]"""
|
||||
user = self.manager.create_user(name, access, secret, True)
|
||||
try:
|
||||
user = self.manager.create_user(name, access, secret, True)
|
||||
except exception.DBError, e:
|
||||
_db_error(e)
|
||||
self._print_export(user)
|
||||
|
||||
def create(self, name, access=None, secret=None):
|
||||
"""creates a new user and prints exports
|
||||
arguments: name [access] [secret]"""
|
||||
user = self.manager.create_user(name, access, secret, False)
|
||||
try:
|
||||
user = self.manager.create_user(name, access, secret, False)
|
||||
except exception.DBError, e:
|
||||
_db_error(e)
|
||||
self._print_export(user)
|
||||
|
||||
def delete(self, name):
|
||||
@@ -409,9 +423,14 @@ class ProjectCommands(object):
|
||||
with open(filename, 'w') as f:
|
||||
f.write(zip_file)
|
||||
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')
|
||||
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')
|
||||
except exception.ProcessExecutionError, e:
|
||||
print e
|
||||
print _("The above error may show that the certificate db has not "
|
||||
"been created.\nPlease create a database by running a "
|
||||
"nova-api server on this host.")
|
||||
|
||||
|
||||
class FloatingIpCommands(object):
|
||||
@@ -476,9 +495,9 @@ class NetworkCommands(object):
|
||||
cidr=fixed_range,
|
||||
num_networks=int(num_networks),
|
||||
network_size=int(network_size),
|
||||
cidr_v6=fixed_range_v6,
|
||||
vlan_start=int(vlan_start),
|
||||
vpn_start=int(vpn_start),
|
||||
cidr_v6=fixed_range_v6)
|
||||
vpn_start=int(vpn_start))
|
||||
|
||||
|
||||
class ServiceCommands(object):
|
||||
|
||||
150
contrib/nova.sh
150
contrib/nova.sh
@@ -1,15 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
DIR=`pwd`
|
||||
CMD=$1
|
||||
SOURCE_BRANCH=lp:nova
|
||||
if [ -n "$2" ]; then
|
||||
SOURCE_BRANCH=$2
|
||||
if [ "$CMD" = "branch" ]; then
|
||||
SOURCE_BRANCH=${2:-lp:nova}
|
||||
DIRNAME=${3:-nova}
|
||||
else
|
||||
DIRNAME=${2:-nova}
|
||||
fi
|
||||
DIRNAME=nova
|
||||
|
||||
NOVA_DIR=$DIR/$DIRNAME
|
||||
if [ -n "$3" ]; then
|
||||
NOVA_DIR=$DIR/$3
|
||||
fi
|
||||
|
||||
if [ ! -n "$HOST_IP" ]; then
|
||||
# NOTE(vish): This will just get the first ip in the list, so if you
|
||||
@@ -24,6 +23,8 @@ TEST=${TEST:-0}
|
||||
USE_LDAP=${USE_LDAP:-0}
|
||||
# Use OpenDJ instead of OpenLDAP when using LDAP
|
||||
USE_OPENDJ=${USE_OPENDJ:-0}
|
||||
# Use IPv6
|
||||
USE_IPV6=${USE_IPV6:-0}
|
||||
LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu}
|
||||
NET_MAN=${NET_MAN:-VlanManager}
|
||||
# NOTE(vish): If you are using FlatDHCP on multiple hosts, set the interface
|
||||
@@ -43,8 +44,69 @@ else
|
||||
AUTH=dbdriver.DbDriver
|
||||
fi
|
||||
|
||||
mkdir -p /etc/nova
|
||||
cat >$NOVA_DIR/bin/nova.conf << NOVA_CONF_EOF
|
||||
if [ "$CMD" == "branch" ]; then
|
||||
sudo apt-get install -y bzr
|
||||
if [ ! -e "$DIR/.bzr" ]; then
|
||||
bzr init-repo $DIR
|
||||
fi
|
||||
rm -rf $NOVA_DIR
|
||||
bzr branch $SOURCE_BRANCH $NOVA_DIR
|
||||
cd $NOVA_DIR
|
||||
mkdir -p $NOVA_DIR/instances
|
||||
mkdir -p $NOVA_DIR/networks
|
||||
exit
|
||||
fi
|
||||
|
||||
# You should only have to run this once
|
||||
if [ "$CMD" == "install" ]; then
|
||||
sudo apt-get install -y python-software-properties
|
||||
sudo add-apt-repository ppa:nova-core/trunk
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y dnsmasq-base kpartx kvm gawk iptables ebtables
|
||||
sudo apt-get install -y user-mode-linux kvm libvirt-bin
|
||||
sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server
|
||||
sudo apt-get install -y lvm2 iscsitarget open-iscsi
|
||||
sudo apt-get install -y socat
|
||||
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 modprobe nbd
|
||||
sudo apt-get install -y python-twisted python-sqlalchemy python-mox python-greenlet python-carrot
|
||||
sudo apt-get install -y python-migrate python-eventlet python-gflags python-ipy python-tempita
|
||||
sudo apt-get install -y python-libvirt python-libxml2 python-routes python-cheetah
|
||||
sudo apt-get install -y python-netaddr python-paste python-pastedeploy python-glance
|
||||
|
||||
if [ "$USE_IPV6" == 1 ]; then
|
||||
sudo apt-get install -y radvd
|
||||
sudo bash -c "echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"
|
||||
sudo bash -c "echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra"
|
||||
fi
|
||||
|
||||
if [ "$USE_MYSQL" == 1 ]; then
|
||||
cat <<MYSQL_PRESEED | debconf-set-selections
|
||||
mysql-server-5.1 mysql-server/root_password password $MYSQL_PASS
|
||||
mysql-server-5.1 mysql-server/root_password_again password $MYSQL_PASS
|
||||
mysql-server-5.1 mysql-server/start_on_boot boolean true
|
||||
MYSQL_PRESEED
|
||||
apt-get install -y mysql-server python-mysqldb
|
||||
fi
|
||||
mkdir -p $DIR/images
|
||||
wget -c http://images.ansolabs.com/tty.tgz
|
||||
tar -C $DIR/images -zxf tty.tgz
|
||||
exit
|
||||
fi
|
||||
|
||||
NL=`echo -ne '\015'`
|
||||
|
||||
function screen_it {
|
||||
screen -S nova -X screen -t $1
|
||||
screen -S nova -p $1 -X stuff "$2$NL"
|
||||
}
|
||||
|
||||
if [ "$CMD" == "run" ]; then
|
||||
|
||||
cat >$NOVA_DIR/bin/nova.conf << NOVA_CONF_EOF
|
||||
--verbose
|
||||
--nodaemon
|
||||
--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf
|
||||
@@ -56,68 +118,18 @@ cat >$NOVA_DIR/bin/nova.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
|
||||
bzr branch $SOURCE_BRANCH $NOVA_DIR
|
||||
cd $NOVA_DIR
|
||||
mkdir -p $NOVA_DIR/instances
|
||||
mkdir -p $NOVA_DIR/networks
|
||||
fi
|
||||
|
||||
# You should only have to run this once
|
||||
if [ "$CMD" == "install" ]; then
|
||||
sudo apt-get install -y python-software-properties
|
||||
sudo add-apt-repository ppa:nova-core/trunk
|
||||
sudo apt-get update
|
||||
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 euca2ools vlan curl rabbitmq-server
|
||||
sudo apt-get install -y lvm2 iscsitarget open-iscsi
|
||||
sudo apt-get install -y socat
|
||||
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 modprobe nbd
|
||||
sudo apt-get install -y python-twisted python-sqlalchemy python-mox python-greenlet python-carrot
|
||||
sudo apt-get install -y python-daemon python-eventlet python-gflags python-ipy
|
||||
sudo apt-get install -y python-libvirt python-libxml2 python-routes python-cheetah
|
||||
sudo apt-get install -y python-paste python-pastedeploy
|
||||
#For IPV6
|
||||
sudo apt-get install -y python-netaddr
|
||||
sudo apt-get install -y radvd
|
||||
#(Nati) Note that this configuration is only needed for nova-network node.
|
||||
sudo bash -c "echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"
|
||||
sudo bash -c "echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra"
|
||||
|
||||
if [ "$USE_MYSQL" == 1 ]; then
|
||||
cat <<MYSQL_PRESEED | debconf-set-selections
|
||||
mysql-server-5.1 mysql-server/root_password password $MYSQL_PASS
|
||||
mysql-server-5.1 mysql-server/root_password_again password $MYSQL_PASS
|
||||
mysql-server-5.1 mysql-server/start_on_boot boolean true
|
||||
MYSQL_PRESEED
|
||||
apt-get install -y mysql-server python-mysqldb
|
||||
if [ -n "$FLAT_INTERFACE" ]; then
|
||||
echo "--flat_interface=$FLAT_INTERFACE" >>$NOVA_DIR/bin/nova.conf
|
||||
fi
|
||||
wget http://c2477062.cdn.cloudfiles.rackspacecloud.com/images.tgz
|
||||
tar -C $DIR -zxf images.tgz
|
||||
fi
|
||||
|
||||
NL=`echo -ne '\015'`
|
||||
if [ "$USE_IPV6" == 1 ]; then
|
||||
echo "--use_ipv6" >>$NOVA_DIR/bin/nova.conf
|
||||
fi
|
||||
|
||||
function screen_it {
|
||||
screen -S nova -X screen -t $1
|
||||
screen -S nova -p $1 -X stuff "$2$NL"
|
||||
}
|
||||
|
||||
if [ "$CMD" == "run" ]; then
|
||||
killall dnsmasq
|
||||
#For IPv6
|
||||
killall radvd
|
||||
if [ "$USE_IPV6" == 1 ]; then
|
||||
killall radvd
|
||||
fi
|
||||
screen -d -m -S nova -t nova
|
||||
sleep 1
|
||||
if [ "$USE_MYSQL" == 1 ]; then
|
||||
@@ -150,6 +162,8 @@ if [ "$CMD" == "run" ]; then
|
||||
cd $DIR
|
||||
fi
|
||||
|
||||
# create the database
|
||||
$NOVA_DIR/bin/nova-manage db sync
|
||||
# create an admin user called 'admin'
|
||||
$NOVA_DIR/bin/nova-manage user admin admin admin admin
|
||||
# create a project called 'admin' with project manager of 'admin'
|
||||
@@ -178,6 +192,7 @@ if [ "$CMD" == "run" ] || [ "$CMD" == "terminate" ]; then
|
||||
sleep 2
|
||||
# delete volumes
|
||||
. $NOVA_DIR/novarc; euca-describe-volumes | grep vol- | cut -f2 | xargs -n1 euca-delete-volume
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
if [ "$CMD" == "run" ] || [ "$CMD" == "clean" ]; then
|
||||
@@ -192,5 +207,4 @@ if [ "$CMD" == "scrub" ]; then
|
||||
else
|
||||
virsh list | grep i- | awk '{print \$1}' | xargs -n1 virsh destroy
|
||||
fi
|
||||
vblade-persist ls | grep vol- | awk '{print \$1\" \"\$2}' | xargs -n2 vblade-persist destroy
|
||||
fi
|
||||
|
||||
@@ -26,6 +26,7 @@ Assumptions
|
||||
* Networking is configured between/through the physical machines on a single subnet.
|
||||
* Installation and execution are both performed by ROOT user.
|
||||
|
||||
|
||||
Scripted Installation
|
||||
---------------------
|
||||
A script available to get your OpenStack cloud running quickly. You can copy the file to the server where you want to install OpenStack Compute services - typically you would install a compute node and a cloud controller node.
|
||||
|
||||
@@ -42,6 +42,17 @@ You can also run with a category argument such as user to see a list of all comm
|
||||
|
||||
These sections describe the available categories and arguments for nova-manage.
|
||||
|
||||
Nova Db
|
||||
~~~~~~~
|
||||
|
||||
``nova-manage db version``
|
||||
|
||||
Print the current database version.
|
||||
|
||||
``nova-manage db sync``
|
||||
|
||||
Sync the database up to the most recent version. This is the standard way to create the db as well.
|
||||
|
||||
Nova User
|
||||
~~~~~~~~~
|
||||
|
||||
|
||||
@@ -52,7 +52,13 @@ When the installation is complete, you'll see the following lines:
|
||||
Finished processing dependencies for nova==2010.1
|
||||
|
||||
|
||||
Step 4: Create a Nova administrator
|
||||
Step 4: Create the Nova Database
|
||||
--------------------------------
|
||||
Type or copy/paste in the following line to create your nova db::
|
||||
|
||||
sudo nova-manage db sync
|
||||
|
||||
Step 5: Create a Nova administrator
|
||||
-----------------------------------
|
||||
Type or copy/paste in the following line to create a user named "anne."::
|
||||
|
||||
@@ -63,7 +69,7 @@ You see an access key and a secret key export, such as these made-up ones:::
|
||||
export EC2_ACCESS_KEY=4e6498a2-blah-blah-blah-17d1333t97fd
|
||||
export EC2_SECRET_KEY=0a520304-blah-blah-blah-340sp34k05bbe9a7
|
||||
|
||||
Step 5: Create the network
|
||||
Step 6: Create the network
|
||||
--------------------------
|
||||
|
||||
Type or copy/paste in the following line to create a network prior to creating a project.
|
||||
@@ -76,7 +82,7 @@ For this command, the IP address is the cidr notation for your netmask, such as
|
||||
|
||||
After running this command, entries are made in the 'networks' and 'fixed_ips' table in the database.
|
||||
|
||||
Step 6: Create a project with the user you created
|
||||
Step 7: Create a project with the user you created
|
||||
--------------------------------------------------
|
||||
Type or copy/paste in the following line to create a project named IRT (for Ice Road Truckers, of course) with the newly-created user named anne.
|
||||
|
||||
@@ -106,7 +112,7 @@ Type or copy/paste in the following line to create a project named IRT (for Ice
|
||||
Data Base Updated
|
||||
|
||||
|
||||
Step 7: Unzip the nova.zip
|
||||
Step 8: Unzip the nova.zip
|
||||
--------------------------
|
||||
|
||||
You should have a nova.zip file in your current working directory. Unzip it with this command:
|
||||
@@ -128,7 +134,7 @@ You'll see these files extract.
|
||||
extracting: cacert.pem
|
||||
|
||||
|
||||
Step 8: Source the rc file
|
||||
Step 9: Source the rc file
|
||||
--------------------------
|
||||
Type or copy/paste the following to source the novarc file in your current working directory.
|
||||
|
||||
@@ -137,14 +143,14 @@ Type or copy/paste the following to source the novarc file in your current worki
|
||||
. novarc
|
||||
|
||||
|
||||
Step 9: Pat yourself on the back :)
|
||||
Step 10: Pat yourself on the back :)
|
||||
-----------------------------------
|
||||
Congratulations, your cloud is up and running, you’ve created an admin user, created a network, retrieved the user's credentials and put them in your environment.
|
||||
|
||||
Now you need an image.
|
||||
|
||||
|
||||
Step 9: Get an image
|
||||
Step 11: Get an image
|
||||
--------------------
|
||||
To make things easier, we've provided a small image on the Rackspace CDN. Use this command to get it on your server.
|
||||
|
||||
@@ -168,7 +174,7 @@ To make things easier, we've provided a small image on the Rackspace CDN. Use th
|
||||
|
||||
|
||||
|
||||
Step 10: Decompress the image file
|
||||
Step 12: Decompress the image file
|
||||
----------------------------------
|
||||
Use this command to extract the image files:::
|
||||
|
||||
@@ -187,7 +193,7 @@ You get a directory listing like so:::
|
||||
|-- image
|
||||
`-- info.json
|
||||
|
||||
Step 11: Send commands to upload sample image to the cloud
|
||||
Step 13: Send commands to upload sample image to the cloud
|
||||
----------------------------------------------------------
|
||||
|
||||
Type or copy/paste the following commands to create a manifest for the kernel.::
|
||||
|
||||
@@ -42,6 +42,17 @@ You can also run with a category argument such as user to see a list of all comm
|
||||
|
||||
These sections describe the available categories and arguments for nova-manage.
|
||||
|
||||
Nova Db
|
||||
~~~~~~~
|
||||
|
||||
``nova-manage db version``
|
||||
|
||||
Print the current database version.
|
||||
|
||||
``nova-manage db sync``
|
||||
|
||||
Sync the database up to the most recent version. This is the standard way to create the db as well.
|
||||
|
||||
Nova User
|
||||
~~~~~~~~~
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"machine" : ["kernel", "ramdisk"]
|
||||
}
|
||||
@@ -190,6 +190,45 @@ class HostInfo(object):
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
class InstanceType(object):
|
||||
"""
|
||||
Information about a Nova instance type, as parsed through SAX.
|
||||
|
||||
**Fields include**
|
||||
|
||||
* name
|
||||
* vcpus
|
||||
* disk_gb
|
||||
* memory_mb
|
||||
* flavor_id
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, connection=None):
|
||||
self.connection = connection
|
||||
self.name = None
|
||||
self.vcpus = None
|
||||
self.disk_gb = None
|
||||
self.memory_mb = None
|
||||
self.flavor_id = None
|
||||
|
||||
def __repr__(self):
|
||||
return 'InstanceType:%s' % self.name
|
||||
|
||||
def startElement(self, name, attrs, connection):
|
||||
return None
|
||||
|
||||
def endElement(self, name, value, connection):
|
||||
if name == "memoryMb":
|
||||
self.memory_mb = str(value)
|
||||
elif name == "flavorId":
|
||||
self.flavor_id = str(value)
|
||||
elif name == "diskGb":
|
||||
self.disk_gb = str(value)
|
||||
else:
|
||||
setattr(self, name, str(value))
|
||||
|
||||
|
||||
class NovaAdminClient(object):
|
||||
|
||||
def __init__(
|
||||
@@ -373,3 +412,8 @@ class NovaAdminClient(object):
|
||||
|
||||
def get_hosts(self):
|
||||
return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)])
|
||||
|
||||
def get_instance_types(self):
|
||||
"""Grabs the list of all users."""
|
||||
return self.apiconn.get_list('DescribeInstanceTypes', {},
|
||||
[('item', InstanceType)])
|
||||
|
||||
@@ -33,6 +33,7 @@ from nova import log as logging
|
||||
from nova import utils
|
||||
from nova import wsgi
|
||||
from nova.api.ec2 import apirequest
|
||||
from nova.api.ec2 import cloud
|
||||
from nova.auth import manager
|
||||
|
||||
|
||||
@@ -170,7 +171,7 @@ class Authenticate(wsgi.Middleware):
|
||||
req.path)
|
||||
# Be explicit for what exceptions are 403, the rest bubble as 500
|
||||
except (exception.NotFound, exception.NotAuthorized) as ex:
|
||||
LOG.audit(_("Authentication Failure: %s"), str(ex))
|
||||
LOG.audit(_("Authentication Failure: %s"), ex.args[0])
|
||||
raise webob.exc.HTTPForbidden()
|
||||
|
||||
# Authenticated!
|
||||
@@ -213,7 +214,8 @@ class Requestify(wsgi.Middleware):
|
||||
LOG.debug(_('arg: %(key)s\t\tval: %(value)s') % locals())
|
||||
|
||||
# Success!
|
||||
api_request = apirequest.APIRequest(self.controller, action, args)
|
||||
api_request = apirequest.APIRequest(self.controller, action,
|
||||
req.params['Version'], args)
|
||||
req.environ['ec2.request'] = api_request
|
||||
req.environ['ec2.action_args'] = args
|
||||
return self.application
|
||||
@@ -313,18 +315,31 @@ class Executor(wsgi.Application):
|
||||
result = None
|
||||
try:
|
||||
result = api_request.invoke(context)
|
||||
except exception.InstanceNotFound as ex:
|
||||
LOG.info(_('InstanceNotFound raised: %s'), ex.args[0],
|
||||
context=context)
|
||||
ec2_id = cloud.id_to_ec2_id(ex.instance_id)
|
||||
message = _('Instance %s not found') % ec2_id
|
||||
return self._error(req, context, type(ex).__name__, message)
|
||||
except exception.VolumeNotFound as ex:
|
||||
LOG.info(_('VolumeNotFound raised: %s'), ex.args[0],
|
||||
context=context)
|
||||
ec2_id = cloud.id_to_ec2_id(ex.volume_id, 'vol-%08x')
|
||||
message = _('Volume %s not found') % ec2_id
|
||||
return self._error(req, context, type(ex).__name__, message)
|
||||
except exception.NotFound as ex:
|
||||
LOG.info(_('NotFound raised: %s'), str(ex), context=context)
|
||||
return self._error(req, context, type(ex).__name__, str(ex))
|
||||
LOG.info(_('NotFound raised: %s'), ex.args[0], context=context)
|
||||
return self._error(req, context, type(ex).__name__, ex.args[0])
|
||||
except exception.ApiError as ex:
|
||||
LOG.exception(_('ApiError raised: %s'), str(ex), context=context)
|
||||
LOG.exception(_('ApiError raised: %s'), ex.args[0],
|
||||
context=context)
|
||||
if ex.code:
|
||||
return self._error(req, context, ex.code, str(ex))
|
||||
return self._error(req, context, ex.code, ex.args[0])
|
||||
else:
|
||||
return self._error(req, context, type(ex).__name__, str(ex))
|
||||
return self._error(req, context, type(ex).__name__, ex.args[0])
|
||||
except Exception as ex:
|
||||
extra = {'environment': req.environ}
|
||||
LOG.exception(_('Unexpected error raised: %s'), str(ex),
|
||||
LOG.exception(_('Unexpected error raised: %s'), ex.args[0],
|
||||
extra=extra, context=context)
|
||||
return self._error(req,
|
||||
context,
|
||||
@@ -347,7 +362,8 @@ class Executor(wsgi.Application):
|
||||
'<Response><Errors><Error><Code>%s</Code>'
|
||||
'<Message>%s</Message></Error></Errors>'
|
||||
'<RequestID>%s</RequestID></Response>' %
|
||||
(code, message, context.request_id))
|
||||
(utils.utf8(code), utils.utf8(message),
|
||||
utils.utf8(context.request_id)))
|
||||
return resp
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ from nova import db
|
||||
from nova import exception
|
||||
from nova import log as logging
|
||||
from nova.auth import manager
|
||||
from nova.compute import instance_types
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.api.ec2.admin')
|
||||
@@ -62,6 +63,14 @@ def host_dict(host):
|
||||
return {}
|
||||
|
||||
|
||||
def instance_dict(name, inst):
|
||||
return {'name': name,
|
||||
'memory_mb': inst['memory_mb'],
|
||||
'vcpus': inst['vcpus'],
|
||||
'disk_gb': inst['local_gb'],
|
||||
'flavor_id': inst['flavorid']}
|
||||
|
||||
|
||||
class AdminController(object):
|
||||
"""
|
||||
API Controller for users, hosts, nodes, and workers.
|
||||
@@ -70,6 +79,10 @@ class AdminController(object):
|
||||
def __str__(self):
|
||||
return 'AdminController'
|
||||
|
||||
def describe_instance_types(self, _context, **_kwargs):
|
||||
return {'instanceTypeSet': [instance_dict(n, v) for n, v in
|
||||
instance_types.INSTANCE_TYPES.iteritems()]}
|
||||
|
||||
def describe_user(self, _context, name, **_kwargs):
|
||||
"""Returns user data, including access and secret keys."""
|
||||
return user_dict(manager.AuthManager().get_user(name))
|
||||
|
||||
@@ -83,9 +83,10 @@ def _try_convert(value):
|
||||
|
||||
|
||||
class APIRequest(object):
|
||||
def __init__(self, controller, action, args):
|
||||
def __init__(self, controller, action, version, args):
|
||||
self.controller = controller
|
||||
self.action = action
|
||||
self.version = version
|
||||
self.args = args
|
||||
|
||||
def invoke(self, context):
|
||||
@@ -132,7 +133,7 @@ class APIRequest(object):
|
||||
|
||||
response_el = xml.createElement(self.action + 'Response')
|
||||
response_el.setAttribute('xmlns',
|
||||
'http://ec2.amazonaws.com/doc/2009-11-30/')
|
||||
'http://ec2.amazonaws.com/doc/%s/' % self.version)
|
||||
request_id_el = xml.createElement('requestId')
|
||||
request_id_el.appendChild(xml.createTextNode(request_id))
|
||||
response_el.appendChild(request_id_el)
|
||||
|
||||
@@ -529,11 +529,14 @@ class CloudController(object):
|
||||
|
||||
def describe_volumes(self, context, volume_id=None, **kwargs):
|
||||
if volume_id:
|
||||
volume_id = [ec2_id_to_id(x) for x in volume_id]
|
||||
volumes = self.volume_api.get_all(context)
|
||||
# NOTE(vish): volume_id is an optional list of volume ids to filter by.
|
||||
volumes = [self._format_volume(context, v) for v in volumes
|
||||
if volume_id is None or v['id'] in volume_id]
|
||||
volumes = []
|
||||
for ec2_id in volume_id:
|
||||
internal_id = ec2_id_to_id(ec2_id)
|
||||
volume = self.volume_api.get(context, internal_id)
|
||||
volumes.append(volume)
|
||||
else:
|
||||
volumes = self.volume_api.get_all(context)
|
||||
volumes = [self._format_volume(context, v) for v in volumes]
|
||||
return {'volumeSet': volumes}
|
||||
|
||||
def _format_volume(self, context, volume):
|
||||
@@ -658,8 +661,11 @@ class CloudController(object):
|
||||
reservations = {}
|
||||
# NOTE(vish): instance_id is an optional list of ids to filter by
|
||||
if instance_id:
|
||||
instance_id = [ec2_id_to_id(x) for x in instance_id]
|
||||
instances = [self.compute_api.get(context, x) for x in instance_id]
|
||||
instances = []
|
||||
for ec2_id in instance_id:
|
||||
internal_id = ec2_id_to_id(ec2_id)
|
||||
instance = self.compute_api.get(context, internal_id)
|
||||
instances.append(instance)
|
||||
else:
|
||||
instances = self.compute_api.get_all(context, **kwargs)
|
||||
for instance in instances:
|
||||
|
||||
@@ -38,9 +38,6 @@ from nova.api.openstack import shared_ip_groups
|
||||
|
||||
LOG = logging.getLogger('nova.api.openstack')
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_string('os_krm_mapping_file',
|
||||
'krm_mapping.json',
|
||||
'Location of OpenStack Flavor/OS:EC2 Kernel/Ramdisk/Machine JSON file.')
|
||||
flags.DEFINE_bool('allow_admin_api',
|
||||
False,
|
||||
'When True, this API service will accept admin operations.')
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_image_id_from_image_hash(image_service, context, image_hash):
|
||||
except NotImplementedError:
|
||||
items = image_service.index(context)
|
||||
for image in items:
|
||||
image_id = image['imageId']
|
||||
image_id = image['id']
|
||||
if abs(hash(image_id)) == int(image_hash):
|
||||
return image_id
|
||||
raise exception.NotFound(image_hash)
|
||||
|
||||
@@ -124,17 +124,23 @@ class Controller(wsgi.Controller):
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
|
||||
def _get_kernel_ramdisk_from_image(self, image_id):
|
||||
mapping_filename = FLAGS.os_krm_mapping_file
|
||||
def _get_kernel_ramdisk_from_image(self, req, image_id):
|
||||
"""
|
||||
Machine images are associated with Kernels and Ramdisk images via
|
||||
metadata stored in Glance as 'image_properties'
|
||||
"""
|
||||
def lookup(param):
|
||||
_image_id = image_id
|
||||
try:
|
||||
return image['properties'][param]
|
||||
except KeyError:
|
||||
raise exception.NotFound(
|
||||
_("%(param)s property not found for image %(_image_id)s") %
|
||||
locals())
|
||||
|
||||
with open(mapping_filename) as f:
|
||||
mapping = json.load(f)
|
||||
if image_id in mapping:
|
||||
return mapping[image_id]
|
||||
|
||||
msg = _("No entry for image '%(image_id)s'"
|
||||
" in mapping file '%(mapping_filename)s'") % locals()
|
||||
raise exception.NotFound(msg)
|
||||
image_id = str(image_id)
|
||||
image = self._image_service.show(req.environ['nova.context'], image_id)
|
||||
return lookup('kernel_id'), lookup('ramdisk_id')
|
||||
|
||||
def create(self, req):
|
||||
""" Creates a new server for a given user """
|
||||
@@ -146,7 +152,8 @@ class Controller(wsgi.Controller):
|
||||
req.environ['nova.context'])[0]
|
||||
image_id = common.get_image_id_from_image_hash(self._image_service,
|
||||
req.environ['nova.context'], env['server']['imageId'])
|
||||
kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(image_id)
|
||||
kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(
|
||||
req, image_id)
|
||||
instances = self.compute_api.create(
|
||||
req.environ['nova.context'],
|
||||
instance_types.get_by_flavor_id(env['server']['flavorId']),
|
||||
|
||||
@@ -318,7 +318,7 @@ class API(base.Base):
|
||||
|
||||
def get(self, context, instance_id):
|
||||
"""Get a single instance with the given ID."""
|
||||
rv = self.db.instance_get_by_id(context, instance_id)
|
||||
rv = self.db.instance_get(context, instance_id)
|
||||
return dict(rv.iteritems())
|
||||
|
||||
def get_all(self, context, project_id=None, reservation_id=None,
|
||||
|
||||
@@ -118,7 +118,7 @@ class ComputeManager(manager.Manager):
|
||||
"""Do any initialization that needs to be run if this is a
|
||||
standalone service.
|
||||
"""
|
||||
self.driver.init_host()
|
||||
self.driver.init_host(host=self.host)
|
||||
|
||||
def _update_state(self, context, instance_id):
|
||||
"""Update the state of an instance from the driver info."""
|
||||
|
||||
@@ -71,7 +71,6 @@ class NoMoreTargets(exception.Error):
|
||||
"""No more available blades"""
|
||||
pass
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
@@ -351,6 +350,11 @@ def instance_get_all_by_project(context, project_id):
|
||||
return IMPL.instance_get_all_by_project(context, project_id)
|
||||
|
||||
|
||||
def instance_get_all_by_host(context, host):
|
||||
"""Get all instance belonging to a host."""
|
||||
return IMPL.instance_get_all_by_host(context, host)
|
||||
|
||||
|
||||
def instance_get_all_by_reservation(context, reservation_id):
|
||||
"""Get all instance belonging to a reservation."""
|
||||
return IMPL.instance_get_all_by_reservation(context, reservation_id)
|
||||
@@ -375,11 +379,6 @@ def instance_get_project_vpn(context, project_id):
|
||||
return IMPL.instance_get_project_vpn(context, project_id)
|
||||
|
||||
|
||||
def instance_get_by_id(context, instance_id):
|
||||
"""Get an instance by id."""
|
||||
return IMPL.instance_get_by_id(context, instance_id)
|
||||
|
||||
|
||||
def instance_is_vpn(context, instance_id):
|
||||
"""True if instance is a vpn."""
|
||||
return IMPL.instance_is_vpn(context, instance_id)
|
||||
|
||||
@@ -685,6 +685,7 @@ def instance_get(context, instance_id, session=None):
|
||||
options(joinedload_all('fixed_ip.floating_ips')).\
|
||||
options(joinedload_all('security_groups.rules')).\
|
||||
options(joinedload('volumes')).\
|
||||
options(joinedload_all('fixed_ip.network')).\
|
||||
filter_by(id=instance_id).\
|
||||
filter_by(deleted=can_read_deleted(context)).\
|
||||
first()
|
||||
@@ -698,7 +699,9 @@ def instance_get(context, instance_id, session=None):
|
||||
filter_by(deleted=False).\
|
||||
first()
|
||||
if not result:
|
||||
raise exception.NotFound(_('No instance for id %s') % instance_id)
|
||||
raise exception.InstanceNotFound(_('Instance %s not found')
|
||||
% instance_id,
|
||||
instance_id)
|
||||
|
||||
return result
|
||||
|
||||
@@ -724,6 +727,17 @@ def instance_get_all_by_user(context, user_id):
|
||||
all()
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def instance_get_all_by_host(context, host):
|
||||
session = get_session()
|
||||
return session.query(models.Instance).\
|
||||
options(joinedload_all('fixed_ip.floating_ips')).\
|
||||
options(joinedload('security_groups')).\
|
||||
filter_by(host=host).\
|
||||
filter_by(deleted=can_read_deleted(context)).\
|
||||
all()
|
||||
|
||||
|
||||
@require_context
|
||||
def instance_get_all_by_project(context, project_id):
|
||||
authorize_project_context(context, project_id)
|
||||
@@ -770,33 +784,6 @@ def instance_get_project_vpn(context, project_id):
|
||||
first()
|
||||
|
||||
|
||||
@require_context
|
||||
def instance_get_by_id(context, instance_id):
|
||||
session = get_session()
|
||||
|
||||
if is_admin_context(context):
|
||||
result = session.query(models.Instance).\
|
||||
options(joinedload_all('fixed_ip.floating_ips')).\
|
||||
options(joinedload('security_groups')).\
|
||||
options(joinedload_all('fixed_ip.network')).\
|
||||
filter_by(id=instance_id).\
|
||||
filter_by(deleted=can_read_deleted(context)).\
|
||||
first()
|
||||
elif is_user_context(context):
|
||||
result = session.query(models.Instance).\
|
||||
options(joinedload('security_groups')).\
|
||||
options(joinedload_all('fixed_ip.floating_ips')).\
|
||||
options(joinedload_all('fixed_ip.network')).\
|
||||
filter_by(project_id=context.project_id).\
|
||||
filter_by(id=instance_id).\
|
||||
filter_by(deleted=False).\
|
||||
first()
|
||||
if not result:
|
||||
raise exception.NotFound(_('Instance %s not found') % (instance_id))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def instance_get_fixed_address(context, instance_id):
|
||||
session = get_session()
|
||||
@@ -1396,17 +1383,20 @@ def volume_get(context, volume_id, session=None):
|
||||
|
||||
if is_admin_context(context):
|
||||
result = session.query(models.Volume).\
|
||||
options(joinedload('instance')).\
|
||||
filter_by(id=volume_id).\
|
||||
filter_by(deleted=can_read_deleted(context)).\
|
||||
first()
|
||||
elif is_user_context(context):
|
||||
result = session.query(models.Volume).\
|
||||
options(joinedload('instance')).\
|
||||
filter_by(project_id=context.project_id).\
|
||||
filter_by(id=volume_id).\
|
||||
filter_by(deleted=False).\
|
||||
first()
|
||||
if not result:
|
||||
raise exception.NotFound(_('No volume for id %s') % volume_id)
|
||||
raise exception.VolumeNotFound(_('Volume %s not found') % volume_id,
|
||||
volume_id)
|
||||
|
||||
return result
|
||||
|
||||
@@ -1451,7 +1441,8 @@ def volume_get_instance(context, volume_id):
|
||||
options(joinedload('instance')).\
|
||||
first()
|
||||
if not result:
|
||||
raise exception.NotFound(_('Volume %s not found') % ec2_id)
|
||||
raise exception.VolumeNotFound(_('Volume %s not found') % volume_id,
|
||||
volume_id)
|
||||
|
||||
return result.instance
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ Session Handling for SQLAlchemy backend
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
@@ -43,4 +44,6 @@ def get_session(autocommit=True, expire_on_commit=False):
|
||||
autocommit=autocommit,
|
||||
expire_on_commit=expire_on_commit))
|
||||
session = _MAKER()
|
||||
session.query = exception.wrap_db_error(session.query)
|
||||
session.flush = exception.wrap_db_error(session.flush)
|
||||
return session
|
||||
|
||||
@@ -46,7 +46,6 @@ class Error(Exception):
|
||||
|
||||
|
||||
class ApiError(Error):
|
||||
|
||||
def __init__(self, message='Unknown', code='Unknown'):
|
||||
self.message = message
|
||||
self.code = code
|
||||
@@ -57,6 +56,18 @@ class NotFound(Error):
|
||||
pass
|
||||
|
||||
|
||||
class InstanceNotFound(NotFound):
|
||||
def __init__(self, message, instance_id):
|
||||
self.instance_id = instance_id
|
||||
super(InstanceNotFound, self).__init__(message)
|
||||
|
||||
|
||||
class VolumeNotFound(NotFound):
|
||||
def __init__(self, message, volume_id):
|
||||
self.volume_id = volume_id
|
||||
super(VolumeNotFound, self).__init__(message)
|
||||
|
||||
|
||||
class Duplicate(Error):
|
||||
pass
|
||||
|
||||
@@ -81,6 +92,24 @@ class TimeoutException(Error):
|
||||
pass
|
||||
|
||||
|
||||
class DBError(Error):
|
||||
"""Wraps an implementation specific exception"""
|
||||
def __init__(self, inner_exception):
|
||||
self.inner_exception = inner_exception
|
||||
super(DBError, self).__init__(str(inner_exception))
|
||||
|
||||
|
||||
def wrap_db_error(f):
|
||||
def _wrap(*args, **kwargs):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except Exception, e:
|
||||
LOG.exception(_('DB exception wrapped'))
|
||||
raise DBError(e)
|
||||
return _wrap
|
||||
_wrap.func_name = f.func_name
|
||||
|
||||
|
||||
def wrap_exception(f):
|
||||
def _wrap(*args, **kw):
|
||||
try:
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import cPickle as pickle
|
||||
import os.path
|
||||
import random
|
||||
import tempfile
|
||||
|
||||
from nova import exception
|
||||
from nova.image import service
|
||||
@@ -26,15 +27,12 @@ from nova.image import service
|
||||
class LocalImageService(service.BaseImageService):
|
||||
|
||||
"""Image service storing images to local disk.
|
||||
It assumes that image_ids are integers.
|
||||
|
||||
It assumes that image_ids are integers."""
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._path = "/tmp/nova/images"
|
||||
try:
|
||||
os.makedirs(self._path)
|
||||
except OSError: # Exists
|
||||
pass
|
||||
self._path = tempfile.mkdtemp()
|
||||
|
||||
def _path_to(self, image_id):
|
||||
return os.path.join(self._path, str(image_id))
|
||||
@@ -56,9 +54,7 @@ class LocalImageService(service.BaseImageService):
|
||||
raise exception.NotFound
|
||||
|
||||
def create(self, context, data):
|
||||
"""
|
||||
Store the image data and return the new image id.
|
||||
"""
|
||||
"""Store the image data and return the new image id."""
|
||||
id = random.randint(0, 2 ** 31 - 1)
|
||||
data['id'] = id
|
||||
self.update(context, id, data)
|
||||
@@ -72,8 +68,9 @@ class LocalImageService(service.BaseImageService):
|
||||
raise exception.NotFound
|
||||
|
||||
def delete(self, context, image_id):
|
||||
"""
|
||||
Delete the given image. Raises OSError if the image does not exist.
|
||||
"""Delete the given image.
|
||||
Raises OSError if the image does not exist.
|
||||
|
||||
"""
|
||||
try:
|
||||
os.unlink(self._path_to(image_id))
|
||||
@@ -81,8 +78,13 @@ class LocalImageService(service.BaseImageService):
|
||||
raise exception.NotFound
|
||||
|
||||
def delete_all(self):
|
||||
"""
|
||||
Clears out all images in local directory
|
||||
"""
|
||||
"""Clears out all images in local directory."""
|
||||
for id in self._ids():
|
||||
os.unlink(self._path_to(id))
|
||||
|
||||
def delete_imagedir(self):
|
||||
"""Deletes the local directory.
|
||||
Raises OSError if directory is not empty.
|
||||
|
||||
"""
|
||||
os.rmdir(self._path)
|
||||
|
||||
@@ -65,12 +65,19 @@ class S3ImageService(service.BaseImageService):
|
||||
'image_id': image_id}))
|
||||
return image_id
|
||||
|
||||
def _fix_image_id(self, images):
|
||||
"""S3 has imageId but OpenStack wants id"""
|
||||
for image in images:
|
||||
if 'imageId' in image:
|
||||
image['id'] = image['imageId']
|
||||
return images
|
||||
|
||||
def index(self, context):
|
||||
"""Return a list of all images that a user can see."""
|
||||
response = self._conn(context).make_request(
|
||||
method='GET',
|
||||
bucket='_images')
|
||||
return json.loads(response.read())
|
||||
return self._fix_image_id(json.loads(response.read()))
|
||||
|
||||
def show(self, context, image_id):
|
||||
"""return a image object if the context has permissions"""
|
||||
|
||||
@@ -198,9 +198,9 @@ def ensure_bridge(bridge, interface, net_attrs=None):
|
||||
net_attrs['broadcast'],
|
||||
net_attrs['netmask']))
|
||||
if(FLAGS.use_ipv6):
|
||||
_execute("sudo ifconfig %s add %s up" % \
|
||||
(bridge,
|
||||
net_attrs['cidr_v6']))
|
||||
_execute("sudo ip -f inet6 addr change %s dev %s" %
|
||||
(net_attrs['cidr_v6'], bridge))
|
||||
_execute("sudo ifconfig %s up" % bridge)
|
||||
else:
|
||||
_execute("sudo ifconfig %s up" % bridge)
|
||||
if FLAGS.use_nova_chains:
|
||||
@@ -298,10 +298,9 @@ interface %s
|
||||
% pid, check_exit_code=False)
|
||||
if conffile in out:
|
||||
try:
|
||||
_execute('sudo kill -HUP %d' % pid)
|
||||
return
|
||||
_execute('sudo kill %d' % pid)
|
||||
except Exception as exc: # pylint: disable-msg=W0703
|
||||
LOG.debug(_("Hupping radvd threw %s"), exc)
|
||||
LOG.debug(_("killing radvd threw %s"), exc)
|
||||
else:
|
||||
LOG.debug(_("Pid %d is stale, relaunching radvd"), pid)
|
||||
command = _ra_cmd(network_ref)
|
||||
|
||||
@@ -395,6 +395,7 @@ class FlatDHCPManager(FlatManager):
|
||||
standalone service.
|
||||
"""
|
||||
super(FlatDHCPManager, self).init_host()
|
||||
self.driver.init_host()
|
||||
self.driver.metadata_forward()
|
||||
|
||||
def setup_compute_network(self, context, instance_id):
|
||||
@@ -427,6 +428,10 @@ class FlatDHCPManager(FlatManager):
|
||||
self.driver.ensure_bridge(network_ref['bridge'],
|
||||
FLAGS.flat_interface,
|
||||
network_ref)
|
||||
if not FLAGS.fake_network:
|
||||
self.driver.update_dhcp(context, network_id)
|
||||
if(FLAGS.use_ipv6):
|
||||
self.driver.update_ra(context, network_id)
|
||||
|
||||
|
||||
class VlanManager(NetworkManager):
|
||||
@@ -460,8 +465,8 @@ class VlanManager(NetworkManager):
|
||||
standalone service.
|
||||
"""
|
||||
super(VlanManager, self).init_host()
|
||||
self.driver.metadata_forward()
|
||||
self.driver.init_host()
|
||||
self.driver.metadata_forward()
|
||||
|
||||
def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):
|
||||
"""Gets a fixed ip from the pool."""
|
||||
@@ -496,7 +501,7 @@ class VlanManager(NetworkManager):
|
||||
network_ref['bridge'])
|
||||
|
||||
def create_networks(self, context, cidr, num_networks, network_size,
|
||||
vlan_start, vpn_start, cidr_v6):
|
||||
cidr_v6, vlan_start, vpn_start):
|
||||
"""Create networks based on parameters."""
|
||||
fixed_net = IPy.IP(cidr)
|
||||
fixed_net_v6 = IPy.IP(cidr_v6)
|
||||
|
||||
@@ -157,8 +157,9 @@ class Service(object):
|
||||
report_interval = FLAGS.report_interval
|
||||
if not periodic_interval:
|
||||
periodic_interval = FLAGS.periodic_interval
|
||||
logging.audit(_("Starting %s node (version %s)"), topic,
|
||||
version.version_string_with_vcs())
|
||||
vcs_string = version.version_string_with_vcs()
|
||||
logging.audit(_("Starting %(topic)s node (version %(vcs_string)s)")
|
||||
% locals())
|
||||
service_obj = cls(host, binary, topic, manager,
|
||||
report_interval, periodic_interval)
|
||||
|
||||
|
||||
@@ -69,9 +69,10 @@ class TestCase(unittest.TestCase):
|
||||
network_manager.VlanManager().create_networks(ctxt,
|
||||
FLAGS.fixed_range,
|
||||
5, 16,
|
||||
FLAGS.fixed_range_v6,
|
||||
FLAGS.vlan_start,
|
||||
FLAGS.vpn_start,
|
||||
FLAGS.fixed_range_v6)
|
||||
)
|
||||
|
||||
# emulate some of the mox stuff, we can't use the metaclass
|
||||
# because it screws with our generators
|
||||
|
||||
@@ -143,6 +143,7 @@ class LocalImageServiceTest(unittest.TestCase,
|
||||
|
||||
def tearDown(self):
|
||||
self.service.delete_all()
|
||||
self.service.delete_imagedir()
|
||||
self.stubs.UnsetAll()
|
||||
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class ServersTest(unittest.TestCase):
|
||||
fakes.stub_out_key_pair_funcs(self.stubs)
|
||||
fakes.stub_out_image_service(self.stubs)
|
||||
self.stubs.Set(nova.db.api, 'instance_get_all', return_servers)
|
||||
self.stubs.Set(nova.db.api, 'instance_get_by_id', return_server)
|
||||
self.stubs.Set(nova.db.api, 'instance_get', return_server)
|
||||
self.stubs.Set(nova.db.api, 'instance_get_all_by_user',
|
||||
return_servers)
|
||||
self.stubs.Set(nova.db.api, 'instance_add_security_group',
|
||||
|
||||
@@ -36,6 +36,7 @@ from nova.auth import manager
|
||||
class FakeHttplibSocket(object):
|
||||
"""a fake socket implementation for httplib.HTTPResponse, trivial"""
|
||||
def __init__(self, response_string):
|
||||
self.response_string = response_string
|
||||
self._buffer = StringIO.StringIO(response_string)
|
||||
|
||||
def makefile(self, _mode, _other):
|
||||
@@ -66,13 +67,16 @@ class FakeHttplibConnection(object):
|
||||
# For some reason, the response doesn't have "HTTP/1.0 " prepended; I
|
||||
# guess that's a function the web server usually provides.
|
||||
resp = "HTTP/1.0 %s" % resp
|
||||
sock = FakeHttplibSocket(resp)
|
||||
self.http_response = httplib.HTTPResponse(sock)
|
||||
self.sock = FakeHttplibSocket(resp)
|
||||
self.http_response = httplib.HTTPResponse(self.sock)
|
||||
self.http_response.begin()
|
||||
|
||||
def getresponse(self):
|
||||
return self.http_response
|
||||
|
||||
def getresponsebody(self):
|
||||
return self.sock.response_string
|
||||
|
||||
def close(self):
|
||||
"""Required for compatibility with boto/tornado"""
|
||||
pass
|
||||
@@ -104,7 +108,7 @@ class ApiEc2TestCase(test.TestCase):
|
||||
self.app = ec2.Authenticate(ec2.Requestify(ec2.Executor(),
|
||||
'nova.api.ec2.cloud.CloudController'))
|
||||
|
||||
def expect_http(self, host=None, is_secure=False):
|
||||
def expect_http(self, host=None, is_secure=False, api_version=None):
|
||||
"""Returns a new EC2 connection"""
|
||||
self.ec2 = boto.connect_ec2(
|
||||
aws_access_key_id='fake',
|
||||
@@ -113,13 +117,31 @@ class ApiEc2TestCase(test.TestCase):
|
||||
region=regioninfo.RegionInfo(None, 'test', self.host),
|
||||
port=8773,
|
||||
path='/services/Cloud')
|
||||
if api_version:
|
||||
self.ec2.APIVersion = api_version
|
||||
|
||||
self.mox.StubOutWithMock(self.ec2, 'new_http_connection')
|
||||
http = FakeHttplibConnection(
|
||||
self.http = FakeHttplibConnection(
|
||||
self.app, '%s:8773' % (self.host), False)
|
||||
# pylint: disable-msg=E1103
|
||||
self.ec2.new_http_connection(host, is_secure).AndReturn(http)
|
||||
return http
|
||||
self.ec2.new_http_connection(host, is_secure).AndReturn(self.http)
|
||||
return self.http
|
||||
|
||||
def test_xmlns_version_matches_request_version(self):
|
||||
self.expect_http(api_version='2010-10-30')
|
||||
self.mox.ReplayAll()
|
||||
|
||||
user = self.manager.create_user('fake', 'fake', 'fake')
|
||||
project = self.manager.create_project('fake', 'fake', 'fake')
|
||||
|
||||
# Any request should be fine
|
||||
self.ec2.get_all_instances()
|
||||
self.assertTrue(self.ec2.APIVersion in self.http.getresponsebody(),
|
||||
'The version in the xmlns of the response does '
|
||||
'not match the API version given in the request.')
|
||||
|
||||
self.manager.delete_project(project)
|
||||
self.manager.delete_user(user)
|
||||
|
||||
def test_describe_instances(self):
|
||||
"""Test that, after creating a user and a project, the describe
|
||||
|
||||
100
nova/tests/test_localization.py
Normal file
100
nova/tests/test_localization.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Copyright 2011 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import nova
|
||||
|
||||
|
||||
class LocalizationTestCase(unittest.TestCase):
|
||||
def test_multiple_positional_format_placeholders(self):
|
||||
pat = re.compile("\W_\(")
|
||||
single_pat = re.compile("\W%\W")
|
||||
root_path = os.path.dirname(nova.__file__)
|
||||
problems = {}
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for fname in files:
|
||||
if not fname.endswith(".py"):
|
||||
continue
|
||||
pth = os.path.join(root, fname)
|
||||
txt = fulltext = file(pth).read()
|
||||
txt_lines = fulltext.splitlines()
|
||||
if not pat.search(txt):
|
||||
continue
|
||||
problems[pth] = []
|
||||
pos = txt.find("_(")
|
||||
while pos > -1:
|
||||
# Make sure that this isn't part of a dunder;
|
||||
# e.g., __init__(...
|
||||
# or something like 'self.assert_(...'
|
||||
test_txt = txt[pos - 1: pos + 10]
|
||||
if not (pat.search(test_txt)):
|
||||
txt = txt[pos + 2:]
|
||||
pos = txt.find("_(")
|
||||
continue
|
||||
pos += 2
|
||||
txt = txt[pos:]
|
||||
innerChars = []
|
||||
# Count pairs of open/close parens until _() closing
|
||||
# paren is found.
|
||||
parenCount = 1
|
||||
pos = 0
|
||||
while parenCount > 0:
|
||||
char = txt[pos]
|
||||
if char == "(":
|
||||
parenCount += 1
|
||||
elif char == ")":
|
||||
parenCount -= 1
|
||||
innerChars.append(char)
|
||||
pos += 1
|
||||
inner_all = "".join(innerChars)
|
||||
# Filter out '%%' and '%('
|
||||
inner = inner_all.replace("%%", "").replace("%(", "")
|
||||
# Filter out the single '%' operators
|
||||
inner = single_pat.sub("", inner)
|
||||
# Within the remaining content, count %
|
||||
fmtCount = inner.count("%")
|
||||
if fmtCount > 1:
|
||||
inner_first = inner_all.splitlines()[0]
|
||||
lns = ["%s" % (p + 1)
|
||||
for p, t in enumerate(txt_lines)
|
||||
if inner_first in t]
|
||||
lnums = ", ".join(lns)
|
||||
# Using ugly string concatenation to avoid having
|
||||
# this test fail itself.
|
||||
inner_all = "_" + "(" + "%s" % inner_all
|
||||
problems[pth].append("Line: %s Text: %s" %
|
||||
(lnums, inner_all))
|
||||
# Look for more
|
||||
pos = txt.find("_(")
|
||||
if not problems[pth]:
|
||||
del problems[pth]
|
||||
if problems:
|
||||
out = ["Problem(s) found in localized string formatting",
|
||||
"(see http://www.gnu.org/software/hello/manual/"
|
||||
"gettext/Python.html for more information)",
|
||||
"",
|
||||
" ------------ Files to fix ------------"]
|
||||
for pth in problems:
|
||||
out.append(" %s:" % pth)
|
||||
for val in set(problems[pth]):
|
||||
out.append(" %s" % val)
|
||||
raise AssertionError("\n".join(out))
|
||||
@@ -221,7 +221,12 @@ class IptablesFirewallTestCase(test.TestCase):
|
||||
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
||||
self.context = context.RequestContext('fake', 'fake')
|
||||
self.network = utils.import_object(FLAGS.network_manager)
|
||||
self.fw = libvirt_conn.IptablesFirewallDriver()
|
||||
|
||||
class FakeLibvirtConnection(object):
|
||||
pass
|
||||
self.fake_libvirt_connection = FakeLibvirtConnection()
|
||||
self.fw = libvirt_conn.IptablesFirewallDriver(
|
||||
get_connection=lambda: self.fake_libvirt_connection)
|
||||
|
||||
def tearDown(self):
|
||||
self.manager.delete_project(self.project)
|
||||
@@ -474,6 +479,19 @@ class NWFilterTestCase(test.TestCase):
|
||||
'project_id': 'fake'})
|
||||
inst_id = instance_ref['id']
|
||||
|
||||
ip = '10.11.12.13'
|
||||
|
||||
network_ref = db.project_get_network(self.context,
|
||||
'fake')
|
||||
|
||||
fixed_ip = {'address': ip,
|
||||
'network_id': network_ref['id']}
|
||||
|
||||
admin_ctxt = context.get_admin_context()
|
||||
db.fixed_ip_create(admin_ctxt, fixed_ip)
|
||||
db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
|
||||
'instance_id': instance_ref['id']})
|
||||
|
||||
def _ensure_all_called():
|
||||
instance_filter = 'nova-instance-%s' % instance_ref['name']
|
||||
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
|
||||
|
||||
@@ -206,21 +206,17 @@ def last_octet(address):
|
||||
def get_my_linklocal(interface):
|
||||
try:
|
||||
if_str = execute("ip -f inet6 -o addr show %s" % interface)
|
||||
condition = "\s+inet6\s+([0-9a-f:]+/\d+)\s+scope\s+link"
|
||||
condition = "\s+inet6\s+([0-9a-f:]+)/\d+\s+scope\s+link"
|
||||
links = [re.search(condition, x) for x in if_str[0].split('\n')]
|
||||
address = [w.group(1) for w in links if w is not None]
|
||||
if address[0] is not None:
|
||||
return address[0]
|
||||
else:
|
||||
return 'fe00::'
|
||||
except IndexError as ex:
|
||||
LOG.warn(_("Couldn't get Link Local IP of %(interface)s :%(ex)s")
|
||||
% locals())
|
||||
except ProcessExecutionError as ex:
|
||||
LOG.warn(_("Couldn't get Link Local IP of %(interface)s :%(ex)s")
|
||||
% locals())
|
||||
except:
|
||||
return 'fe00::'
|
||||
raise exception.Error(_("Link Local address is not found.:%s")
|
||||
% if_str)
|
||||
except Exception as ex:
|
||||
raise exception.Error(_("Couldn't get Link Local IP of %(interface)s"
|
||||
" :%(ex)s") % locals())
|
||||
|
||||
|
||||
def to_global_ipv6(prefix, mac):
|
||||
|
||||
@@ -76,9 +76,10 @@ class FakeConnection(object):
|
||||
cls._instance = cls()
|
||||
return cls._instance
|
||||
|
||||
def init_host(self):
|
||||
def init_host(self, host):
|
||||
"""
|
||||
Initialize anything that is necessary for the driver to function
|
||||
Initialize anything that is necessary for the driver to function,
|
||||
including catching up with currently running VM's on the given host.
|
||||
"""
|
||||
return
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ class HyperVConnection(object):
|
||||
self._conn = wmi.WMI(moniker='//./root/virtualization')
|
||||
self._cim_conn = wmi.WMI(moniker='//./root/cimv2')
|
||||
|
||||
def init_host(self):
|
||||
def init_host(self, host):
|
||||
#FIXME(chiradeep): implement this
|
||||
LOG.debug(_('In init host'))
|
||||
pass
|
||||
@@ -191,7 +191,7 @@ class HyperVConnection(object):
|
||||
vcpus = long(instance['vcpus'])
|
||||
procsetting.VirtualQuantity = vcpus
|
||||
procsetting.Reservation = vcpus
|
||||
procsetting.Limit = vcpus
|
||||
procsetting.Limit = 100000 # static assignment to 100%
|
||||
|
||||
(job, ret_val) = vs_man_svc.ModifyVirtualSystemResources(
|
||||
vm.path_(), [procsetting.GetText_(1)])
|
||||
|
||||
@@ -111,5 +111,8 @@ def _image_path(path):
|
||||
|
||||
|
||||
def image_url(image):
|
||||
if FLAGS.image_service == "nova.image.glance.GlanceImageService":
|
||||
return "http://%s:%s/images/%s" % (FLAGS.glance_host,
|
||||
FLAGS.glance_port, image)
|
||||
return "http://%s:%s/_images/%s/image" % (FLAGS.s3_host, FLAGS.s3_port,
|
||||
image)
|
||||
|
||||
@@ -76,9 +76,11 @@
|
||||
<filterref filter="nova-instance-${name}">
|
||||
<parameter name="IP" value="${ip_address}" />
|
||||
<parameter name="DHCPSERVER" value="${dhcp_server}" />
|
||||
<parameter name="RASERVER" value="${ra_server}" />
|
||||
#if $getVar('extra_params', False)
|
||||
${extra_params}
|
||||
#end if
|
||||
#if $getVar('ra_server', False)
|
||||
<parameter name="RASERVER" value="${ra_server}" />
|
||||
#end if
|
||||
</filterref>
|
||||
</interface>
|
||||
|
||||
@@ -149,16 +149,34 @@ class LibvirtConnection(object):
|
||||
self._wrapped_conn = None
|
||||
self.read_only = read_only
|
||||
|
||||
self.nwfilter = NWFilterFirewall(self._get_connection)
|
||||
fw_class = utils.import_class(FLAGS.firewall_driver)
|
||||
self.firewall_driver = fw_class(get_connection=self._get_connection)
|
||||
|
||||
if not FLAGS.firewall_driver:
|
||||
self.firewall_driver = self.nwfilter
|
||||
self.nwfilter.handle_security_groups = True
|
||||
else:
|
||||
self.firewall_driver = utils.import_object(FLAGS.firewall_driver)
|
||||
def init_host(self, host):
|
||||
# Adopt existing VM's running here
|
||||
ctxt = context.get_admin_context()
|
||||
for instance in db.instance_get_all_by_host(ctxt, host):
|
||||
try:
|
||||
LOG.debug(_('Checking state of %s'), instance['name'])
|
||||
state = self.get_info(instance['name'])['state']
|
||||
except exception.NotFound:
|
||||
state = power_state.SHUTOFF
|
||||
|
||||
def init_host(self):
|
||||
pass
|
||||
LOG.debug(_('Current state of %(name)s was %(state)s.'),
|
||||
{'name': instance['name'], 'state': state})
|
||||
db.instance_set_state(ctxt, instance['id'], state)
|
||||
|
||||
if state == power_state.SHUTOFF:
|
||||
# TODO(soren): This is what the compute manager does when you
|
||||
# terminate # an instance. At some point I figure we'll have a
|
||||
# "terminated" state and some sort of cleanup job that runs
|
||||
# occasionally, cleaning them out.
|
||||
db.instance_destroy(ctxt, instance['id'])
|
||||
|
||||
if state != power_state.RUNNING:
|
||||
continue
|
||||
self.firewall_driver.prepare_instance_filter(instance)
|
||||
self.firewall_driver.apply_instance_filter(instance)
|
||||
|
||||
def _get_connection(self):
|
||||
if not self._wrapped_conn or not self._test_connection():
|
||||
@@ -386,7 +404,7 @@ class LibvirtConnection(object):
|
||||
instance['id'],
|
||||
power_state.NOSTATE,
|
||||
'launching')
|
||||
self.nwfilter.setup_basic_filtering(instance)
|
||||
self.firewall_driver.setup_basic_filtering(instance)
|
||||
self.firewall_driver.prepare_instance_filter(instance)
|
||||
self._create_image(instance, xml)
|
||||
self._conn.createXML(xml, 0)
|
||||
@@ -655,8 +673,7 @@ class LibvirtConnection(object):
|
||||
# Assume that the gateway also acts as the dhcp server.
|
||||
dhcp_server = network['gateway']
|
||||
ra_server = network['ra_server']
|
||||
if not ra_server:
|
||||
ra_server = 'fd00::'
|
||||
|
||||
if FLAGS.allow_project_net_traffic:
|
||||
if FLAGS.use_ipv6:
|
||||
net, mask = _get_net_and_mask(network['cidr'])
|
||||
@@ -695,11 +712,13 @@ class LibvirtConnection(object):
|
||||
'mac_address': instance['mac_address'],
|
||||
'ip_address': ip_address,
|
||||
'dhcp_server': dhcp_server,
|
||||
'ra_server': ra_server,
|
||||
'extra_params': extra_params,
|
||||
'rescue': rescue,
|
||||
'local': instance_type['local_gb'],
|
||||
'driver_type': driver_type}
|
||||
|
||||
if ra_server:
|
||||
xml_info['ra_server'] = ra_server + "/128"
|
||||
if not rescue:
|
||||
if instance['kernel_id']:
|
||||
xml_info['kernel'] = xml_info['basepath'] + "/kernel"
|
||||
@@ -882,6 +901,20 @@ class FirewallDriver(object):
|
||||
the security group."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def setup_basic_filtering(self, instance):
|
||||
"""Create rules to block spoofing and allow dhcp.
|
||||
|
||||
This gets called when spawning an instance, before
|
||||
:method:`prepare_instance_filter`.
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _ra_server_for_instance(self, instance):
|
||||
network = db.network_get_by_instance(context.get_admin_context(),
|
||||
instance['id'])
|
||||
return network['ra_server']
|
||||
|
||||
|
||||
class NWFilterFirewall(FirewallDriver):
|
||||
"""
|
||||
@@ -929,11 +962,15 @@ class NWFilterFirewall(FirewallDriver):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, get_connection):
|
||||
def __init__(self, get_connection, **kwargs):
|
||||
self._libvirt_get_connection = get_connection
|
||||
self.static_filters_configured = False
|
||||
self.handle_security_groups = False
|
||||
|
||||
def apply_instance_filter(self, instance):
|
||||
"""No-op. Everything is done in prepare_instance_filter"""
|
||||
pass
|
||||
|
||||
def _get_connection(self):
|
||||
return self._libvirt_get_connection()
|
||||
_conn = property(_get_connection)
|
||||
@@ -1092,7 +1129,9 @@ class NWFilterFirewall(FirewallDriver):
|
||||
'nova-base-ipv6',
|
||||
'nova-allow-dhcp-server']
|
||||
if FLAGS.use_ipv6:
|
||||
instance_secgroup_filter_children += ['nova-allow-ra-server']
|
||||
ra_server = self._ra_server_for_instance(instance)
|
||||
if ra_server:
|
||||
instance_secgroup_filter_children += ['nova-allow-ra-server']
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
@@ -1119,10 +1158,6 @@ class NWFilterFirewall(FirewallDriver):
|
||||
|
||||
return
|
||||
|
||||
def apply_instance_filter(self, instance):
|
||||
"""No-op. Everything is done in prepare_instance_filter"""
|
||||
pass
|
||||
|
||||
def refresh_security_group_rules(self, security_group_id):
|
||||
return self._define_filter(
|
||||
self.security_group_to_nwfilter_xml(security_group_id))
|
||||
@@ -1170,9 +1205,14 @@ class NWFilterFirewall(FirewallDriver):
|
||||
|
||||
|
||||
class IptablesFirewallDriver(FirewallDriver):
|
||||
def __init__(self, execute=None):
|
||||
def __init__(self, execute=None, **kwargs):
|
||||
self.execute = execute or utils.execute
|
||||
self.instances = {}
|
||||
self.nwfilter = NWFilterFirewall(kwargs['get_connection'])
|
||||
|
||||
def setup_basic_filtering(self, instance):
|
||||
"""Use NWFilter from libvirt for this."""
|
||||
return self.nwfilter.setup_basic_filtering(instance)
|
||||
|
||||
def apply_instance_filter(self, instance):
|
||||
"""No-op. Everything is done in prepare_instance_filter"""
|
||||
@@ -1228,6 +1268,7 @@ class IptablesFirewallDriver(FirewallDriver):
|
||||
|
||||
our_chains += [':nova-local - [0:0]']
|
||||
our_rules += ['-A FORWARD -j nova-local']
|
||||
our_rules += ['-A OUTPUT -j nova-local']
|
||||
|
||||
security_groups = {}
|
||||
# Add our chains
|
||||
@@ -1268,13 +1309,23 @@ class IptablesFirewallDriver(FirewallDriver):
|
||||
if(ip_version == 4):
|
||||
# Allow DHCP responses
|
||||
dhcp_server = self._dhcp_server_for_instance(instance)
|
||||
our_rules += ['-A %s -s %s -p udp --sport 67 --dport 68' %
|
||||
(chain_name, dhcp_server)]
|
||||
our_rules += ['-A %s -s %s -p udp --sport 67 --dport 68 '
|
||||
'-j ACCEPT ' % (chain_name, dhcp_server)]
|
||||
#Allow project network traffic
|
||||
if (FLAGS.allow_project_net_traffic):
|
||||
cidr = self._project_cidr_for_instance(instance)
|
||||
our_rules += ['-A %s -s %s -j ACCEPT' % (chain_name, cidr)]
|
||||
elif(ip_version == 6):
|
||||
# Allow RA responses
|
||||
ra_server = self._ra_server_for_instance(instance)
|
||||
our_rules += ['-A %s -s %s -p icmpv6' %
|
||||
(chain_name, ra_server)]
|
||||
if ra_server:
|
||||
our_rules += ['-A %s -s %s -p icmpv6 -j ACCEPT' %
|
||||
(chain_name, ra_server + "/128")]
|
||||
#Allow project network traffic
|
||||
if (FLAGS.allow_project_net_traffic):
|
||||
cidrv6 = self._project_cidrv6_for_instance(instance)
|
||||
our_rules += ['-A %s -s %s -j ACCEPT' %
|
||||
(chain_name, cidrv6)]
|
||||
|
||||
# If nothing matches, jump to the fallback chain
|
||||
our_rules += ['-A %s -j nova-fallback' % (chain_name,)]
|
||||
@@ -1369,3 +1420,13 @@ class IptablesFirewallDriver(FirewallDriver):
|
||||
network = db.network_get_by_instance(context.get_admin_context(),
|
||||
instance['id'])
|
||||
return network['ra_server']
|
||||
|
||||
def _project_cidr_for_instance(self, instance):
|
||||
network = db.network_get_by_instance(context.get_admin_context(),
|
||||
instance['id'])
|
||||
return network['cidr']
|
||||
|
||||
def _project_cidrv6_for_instance(self, instance):
|
||||
network = db.network_get_by_instance(context.get_admin_context(),
|
||||
instance['id'])
|
||||
return network['cidr_v6']
|
||||
|
||||
@@ -640,7 +640,7 @@ def with_vdi_attached_here(session, vdi, read_only, f):
|
||||
session.get_xenapi().VBD.plug(vbd)
|
||||
LOG.debug(_('Plugging VBD %s done.'), vbd)
|
||||
orig_dev = session.get_xenapi().VBD.get_device(vbd)
|
||||
LOG.debug(_('VBD %s plugged as %s'), vbd, orig_dev)
|
||||
LOG.debug(_('VBD %(vbd)s plugged as %(orig_dev)s') % locals())
|
||||
dev = remap_vbd_dev(orig_dev)
|
||||
if dev != orig_dev:
|
||||
LOG.debug(_('VBD %(vbd)s plugged into wrong dev, '
|
||||
|
||||
@@ -149,7 +149,7 @@ class VMOps(object):
|
||||
if isinstance(instance_or_vm, (int, long)):
|
||||
ctx = context.get_admin_context()
|
||||
try:
|
||||
instance_obj = db.instance_get_by_id(ctx, instance_or_vm)
|
||||
instance_obj = db.instance_get(ctx, instance_or_vm)
|
||||
instance_name = instance_obj.name
|
||||
except exception.NotFound:
|
||||
# The unit tests screw this up, as they use an integer for
|
||||
|
||||
@@ -141,7 +141,7 @@ class XenAPIConnection(object):
|
||||
self._vmops = VMOps(session)
|
||||
self._volumeops = VolumeOps(session)
|
||||
|
||||
def init_host(self):
|
||||
def init_host(self, host):
|
||||
#FIXME(armando): implement this
|
||||
#NOTE(armando): would we need a method
|
||||
#to call when shutting down the host?
|
||||
|
||||
@@ -26,6 +26,7 @@ import logging
|
||||
import logging.handlers
|
||||
import re
|
||||
import time
|
||||
import XenAPI
|
||||
|
||||
|
||||
##### Logging setup
|
||||
|
||||
Reference in New Issue
Block a user