Merge trunk

This commit is contained in:
Soren Hansen
2010-12-15 11:54:00 +01:00
27 changed files with 362 additions and 86 deletions

View File

@@ -3,6 +3,7 @@ Anne Gentle <anne@openstack.org>
Anthony Young <sleepsonthefloor@gmail.com>
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
Chris Behrens <cbehrens@codestud.com>
Chmouel Boudjnah <chmouel@chmouel.com>
Dean Troyer <dtroyer@gmail.com>
Devin Carlen <devin.carlen@gmail.com>
Eric Day <eday@oddments.org>
@@ -20,8 +21,11 @@ Michael Gundlach <michael.gundlach@rackspace.com>
Monty Taylor <mordred@inaugust.com>
Paul Voccio <paul@openstack.org>
Rick Clark <rick@openstack.org>
Ryan Lucio <rlucio@internap.com>
Sandy Walsh <sandy.walsh@rackspace.com>
Soren Hansen <soren.hansen@rackspace.com>
Todd Willey <todd@ansolabs.com>
Trey Morris <trey.morris@rackspace.com>
Vishvananda Ishaya <vishvananda@gmail.com>
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
Zhixue Wu <Zhixue.Wu@citrix.com>

View File

@@ -21,6 +21,7 @@
Nova API daemon.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import flags
from nova import utils
from nova import server

View File

@@ -21,6 +21,7 @@
Twistd daemon for the nova compute nodes.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import service
from nova import twistd
from nova import utils

View File

@@ -21,6 +21,7 @@
Handle lease database updates from DHCP servers.
"""
import gettext
import logging
import os
import sys
@@ -33,6 +34,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import context
from nova import db
from nova import flags

View File

@@ -21,6 +21,7 @@
Download images from Canonical Image Store
"""
import gettext
import json
import os
import tempfile
@@ -37,6 +38,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import flags
from nova import utils
from nova.objectstore import image

View File

@@ -21,6 +21,7 @@
Daemon for Nova RRD based instance resource monitoring.
"""
import gettext
import os
import logging
import sys
@@ -34,6 +35,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import utils
from nova import twistd
from nova.compute import monitor

View File

@@ -53,6 +53,7 @@
CLI interface for nova management.
"""
import gettext
import logging
import os
import sys
@@ -68,6 +69,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import context
from nova import db
from nova import exception
@@ -359,9 +362,14 @@ class ProjectCommands(object):
def zipfile(self, project_id, user_id, filename='nova.zip'):
"""Exports credentials for project to a zip file
arguments: project_id user_id [filename='nova.zip]"""
zip_file = self.manager.get_credentials(user_id, project_id)
with open(filename, 'w') as f:
f.write(zip_file)
try:
zip_file = self.manager.get_credentials(user_id, project_id)
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')
class FloatingIpCommands(object):

View File

@@ -21,6 +21,7 @@
Twistd daemon for the nova network nodes.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import service
from nova import twistd
from nova import utils

View File

@@ -21,6 +21,7 @@
Twisted daemon for nova objectstore. Supports S3 API.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import flags
from nova import utils
from nova import twistd

View File

@@ -21,6 +21,7 @@
Twistd daemon for the nova scheduler nodes.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import service
from nova import twistd
from nova import utils

View File

@@ -21,6 +21,7 @@
Twistd daemon for the nova volume nodes.
"""
import gettext
import os
import sys
@@ -32,6 +33,8 @@ 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)
gettext.install('nova', unicode=1)
from nova import service
from nova import twistd
from nova import utils

View File

@@ -23,7 +23,7 @@ In Nova, users organize their cloud resources in projects. A Nova project consis
Nova Network Strategies
-----------------------
Currently, Nova supports three kinds of networks, implemented in three "Network Manager" types respectively: Flat Network Manager, Flat DHCP Network Manager, and VLAN Network Manager. The three kinds of networks can c-exist in a cloud system. However, the scheduler for selecting the type of network for a given project is not yet implemented. Here is a brief description of each of the different network strategies, with a focus on the VLAN Manager in a separate section.
Currently, Nova supports three kinds of networks, implemented in three "Network Manager" types respectively: Flat Network Manager, Flat DHCP Network Manager, and VLAN Network Manager. The three kinds of networks can co-exist in a cloud system. However, the scheduler for selecting the type of network for a given project is not yet implemented. Here is a brief description of each of the different network strategies, with a focus on the VLAN Manager in a separate section.
Read more about Nova network strategies here:

View File

@@ -35,7 +35,6 @@ Requirements for a multi-node installation
* For a recommended HA setup, consider a MySQL master/slave replication, with as many slaves as you like, and probably a heartbeat to kick one of the slaves into being a master if it dies.
* For performance optimization, split reads and writes to the database. MySQL proxy is the easiest way to make this work if running MySQL.
Assumptions
^^^^^^^^^^^
@@ -69,14 +68,14 @@ Step 1 Use apt-get to get the latest code
It is highly likely that there will be errors when the nova services come up since they are not yet configured. Don't worry, you're only at step 1!
Step 2 Setup configuration files (installed in /etc/nova)
Step 2 Setup configuration file (installed in /etc/nova)
---------------------------------------------------------
Note: CC_ADDR=<the external IP address of your cloud controller>
1. These need to be defined in EACH configuration file
Nova development has consolidated all .conf files to nova.conf as of November 2010. References to specific .conf files may be ignored.
::
#. These need to be defined in the nova.conf configuration file::
--sql_connection=mysql://root:nova@$CC_ADDR/nova # location of nova sql db
--s3_host=$CC_ADDR # This is where nova is hosting the objectstore service, which
@@ -87,31 +86,14 @@ Note: CC_ADDR=<the external IP address of your cloud controller>
--ec2_url=http://$CC_ADDR:8773/services/Cloud
--network_manager=nova.network.manager.FlatManager # simple, no-vlan networking type
2. nova-manage specific flags
::
--fixed_range=<network/prefix> # ip network to use for VM guests, ex 192.168.2.64/26
--network_size=<# of addrs> # number of ip addrs to use for VM guests, ex 64
3. nova-network specific flags
::
--fixed_range=<network/prefix> # ip network to use for VM guests, ex 192.168.2.64/26
--network_size=<# of addrs> # number of ip addrs to use for VM guests, ex 64
4. Create a nova group
::
#. Create a nova group::
sudo addgroup nova
5. nova-objectstore specific flags < no specific config needed >
Config files should be have their owner set to root:nova, and mode set to 0640, since they contain your MySQL server's root password.
The Nova config file should have its owner set to root:nova, and mode set to 0640, since they contain your MySQL server's root password.
::
@@ -121,7 +103,7 @@ Config files should be have their owner set to root:nova, and mode set to 0640,
Step 3 Setup the sql db
-----------------------
1. First you 'preseed' (using vishy's :doc:`../quickstart`). Run this as root.
1. First you 'preseed' (using the Quick Start method :doc:`../quickstart`). Run this as root.
::

View File

@@ -9,7 +9,7 @@ The fastest way to get a test cloud running is through our :doc:`../quickstart`.
Step 1 and 2: Get the latest Nova code system software
------------------------------------------------------
Depending on your system, the mehod for accomplishing this varies
Depending on your system, the method for accomplishing this varies
.. toctree::
:maxdepth: 1
@@ -139,7 +139,7 @@ Type or copy/paste the following to source the novarc file in your current worki
Step 9: Pat yourself on the back :)
-----------------------------------
Congratulations, your cloud is up and running, youve created an admin user, retrieved the user's credentials and put them in your environment.
Congratulations, your cloud is up and running, youve created an admin user, created a network, retrieved the user's credentials and put them in your environment.
Now you need an image.

View File

@@ -54,6 +54,8 @@ Cloud computing offers different service models depending on the capabilities a
The US-based National Institute of Standards and Technology offers definitions for cloud computing
and the service models that are emerging.
These definitions are summarized from http://csrc.nist.gov/groups/SNS/cloud-computing/.
SaaS - Software as a Service
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,12 +74,15 @@ IaaS - Infrastructure as a Service
Provides infrastructure such as computer instances, network connections, and storage so that people
can run any software or operating system.
.. todo:: Use definitions from http://csrc.nist.gov/groups/SNS/cloud-computing/ and attribute NIST
Types of Cloud Deployments
--------------------------
.. todo:: describe public/private/hybrid/etc
When you hear terms such as public cloud or private cloud, these refer to the deployment model for the cloud. A private cloud operates for a single organization, but can be managed on-premise or off-premise. A public cloud has an infrastructure that is available to the general public or a large industry group and is likely owned by a cloud services company.
The NIST also defines community cloud as shared by several organizations supporting a specific community with shared concerns.
A hybrid cloud can be a deployment model, as a composition of both public and private clouds, or a hybrid model for cloud computing may involve both virtual and physical servers.
Work in the Clouds
------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -26,7 +26,7 @@ Nova is written with the following design guidelines in mind:
* **Component based architecture**: Quickly add new behaviors
* **Highly available**: Scale to very serious workloads
* **Fault-Tollerant**: Isloated processes avoid cascading failures
* **Fault-Tolerant**: Isolated processes avoid cascading failures
* **Recoverable**: Failures should be easy to diagnose, debug, and rectify
* **Open Standards**: Be a reference implementation for a community-driven api
* **API Compatibility**: Nova strives to provide API-compatible with popular systems like Amazon EC2
@@ -62,8 +62,6 @@ Administrator's Documentation
adminguide/single.node.install
adminguide/multi.node.install
.. todo:: add swiftadmin
Developer Docs
==============

View File

@@ -1,2 +1,48 @@
Installing the Live CD
======================
If you'd like to set up a sandbox installation of Nova, you can use one of these Live CD images.
If you don't already have VirtualBox installed, you can download it from http://www.virtualbox.org/wiki/Downloads.
Download the zip or iso file and then follow these steps to try Nova in a virtual environment.
http://c0047913.cdn1.cloudfiles.rackspacecloud.com/OpenStackNova.x86_64-2010.1.2.iso (OpenSUSE image; root password is "linux" for this image)
http://c0028699.cdn1.cloudfiles.rackspacecloud.com/nova-vm.zip (~900 MB) (log in information is nova/nova)
Once a VM is configured and started, here are the basics:
#. Login to Ubuntu using ID nova and Password nova.
#. Switch to running as sudo (enter nova when prompted for the password)::
sudo -s
#. To run Nova for the first time, enter::
cd /var/openstack/
#. Now that you're in the correct directory, enter::
./nova.sh run
.. image:: images/novashvirtually.png
If it's already running, use screen -ls, and when the nova screen is presented,then enter screen -d -r nova.
These are the steps to get an instance running (the image is already provided in this environment). Enter these commands in the "test" screen.
::
euca-add-keypair test > test.pem
chmod 600 test.pem
euca-run-instances -k test -t m1.tiny ami-tiny
euca-describe-instances
ssh -i test.pem root@10.0.0.3
To see output from the various workers, switch screen windows with Ctrl+A " (quotation mark).
.. image:: images/novascreens.png

View File

@@ -40,6 +40,8 @@ flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com',
flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users')
flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
'OU for Users')
flags.DEFINE_boolean('ldap_user_modify_only', False,
'Modify attributes for users instead of creating/deleting')
flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com',
'OU for Projects')
flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com',
@@ -89,8 +91,7 @@ class LdapDriver(object):
def get_user(self, uid):
"""Retrieve user by id"""
attr = self.__find_object(self.__uid_to_dn(uid),
'(objectclass=novaUser)')
attr = self.__get_ldap_user(uid)
return self.__to_user(attr)
def get_user_from_access_key(self, access):
@@ -110,7 +111,12 @@ class LdapDriver(object):
"""Retrieve list of users"""
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
'(objectclass=novaUser)')
return [self.__to_user(attr) for attr in attrs]
users = []
for attr in attrs:
user = self.__to_user(attr)
if user is not None:
users.append(user)
return users
def get_projects(self, uid=None):
"""Retrieve list of projects"""
@@ -125,21 +131,52 @@ class LdapDriver(object):
"""Create a user"""
if self.__user_exists(name):
raise exception.Duplicate("LDAP user %s already exists" % name)
attr = [
('objectclass', ['person',
'organizationalPerson',
'inetOrgPerson',
'novaUser']),
('ou', [FLAGS.ldap_user_unit]),
('uid', [name]),
('sn', [name]),
('cn', [name]),
('secretKey', [secret_key]),
('accessKey', [access_key]),
('isAdmin', [str(is_admin).upper()]),
]
self.conn.add_s(self.__uid_to_dn(name), attr)
return self.__to_user(dict(attr))
if FLAGS.ldap_user_modify_only:
if self.__ldap_user_exists(name):
# Retrieve user by name
user = self.__get_ldap_user(name)
# Entry could be malformed, test for missing attrs.
# Malformed entries are useless, replace attributes found.
attr = []
if 'secretKey' in user.keys():
attr.append((self.ldap.MOD_REPLACE, 'secretKey', \
[secret_key]))
else:
attr.append((self.ldap.MOD_ADD, 'secretKey', \
[secret_key]))
if 'accessKey' in user.keys():
attr.append((self.ldap.MOD_REPLACE, 'accessKey', \
[access_key]))
else:
attr.append((self.ldap.MOD_ADD, 'accessKey', \
[access_key]))
if 'isAdmin' in user.keys():
attr.append((self.ldap.MOD_REPLACE, 'isAdmin', \
[str(is_admin).upper()]))
else:
attr.append((self.ldap.MOD_ADD, 'isAdmin', \
[str(is_admin).upper()]))
self.conn.modify_s(self.__uid_to_dn(name), attr)
return self.get_user(name)
else:
raise exception.NotFound("LDAP object for %s doesn't exist"
% name)
else:
attr = [
('objectclass', ['person',
'organizationalPerson',
'inetOrgPerson',
'novaUser']),
('ou', [FLAGS.ldap_user_unit]),
('uid', [name]),
('sn', [name]),
('cn', [name]),
('secretKey', [secret_key]),
('accessKey', [access_key]),
('isAdmin', [str(is_admin).upper()]),
]
self.conn.add_s(self.__uid_to_dn(name), attr)
return self.__to_user(dict(attr))
def create_project(self, name, manager_uid,
description=None, member_uids=None):
@@ -155,7 +192,7 @@ class LdapDriver(object):
if description is None:
description = name
members = []
if member_uids != None:
if member_uids is not None:
for member_uid in member_uids:
if not self.__user_exists(member_uid):
raise exception.NotFound("Project can't be created "
@@ -256,7 +293,24 @@ class LdapDriver(object):
if not self.__user_exists(uid):
raise exception.NotFound("User %s doesn't exist" % uid)
self.__remove_from_all(uid)
self.conn.delete_s(self.__uid_to_dn(uid))
if FLAGS.ldap_user_modify_only:
# Delete attributes
attr = []
# Retrieve user by name
user = self.__get_ldap_user(uid)
if 'secretKey' in user.keys():
attr.append((self.ldap.MOD_DELETE, 'secretKey', \
user['secretKey']))
if 'accessKey' in user.keys():
attr.append((self.ldap.MOD_DELETE, 'accessKey', \
user['accessKey']))
if 'isAdmin' in user.keys():
attr.append((self.ldap.MOD_DELETE, 'isAdmin', \
user['isAdmin']))
self.conn.modify_s(self.__uid_to_dn(uid), attr)
else:
# Delete entry
self.conn.delete_s(self.__uid_to_dn(uid))
def delete_project(self, project_id):
"""Delete a project"""
@@ -265,7 +319,7 @@ class LdapDriver(object):
self.__delete_group(project_dn)
def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
"""Modify an existing project"""
"""Modify an existing user"""
if not access_key and not secret_key and admin is None:
return
attr = []
@@ -279,11 +333,21 @@ class LdapDriver(object):
def __user_exists(self, uid):
"""Check if user exists"""
return self.get_user(uid) != None
return self.get_user(uid) is not None
def __ldap_user_exists(self, uid):
"""Check if the user exists in ldap"""
return self.__get_ldap_user(uid) is not None
def __project_exists(self, project_id):
"""Check if project exists"""
return self.get_project(project_id) != None
return self.get_project(project_id) is not None
def __get_ldap_user(self, uid):
"""Retrieve LDAP user entry by id"""
attr = self.__find_object(self.__uid_to_dn(uid),
'(objectclass=novaUser)')
return attr
def __find_object(self, dn, query=None, scope=None):
"""Find an object by dn and query"""
@@ -330,12 +394,12 @@ class LdapDriver(object):
def __group_exists(self, dn):
"""Check if group exists"""
return self.__find_object(dn, '(objectclass=groupOfNames)') != None
return self.__find_object(dn, '(objectclass=groupOfNames)') is not None
@staticmethod
def __role_to_dn(role, project_id=None):
"""Convert role to corresponding dn"""
if project_id == None:
if project_id is None:
return FLAGS.__getitem__("ldap_%s" % role).value
else:
return 'cn=%s,cn=%s,%s' % (role,
@@ -349,7 +413,7 @@ class LdapDriver(object):
raise exception.Duplicate("Group can't be created because "
"group %s already exists" % name)
members = []
if member_uids != None:
if member_uids is not None:
for member_uid in member_uids:
if not self.__user_exists(member_uid):
raise exception.NotFound("Group can't be created "
@@ -375,7 +439,7 @@ class LdapDriver(object):
res = self.__find_object(group_dn,
'(member=%s)' % self.__uid_to_dn(uid),
self.ldap.SCOPE_BASE)
return res != None
return res is not None
def __add_to_group(self, uid, group_dn):
"""Add user to group"""
@@ -447,18 +511,22 @@ class LdapDriver(object):
@staticmethod
def __to_user(attr):
"""Convert ldap attributes to User object"""
if attr == None:
if attr is None:
return None
if ('accessKey' in attr.keys() and 'secretKey' in attr.keys() \
and 'isAdmin' in attr.keys()):
return {
'id': attr['uid'][0],
'name': attr['cn'][0],
'access': attr['accessKey'][0],
'secret': attr['secretKey'][0],
'admin': (attr['isAdmin'][0] == 'TRUE')}
else:
return None
return {
'id': attr['uid'][0],
'name': attr['cn'][0],
'access': attr['accessKey'][0],
'secret': attr['secretKey'][0],
'admin': (attr['isAdmin'][0] == 'TRUE')}
def __to_project(self, attr):
"""Convert ldap attributes to Project object"""
if attr == None:
if attr is None:
return None
member_dns = attr.get('member', [])
return {

View File

@@ -624,6 +624,10 @@ class AuthManager(object):
with self.driver() as drv:
drv.modify_user(uid, access_key, secret_key, admin)
@staticmethod
def get_key_pairs(context):
return db.key_pair_get_all_by_user(context.elevated(), context.user_id)
def get_credentials(self, user, project=None):
"""Get credential zip for user in project"""
if not isinstance(user, User):

119
nova/auth/opendj.sh Executable file
View File

@@ -0,0 +1,119 @@
#!/usr/bin/env bash
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# LDAP INSTALL SCRIPT - IS IDEMPOTENT, does not scrub users
apt-get install -y ldap-utils python-ldap openjdk-6-jre
if [ ! -d "/usr/opendj" ]
then
# TODO(rlane): Wikimedia Foundation is the current package maintainer.
# After the package is included in Ubuntu's channel, change this.
wget http://apt.wikimedia.org/wikimedia/pool/main/o/opendj/opendj_2.4.0-7_amd64.deb
dpkg -i opendj_2.4.0-7_amd64.deb
fi
abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"`
schemapath='/var/opendj/instance/config/schema'
cp $abspath/openssh-lpk_sun.schema $schemapath/97-openssh-lpk_sun.ldif
cp $abspath/nova_sun.schema $schemapath/98-nova_sun.ldif
chown opendj:opendj $schemapath/97-openssh-lpk_sun.ldif
chown opendj:opendj $schemapath/98-nova_sun.ldif
cat >/etc/ldap/ldap.conf <<LDAP_CONF_EOF
# LDAP Client Settings
URI ldap://localhost
BASE dc=example,dc=com
BINDDN cn=Directory Manager
SIZELIMIT 0
TIMELIMIT 0
LDAP_CONF_EOF
cat >/etc/ldap/base.ldif <<BASE_LDIF_EOF
# This is the root of the directory tree
dn: dc=example,dc=com
description: Example.Com, your trusted non-existent corporation.
dc: example
o: Example.Com
objectClass: top
objectClass: dcObject
objectClass: organization
# Subtree for users
dn: ou=Users,dc=example,dc=com
ou: Users
description: Users
objectClass: organizationalUnit
# Subtree for groups
dn: ou=Groups,dc=example,dc=com
ou: Groups
description: Groups
objectClass: organizationalUnit
# Subtree for system accounts
dn: ou=System,dc=example,dc=com
ou: System
description: Special accounts used by software applications.
objectClass: organizationalUnit
# Special Account for Authentication:
dn: uid=authenticate,ou=System,dc=example,dc=com
uid: authenticate
ou: System
description: Special account for authenticating users
userPassword: {MD5}TLnIqASP0CKUR3/LGkEZGg==
objectClass: account
objectClass: simpleSecurityObject
# create the sysadmin entry
dn: cn=developers,ou=Groups,dc=example,dc=com
objectclass: groupOfNames
cn: developers
description: IT admin group
member: uid=admin,ou=Users,dc=example,dc=com
dn: cn=sysadmins,ou=Groups,dc=example,dc=com
objectclass: groupOfNames
cn: sysadmins
description: IT admin group
member: uid=admin,ou=Users,dc=example,dc=com
dn: cn=netadmins,ou=Groups,dc=example,dc=com
objectclass: groupOfNames
cn: netadmins
description: Network admin group
member: uid=admin,ou=Users,dc=example,dc=com
dn: cn=cloudadmins,ou=Groups,dc=example,dc=com
objectclass: groupOfNames
cn: cloudadmins
description: Cloud admin group
member: uid=admin,ou=Users,dc=example,dc=com
dn: cn=itsec,ou=Groups,dc=example,dc=com
objectclass: groupOfNames
cn: itsec
description: IT security users group
member: uid=admin,ou=Users,dc=example,dc=com
BASE_LDIF_EOF
/etc/init.d/opendj stop
su - opendj -c '/usr/opendj/setup -i -b "dc=example,dc=com" -l /etc/ldap/base.ldif -S -w changeme -O -n --noPropertiesFile'
/etc/init.d/opendj start

View File

@@ -259,7 +259,7 @@ DEFINE_string('scheduler_manager', 'nova.scheduler.manager.SchedulerManager',
'Manager for scheduler')
# The service to use for image search and retrieval
DEFINE_string('image_service', 'nova.image.local.LocalImageService',
DEFINE_string('image_service', 'nova.image.s3.S3ImageService',
'The service to use for retrieving and searching for images.')
DEFINE_string('host', socket.gethostname(),

View File

@@ -29,3 +29,8 @@
.. moduleauthor:: Manish Singh <yosh@gimp.org>
.. moduleauthor:: Andy Smith <andy@anarkystic.com>
"""
# See http://code.google.com/p/python-nose/issues/detail?id=373
# The code below enables nosetests to work with i18n _() blocks
import __builtin__
setattr(__builtin__, '_', lambda x: x)

View File

@@ -126,6 +126,19 @@ class CloudTestCase(test.TrialTestCase):
db.instance_destroy(self.context, inst['id'])
db.floating_ip_destroy(self.context, address)
def test_describe_volumes(self):
"""Makes sure describe_volumes works and filters results."""
vol1 = db.volume_create(self.context, {})
vol2 = db.volume_create(self.context, {})
result = self.cloud.describe_volumes(self.context)
self.assertEqual(len(result['volumeSet']), 2)
result = self.cloud.describe_volumes(self.context,
volume_id=[vol2['ec2_id']])
self.assertEqual(len(result['volumeSet']), 1)
self.assertEqual(result['volumeSet'][0]['volumeId'], vol2['ec2_id'])
db.volume_destroy(self.context, vol1['id'])
db.volume_destroy(self.context, vol2['id'])
def test_console_output(self):
image_id = FLAGS.default_image
instance_type = FLAGS.default_instance_type

View File

@@ -72,33 +72,27 @@ class ComputeTestCase(test.TrialTestCase):
"""Verify that an instance cannot be created without a display_name."""
cases = [dict(), dict(display_name=None)]
for instance in cases:
ref = self.compute_api.create_instance(self.context, None,
**instance)
ref = self.compute_api.create_instances(self.context,
FLAGS.default_instance_type, None, **instance)
try:
self.assertNotEqual(ref.display_name, None)
self.assertNotEqual(ref[0].display_name, None)
finally:
db.instance_destroy(self.context, ref['id'])
db.instance_destroy(self.context, ref[0]['id'])
def test_create_instance_associates_security_groups(self):
"""Make sure create_instance associates security groups"""
inst = {}
inst['user_id'] = self.user.id
inst['project_id'] = self.project.id
"""Make sure create_instances associates security groups"""
values = {'name': 'default',
'description': 'default',
'user_id': self.user.id,
'project_id': self.project.id}
group = db.security_group_create(self.context, values)
ref = self.compute_api.create_instance(self.context,
security_groups=[group['id']],
**inst)
# reload to get groups
instance_ref = db.instance_get(self.context, ref['id'])
ref = self.compute_api.create_instances(self.context,
FLAGS.default_instance_type, None, security_group=['default'])
try:
self.assertEqual(len(instance_ref['security_groups']), 1)
self.assertEqual(len(ref[0]['security_groups']), 1)
finally:
db.security_group_destroy(self.context, group['id'])
db.instance_destroy(self.context, instance_ref['id'])
db.instance_destroy(self.context, ref[0]['id'])
@defer.inlineCallbacks
def test_run_terminate(self):

View File

@@ -40,9 +40,12 @@ Due to our use of multiprocessing it we frequently get some ignorable
"""
import __main__
import gettext
import os
import sys
gettext.install('nova', unicode=1)
from twisted.scripts import trial as trial_script
from nova import flags