Merge "Implements config_drive as extension"
This commit is contained in:
94
nova/api/openstack/compute/contrib/config_drive.py
Normal file
94
nova/api/openstack/compute/contrib/config_drive.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 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.
|
||||
|
||||
"""Config Drive extension"""
|
||||
|
||||
import webob
|
||||
import webob.exc
|
||||
|
||||
from nova.api.openstack.compute import servers
|
||||
from nova.api.openstack.compute import views
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api.openstack import xmlutil
|
||||
from nova.compute import api as compute_api
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
authorize = extensions.soft_extension_authorizer('compute', 'config_drive')
|
||||
|
||||
|
||||
class ServerConfigDriveTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('server')
|
||||
root.set('config_drive', 'config_drive')
|
||||
return xmlutil.SlaveTemplate(root, 1)
|
||||
|
||||
|
||||
class ServersConfigDriveTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('servers')
|
||||
elem = xmlutil.SubTemplateElement(root, 'server', selector='servers')
|
||||
elem.set('config_drive', 'config_drive')
|
||||
return xmlutil.SlaveTemplate(root, 1)
|
||||
|
||||
|
||||
class Controller(servers.Controller):
|
||||
|
||||
def _add_config_drive(self, req, servers):
|
||||
for server in servers:
|
||||
db_server = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show'/'detail' methods.
|
||||
server['config_drive'] = db_server['config_drive']
|
||||
|
||||
def _show(self, req, resp_obj):
|
||||
if 'server' in resp_obj.obj:
|
||||
resp_obj.attach(xml=ServerConfigDriveTemplate())
|
||||
server = resp_obj.obj['server']
|
||||
self._add_config_drive(req, [server])
|
||||
|
||||
@wsgi.extends
|
||||
def show(self, req, resp_obj, id):
|
||||
context = req.environ['nova.context']
|
||||
if authorize(context):
|
||||
self._show(req, resp_obj)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
if 'servers' in resp_obj.obj and authorize(context):
|
||||
resp_obj.attach(xml=ServersConfigDriveTemplate())
|
||||
servers = resp_obj.obj['servers']
|
||||
self._add_config_drive(req, servers)
|
||||
|
||||
|
||||
class Config_drive(extensions.ExtensionDescriptor):
|
||||
"""Config Drive Extension"""
|
||||
|
||||
name = "ConfigDrive"
|
||||
alias = "os-config_drive"
|
||||
namespace = "http://docs.openstack.org/compute/ext/config_drive/api/v1.1"
|
||||
updated = "2012-07-16T00:00:00+00:00"
|
||||
|
||||
def get_controller_extensions(self):
|
||||
controller = Controller()
|
||||
extension = extensions.ControllerExtension(self, 'servers', controller)
|
||||
return [extension]
|
||||
@@ -104,7 +104,6 @@ class ViewBuilder(common.ViewBuilder):
|
||||
"addresses": self._get_addresses(request, instance),
|
||||
"accessIPv4": instance.get("access_ip_v4") or "",
|
||||
"accessIPv6": instance.get("access_ip_v6") or "",
|
||||
"config_drive": instance.get("config_drive"),
|
||||
"links": self._get_links(request,
|
||||
instance["uuid"],
|
||||
self._collection_name),
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright 2012 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 webob
|
||||
|
||||
from nova.api.openstack.compute.contrib import config_drive
|
||||
from nova import db
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
import nova.tests.image.fake
|
||||
|
||||
|
||||
class ConfigDriveTest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ConfigDriveTest, self).setUp()
|
||||
self.Controller = config_drive.Controller()
|
||||
fakes.stub_out_networking(self.stubs)
|
||||
fakes.stub_out_rate_limiting(self.stubs)
|
||||
nova.tests.image.fake.stub_out_image_service(self.stubs)
|
||||
|
||||
def test_show(self):
|
||||
self.stubs.Set(db, 'instance_get',
|
||||
fakes.fake_instance_get())
|
||||
req = webob.Request.blank('/v2/fake/servers/1')
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
response = req.get_response(fakes.wsgi_app())
|
||||
self.assertEquals(response.status_int, 200)
|
||||
res_dict = jsonutils.loads(response.body)
|
||||
self.assertTrue('config_drive' in res_dict['server'])
|
||||
|
||||
def test_detail_servers(self):
|
||||
self.stubs.Set(db, 'instance_get',
|
||||
fakes.fake_instance_get())
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/servers/detail')
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
server_dicts = jsonutils.loads(res.body)['servers']
|
||||
for server_dict in server_dicts:
|
||||
self.asserTrue('config_drive' in server_dict)
|
||||
@@ -200,7 +200,6 @@ class ServersControllerTest(test.TestCase):
|
||||
"metadata": {
|
||||
"seq": "1",
|
||||
},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -267,7 +266,6 @@ class ServersControllerTest(test.TestCase):
|
||||
"metadata": {
|
||||
"seq": "1",
|
||||
},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -337,7 +335,6 @@ class ServersControllerTest(test.TestCase):
|
||||
"metadata": {
|
||||
"seq": "1",
|
||||
},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -3005,7 +3002,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -3073,7 +3069,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -3217,7 +3212,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
@@ -3278,7 +3272,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"config_drive": None,
|
||||
"accessIPv4": "1.2.3.4",
|
||||
"accessIPv6": "",
|
||||
"links": [
|
||||
@@ -3341,7 +3334,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"config_drive": None,
|
||||
"accessIPv4": "",
|
||||
"accessIPv6": "fead::1234",
|
||||
"links": [
|
||||
@@ -3408,7 +3400,6 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
]
|
||||
},
|
||||
"metadata": {"Open": "Stack"},
|
||||
"config_drive": None,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
|
||||
@@ -397,7 +397,7 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
|
||||
flavor_id="1", name=None, key_name='',
|
||||
access_ipv4=None, access_ipv6=None, progress=0,
|
||||
auto_disk_config=False, display_name=None,
|
||||
include_fake_metadata=True,
|
||||
include_fake_metadata=True, config_drive=None,
|
||||
power_state=None, nw_cache=None, metadata=None,
|
||||
security_groups=None):
|
||||
|
||||
@@ -446,6 +446,7 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
|
||||
"launch_index": 0,
|
||||
"key_name": key_name,
|
||||
"key_data": key_data,
|
||||
"config_drive": config_drive,
|
||||
"vm_state": vm_state or vm_states.BUILDING,
|
||||
"task_state": task_state,
|
||||
"power_state": power_state,
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
"compute_extension:aggregates": [],
|
||||
"compute_extension:certificates": [],
|
||||
"compute_extension:cloudpipe": [],
|
||||
"compute_extension:config_drive": [],
|
||||
"compute_extension:console_output": [],
|
||||
"compute_extension:consoles": [],
|
||||
"compute_extension:createserverext": [],
|
||||
|
||||
Reference in New Issue
Block a user