OCCI 1.2 Contextualization
Introduces two new mixins defined in the OCCI 1.2 spec for handling contextualization: user_data and ssh_key. Functionality is similar to the already existing OpenStack mixins, which may be deprecated in the future. Partially-Implements: blueprint occi-1-2-core Change-Id: Ibb6624e3e15bf7b9f3ad39786dcefb36b1a9a797
This commit is contained in:
parent
db9dae4a26
commit
e30fdd75f4
|
@ -21,11 +21,12 @@ import ooi.api.helpers
|
||||||
from ooi import exception
|
from ooi import exception
|
||||||
from ooi.occi.core import collection
|
from ooi.occi.core import collection
|
||||||
from ooi.occi.infrastructure import compute
|
from ooi.occi.infrastructure import compute
|
||||||
|
from ooi.occi.infrastructure import contextualization
|
||||||
from ooi.occi.infrastructure import network
|
from ooi.occi.infrastructure import network
|
||||||
from ooi.occi.infrastructure import storage
|
from ooi.occi.infrastructure import storage
|
||||||
from ooi.occi.infrastructure import storage_link
|
from ooi.occi.infrastructure import storage_link
|
||||||
from ooi.occi import validator as occi_validator
|
from ooi.occi import validator as occi_validator
|
||||||
from ooi.openstack import contextualization
|
from ooi.openstack import contextualization as os_contextualization
|
||||||
from ooi.openstack import helpers
|
from ooi.openstack import helpers
|
||||||
from ooi.openstack import network as os_network
|
from ooi.openstack import network as os_network
|
||||||
from ooi.openstack import templates
|
from ooi.openstack import templates
|
||||||
|
@ -148,7 +149,9 @@ class Controller(ooi.api.base.Controller):
|
||||||
],
|
],
|
||||||
"optional_mixins": [
|
"optional_mixins": [
|
||||||
contextualization.user_data,
|
contextualization.user_data,
|
||||||
contextualization.public_key,
|
contextualization.ssh_key,
|
||||||
|
os_contextualization.user_data,
|
||||||
|
os_contextualization.public_key,
|
||||||
],
|
],
|
||||||
"optional_links": [
|
"optional_links": [
|
||||||
storage.StorageResource.kind,
|
storage.StorageResource.kind,
|
||||||
|
@ -166,26 +169,45 @@ class Controller(ooi.api.base.Controller):
|
||||||
flavor = obj["schemes"][templates.OpenStackResourceTemplate.scheme][0]
|
flavor = obj["schemes"][templates.OpenStackResourceTemplate.scheme][0]
|
||||||
user_data, key_name, key_data = None, None, None
|
user_data, key_name, key_data = None, None, None
|
||||||
create_key, create_key_tmp = False, False
|
create_key, create_key_tmp = False, False
|
||||||
if contextualization.user_data.scheme in obj["schemes"]:
|
# TODO(enolfc): deprecate OS Contextualization in the future
|
||||||
|
# meanwhile, raise 409 conflict if both contextualizations types appear
|
||||||
|
if (os_contextualization.user_data.scheme in obj["schemes"] and
|
||||||
|
contextualization.user_data.scheme in obj["schemes"]):
|
||||||
|
raise exception.OCCIMixinConflict()
|
||||||
|
|
||||||
|
if os_contextualization.user_data.scheme in obj["schemes"]:
|
||||||
user_data = attrs.get("org.openstack.compute.user_data")
|
user_data = attrs.get("org.openstack.compute.user_data")
|
||||||
if contextualization.public_key.scheme in obj["schemes"]:
|
if contextualization.user_data.scheme in obj["schemes"]:
|
||||||
|
user_data = attrs.get("occi.compute.user_data")
|
||||||
|
|
||||||
|
if (os_contextualization.public_key.scheme in obj["schemes"] and
|
||||||
|
contextualization.ssh_key.scheme in obj["schemes"]):
|
||||||
|
raise exception.OCCIMixinConflict()
|
||||||
|
|
||||||
|
key_name = key_data = None
|
||||||
|
if os_contextualization.public_key.scheme in obj["schemes"]:
|
||||||
key_name = attrs.get("org.openstack.credentials.publickey.name")
|
key_name = attrs.get("org.openstack.credentials.publickey.name")
|
||||||
key_data = attrs.get("org.openstack.credentials.publickey.data")
|
key_data = attrs.get("org.openstack.credentials.publickey.data")
|
||||||
|
|
||||||
if key_name and key_data:
|
if contextualization.ssh_key.scheme in obj["schemes"]:
|
||||||
create_key = True
|
if key_data or key_name:
|
||||||
elif not key_name and key_data:
|
raise exception.OCCIMixinConflict()
|
||||||
# NOTE(orviz) To be occi-os compliant, not
|
key_data = attrs.get("occi.credentials.ssh_key")
|
||||||
# raise exception.MissingKeypairName
|
|
||||||
key_name = uuid.uuid4().hex
|
|
||||||
create_key = True
|
|
||||||
create_key_tmp = True
|
|
||||||
|
|
||||||
if create_key:
|
if key_name and key_data:
|
||||||
# add keypair: if key_name already exists, a 409 HTTP code
|
create_key = True
|
||||||
# will be returned by OpenStack
|
elif not key_name and key_data:
|
||||||
self.os_helper.keypair_create(req, key_name,
|
# NOTE(orviz) To be occi-os compliant, not
|
||||||
public_key=key_data)
|
# raise exception.MissingKeypairName
|
||||||
|
key_name = uuid.uuid4().hex
|
||||||
|
create_key = True
|
||||||
|
create_key_tmp = True
|
||||||
|
|
||||||
|
if create_key:
|
||||||
|
# add keypair: if key_name already exists, a 409 HTTP code
|
||||||
|
# will be returned by OpenStack
|
||||||
|
self.os_helper.keypair_create(req, key_name,
|
||||||
|
public_key=key_data)
|
||||||
|
|
||||||
block_device_mapping_v2 = self._build_block_mapping(req, obj)
|
block_device_mapping_v2 = self._build_block_mapping(req, obj)
|
||||||
networks = self._get_network_from_req(req, obj)
|
networks = self._get_network_from_req(req, obj)
|
||||||
|
|
|
@ -20,12 +20,13 @@ from ooi.occi.core import entity
|
||||||
from ooi.occi.core import link
|
from ooi.occi.core import link
|
||||||
from ooi.occi.core import resource
|
from ooi.occi.core import resource
|
||||||
from ooi.occi.infrastructure import compute
|
from ooi.occi.infrastructure import compute
|
||||||
|
from ooi.occi.infrastructure import contextualization
|
||||||
from ooi.occi.infrastructure import network
|
from ooi.occi.infrastructure import network
|
||||||
from ooi.occi.infrastructure import network_link
|
from ooi.occi.infrastructure import network_link
|
||||||
from ooi.occi.infrastructure import storage
|
from ooi.occi.infrastructure import storage
|
||||||
from ooi.occi.infrastructure import storage_link
|
from ooi.occi.infrastructure import storage_link
|
||||||
from ooi.occi.infrastructure import templates as infra_templates
|
from ooi.occi.infrastructure import templates as infra_templates
|
||||||
from ooi.openstack import contextualization
|
from ooi.openstack import contextualization as os_contextualization
|
||||||
from ooi.openstack import network as os_network
|
from ooi.openstack import network as os_network
|
||||||
from ooi.openstack import templates
|
from ooi.openstack import templates
|
||||||
|
|
||||||
|
@ -108,8 +109,12 @@ class Controller(base.Controller):
|
||||||
mixins.extend(self._os_tpls(req))
|
mixins.extend(self._os_tpls(req))
|
||||||
|
|
||||||
# OpenStack Contextualization
|
# OpenStack Contextualization
|
||||||
|
mixins.append(os_contextualization.user_data)
|
||||||
|
mixins.append(os_contextualization.public_key)
|
||||||
|
|
||||||
|
# OCCI Contextualization
|
||||||
mixins.append(contextualization.user_data)
|
mixins.append(contextualization.user_data)
|
||||||
mixins.append(contextualization.public_key)
|
mixins.append(contextualization.ssh_key)
|
||||||
|
|
||||||
# OpenStack Floating IP Pools
|
# OpenStack Floating IP Pools
|
||||||
mixins.extend(self._ip_pools(req))
|
mixins.extend(self._ip_pools(req))
|
||||||
|
|
|
@ -147,3 +147,8 @@ class NetworkPoolFound(NotFound):
|
||||||
class MissingKeypairName(Invalid):
|
class MissingKeypairName(Invalid):
|
||||||
msg_fmt = "Missing Keypair Name"
|
msg_fmt = "Missing Keypair Name"
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
|
|
||||||
|
class OCCIMixinConflict(OCCIException):
|
||||||
|
msg_fmt = "Conflicting OCCI Mixins used in request"
|
||||||
|
code = 409
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Copyright 2015 Spanish National Research Council
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from ooi.occi.core import attribute
|
||||||
|
from ooi.occi.core import mixin
|
||||||
|
from ooi.occi import helpers
|
||||||
|
from ooi.occi.infrastructure import compute
|
||||||
|
|
||||||
|
|
||||||
|
class SSHKey(mixin.Mixin):
|
||||||
|
scheme = helpers.build_scheme("infrastructure/credentials")
|
||||||
|
term = "ssh_key"
|
||||||
|
|
||||||
|
def __init__(self, ssh_key=None):
|
||||||
|
attrs = [
|
||||||
|
attribute.MutableAttribute(
|
||||||
|
"occi.crendentials.ssh.publickey", ssh_key, required=True,
|
||||||
|
description=("The contents of the public key file to be "
|
||||||
|
"injected into the Compute Resource"),
|
||||||
|
attr_type=attribute.AttributeType.string_type),
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = attribute.AttributeCollection({a.name: a for a in attrs})
|
||||||
|
|
||||||
|
super(SSHKey, self).__init__(SSHKey.scheme, SSHKey.term,
|
||||||
|
"Credentials mixin",
|
||||||
|
attributes=attrs,
|
||||||
|
applies=[compute.ComputeResource.kind])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ssh_key(self):
|
||||||
|
attr = "occi.crendentials.ssh.publickey"
|
||||||
|
return self.attributes[attr].value
|
||||||
|
|
||||||
|
@ssh_key.setter
|
||||||
|
def ssh_key(self, value):
|
||||||
|
attr = "occi.crendentials.ssh.publickey"
|
||||||
|
self.attributes[attr].value = value
|
||||||
|
|
||||||
|
|
||||||
|
class UserData(mixin.Mixin):
|
||||||
|
scheme = helpers.build_scheme("infrastructure/compute")
|
||||||
|
term = "user_data"
|
||||||
|
|
||||||
|
def __init__(self, user_data=None):
|
||||||
|
attrs = [
|
||||||
|
attribute.MutableAttribute(
|
||||||
|
"occi.compute.userdata", user_data, required=True,
|
||||||
|
description=("Contextualization data (e.g., script, "
|
||||||
|
"executable) that the client supplies once and "
|
||||||
|
"only once. It cannot be updated."),
|
||||||
|
attr_type=attribute.AttributeType.string_type),
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = attribute.AttributeCollection({a.name: a for a in attrs})
|
||||||
|
|
||||||
|
super(UserData, self).__init__(UserData.scheme,
|
||||||
|
UserData.term,
|
||||||
|
"Contextualization mixin",
|
||||||
|
attributes=attrs,
|
||||||
|
applies=[compute.ComputeResource.kind])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user_data(self):
|
||||||
|
attr = "occi.compute.userdata"
|
||||||
|
return self.attributes[attr].value
|
||||||
|
|
||||||
|
@user_data.setter
|
||||||
|
def user_data(self, value):
|
||||||
|
attr = "occi.compute.userdata"
|
||||||
|
self.attributes[attr].value = value
|
||||||
|
|
||||||
|
ssh_key = SSHKey()
|
||||||
|
user_data = UserData()
|
|
@ -409,6 +409,16 @@ def fake_query_results():
|
||||||
'scheme="http://schemas.openstack.org/instance/credentials#"; '
|
'scheme="http://schemas.openstack.org/instance/credentials#"; '
|
||||||
'class="mixin"; title="Contextualization extension - public_key"')
|
'class="mixin"; title="Contextualization extension - public_key"')
|
||||||
|
|
||||||
|
# OCCI contextualization
|
||||||
|
cats.append(
|
||||||
|
'user_data; '
|
||||||
|
'scheme="http://schemas.ogf.org/occi/infrastructure/compute#"; '
|
||||||
|
'class="mixin"; title="Contextualization mixin"')
|
||||||
|
cats.append(
|
||||||
|
'ssh_key; '
|
||||||
|
'scheme="http://schemas.ogf.org/occi/infrastructure/credentials#"; '
|
||||||
|
'class="mixin"; title="Credentials mixin"')
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for c in cats:
|
for c in cats:
|
||||||
result.append(("Category", c))
|
result.append(("Category", c))
|
||||||
|
|
|
@ -257,7 +257,7 @@ class TestComputeController(test_middleware.TestMiddleware):
|
||||||
self.assertEqual(400, resp.status_code)
|
self.assertEqual(400, resp.status_code)
|
||||||
self.assertDefaults(resp)
|
self.assertDefaults(resp)
|
||||||
|
|
||||||
def test_create_with_context(self):
|
def test_create_with_os_context(self):
|
||||||
tenant = fakes.tenants["foo"]
|
tenant = fakes.tenants["foo"]
|
||||||
|
|
||||||
app = self.get_app()
|
app = self.get_app()
|
||||||
|
@ -292,6 +292,41 @@ class TestComputeController(test_middleware.TestMiddleware):
|
||||||
self.assertExpectedResult(expected, resp)
|
self.assertExpectedResult(expected, resp)
|
||||||
self.assertDefaults(resp)
|
self.assertDefaults(resp)
|
||||||
|
|
||||||
|
def test_create_with_occi_context(self):
|
||||||
|
tenant = fakes.tenants["foo"]
|
||||||
|
|
||||||
|
app = self.get_app()
|
||||||
|
headers = {
|
||||||
|
'Category': (
|
||||||
|
'compute;'
|
||||||
|
'scheme="http://schemas.ogf.org/occi/infrastructure#";'
|
||||||
|
'class="kind",'
|
||||||
|
'foo;'
|
||||||
|
'scheme="http://schemas.openstack.org/template/resource#";'
|
||||||
|
'class="mixin",'
|
||||||
|
'bar;'
|
||||||
|
'scheme="http://schemas.openstack.org/template/os#";'
|
||||||
|
'class="mixin",'
|
||||||
|
'user_data;'
|
||||||
|
'scheme="http://schemas.ogf.org/occi/infrastructure/compute#";'
|
||||||
|
'class="mixin"'
|
||||||
|
),
|
||||||
|
'X-OCCI-Attribute': (
|
||||||
|
'occi.compute.user_data="foo"'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
req = self._build_req("/compute", tenant["id"], method="POST",
|
||||||
|
headers=headers)
|
||||||
|
resp = req.get_response(app)
|
||||||
|
|
||||||
|
expected = [("X-OCCI-Location",
|
||||||
|
utils.join_url(self.application_url + "/",
|
||||||
|
"compute/%s" % "foo"))]
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.assertExpectedResult(expected, resp)
|
||||||
|
self.assertDefaults(resp)
|
||||||
|
|
||||||
def test_create_vm_with_storage(self):
|
def test_create_vm_with_storage(self):
|
||||||
tenant = fakes.tenants["foo"]
|
tenant = fakes.tenants["foo"]
|
||||||
target = utils.join_url(self.application_url + "/",
|
target = utils.join_url(self.application_url + "/",
|
||||||
|
|
|
@ -24,9 +24,10 @@ from ooi.api import helpers
|
||||||
from ooi import exception
|
from ooi import exception
|
||||||
from ooi.occi.core import collection
|
from ooi.occi.core import collection
|
||||||
from ooi.occi.infrastructure import compute as occi_compute
|
from ooi.occi.infrastructure import compute as occi_compute
|
||||||
|
from ooi.occi.infrastructure import contextualization
|
||||||
from ooi.occi.infrastructure import network as occi_network
|
from ooi.occi.infrastructure import network as occi_network
|
||||||
from ooi.occi.infrastructure import storage as occi_storage
|
from ooi.occi.infrastructure import storage as occi_storage
|
||||||
from ooi.openstack import contextualization
|
from ooi.openstack import contextualization as os_contextualization
|
||||||
from ooi.openstack import templates
|
from ooi.openstack import templates
|
||||||
from ooi.tests import base
|
from ooi.tests import base
|
||||||
from ooi.tests import fakes
|
from ooi.tests import fakes
|
||||||
|
@ -272,8 +273,8 @@ class TestComputeController(base.TestController):
|
||||||
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
||||||
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
||||||
@mock.patch("ooi.occi.validator.Validator")
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
def test_create_server_with_context(self, m_validator, m_net,
|
def test_create_server_with_os_context(self, m_validator, m_net,
|
||||||
m_create):
|
m_create):
|
||||||
tenant = fakes.tenants["foo"]
|
tenant = fakes.tenants["foo"]
|
||||||
req = self._build_req(tenant["id"])
|
req = self._build_req(tenant["id"])
|
||||||
obj = {
|
obj = {
|
||||||
|
@ -284,8 +285,7 @@ class TestComputeController(base.TestController):
|
||||||
"schemes": {
|
"schemes": {
|
||||||
templates.OpenStackOSTemplate.scheme: ["foo"],
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
contextualization.user_data.scheme: None,
|
os_contextualization.user_data.scheme: None,
|
||||||
contextualization.public_key.scheme: None,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
# NOTE(aloga): the mocked call is
|
# NOTE(aloga): the mocked call is
|
||||||
|
@ -306,12 +306,69 @@ class TestComputeController(base.TestController):
|
||||||
block_device_mapping_v2=[],
|
block_device_mapping_v2=[],
|
||||||
networks=net)
|
networks=net)
|
||||||
|
|
||||||
|
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
||||||
|
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
||||||
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
|
def test_create_server_with_occi_context(self, m_validator, m_net,
|
||||||
|
m_create):
|
||||||
|
tenant = fakes.tenants["foo"]
|
||||||
|
req = self._build_req(tenant["id"])
|
||||||
|
obj = {
|
||||||
|
"attributes": {
|
||||||
|
"occi.core.title": "foo instance",
|
||||||
|
"occi.compute.user_data": "bazonk",
|
||||||
|
},
|
||||||
|
"schemes": {
|
||||||
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
|
contextualization.user_data.scheme: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
# NOTE(aloga): the mocked call is
|
||||||
|
# "parser = req.get_parser()(req.headers, req.body)"
|
||||||
|
req.get_parser = mock.MagicMock()
|
||||||
|
# NOTE(aloga): MOG!
|
||||||
|
req.get_parser.return_value.return_value.parse.return_value = obj
|
||||||
|
m_validator.validate.return_value = True
|
||||||
|
server = {"id": uuid.uuid4().hex}
|
||||||
|
m_create.return_value = server
|
||||||
|
net = [{'uuid': uuid.uuid4().hex}]
|
||||||
|
m_net.return_value = net
|
||||||
|
ret = self.controller.create(req, None) # noqa
|
||||||
|
self.assertIsInstance(ret, collection.Collection)
|
||||||
|
m_create.assert_called_with(mock.ANY, "foo instance", "foo", "bar",
|
||||||
|
user_data="bazonk",
|
||||||
|
key_name=None,
|
||||||
|
block_device_mapping_v2=[],
|
||||||
|
networks=net)
|
||||||
|
|
||||||
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
|
def test_create_server_with_context_conflict(self, m_validator):
|
||||||
|
tenant = fakes.tenants["foo"]
|
||||||
|
req = self._build_req(tenant["id"])
|
||||||
|
obj = {
|
||||||
|
"attributes": {
|
||||||
|
"occi.core.title": "foo instance",
|
||||||
|
},
|
||||||
|
"schemes": {
|
||||||
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
|
os_contextualization.user_data.scheme: None,
|
||||||
|
contextualization.user_data.scheme: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req.get_parser = mock.MagicMock()
|
||||||
|
req.get_parser.return_value.return_value.parse.return_value = obj
|
||||||
|
m_validator.validate.return_value = True
|
||||||
|
self.assertRaises(exception.OCCIMixinConflict, self.controller.create,
|
||||||
|
req, None)
|
||||||
|
|
||||||
@mock.patch.object(helpers.OpenStackHelper, "keypair_create")
|
@mock.patch.object(helpers.OpenStackHelper, "keypair_create")
|
||||||
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
||||||
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
||||||
@mock.patch("ooi.occi.validator.Validator")
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
def test_create_server_with_sshkeys(self, m_validator, m_net,
|
def test_create_server_with_os_sshkey(self, m_validator, m_net,
|
||||||
m_server, m_keypair):
|
m_server, m_keypair):
|
||||||
tenant = fakes.tenants["foo"]
|
tenant = fakes.tenants["foo"]
|
||||||
req = self._build_req(tenant["id"])
|
req = self._build_req(tenant["id"])
|
||||||
obj = {
|
obj = {
|
||||||
|
@ -323,7 +380,7 @@ class TestComputeController(base.TestController):
|
||||||
"schemes": {
|
"schemes": {
|
||||||
templates.OpenStackOSTemplate.scheme: ["foo"],
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
contextualization.public_key.scheme: None,
|
os_contextualization.public_key.scheme: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req.get_parser = mock.MagicMock()
|
req.get_parser = mock.MagicMock()
|
||||||
|
@ -349,9 +406,9 @@ class TestComputeController(base.TestController):
|
||||||
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
||||||
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
||||||
@mock.patch("ooi.occi.validator.Validator")
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
def test_create_server_with_no_sshkey_name(self, m_validator, m_net,
|
def test_create_server_with_os_sshkey_no_name(self, m_validator, m_net,
|
||||||
m_server, m_keypair,
|
m_server, m_keypair,
|
||||||
m_keypair_delete):
|
m_keypair_delete):
|
||||||
tenant = fakes.tenants["foo"]
|
tenant = fakes.tenants["foo"]
|
||||||
req = self._build_req(tenant["id"])
|
req = self._build_req(tenant["id"])
|
||||||
obj = {
|
obj = {
|
||||||
|
@ -362,7 +419,7 @@ class TestComputeController(base.TestController):
|
||||||
"schemes": {
|
"schemes": {
|
||||||
templates.OpenStackOSTemplate.scheme: ["foo"],
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
contextualization.public_key.scheme: None,
|
os_contextualization.public_key.scheme: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req.get_parser = mock.MagicMock()
|
req.get_parser = mock.MagicMock()
|
||||||
|
@ -384,6 +441,67 @@ class TestComputeController(base.TestController):
|
||||||
networks=net)
|
networks=net)
|
||||||
m_keypair_delete.assert_called_with(mock.ANY, mock.ANY)
|
m_keypair_delete.assert_called_with(mock.ANY, mock.ANY)
|
||||||
|
|
||||||
|
@mock.patch.object(helpers.OpenStackHelper, "keypair_delete")
|
||||||
|
@mock.patch.object(helpers.OpenStackHelper, "keypair_create")
|
||||||
|
@mock.patch.object(helpers.OpenStackHelper, "create_server")
|
||||||
|
@mock.patch.object(compute.Controller, "_get_network_from_req")
|
||||||
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
|
def test_create_server_with_occi_sshkey(self, m_validator, m_net,
|
||||||
|
m_server, m_keypair,
|
||||||
|
m_keypair_delete):
|
||||||
|
tenant = fakes.tenants["foo"]
|
||||||
|
req = self._build_req(tenant["id"])
|
||||||
|
obj = {
|
||||||
|
"attributes": {
|
||||||
|
"occi.core.title": "foo instance",
|
||||||
|
"occi.credentials.ssh_key": "wtfoodata"
|
||||||
|
},
|
||||||
|
"schemes": {
|
||||||
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
|
contextualization.ssh_key.scheme: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req.get_parser = mock.MagicMock()
|
||||||
|
req.get_parser.return_value.return_value.parse.return_value = obj
|
||||||
|
m_validator.validate.return_value = True
|
||||||
|
server = {"id": uuid.uuid4().hex}
|
||||||
|
m_server.return_value = server
|
||||||
|
m_keypair.return_value = None
|
||||||
|
net = [{'uuid': uuid.uuid4().hex}]
|
||||||
|
m_net.return_value = net
|
||||||
|
ret = self.controller.create(req, None) # noqa
|
||||||
|
self.assertIsInstance(ret, collection.Collection)
|
||||||
|
m_keypair.assert_called_with(mock.ANY, mock.ANY,
|
||||||
|
public_key="wtfoodata")
|
||||||
|
m_server.assert_called_with(mock.ANY, "foo instance", "foo", "bar",
|
||||||
|
user_data=None,
|
||||||
|
key_name=mock.ANY,
|
||||||
|
block_device_mapping_v2=[],
|
||||||
|
networks=net)
|
||||||
|
m_keypair_delete.assert_called_with(mock.ANY, mock.ANY)
|
||||||
|
|
||||||
|
@mock.patch("ooi.occi.validator.Validator")
|
||||||
|
def test_create_server_with_sshkey_conflict(self, m_validator):
|
||||||
|
tenant = fakes.tenants["foo"]
|
||||||
|
req = self._build_req(tenant["id"])
|
||||||
|
obj = {
|
||||||
|
"attributes": {
|
||||||
|
"occi.core.title": "foo instance",
|
||||||
|
},
|
||||||
|
"schemes": {
|
||||||
|
templates.OpenStackOSTemplate.scheme: ["foo"],
|
||||||
|
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||||
|
os_contextualization.public_key.scheme: None,
|
||||||
|
contextualization.ssh_key.scheme: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req.get_parser = mock.MagicMock()
|
||||||
|
req.get_parser.return_value.return_value.parse.return_value = obj
|
||||||
|
m_validator.validate.return_value = True
|
||||||
|
self.assertRaises(exception.OCCIMixinConflict, self.controller.create,
|
||||||
|
req, None)
|
||||||
|
|
||||||
def test_build_block_mapping_no_links(self):
|
def test_build_block_mapping_no_links(self):
|
||||||
ret = self.controller._build_block_mapping(None, {})
|
ret = self.controller._build_block_mapping(None, {})
|
||||||
self.assertEqual([], ret)
|
self.assertEqual([], ret)
|
||||||
|
|
|
@ -20,12 +20,13 @@ from ooi.occi.core import entity
|
||||||
from ooi.occi.core import link
|
from ooi.occi.core import link
|
||||||
from ooi.occi.core import resource
|
from ooi.occi.core import resource
|
||||||
from ooi.occi.infrastructure import compute
|
from ooi.occi.infrastructure import compute
|
||||||
|
from ooi.occi.infrastructure import contextualization
|
||||||
from ooi.occi.infrastructure import network
|
from ooi.occi.infrastructure import network
|
||||||
from ooi.occi.infrastructure import network_link
|
from ooi.occi.infrastructure import network_link
|
||||||
from ooi.occi.infrastructure import storage
|
from ooi.occi.infrastructure import storage
|
||||||
from ooi.occi.infrastructure import storage_link
|
from ooi.occi.infrastructure import storage_link
|
||||||
from ooi.occi.infrastructure import templates as infra_templates
|
from ooi.occi.infrastructure import templates as infra_templates
|
||||||
from ooi.openstack import contextualization
|
from ooi.openstack import contextualization as os_contextualization
|
||||||
from ooi.openstack import network as os_network
|
from ooi.openstack import network as os_network
|
||||||
from ooi.openstack import templates
|
from ooi.openstack import templates
|
||||||
from ooi.tests import base
|
from ooi.tests import base
|
||||||
|
@ -74,8 +75,10 @@ class TestQueryController(base.TestController):
|
||||||
network_link.ip_network_interface,
|
network_link.ip_network_interface,
|
||||||
infra_templates.os_tpl,
|
infra_templates.os_tpl,
|
||||||
infra_templates.resource_tpl,
|
infra_templates.resource_tpl,
|
||||||
|
os_contextualization.user_data,
|
||||||
|
os_contextualization.public_key,
|
||||||
contextualization.user_data,
|
contextualization.user_data,
|
||||||
contextualization.public_key,
|
contextualization.ssh_key,
|
||||||
]
|
]
|
||||||
|
|
||||||
expected_actions = [
|
expected_actions = [
|
||||||
|
@ -141,8 +144,10 @@ class TestQueryController(base.TestController):
|
||||||
network_link.ip_network_interface,
|
network_link.ip_network_interface,
|
||||||
infra_templates.os_tpl,
|
infra_templates.os_tpl,
|
||||||
infra_templates.resource_tpl,
|
infra_templates.resource_tpl,
|
||||||
|
os_contextualization.user_data,
|
||||||
|
os_contextualization.public_key,
|
||||||
contextualization.user_data,
|
contextualization.user_data,
|
||||||
contextualization.public_key,
|
contextualization.ssh_key,
|
||||||
]
|
]
|
||||||
|
|
||||||
expected_actions = [
|
expected_actions = [
|
||||||
|
|
|
@ -18,6 +18,7 @@ from ooi.occi.core import link
|
||||||
from ooi.occi.core import mixin
|
from ooi.occi.core import mixin
|
||||||
from ooi.occi.core import resource
|
from ooi.occi.core import resource
|
||||||
from ooi.occi.infrastructure import compute
|
from ooi.occi.infrastructure import compute
|
||||||
|
from ooi.occi.infrastructure import contextualization
|
||||||
from ooi.occi.infrastructure import network
|
from ooi.occi.infrastructure import network
|
||||||
from ooi.occi.infrastructure import network_link
|
from ooi.occi.infrastructure import network_link
|
||||||
from ooi.occi.infrastructure import storage
|
from ooi.occi.infrastructure import storage
|
||||||
|
@ -340,3 +341,21 @@ class TestOCCINetworkInterface(base.TestCase):
|
||||||
self.assertEqual("00:01:02:03:04:05", l.mac)
|
self.assertEqual("00:01:02:03:04:05", l.mac)
|
||||||
self.assertEqual("foo", l.state)
|
self.assertEqual("foo", l.state)
|
||||||
self.assertEqual("msg", l.message)
|
self.assertEqual("msg", l.message)
|
||||||
|
|
||||||
|
|
||||||
|
class TestOCCIUserData(base.TestCase):
|
||||||
|
def test_occi_userdata(self):
|
||||||
|
user_data = "foobar"
|
||||||
|
mxn = contextualization.UserData(user_data)
|
||||||
|
self.assertEqual("user_data", mxn.term)
|
||||||
|
self.assertEqual(user_data, mxn.user_data)
|
||||||
|
self.assertEqual([compute.ComputeResource.kind], mxn.applies)
|
||||||
|
|
||||||
|
|
||||||
|
class TestOCCISSHKey(base.TestCase):
|
||||||
|
def test_occi_ssh_key(self):
|
||||||
|
key_data = "1234"
|
||||||
|
mxn = contextualization.SSHKey(key_data)
|
||||||
|
self.assertEqual("ssh_key", mxn.term)
|
||||||
|
self.assertEqual(key_data, mxn.ssh_key)
|
||||||
|
self.assertEqual([compute.ComputeResource.kind], mxn.applies)
|
||||||
|
|
Loading…
Reference in New Issue