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:
Hongbin Lu 2015-02-08 18:50:33 +00:00
parent d35c05bc3c
commit d28a780d77
5 changed files with 85 additions and 3 deletions

View File

@ -278,8 +278,8 @@ class BaysController(rest.RestController):
if rpc_bay[field] != patch_val:
rpc_bay[field] = patch_val
rpc_bay.save()
return Bay.convert_with_links(rpc_bay)
res_bay = pecan.request.rpcapi.bay_update(rpc_bay)
return Bay.convert_with_links(res_bay)
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
def delete(self, bay_uuid):

View File

@ -59,6 +59,9 @@ class API(rpc_service.API):
def bay_show(self, context, uuid):
return objects.Bay.get_by_uuid(context, uuid)
def bay_update(self, bay):
return self._call('bay_update', bay=bay)
# Service Operations
def service_create(self, service):

View File

@ -17,6 +17,7 @@ from heatclient import exc
from oslo_config import cfg
from magnum.common import clients
from magnum.common import exception
from magnum.common import short_id
from magnum import objects
from magnum.openstack.common._i18n import _
@ -87,6 +88,20 @@ def _create_stack(context, osc, bay):
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):
parsed_outputs = {}
@ -122,6 +137,30 @@ class Handler(object):
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):
LOG.debug('k8s_heat bay_delete')
osc = clients.OpenStackClients(context)
@ -156,7 +195,8 @@ class Handler(object):
def poll_and_check():
stack = osc.heat().stacks.get(bay.stack_id)
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)
master_address = parsed_outputs["kube_master"]
minion_address = parsed_outputs["kube_minions_external"]

View File

@ -129,6 +129,14 @@ class TestPatch(api_base.FunctionalTest):
self.bay = obj_utils.create_test_bay(self.context,
name='bay_example_A',
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')
def test_replace_ok(self, mock_utcnow):

View File

@ -230,3 +230,34 @@ class TestBayK8sHeat(base.TestCase):
'files': dict(exptected_files)
}
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)