summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorAndy Smith <code@term.ie>2010-12-10 11:46:29 -0800
committerAndy Smith <code@term.ie>2010-12-10 11:46:29 -0800
commite3aae367c2d449bfc25216865f37182953b535f4 (patch)
treec7bacce0d21577041edcfa5a394d46f4f32d52ab /nova
parent4d06429290a373ae3a42b1f9b58d7253d269e048 (diff)
parent1a759c3722610d720dd8dabf816db146c1063937 (diff)
merge-a-tat-tat upstream to this branch
Diffstat (limited to 'nova')
-rw-r--r--nova/api/ec2/cloud.py1
-rw-r--r--nova/api/openstack/__init__.py8
-rw-r--r--nova/compute/api.py17
-rw-r--r--nova/tests/api/openstack/test_adminapi.py61
-rw-r--r--nova/virt/xenapi/vm_utils.py48
-rw-r--r--nova/virt/xenapi/vmops.py12
-rw-r--r--nova/virt/xenapi_conn.py4
7 files changed, 144 insertions, 7 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 4eef5e1ef..05f8c3d0b 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -753,7 +753,6 @@ class CloudController(object):
ramdisk_id=kwargs.get('ramdisk_id'),
display_name=kwargs.get('display_name'),
description=kwargs.get('display_description'),
- user_data=kwargs.get('user_data', ''),
key_name=kwargs.get('key_name'),
security_group=kwargs.get('security_group'),
generate_hostname=internal_id_to_ec2_id)
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index 4ca108c4e..c9efe5222 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -48,6 +48,10 @@ flags.DEFINE_string('nova_api_auth',
'nova.api.openstack.auth.BasicApiAuthManager',
'The auth mechanism to use for the OpenStack API implemenation')
+flags.DEFINE_bool('allow_admin_api',
+ False,
+ 'When True, this API service will accept admin operations.')
+
class API(wsgi.Middleware):
"""WSGI entry point for all OpenStack API requests."""
@@ -183,6 +187,10 @@ class APIRouter(wsgi.Router):
mapper.resource("sharedipgroup", "sharedipgroups",
controller=sharedipgroups.Controller())
+ if FLAGS.allow_admin_api:
+ logging.debug("Including admin operations in API.")
+ # TODO: Place routes for admin operations here.
+
super(APIRouter, self).__init__(mapper)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index cb23dae55..8e0efa4cc 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -55,9 +55,8 @@ class ComputeAPI(base.Base):
def create_instances(self, context, instance_type, image_id, min_count=1,
max_count=1, kernel_id=None, ramdisk_id=None,
- display_name='', description='', user_data='',
- key_name=None, key_data=None,
- security_group='default',
+ display_name='', description='', key_name=None,
+ key_data=None, security_group='default',
generate_hostname=generate_default_hostname):
"""Create the number of instances requested if quote and
other arguments check out ok."""
@@ -158,8 +157,8 @@ class ComputeAPI(base.Base):
{"method": "setup_fixed_ip",
"args": {"address": address}})
- logging.debug("Casting to scheduler for %s/%s's instance %s" %
- (context.project_id, context.user_id, instance_id))
+ logging.debug("Casting to scheduler for %s/%s's instance %s",
+ context.project_id, context.user_id, instance_id)
rpc.cast(context,
FLAGS.scheduler_topic,
{"method": "run_instance",
@@ -169,6 +168,12 @@ class ComputeAPI(base.Base):
return instances
def ensure_default_security_group(self, context):
+ """ Create security group for the security context if it
+ does not already exist
+
+ :param context: the security context
+
+ """
try:
db.security_group_get_by_name(context, context.project_id,
'default')
@@ -177,7 +182,7 @@ class ComputeAPI(base.Base):
'description': 'default',
'user_id': context.user_id,
'project_id': context.project_id}
- group = db.security_group_create(context, values)
+ db.security_group_create(context, values)
def update_instance(self, context, instance_id, **kwargs):
"""Updates the instance in the datastore.
diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py
new file mode 100644
index 000000000..1b2e1654d
--- /dev/null
+++ b/nova/tests/api/openstack/test_adminapi.py
@@ -0,0 +1,61 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# 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.
+
+import unittest
+
+import stubout
+import webob
+
+import nova.api
+from nova import flags
+from nova.tests.api.openstack import fakes
+
+FLAGS = flags.FLAGS
+
+
+class AdminAPITest(unittest.TestCase):
+ def setUp(self):
+ self.stubs = stubout.StubOutForTesting()
+ fakes.FakeAuthManager.auth_data = {}
+ fakes.FakeAuthDatabase.data = {}
+ fakes.stub_out_networking(self.stubs)
+ fakes.stub_out_rate_limiting(self.stubs)
+ fakes.stub_out_auth(self.stubs)
+ self.allow_admin = FLAGS.allow_admin_api
+
+ def tearDown(self):
+ self.stubs.UnsetAll()
+ FLAGS.allow_admin_api = self.allow_admin
+
+ def test_admin_enabled(self):
+ FLAGS.allow_admin_api = True
+ # We should still be able to access public operations.
+ req = webob.Request.blank('/v1.0/flavors')
+ res = req.get_response(nova.api.API('os'))
+ self.assertEqual(res.status_int, 200)
+ # TODO: Confirm admin operations are available.
+
+ def test_admin_disabled(self):
+ FLAGS.allow_admin_api = False
+ # We should still be able to access public operations.
+ req = webob.Request.blank('/v1.0/flavors')
+ res = req.get_response(nova.api.API('os'))
+ self.assertEqual(res.status_int, 200)
+ # TODO: Confirm admin operations are unavailable.
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index b72b8e13d..dde138404 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -20,6 +20,8 @@ their attributes like VDIs, VIFs, as well as their lookup functions.
"""
import logging
+import urllib
+from xml.dom import minidom
from nova import utils
from nova.auth.manager import AuthManager
@@ -44,6 +46,15 @@ class VMHelper():
The class that wraps the helper methods together.
"""
def __init__(self):
+ return
+
+ @classmethod
+ def late_import(cls):
+ """
+ Load the XenAPI module in for helper class, if required.
+ This is to avoid to install the XenAPI library when other
+ hypervisors are used
+ """
global XenAPI
if XenAPI is None:
XenAPI = __import__('XenAPI')
@@ -208,3 +219,40 @@ class VMHelper():
'mem': long(record['memory_dynamic_max']) >> 10,
'num_cpu': record['VCPUs_max'],
'cpu_time': 0}
+
+ @classmethod
+ def compile_diagnostics(cls, session, record):
+ """Compile VM diagnostics data"""
+ try:
+ host = session.get_xenapi_host()
+ host_ip = session.get_xenapi().host.get_record(host)["address"]
+ metrics = session.get_xenapi().VM_guest_metrics.get_record(
+ record["guest_metrics"])
+ diags = {
+ "Kernel": metrics["os_version"]["uname"],
+ "Distro": metrics["os_version"]["name"]}
+ xml = get_rrd(host_ip, record["uuid"])
+ if xml:
+ rrd = minidom.parseString(xml)
+ for i, node in enumerate(rrd.firstChild.childNodes):
+ # We don't want all of the extra garbage
+ if i >= 3 and i <= 11:
+ ref = node.childNodes
+ # Name and Value
+ diags[ref[0].firstChild.data] = ref[6].firstChild.data
+ return diags
+ except XenAPI.Failure as e:
+ return {"Unable to retrieve diagnostics": e}
+
+
+def get_rrd(host, uuid):
+ """Return the VM RRD XML as a string"""
+ try:
+ xml = urllib.urlopen("http://%s:%s@%s/vm_rrd?uuid=%s" % (
+ FLAGS.xenapi_connection_username,
+ FLAGS.xenapi_connection_password,
+ host,
+ uuid))
+ return xml.read()
+ except IOError:
+ return None
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 0223e512a..13871b479 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -22,6 +22,7 @@ import logging
from nova import db
from nova import context
+
from nova.auth.manager import AuthManager
from nova.virt.xenapi.network_utils import NetworkHelper
from nova.virt.xenapi.vm_utils import VMHelper
@@ -38,6 +39,8 @@ class VMOps(object):
if XenAPI is None:
XenAPI = __import__('XenAPI')
self._session = session
+ # Load XenAPI module in the helper class
+ VMHelper.late_import()
def list_instances(self):
""" List VM instances """
@@ -123,6 +126,15 @@ class VMOps(object):
rec = self._session.get_xenapi().VM.get_record(vm)
return VMHelper.compile_info(rec)
+ @defer.inlineCallbacks
+ def get_diagnostics(self, instance_id):
+ """Return data about VM diagnostics"""
+ vm = yield VMHelper.lookup(self._session, instance_id)
+ if vm is None:
+ raise Exception("instance not present %s" % instance_id)
+ rec = yield self._session.get_xenapi().VM.get_record(vm)
+ defer.returnValue(VMHelper.compile_diagnostics(self._session, rec))
+
def get_console_output(self, instance):
""" Return snapshot of console """
# TODO: implement this to fix pylint!
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 96d211cc0..df8e42d34 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -124,6 +124,10 @@ class XenAPIConnection(object):
""" Return data about VM instance """
return self._vmops.get_info(instance_id)
+ def get_diagnostics(self, instance_id):
+ """Return data about VM diagnostics"""
+ return self._vmops.get_diagnostics(instance_id)
+
def get_console_output(self, instance):
""" Return snapshot of console """
return self._vmops.get_console_output(instance)