summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTodd Willey <todd@ansolabs.com>2010-11-01 14:13:58 -0400
committerTodd Willey <todd@ansolabs.com>2010-11-01 14:13:58 -0400
commitb76286c5ef2b2182cb0c2cc42b31971656e8f70f (patch)
tree8141344278733882ddd57f9b0f5dfb1991860651
parentbf15a6eb3de8c688dc1364959dd3e00d3e26a563 (diff)
parentab1c34f71745b901f40fd6a72dffc7a29a864990 (diff)
downloadnova-b76286c5ef2b2182cb0c2cc42b31971656e8f70f.tar.gz
nova-b76286c5ef2b2182cb0c2cc42b31971656e8f70f.tar.xz
nova-b76286c5ef2b2182cb0c2cc42b31971656e8f70f.zip
Merge trunk and apply some sphinx love.
-rw-r--r--doc/source/_ga/layout.html (renamed from doc/source/_templates/layout.html)0
-rw-r--r--doc/source/_templates/.DS_Storebin0 -> 6148 bytes
-rw-r--r--doc/source/conf.py8
-rw-r--r--nova/adminclient.py76
-rw-r--r--nova/api/ec2/cloud.py34
-rw-r--r--nova/api/openstack/servers.py25
-rw-r--r--nova/compute/manager.py40
-rw-r--r--nova/crypto.py15
-rw-r--r--nova/db/sqlalchemy/api.py66
-rw-r--r--nova/db/sqlalchemy/models.py10
-rw-r--r--nova/tests/api/openstack/fakes.py1
-rw-r--r--nova/tests/api/openstack/test_api.py6
-rw-r--r--nova/tests/api/openstack/test_servers.py4
-rw-r--r--nova/utils.py5
14 files changed, 173 insertions, 117 deletions
diff --git a/doc/source/_templates/layout.html b/doc/source/_ga/layout.html
index 0b72a77ac..0b72a77ac 100644
--- a/doc/source/_templates/layout.html
+++ b/doc/source/_ga/layout.html
diff --git a/doc/source/_templates/.DS_Store b/doc/source/_templates/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
--- /dev/null
+++ b/doc/source/_templates/.DS_Store
Binary files differ
diff --git a/doc/source/conf.py b/doc/source/conf.py
index e91860536..27bc4ea6c 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -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'
diff --git a/nova/adminclient.py b/nova/adminclient.py
index b7a3d2c32..0227cddd7 100644
--- a/nova/adminclient.py
+++ b/nova/adminclient.py
@@ -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
-
- and an optional field containing a zip with X509 cert & rc
- file
+ Information about a Nova user, as parsed through SAX.
+
+ **Fields Include**
+
+ * username
+ * accesskey
+ * secretkey
+ * file (optional) containing zip of 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
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index dd5fe4065..f2a6dc3b0 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -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)
- inst_id = instance_ref['id']
- for security_group_id in security_groups:
- db.instance_add_security_group(elevated,
- inst_id,
- security_group_id)
+ 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']
- 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'])
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index ef773c3be..1d8aa2fa4 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -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']
+
+ inst['hostname'] = str(ref['internal_id'])
+ self.compute_manager.update_instance(ctxt, inst['id'], **inst)
- network_manager = utils.import_object(FLAGS.network_manager)
- address = network_manager.allocate_fixed_ip(ctxt,
- inst['id'])
+ 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,
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 3346d1299..d63a66b91 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -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):
diff --git a/nova/crypto.py b/nova/crypto.py
index 16b4f5e1f..d73559587 100644
--- a/nova/crypto.py
+++ b/nova/crypto.py
@@ -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)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index d9b98655e..d8a08994a 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -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)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 29c3b74da..c79cc623e 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -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"""
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index 7ecb72ab3..1b8c18974 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -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
diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py
index a8c0ff9f8..dd83991b9 100644
--- a/nova/tests/api/openstack/test_api.py
+++ b/nova/tests/api/openstack/test_api.py
@@ -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
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 55efcf733..785fb6f3a 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -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
diff --git a/nova/utils.py b/nova/utils.py
index 2c53b027e..bc495a691 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -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, {'"': "&quot;"})
@@ -232,4 +232,3 @@ def utf8(value):
return value.encode("utf-8")
assert isinstance(value, str)
return value
-