Implement update bay node_count
It is implemented by updating the Heat stack with the new node_count Partially implements: blueprint update-node-count Change-Id: I2c331043bb6e6fce14fc82932dcd9c3677448598
This commit is contained in:
parent
d35c05bc3c
commit
d28a780d77
|
@ -278,8 +278,8 @@ class BaysController(rest.RestController):
|
||||||
if rpc_bay[field] != patch_val:
|
if rpc_bay[field] != patch_val:
|
||||||
rpc_bay[field] = patch_val
|
rpc_bay[field] = patch_val
|
||||||
|
|
||||||
rpc_bay.save()
|
res_bay = pecan.request.rpcapi.bay_update(rpc_bay)
|
||||||
return Bay.convert_with_links(rpc_bay)
|
return Bay.convert_with_links(res_bay)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
||||||
def delete(self, bay_uuid):
|
def delete(self, bay_uuid):
|
||||||
|
|
|
@ -59,6 +59,9 @@ class API(rpc_service.API):
|
||||||
def bay_show(self, context, uuid):
|
def bay_show(self, context, uuid):
|
||||||
return objects.Bay.get_by_uuid(context, uuid)
|
return objects.Bay.get_by_uuid(context, uuid)
|
||||||
|
|
||||||
|
def bay_update(self, bay):
|
||||||
|
return self._call('bay_update', bay=bay)
|
||||||
|
|
||||||
# Service Operations
|
# Service Operations
|
||||||
|
|
||||||
def service_create(self, service):
|
def service_create(self, service):
|
||||||
|
|
|
@ -17,6 +17,7 @@ from heatclient import exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from magnum.common import clients
|
from magnum.common import clients
|
||||||
|
from magnum.common import exception
|
||||||
from magnum.common import short_id
|
from magnum.common import short_id
|
||||||
from magnum import objects
|
from magnum import objects
|
||||||
from magnum.openstack.common._i18n import _
|
from magnum.openstack.common._i18n import _
|
||||||
|
@ -87,6 +88,20 @@ def _create_stack(context, osc, bay):
|
||||||
return created_stack
|
return created_stack
|
||||||
|
|
||||||
|
|
||||||
|
def _update_stack(context, osc, bay):
|
||||||
|
bay_definition = _extract_bay_definition(context, bay)
|
||||||
|
|
||||||
|
tpl_files, template = template_utils.get_template_contents(
|
||||||
|
cfg.CONF.k8s_heat.template_path)
|
||||||
|
fields = {
|
||||||
|
'parameters': bay_definition,
|
||||||
|
'template': template,
|
||||||
|
'files': dict(list(tpl_files.items()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return osc.heat().stacks.update(bay.stack_id, **fields)
|
||||||
|
|
||||||
|
|
||||||
def _parse_stack_outputs(outputs):
|
def _parse_stack_outputs(outputs):
|
||||||
parsed_outputs = {}
|
parsed_outputs = {}
|
||||||
|
|
||||||
|
@ -122,6 +137,30 @@ class Handler(object):
|
||||||
|
|
||||||
return bay
|
return bay
|
||||||
|
|
||||||
|
def bay_update(self, context, bay):
|
||||||
|
LOG.debug('k8s_heat bay_update')
|
||||||
|
|
||||||
|
osc = clients.OpenStackClients(context)
|
||||||
|
stack = osc.heat().stacks.get(bay.stack_id)
|
||||||
|
if (stack.stack_status != 'CREATE_COMPLETE' and
|
||||||
|
stack.stack_status != 'UPDATE_COMPLETE'):
|
||||||
|
raise exception.MagnumException(_(
|
||||||
|
"Cannot update stack with status: %s") % stack.stack_status)
|
||||||
|
|
||||||
|
delta = bay.obj_what_changed()
|
||||||
|
if 'node_count' in delta:
|
||||||
|
delta.remove('node_count')
|
||||||
|
|
||||||
|
_update_stack(context, osc, bay)
|
||||||
|
self._poll_and_check(osc, bay)
|
||||||
|
|
||||||
|
if delta:
|
||||||
|
raise exception.InvalidParameterValue(err=(
|
||||||
|
"cannot change bay property(ies) %s." % ", ".join(delta)))
|
||||||
|
|
||||||
|
bay.save()
|
||||||
|
return bay
|
||||||
|
|
||||||
def bay_delete(self, context, uuid):
|
def bay_delete(self, context, uuid):
|
||||||
LOG.debug('k8s_heat bay_delete')
|
LOG.debug('k8s_heat bay_delete')
|
||||||
osc = clients.OpenStackClients(context)
|
osc = clients.OpenStackClients(context)
|
||||||
|
@ -156,7 +195,8 @@ class Handler(object):
|
||||||
def poll_and_check():
|
def poll_and_check():
|
||||||
stack = osc.heat().stacks.get(bay.stack_id)
|
stack = osc.heat().stacks.get(bay.stack_id)
|
||||||
attempts['count'] += 1
|
attempts['count'] += 1
|
||||||
if stack.stack_status == 'CREATE_COMPLETE':
|
if (stack.stack_status == 'CREATE_COMPLETE' or
|
||||||
|
stack.stack_status == 'UPDATE_COMPLETE'):
|
||||||
parsed_outputs = _parse_stack_outputs(stack.outputs)
|
parsed_outputs = _parse_stack_outputs(stack.outputs)
|
||||||
master_address = parsed_outputs["kube_master"]
|
master_address = parsed_outputs["kube_master"]
|
||||||
minion_address = parsed_outputs["kube_minions_external"]
|
minion_address = parsed_outputs["kube_minions_external"]
|
||||||
|
|
|
@ -129,6 +129,14 @@ class TestPatch(api_base.FunctionalTest):
|
||||||
self.bay = obj_utils.create_test_bay(self.context,
|
self.bay = obj_utils.create_test_bay(self.context,
|
||||||
name='bay_example_A',
|
name='bay_example_A',
|
||||||
node_count=3)
|
node_count=3)
|
||||||
|
p = mock.patch.object(rpcapi.API, 'bay_update')
|
||||||
|
self.mock_bay_update = p.start()
|
||||||
|
self.mock_bay_update.side_effect = self._simulate_rpc_bay_update
|
||||||
|
self.addCleanup(p.stop)
|
||||||
|
|
||||||
|
def _simulate_rpc_bay_update(self, bay):
|
||||||
|
bay.save()
|
||||||
|
return bay
|
||||||
|
|
||||||
@mock.patch('oslo.utils.timeutils.utcnow')
|
@mock.patch('oslo.utils.timeutils.utcnow')
|
||||||
def test_replace_ok(self, mock_utcnow):
|
def test_replace_ok(self, mock_utcnow):
|
||||||
|
|
|
@ -230,3 +230,34 @@ class TestBayK8sHeat(base.TestCase):
|
||||||
'files': dict(exptected_files)
|
'files': dict(exptected_files)
|
||||||
}
|
}
|
||||||
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
|
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
|
||||||
|
|
||||||
|
@patch('heatclient.common.template_utils.get_template_contents')
|
||||||
|
@patch('magnum.conductor.handlers.bay_k8s_heat._extract_bay_definition')
|
||||||
|
def test_update_stack(self,
|
||||||
|
mock_extract_bay_definition,
|
||||||
|
mock_get_template_contents):
|
||||||
|
|
||||||
|
mock_stack_id = 'xx-xx-xx-xx'
|
||||||
|
expected_template_contents = 'template_contents'
|
||||||
|
exptected_files = []
|
||||||
|
|
||||||
|
mock_tpl_files = mock.MagicMock()
|
||||||
|
mock_tpl_files.items.return_value = exptected_files
|
||||||
|
mock_get_template_contents.return_value = [
|
||||||
|
mock_tpl_files, expected_template_contents]
|
||||||
|
mock_extract_bay_definition.return_value = {}
|
||||||
|
mock_heat_client = mock.MagicMock()
|
||||||
|
mock_osc = mock.MagicMock()
|
||||||
|
mock_osc.heat.return_value = mock_heat_client
|
||||||
|
mock_bay = mock.MagicMock()
|
||||||
|
mock_bay.stack_id = mock_stack_id
|
||||||
|
|
||||||
|
bay_k8s_heat._update_stack({}, mock_osc, mock_bay)
|
||||||
|
|
||||||
|
expected_args = {
|
||||||
|
'parameters': {},
|
||||||
|
'template': expected_template_contents,
|
||||||
|
'files': dict(exptected_files)
|
||||||
|
}
|
||||||
|
mock_heat_client.stacks.update.assert_called_once_with(mock_stack_id,
|
||||||
|
**expected_args)
|
||||||
|
|
Loading…
Reference in New Issue