Merge trunk and apply some sphinx love.

This commit is contained in:
Todd Willey 2010-11-01 14:13:58 -04:00
commit b76286c5ef
14 changed files with 172 additions and 116 deletions

BIN
doc/source/_templates/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -27,7 +27,13 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo',
todo_include_todos = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# Changing the path so that the Hudson build output contains GA code and the source
# docs do not contain the code so local, offline sphinx builds are "clean."
templates_path = []
if os.getenv('HUDSON_PUBLISH_DOCS'):
templates_path = ['_ga', '_templates']
else:
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'

View File

@ -33,14 +33,15 @@ DEFAULT_SECRET_KEY = 'admin'
class UserInfo(object):
"""
Information about a Nova user, as parsed through SAX
fields include:
username
accesskey
secretkey
Information about a Nova user, as parsed through SAX.
**Fields Include**
* username
* accesskey
* secretkey
* file (optional) containing zip of X509 cert & rc file
and an optional field containing a zip with X509 cert & rc
file
"""
def __init__(self, connection=None, username=None, endpoint=None):
@ -68,9 +69,13 @@ class UserInfo(object):
class UserRole(object):
"""
Information about a Nova user's role, as parsed through SAX.
Fields include:
role
**Fields include**
* role
"""
def __init__(self, connection=None):
self.connection = connection
self.role = None
@ -90,12 +95,15 @@ class UserRole(object):
class ProjectInfo(object):
"""
Information about a Nova project, as parsed through SAX
Fields include:
projectname
description
projectManagerId
memberIds
Information about a Nova project, as parsed through SAX.
**Fields include**
* projectname
* description
* projectManagerId
* memberIds
"""
def __init__(self, connection=None):
@ -127,8 +135,11 @@ class ProjectInfo(object):
class ProjectMember(object):
"""
Information about a Nova project member, as parsed through SAX.
Fields include:
memberId
**Fields include**
* memberId
"""
def __init__(self, connection=None):
@ -150,14 +161,18 @@ class ProjectMember(object):
class HostInfo(object):
"""
Information about a Nova Host, as parsed through SAX:
Disk stats
Running Instances
Memory stats
CPU stats
Network address info
Firewall info
Bridge and devices
Information about a Nova Host, as parsed through SAX.
**Fields Include**
* Disk stats
* Running Instances
* Memory stats
* CPU stats
* Network address info
* Firewall info
* Bridge and devices
"""
def __init__(self, connection=None):
@ -257,9 +272,12 @@ class NovaAdminClient(object):
[('item', UserRole)])
def get_user_roles(self, user, project=None):
"""Returns a list of roles for the given user. Omitting project will
return any global roles that the user has. Specifying project will
return only project specific roles."""
"""Returns a list of roles for the given user.
Omitting project will return any global roles that the user has.
Specifying project will return only project specific roles.
"""
params = {'User': user}
if project:
params['Project'] = project

View File

@ -99,6 +99,7 @@ class CloudController(object):
"""
def __init__(self):
self.network_manager = utils.import_object(FLAGS.network_manager)
self.compute_manager = utils.import_object(FLAGS.compute_manager)
self.setup()
def __str__(self):
@ -835,21 +836,21 @@ class CloudController(object):
elevated = context.elevated()
for num in range(num_instances):
instance_ref = db.instance_create(context, base_options)
instance_ref = self.compute_manager.create_instance(context,
security_groups,
mac_address=utils.generate_mac(),
launch_index=num,
**base_options)
inst_id = instance_ref['id']
for security_group_id in security_groups:
db.instance_add_security_group(elevated,
inst_id,
security_group_id)
inst = {}
inst['mac_address'] = utils.generate_mac()
inst['launch_index'] = num
internal_id = instance_ref['internal_id']
ec2_id = internal_id_to_ec2_id(internal_id)
inst['hostname'] = ec2_id
db.instance_update(context, inst_id, inst)
self.compute_manager.update_instance(context,
inst_id,
hostname=ec2_id)
# TODO(vish): This probably should be done in the scheduler
# or in compute as a call. The network should be
# allocated after the host is assigned and setup
@ -895,11 +896,12 @@ class CloudController(object):
id_str)
continue
now = datetime.datetime.utcnow()
db.instance_update(context,
instance_ref['id'],
{'state_description': 'terminating',
'state': 0,
'terminated_at': now})
self.compute_manager.update_instance(context,
instance_ref['id'],
state_description='terminating',
state=0,
terminated_at=now)
# FIXME(ja): where should network deallocate occur?
address = db.instance_get_floating_address(context,
instance_ref['id'])

View File

@ -95,6 +95,7 @@ class Controller(wsgi.Controller):
db_driver = FLAGS.db_driver
self.db_driver = utils.import_object(db_driver)
self.network_manager = utils.import_object(FLAGS.network_manager)
self.compute_manager = utils.import_object(FLAGS.compute_manager)
super(Controller, self).__init__()
def index(self, req):
@ -242,34 +243,30 @@ class Controller(wsgi.Controller):
inst['memory_mb'] = flavor['memory_mb']
inst['vcpus'] = flavor['vcpus']
inst['local_gb'] = flavor['local_gb']
ref = self.db_driver.instance_create(ctxt, inst)
inst['id'] = ref.internal_id
inst['mac_address'] = utils.generate_mac()
#TODO(dietz) is this necessary?
inst['launch_index'] = 0
inst['hostname'] = str(ref.internal_id)
self.db_driver.instance_update(ctxt, inst['id'], inst)
ref = self.compute_manager.create_instance(ctxt, **inst)
inst['id'] = ref['internal_id']
network_manager = utils.import_object(FLAGS.network_manager)
address = network_manager.allocate_fixed_ip(ctxt,
inst['id'])
inst['hostname'] = str(ref['internal_id'])
self.compute_manager.update_instance(ctxt, inst['id'], **inst)
address = self.network_manager.allocate_fixed_ip(ctxt,
inst['id'])
# TODO(vish): This probably should be done in the scheduler
# network is setup when host is assigned
network_topic = self._get_network_topic(ctxt, network_manager)
network_topic = self._get_network_topic(ctxt)
rpc.call(ctxt,
network_topic,
{"method": "setup_fixed_ip",
"args": {"address": address}})
return inst
def _get_network_topic(self, context, network_manager):
def _get_network_topic(self, context):
"""Retrieves the network host for a project"""
network_ref = network_manager.get_network(context)
network_ref = self.network_manager.get_network(context)
host = network_ref['host']
if not host:
host = rpc.call(context,

View File

@ -83,6 +83,46 @@ class ComputeManager(manager.Manager):
"""This call passes stright through to the virtualization driver."""
yield self.driver.refresh_security_group(security_group_id)
def create_instance(self, context, security_groups=[], **kwargs):
"""Creates the instance in the datastore and returns the
new instance as a mapping
:param context: The security context
:param security_groups: list of security group ids to
attach to the instance
:param kwargs: All additional keyword args are treated
as data fields of the instance to be
created
:retval Returns a mapping of the instance information
that has just been created
"""
instance_ref = self.db.instance_create(context, kwargs)
inst_id = instance_ref['id']
elevated = context.elevated()
security_groups = kwargs.get('security_groups', [])
for security_group_id in security_groups:
self.db.instance_add_security_group(elevated,
inst_id,
security_group_id)
return instance_ref
def update_instance(self, context, instance_id, **kwargs):
"""Updates the instance in the datastore.
:param context: The security context
:param instance_id: ID of the instance to update
:param kwargs: All additional keyword args are treated
as data fields of the instance to be
updated
:retval None
"""
self.db.instance_update(context, instance_id, kwargs)
@defer.inlineCallbacks
@exception.wrap_exception
def run_instance(self, context, instance_id, **_kwargs):

View File

@ -15,10 +15,11 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Wrappers around standard crypto, including root and intermediate CAs,
SSH key_pairs and x509 certificates.
Wrappers around standard crypto data elements.
Includes root and intermediate CAs, SSH key_pairs and x509 certificates.
"""
import base64
@ -227,12 +228,12 @@ def mkcacert(subject='nova', years=1):
def compute_md5(fp):
"""
@type fp: file
@param fp: File pointer to the file to MD5 hash. The file pointer will be
:type fp: file
:param fp: File pointer to the file to MD5 hash. The file pointer will be
reset to the beginning of the file before the method returns.
@rtype: tuple
@return: the hex digest version of the MD5 hash
:rtype: tuple
:return: the hex digest version of the MD5 hash
"""
m = hashlib.md5()
fp.seek(0)

View File

@ -236,8 +236,7 @@ def service_get_by_args(context, host, binary):
@require_admin_context
def service_create(context, values):
service_ref = models.Service()
for (key, value) in values.iteritems():
service_ref[key] = value
service_ref.update(values)
service_ref.save()
return service_ref
@ -247,8 +246,7 @@ def service_update(context, service_id, values):
session = get_session()
with session.begin():
service_ref = service_get(context, service_id, session=session)
for (key, value) in values.iteritems():
service_ref[key] = value
service_ref.update(values)
service_ref.save(session=session)
@ -279,8 +277,7 @@ def floating_ip_allocate_address(context, host, project_id):
@require_context
def floating_ip_create(context, values):
floating_ip_ref = models.FloatingIp()
for (key, value) in values.iteritems():
floating_ip_ref[key] = value
floating_ip_ref.update(values)
floating_ip_ref.save()
return floating_ip_ref['address']
@ -451,8 +448,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id):
@require_context
def fixed_ip_create(_context, values):
fixed_ip_ref = models.FixedIp()
for (key, value) in values.iteritems():
fixed_ip_ref[key] = value
fixed_ip_ref.update(values)
fixed_ip_ref.save()
return fixed_ip_ref['address']
@ -523,8 +519,7 @@ def fixed_ip_update(context, address, values):
fixed_ip_ref = fixed_ip_get_by_address(context,
address,
session=session)
for (key, value) in values.iteritems():
fixed_ip_ref[key] = value
fixed_ip_ref.update(values)
fixed_ip_ref.save(session=session)
@ -537,8 +532,7 @@ def fixed_ip_update(context, address, values):
@require_context
def instance_create(context, values):
instance_ref = models.Instance()
for (key, value) in values.iteritems():
instance_ref[key] = value
instance_ref.update(values)
session = get_session()
with session.begin():
@ -731,8 +725,7 @@ def instance_update(context, instance_id, values):
session = get_session()
with session.begin():
instance_ref = instance_get(context, instance_id, session=session)
for (key, value) in values.iteritems():
instance_ref[key] = value
instance_ref.update(values)
instance_ref.save(session=session)
@ -754,8 +747,7 @@ def instance_add_security_group(context, instance_id, security_group_id):
@require_context
def key_pair_create(context, values):
key_pair_ref = models.KeyPair()
for (key, value) in values.iteritems():
key_pair_ref[key] = value
key_pair_ref.update(values)
key_pair_ref.save()
return key_pair_ref
@ -870,8 +862,7 @@ def network_count_reserved_ips(context, network_id):
@require_admin_context
def network_create_safe(context, values):
network_ref = models.Network()
for (key, value) in values.iteritems():
network_ref[key] = value
network_ref.update(values)
try:
network_ref.save()
return network_ref
@ -980,8 +971,7 @@ def network_update(context, network_id, values):
session = get_session()
with session.begin():
network_ref = network_get(context, network_id, session=session)
for (key, value) in values.iteritems():
network_ref[key] = value
network_ref.update(values)
network_ref.save(session=session)
@ -1031,8 +1021,7 @@ def export_device_count(context):
@require_admin_context
def export_device_create_safe(context, values):
export_device_ref = models.ExportDevice()
for (key, value) in values.iteritems():
export_device_ref[key] = value
export_device_ref.update(values)
try:
export_device_ref.save()
return export_device_ref
@ -1060,8 +1049,7 @@ def auth_get_token(_context, token_hash):
def auth_create_token(_context, token):
tk = models.AuthToken()
for k, v in token.iteritems():
tk[k] = v
tk.update(token)
tk.save()
return tk
@ -1087,8 +1075,7 @@ def quota_get(context, project_id, session=None):
@require_admin_context
def quota_create(context, values):
quota_ref = models.Quota()
for (key, value) in values.iteritems():
quota_ref[key] = value
quota_ref.update(values)
quota_ref.save()
return quota_ref
@ -1098,8 +1085,7 @@ def quota_update(context, project_id, values):
session = get_session()
with session.begin():
quota_ref = quota_get(context, project_id, session=session)
for (key, value) in values.iteritems():
quota_ref[key] = value
quota_ref.update(values)
quota_ref.save(session=session)
@ -1148,8 +1134,7 @@ def volume_attached(context, volume_id, instance_id, mountpoint):
@require_context
def volume_create(context, values):
volume_ref = models.Volume()
for (key, value) in values.iteritems():
volume_ref[key] = value
volume_ref.update(values)
session = get_session()
with session.begin():
@ -1306,8 +1291,7 @@ def volume_update(context, volume_id, values):
session = get_session()
with session.begin():
volume_ref = volume_get(context, volume_id, session=session)
for (key, value) in values.iteritems():
volume_ref[key] = value
volume_ref.update(values)
volume_ref.save(session=session)
@ -1400,8 +1384,7 @@ def security_group_create(context, values):
# FIXME(devcamcar): Unless I do this, rules fails with lazy load exception
# once save() is called. This will get cleaned up in next orm pass.
security_group_ref.rules
for (key, value) in values.iteritems():
security_group_ref[key] = value
security_group_ref.update(values)
security_group_ref.save()
return security_group_ref
@ -1455,8 +1438,7 @@ def security_group_rule_get(context, security_group_rule_id, session=None):
@require_context
def security_group_rule_create(context, values):
security_group_rule_ref = models.SecurityGroupIngressRule()
for (key, value) in values.iteritems():
security_group_rule_ref[key] = value
security_group_rule_ref.update(values)
security_group_rule_ref.save()
return security_group_rule_ref
@ -1508,8 +1490,7 @@ def user_get_by_access_key(context, access_key, session=None):
@require_admin_context
def user_create(_context, values):
user_ref = models.User()
for (key, value) in values.iteritems():
user_ref[key] = value
user_ref.update(values)
user_ref.save()
return user_ref
@ -1537,8 +1518,7 @@ def user_get_all(context):
def project_create(_context, values):
project_ref = models.Project()
for (key, value) in values.iteritems():
project_ref[key] = value
project_ref.update(values)
project_ref.save()
return project_ref
@ -1600,8 +1580,7 @@ def user_update(context, user_id, values):
session = get_session()
with session.begin():
user_ref = user_get(context, user_id, session=session)
for (key, value) in values.iteritems():
user_ref[key] = value
user_ref.update(values)
user_ref.save(session=session)
@ -1609,8 +1588,7 @@ def project_update(context, project_id, values):
session = get_session()
with session.begin():
project_ref = project_get(context, project_id, session=session)
for (key, value) in values.iteritems():
project_ref[key] = value
project_ref.update(values)
project_ref.save(session=session)

View File

@ -81,6 +81,16 @@ class NovaBase(object):
n = self._i.next().name
return n, getattr(self, n)
def update(self, values):
"""Make the model object behave like a dict"""
for k, v in values.iteritems():
setattr(self, k, v)
def iteritems(self):
"""Make the model object behave like a dict"""
return iter(self)
# TODO(vish): Store images in the database instead of file system
#class Image(BASE, NovaBase):
# """Represents an image in the datastore"""

View File

@ -30,6 +30,7 @@ from nova import exception as exc
import nova.api.openstack.auth
from nova.image import service
from nova.image.services import glance
from nova.tests import fake_flags
from nova.wsgi import Router

View File

@ -24,22 +24,28 @@ from nova.api.openstack import API
from nova.api.openstack import faults
from webob import Request
class APITest(unittest.TestCase):
def test_exceptions_are_converted_to_faults(self):
@webob.dec.wsgify
def succeed(req):
return 'Succeeded'
@webob.dec.wsgify
def raise_webob_exc(req):
raise webob.exc.HTTPNotFound(explanation='Raised a webob.exc')
@webob.dec.wsgify
def fail(req):
raise Exception("Threw an exception")
@webob.dec.wsgify
def raise_api_fault(req):
exc = webob.exc.HTTPNotFound(explanation='Raised a webob.exc')
return faults.Fault(exc)
api = API()
api.application = succeed

View File

@ -91,9 +91,7 @@ class ServersTest(unittest.TestCase):
pass
def instance_create(context, inst):
class Foo(object):
internal_id = 1
return Foo()
return {'id': 1, 'internal_id': 1}
def fake_method(*args, **kwargs):
pass

View File

@ -213,10 +213,10 @@ def deferredToThread(f):
def xhtml_escape(value):
"""Escapes a string so it is valid within XML or XHTML.
Code is directly from the utf8 function in
http://github.com/facebook/tornado/blob/master/tornado/escape.py
"""
return saxutils.escape(value, {'"': """})
@ -232,4 +232,3 @@ def utf8(value):
return value.encode("utf-8")
assert isinstance(value, str)
return value