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>
|
Anthony Young <sleepsonthefloor@gmail.com>
|
||||||
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
||||||
Chris Behrens <cbehrens@codestud.com>
|
Chris Behrens <cbehrens@codestud.com>
|
||||||
|
Chmouel Boudjnah <chmouel@chmouel.com>
|
||||||
Dean Troyer <dtroyer@gmail.com>
|
Dean Troyer <dtroyer@gmail.com>
|
||||||
Devin Carlen <devin.carlen@gmail.com>
|
Devin Carlen <devin.carlen@gmail.com>
|
||||||
Eric Day <eday@oddments.org>
|
Eric Day <eday@oddments.org>
|
||||||
@@ -20,8 +21,11 @@ Michael Gundlach <michael.gundlach@rackspace.com>
|
|||||||
Monty Taylor <mordred@inaugust.com>
|
Monty Taylor <mordred@inaugust.com>
|
||||||
Paul Voccio <paul@openstack.org>
|
Paul Voccio <paul@openstack.org>
|
||||||
Rick Clark <rick@openstack.org>
|
Rick Clark <rick@openstack.org>
|
||||||
|
Ryan Lucio <rlucio@internap.com>
|
||||||
|
Sandy Walsh <sandy.walsh@rackspace.com>
|
||||||
Soren Hansen <soren.hansen@rackspace.com>
|
Soren Hansen <soren.hansen@rackspace.com>
|
||||||
Todd Willey <todd@ansolabs.com>
|
Todd Willey <todd@ansolabs.com>
|
||||||
|
Trey Morris <trey.morris@rackspace.com>
|
||||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||||
Zhixue Wu <Zhixue.Wu@citrix.com>
|
Zhixue Wu <Zhixue.Wu@citrix.com>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Nova API daemon.
|
Nova API daemon.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova import server
|
from nova import server
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Twistd daemon for the nova compute nodes.
|
Twistd daemon for the nova compute nodes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Handle lease database updates from DHCP servers.
|
Handle lease database updates from DHCP servers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import db
|
from nova import db
|
||||||
from nova import flags
|
from nova import flags
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Download images from Canonical Image Store
|
Download images from Canonical Image Store
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import tempfile
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.objectstore import image
|
from nova.objectstore import image
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Daemon for Nova RRD based instance resource monitoring.
|
Daemon for Nova RRD based instance resource monitoring.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
from nova.compute import monitor
|
from nova.compute import monitor
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
CLI interface for nova management.
|
CLI interface for nova management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import db
|
from nova import db
|
||||||
from nova import exception
|
from nova import exception
|
||||||
@@ -359,9 +362,14 @@ class ProjectCommands(object):
|
|||||||
def zipfile(self, project_id, user_id, filename='nova.zip'):
|
def zipfile(self, project_id, user_id, filename='nova.zip'):
|
||||||
"""Exports credentials for project to a zip file
|
"""Exports credentials for project to a zip file
|
||||||
arguments: project_id user_id [filename='nova.zip]"""
|
arguments: project_id user_id [filename='nova.zip]"""
|
||||||
zip_file = self.manager.get_credentials(user_id, project_id)
|
try:
|
||||||
with open(filename, 'w') as f:
|
zip_file = self.manager.get_credentials(user_id, project_id)
|
||||||
f.write(zip_file)
|
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):
|
class FloatingIpCommands(object):
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Twistd daemon for the nova network nodes.
|
Twistd daemon for the nova network nodes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Twisted daemon for nova objectstore. Supports S3 API.
|
Twisted daemon for nova objectstore. Supports S3 API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Twistd daemon for the nova scheduler nodes.
|
Twistd daemon for the nova scheduler nodes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
Twistd daemon for the nova volume nodes.
|
Twistd daemon for the nova volume nodes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
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')):
|
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import twistd
|
from nova import twistd
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ In Nova, users organize their cloud resources in projects. A Nova project consis
|
|||||||
Nova Network Strategies
|
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:
|
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 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.
|
* For performance optimization, split reads and writes to the database. MySQL proxy is the easiest way to make this work if running MySQL.
|
||||||
|
|
||||||
|
|
||||||
Assumptions
|
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!
|
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>
|
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
|
--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
|
--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
|
--ec2_url=http://$CC_ADDR:8773/services/Cloud
|
||||||
--network_manager=nova.network.manager.FlatManager # simple, no-vlan networking type
|
--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
|
--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
|
--network_size=<# of addrs> # number of ip addrs to use for VM guests, ex 64
|
||||||
|
|
||||||
|
#. Create a nova group::
|
||||||
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
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
sudo addgroup nova
|
sudo addgroup nova
|
||||||
|
|
||||||
5. nova-objectstore specific flags < no specific config needed >
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@@ -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
|
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
|
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::
|
.. toctree::
|
||||||
:maxdepth: 1
|
: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 :)
|
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.
|
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
|
The US-based National Institute of Standards and Technology offers definitions for cloud computing
|
||||||
and the service models that are emerging.
|
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
|
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
|
Provides infrastructure such as computer instances, network connections, and storage so that people
|
||||||
can run any software or operating system.
|
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
|
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
|
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
|
* **Component based architecture**: Quickly add new behaviors
|
||||||
* **Highly available**: Scale to very serious workloads
|
* **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
|
* **Recoverable**: Failures should be easy to diagnose, debug, and rectify
|
||||||
* **Open Standards**: Be a reference implementation for a community-driven api
|
* **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
|
* **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/single.node.install
|
||||||
adminguide/multi.node.install
|
adminguide/multi.node.install
|
||||||
|
|
||||||
.. todo:: add swiftadmin
|
|
||||||
|
|
||||||
Developer Docs
|
Developer Docs
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,48 @@
|
|||||||
Installing the Live CD
|
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_unit', 'Users', 'OID for Users')
|
||||||
flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
|
flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
|
||||||
'OU for Users')
|
'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',
|
flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com',
|
||||||
'OU for Projects')
|
'OU for Projects')
|
||||||
flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com',
|
flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com',
|
||||||
@@ -89,8 +91,7 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def get_user(self, uid):
|
def get_user(self, uid):
|
||||||
"""Retrieve user by id"""
|
"""Retrieve user by id"""
|
||||||
attr = self.__find_object(self.__uid_to_dn(uid),
|
attr = self.__get_ldap_user(uid)
|
||||||
'(objectclass=novaUser)')
|
|
||||||
return self.__to_user(attr)
|
return self.__to_user(attr)
|
||||||
|
|
||||||
def get_user_from_access_key(self, access):
|
def get_user_from_access_key(self, access):
|
||||||
@@ -110,7 +111,12 @@ class LdapDriver(object):
|
|||||||
"""Retrieve list of users"""
|
"""Retrieve list of users"""
|
||||||
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
|
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
|
||||||
'(objectclass=novaUser)')
|
'(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):
|
def get_projects(self, uid=None):
|
||||||
"""Retrieve list of projects"""
|
"""Retrieve list of projects"""
|
||||||
@@ -125,21 +131,52 @@ class LdapDriver(object):
|
|||||||
"""Create a user"""
|
"""Create a user"""
|
||||||
if self.__user_exists(name):
|
if self.__user_exists(name):
|
||||||
raise exception.Duplicate("LDAP user %s already exists" % name)
|
raise exception.Duplicate("LDAP user %s already exists" % name)
|
||||||
attr = [
|
if FLAGS.ldap_user_modify_only:
|
||||||
('objectclass', ['person',
|
if self.__ldap_user_exists(name):
|
||||||
'organizationalPerson',
|
# Retrieve user by name
|
||||||
'inetOrgPerson',
|
user = self.__get_ldap_user(name)
|
||||||
'novaUser']),
|
# Entry could be malformed, test for missing attrs.
|
||||||
('ou', [FLAGS.ldap_user_unit]),
|
# Malformed entries are useless, replace attributes found.
|
||||||
('uid', [name]),
|
attr = []
|
||||||
('sn', [name]),
|
if 'secretKey' in user.keys():
|
||||||
('cn', [name]),
|
attr.append((self.ldap.MOD_REPLACE, 'secretKey', \
|
||||||
('secretKey', [secret_key]),
|
[secret_key]))
|
||||||
('accessKey', [access_key]),
|
else:
|
||||||
('isAdmin', [str(is_admin).upper()]),
|
attr.append((self.ldap.MOD_ADD, 'secretKey', \
|
||||||
]
|
[secret_key]))
|
||||||
self.conn.add_s(self.__uid_to_dn(name), attr)
|
if 'accessKey' in user.keys():
|
||||||
return self.__to_user(dict(attr))
|
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,
|
def create_project(self, name, manager_uid,
|
||||||
description=None, member_uids=None):
|
description=None, member_uids=None):
|
||||||
@@ -155,7 +192,7 @@ class LdapDriver(object):
|
|||||||
if description is None:
|
if description is None:
|
||||||
description = name
|
description = name
|
||||||
members = []
|
members = []
|
||||||
if member_uids != None:
|
if member_uids is not None:
|
||||||
for member_uid in member_uids:
|
for member_uid in member_uids:
|
||||||
if not self.__user_exists(member_uid):
|
if not self.__user_exists(member_uid):
|
||||||
raise exception.NotFound("Project can't be created "
|
raise exception.NotFound("Project can't be created "
|
||||||
@@ -256,7 +293,24 @@ class LdapDriver(object):
|
|||||||
if not self.__user_exists(uid):
|
if not self.__user_exists(uid):
|
||||||
raise exception.NotFound("User %s doesn't exist" % uid)
|
raise exception.NotFound("User %s doesn't exist" % uid)
|
||||||
self.__remove_from_all(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):
|
def delete_project(self, project_id):
|
||||||
"""Delete a project"""
|
"""Delete a project"""
|
||||||
@@ -265,7 +319,7 @@ class LdapDriver(object):
|
|||||||
self.__delete_group(project_dn)
|
self.__delete_group(project_dn)
|
||||||
|
|
||||||
def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
|
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:
|
if not access_key and not secret_key and admin is None:
|
||||||
return
|
return
|
||||||
attr = []
|
attr = []
|
||||||
@@ -279,11 +333,21 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def __user_exists(self, uid):
|
def __user_exists(self, uid):
|
||||||
"""Check if user exists"""
|
"""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):
|
def __project_exists(self, project_id):
|
||||||
"""Check if project exists"""
|
"""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):
|
def __find_object(self, dn, query=None, scope=None):
|
||||||
"""Find an object by dn and query"""
|
"""Find an object by dn and query"""
|
||||||
@@ -330,12 +394,12 @@ class LdapDriver(object):
|
|||||||
|
|
||||||
def __group_exists(self, dn):
|
def __group_exists(self, dn):
|
||||||
"""Check if group exists"""
|
"""Check if group exists"""
|
||||||
return self.__find_object(dn, '(objectclass=groupOfNames)') != None
|
return self.__find_object(dn, '(objectclass=groupOfNames)') is not None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __role_to_dn(role, project_id=None):
|
def __role_to_dn(role, project_id=None):
|
||||||
"""Convert role to corresponding dn"""
|
"""Convert role to corresponding dn"""
|
||||||
if project_id == None:
|
if project_id is None:
|
||||||
return FLAGS.__getitem__("ldap_%s" % role).value
|
return FLAGS.__getitem__("ldap_%s" % role).value
|
||||||
else:
|
else:
|
||||||
return 'cn=%s,cn=%s,%s' % (role,
|
return 'cn=%s,cn=%s,%s' % (role,
|
||||||
@@ -349,7 +413,7 @@ class LdapDriver(object):
|
|||||||
raise exception.Duplicate("Group can't be created because "
|
raise exception.Duplicate("Group can't be created because "
|
||||||
"group %s already exists" % name)
|
"group %s already exists" % name)
|
||||||
members = []
|
members = []
|
||||||
if member_uids != None:
|
if member_uids is not None:
|
||||||
for member_uid in member_uids:
|
for member_uid in member_uids:
|
||||||
if not self.__user_exists(member_uid):
|
if not self.__user_exists(member_uid):
|
||||||
raise exception.NotFound("Group can't be created "
|
raise exception.NotFound("Group can't be created "
|
||||||
@@ -375,7 +439,7 @@ class LdapDriver(object):
|
|||||||
res = self.__find_object(group_dn,
|
res = self.__find_object(group_dn,
|
||||||
'(member=%s)' % self.__uid_to_dn(uid),
|
'(member=%s)' % self.__uid_to_dn(uid),
|
||||||
self.ldap.SCOPE_BASE)
|
self.ldap.SCOPE_BASE)
|
||||||
return res != None
|
return res is not None
|
||||||
|
|
||||||
def __add_to_group(self, uid, group_dn):
|
def __add_to_group(self, uid, group_dn):
|
||||||
"""Add user to group"""
|
"""Add user to group"""
|
||||||
@@ -447,18 +511,22 @@ class LdapDriver(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def __to_user(attr):
|
def __to_user(attr):
|
||||||
"""Convert ldap attributes to User object"""
|
"""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 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):
|
def __to_project(self, attr):
|
||||||
"""Convert ldap attributes to Project object"""
|
"""Convert ldap attributes to Project object"""
|
||||||
if attr == None:
|
if attr is None:
|
||||||
return None
|
return None
|
||||||
member_dns = attr.get('member', [])
|
member_dns = attr.get('member', [])
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -624,6 +624,10 @@ class AuthManager(object):
|
|||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.modify_user(uid, access_key, secret_key, admin)
|
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):
|
def get_credentials(self, user, project=None):
|
||||||
"""Get credential zip for user in project"""
|
"""Get credential zip for user in project"""
|
||||||
if not isinstance(user, User):
|
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')
|
'Manager for scheduler')
|
||||||
|
|
||||||
# The service to use for image search and retrieval
|
# 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.')
|
'The service to use for retrieving and searching for images.')
|
||||||
|
|
||||||
DEFINE_string('host', socket.gethostname(),
|
DEFINE_string('host', socket.gethostname(),
|
||||||
|
|||||||
@@ -29,3 +29,8 @@
|
|||||||
.. moduleauthor:: Manish Singh <yosh@gimp.org>
|
.. moduleauthor:: Manish Singh <yosh@gimp.org>
|
||||||
.. moduleauthor:: Andy Smith <andy@anarkystic.com>
|
.. 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.instance_destroy(self.context, inst['id'])
|
||||||
db.floating_ip_destroy(self.context, address)
|
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):
|
def test_console_output(self):
|
||||||
image_id = FLAGS.default_image
|
image_id = FLAGS.default_image
|
||||||
instance_type = FLAGS.default_instance_type
|
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."""
|
"""Verify that an instance cannot be created without a display_name."""
|
||||||
cases = [dict(), dict(display_name=None)]
|
cases = [dict(), dict(display_name=None)]
|
||||||
for instance in cases:
|
for instance in cases:
|
||||||
ref = self.compute_api.create_instance(self.context, None,
|
ref = self.compute_api.create_instances(self.context,
|
||||||
**instance)
|
FLAGS.default_instance_type, None, **instance)
|
||||||
try:
|
try:
|
||||||
self.assertNotEqual(ref.display_name, None)
|
self.assertNotEqual(ref[0].display_name, None)
|
||||||
finally:
|
finally:
|
||||||
db.instance_destroy(self.context, ref['id'])
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
|
||||||
def test_create_instance_associates_security_groups(self):
|
def test_create_instance_associates_security_groups(self):
|
||||||
"""Make sure create_instance associates security groups"""
|
"""Make sure create_instances associates security groups"""
|
||||||
inst = {}
|
|
||||||
inst['user_id'] = self.user.id
|
|
||||||
inst['project_id'] = self.project.id
|
|
||||||
values = {'name': 'default',
|
values = {'name': 'default',
|
||||||
'description': 'default',
|
'description': 'default',
|
||||||
'user_id': self.user.id,
|
'user_id': self.user.id,
|
||||||
'project_id': self.project.id}
|
'project_id': self.project.id}
|
||||||
group = db.security_group_create(self.context, values)
|
group = db.security_group_create(self.context, values)
|
||||||
ref = self.compute_api.create_instance(self.context,
|
ref = self.compute_api.create_instances(self.context,
|
||||||
security_groups=[group['id']],
|
FLAGS.default_instance_type, None, security_group=['default'])
|
||||||
**inst)
|
|
||||||
# reload to get groups
|
|
||||||
instance_ref = db.instance_get(self.context, ref['id'])
|
|
||||||
try:
|
try:
|
||||||
self.assertEqual(len(instance_ref['security_groups']), 1)
|
self.assertEqual(len(ref[0]['security_groups']), 1)
|
||||||
finally:
|
finally:
|
||||||
db.security_group_destroy(self.context, group['id'])
|
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
|
@defer.inlineCallbacks
|
||||||
def test_run_terminate(self):
|
def test_run_terminate(self):
|
||||||
|
|||||||
@@ -40,9 +40,12 @@ Due to our use of multiprocessing it we frequently get some ignorable
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import __main__
|
import __main__
|
||||||
|
import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from twisted.scripts import trial as trial_script
|
from twisted.scripts import trial as trial_script
|
||||||
|
|
||||||
from nova import flags
|
from nova import flags
|
||||||
|
|||||||
Reference in New Issue
Block a user