Merge trunk
This commit is contained in:
4
Authors
4
Authors
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
::
|
||||
|
||||
|
||||
@@ -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, you’ve created an admin user, retrieved the user's credentials and put them in your environment.
|
||||
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.
|
||||
|
||||
|
||||
@@ -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
|
||||
------------------
|
||||
|
||||
BIN
doc/source/images/novascreens.png
Normal file
BIN
doc/source/images/novascreens.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
doc/source/images/novashvirtually.png
Normal file
BIN
doc/source/images/novashvirtually.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@@ -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
|
||||
==============
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
119
nova/auth/opendj.sh
Executable 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
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user