Add VM resize support
Updates in compute with correct mixin will produce a VM resize. The resize will not be confirmed automatically unless the resize_confirm_window is configured in nova. Change-Id: I8b868a8a4fb403e337d3fe6c08b7d3f65736e545
This commit is contained in:
parent
65bd940498
commit
8f669d9225
|
@ -246,6 +246,28 @@ class Controller(ooi.api.base.Controller):
|
|||
|
||||
return collection.Collection(resources=occi_compute_resources)
|
||||
|
||||
def update(self, req, id, body):
|
||||
# get info from server
|
||||
self.os_helper.get_server(req, id)
|
||||
|
||||
parser = req.get_parser()(req.headers, req.body)
|
||||
scheme = {
|
||||
"mixins": [
|
||||
templates.OpenStackResourceTemplate,
|
||||
],
|
||||
}
|
||||
obj = parser.parse()
|
||||
validator = occi_validator.Validator(obj)
|
||||
validator.validate(scheme)
|
||||
|
||||
# Changes to the flavor (resize)
|
||||
flavor = obj["schemes"][templates.OpenStackResourceTemplate.scheme][0]
|
||||
action_args = {"flavorRef": flavor}
|
||||
self.os_helper.run_action(req, "resize", id, action_args)
|
||||
|
||||
# re-use the show function
|
||||
return self.show(req, id)
|
||||
|
||||
def show(self, req, id):
|
||||
# get info from server
|
||||
s = self.os_helper.get_server(req, id)
|
||||
|
|
|
@ -306,7 +306,8 @@ class OpenStackHelper(BaseHelper):
|
|||
"resume": {"resume": None},
|
||||
"unpause": {"unpause": None},
|
||||
"restart": {"reboot": {"type": "SOFT"}},
|
||||
"save": {"createImage": None}
|
||||
"save": {"createImage": None},
|
||||
"resize": {"resize": None},
|
||||
}
|
||||
|
||||
os_action, default_args = actions_map[action].popitem()
|
||||
|
|
|
@ -711,6 +711,26 @@ class FakeApp(object):
|
|||
"status": "on-line"}}
|
||||
return create_fake_json_resp(s)
|
||||
|
||||
def _do_resize_server(self, req):
|
||||
body = req.json_body.copy()
|
||||
new_flavor = body.popitem()[1]["flavorRef"]
|
||||
r = self._get_from_routes(req)
|
||||
# Make sure subsequent calls to the server are up to date
|
||||
# Some request path knowledge used which should be in this form:
|
||||
# /v2.1/tenant_id/servers/server_id/action
|
||||
p = req.path.split("/")
|
||||
tenant_id = p[2]
|
||||
server_id = p[4]
|
||||
for s in servers[tenant_id]:
|
||||
if s["id"] == server_id:
|
||||
# do a conversion to avoid current id schemas
|
||||
s["flavor"]["id"] = int(new_flavor)
|
||||
break
|
||||
# And repopulate the objects so they are properly returned
|
||||
self._populate("/%s" % tenant_id, "server", servers[tenant_id],
|
||||
actions=True)
|
||||
return r
|
||||
|
||||
def _do_create_attachment(self, req):
|
||||
v = {"volumeAttachment": {"serverId": "foo",
|
||||
"volumeId": "bar",
|
||||
|
@ -764,6 +784,8 @@ class FakeApp(object):
|
|||
"removeSecurityGroup",
|
||||
"addSecurityGroup"]:
|
||||
return self._get_from_routes(req)
|
||||
if action[0] == "resize":
|
||||
return self._do_resize_server(req)
|
||||
elif req.path_info.endswith("os-volume_attachments"):
|
||||
return self._do_create_attachment(req)
|
||||
elif req.path_info.endswith("os-floating-ips"):
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
from ooi.tests import fakes
|
||||
|
@ -239,6 +240,52 @@ class TestComputeController(test_middleware.TestMiddleware):
|
|||
self.assertDefaults(resp)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_modify_vm_flavor(self):
|
||||
tenant = fakes.tenants["foo"]
|
||||
app = self.get_app()
|
||||
flavor_ids = [ids for ids in fakes.flavors]
|
||||
|
||||
for server in fakes.servers[tenant["id"]]:
|
||||
old_flavor = server["flavor"]["id"]
|
||||
# just pick a different one
|
||||
new_flavor = flavor_ids[flavor_ids.index(old_flavor) - 1]
|
||||
headers = {
|
||||
'Category': (
|
||||
'%s ;'
|
||||
'scheme="http://schemas.openstack.org/template/resource#";'
|
||||
'class="mixin"'
|
||||
) % new_flavor
|
||||
}
|
||||
req = self._build_req("/compute/%s" % server["id"], tenant["id"],
|
||||
method="PUT", headers=headers)
|
||||
|
||||
modified_server = copy.deepcopy(server)
|
||||
modified_server["flavor"]["id"] = new_flavor
|
||||
expected = build_occi_server(modified_server)
|
||||
resp = req.get_response(app)
|
||||
self.assertDefaults(resp)
|
||||
self.assertExpectedResult(expected, resp)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_modify_vm_wrong_mixin(self):
|
||||
tenant = fakes.tenants["foo"]
|
||||
app = self.get_app()
|
||||
|
||||
for server in fakes.servers[tenant["id"]]:
|
||||
headers = {
|
||||
'Category': (
|
||||
'foobar;'
|
||||
'scheme="http://schemas.openstack.org/template/os#";'
|
||||
'class="mixin"'
|
||||
)
|
||||
}
|
||||
req = self._build_req("/compute/%s" % server["id"], tenant["id"],
|
||||
method="PUT", headers=headers)
|
||||
|
||||
resp = req.get_response(app)
|
||||
self.assertDefaults(resp)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_create_vm(self):
|
||||
tenant = fakes.tenants["foo"]
|
||||
|
||||
|
|
|
@ -787,3 +787,30 @@ class TestComputeController(base.TestController):
|
|||
block_device_mapping=[],
|
||||
networks=net)
|
||||
m_net.assert_called_with(req, obj)
|
||||
|
||||
@mock.patch.object(compute.Controller, "show")
|
||||
@mock.patch.object(helpers.OpenStackHelper, "run_action")
|
||||
@mock.patch("ooi.occi.validator.Validator")
|
||||
@mock.patch.object(helpers.OpenStackHelper, "get_server")
|
||||
def test_update(self, m_server, m_validator, m_run_action, m_show):
|
||||
tenant = fakes.tenants["foo"]
|
||||
req = self._build_req(tenant["id"])
|
||||
obj = {
|
||||
"schemes": {
|
||||
templates.OpenStackResourceTemplate.scheme: ["bar"],
|
||||
},
|
||||
}
|
||||
# NOTE(aloga): the mocked call is
|
||||
# "parser = req.get_parser()(req.headers, req.body)"
|
||||
req.get_parser = mock.MagicMock()
|
||||
req.get_parser.return_value.return_value.parse.return_value = obj
|
||||
m_validator.validate.return_value = True
|
||||
|
||||
servers = fakes.servers[tenant["id"]]
|
||||
for server in servers:
|
||||
ret = self.controller.update(req, server["id"], None)
|
||||
m_run_action.assert_called_with(mock.ANY, "resize", server["id"],
|
||||
{'flavorRef': 'bar'})
|
||||
m_server.assert_called_with(mock.ANY, server["id"])
|
||||
m_show.assert_called_with(mock.ANY, server["id"])
|
||||
self.assertEqual(m_show.return_value, ret)
|
||||
|
|
Loading…
Reference in New Issue