Skip to content

Commit

Permalink
Fix the problem of live resize cpus for SLES VM
Browse files Browse the repository at this point in the history
Sometimes live resize (increase) cpus on SLES VM can't bring
the new added offline cpu online, but can make it present
then the next resize can bring it online.
Hence, always call 'chcpu -e' to enable the new added cpus.

Signed-off-by: QingFeng Hao <[email protected]>
  • Loading branch information
SeanHQF authored and bjhuangr committed Jul 22, 2024
1 parent bd0601c commit d194948
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 80 deletions.
33 changes: 5 additions & 28 deletions zvmsdk/smtclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -4028,16 +4028,6 @@ def live_resize_cpus(self, userid, count):
% userid)
return
else:
is_ubuntu = False
uname_out = self.execute_cmd(userid, "uname -a")
if uname_out and len(uname_out) >= 1:
distro = uname_out[0]
else:
distro = ''
if 'ubuntu' in distro or 'Ubuntu' in distro \
or 'UBUNTU' in distro:
is_ubuntu = True

if active_count < count:
# Add live cpu
# Get the number of cpus to add to active and check address
Expand All @@ -4050,6 +4040,11 @@ def live_resize_cpus(self, userid, count):
# otherwise need to define and trigger cpu scan.
to_enable_addrs = [a for a in active_new if a in offline_addrs]
to_define_addrs = list(set(active_new) - set(offline_addrs))
if not to_enable_addrs:
# Let's call 'chcpu -e' explictily because 'chcpu -r'
# can't bring the offline cpus online in some Ubuntu &
# SLES distros. Use the safest way to do it.
to_enable_addrs = to_define_addrs
to_enable_addrs.sort()
to_define_addrs.sort()

Expand Down Expand Up @@ -4092,24 +4087,6 @@ def live_resize_cpus(self, userid, count):
raise exception.SDKGuestOperationError(rs=8, userid=userid,
err=msg)

if is_ubuntu:
try:
# need use chcpu -e <cpu-list> to make cpu online for Ubuntu
online_cmd = "chcpu -e " + ','.join(to_define_addrs)
self.execute_cmd(userid, online_cmd)
except exception.SDKSMTRequestFailed as err:
msg = err.format_message()
LOG.error("Enable cpus for ubuntu guest: '%s' "
"failed with error: %s. No rollback is"
" done and you may need to check the "
"status and restart the guest to make"
" the defined cpus online."
% (userid, msg))
raise exception.SDKGuestOperationError(rs=15, userid=userid,
err=msg)
LOG.info("Enabled cpus just defined for ubuntu guest: '%s' finished successfully."
% userid)

# 2, enable cups
if to_enable_addrs:
cmd_str = "chcpu -e " + ','.join(to_enable_addrs)
Expand Down
84 changes: 32 additions & 52 deletions zvmsdk/tests/unit/test_smtclient.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright Contributors to the Feilong Project.
# SPDX-License-Identifier: Apache-2.0

# Copyright 2017,2022 IBM Corp.
# Copyright 2017,2024 IBM Corp.
#
# 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
Expand Down Expand Up @@ -4240,12 +4240,12 @@ def test_live_resize_cpus(self, get_active, resize, get_avail,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_uname = "uname -a"
cmd_def_cpu = "vmcp def cpu 02 03"
cmd_rescan_cpu = "chcpu -r"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])
cmd_enable_cpu = "chcpu -e 02,03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu),
mock.call(userid, cmd_enable_cpu)])
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
Expand Down Expand Up @@ -4279,12 +4279,10 @@ def test_live_resize_cpus_enable_part(self, get_active, resize, get_avail,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_uname = "uname -a"
cmd_def_cpu = "vmcp def cpu 03"
cmd_rescan_cpu = "chcpu -r"
cmd_enable_cpu = "chcpu -e 02"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu),
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu),
mock.call(userid, cmd_enable_cpu)])
request.assert_not_called()
Expand Down Expand Up @@ -4336,10 +4334,8 @@ def test_live_resize_cpus_less_active(self, get_active, resize, get_avail,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_not_called()
cmd_uname = "uname -a"
cmd_disable_cpu = "chcpu -d 04"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_disable_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_disable_cpu)])
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
Expand Down Expand Up @@ -4375,10 +4371,10 @@ def test_live_resize_cpus_revert_definition_equal(self, get_active,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_uname = "uname -a"
cmd_rescan_cpu = "chcpu -r"
cmd_def_cpu = "vmcp def cpu 02 03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
Expand Down Expand Up @@ -4412,17 +4408,12 @@ def test_live_resize_cpus_revert_added_cpus(self, get_active,
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
# exec_cmd.assert_called_once_with(userid, "vmcp def cpu 02 03")
cmd_uname = "uname -a"
cmd_rescan_cpu = "chcpu -r"
cmd_def_cpu = "vmcp def cpu 02 03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])

rd = ("SMAPI testuid API Image_Definition_Delete_DM --operands "
"-k COMMAND_DEFINE_CPU=CPUADDR=02 -k COMMAND_DEFINE_CPU=CPUADDR=03")
rd2 = ("SMAPI testuid API Image_Definition_Update_DM --operands "
"-k SHARE=RELATIVE=200")
calls = [call(rd), call(rd2)]
request.assert_has_calls(calls)
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
@mock.patch.object(smtclient.SMTClient, 'get_active_cpu_offline_addrs')
Expand Down Expand Up @@ -4454,18 +4445,12 @@ def test_live_resize_cpus_revert_deleted_cpus(self, get_active,
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
# exec_cmd.assert_called_once_with(userid, "vmcp def cpu 02 03")
cmd_uname = "uname -a"
cmd_rescan_cpu = "chcpu -r"
cmd_def_cpu = "vmcp def cpu 02 03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])

rd = ("SMAPI testuid API Image_Definition_Update_DM --operands "
"-k COMMAND_DEFINE_CPU=\'CPUADDR=04 TYPE=IFL\' "
"-k COMMAND_DEFINE_CPU=\'CPUADDR=0A TYPE=IFL\'")
rd2 = ("SMAPI testuid API Image_Definition_Update_DM --operands "
"-k SHARE=RELATIVE=200")
calls = [call(rd), call(rd2)]
request.assert_has_calls(calls)
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
@mock.patch.object(smtclient.SMTClient, 'get_active_cpu_offline_addrs')
Expand Down Expand Up @@ -4497,15 +4482,12 @@ def test_live_resize_cpus_revert_failed(self, get_active,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_uname = "uname -a"
cmd_rescan_cpu = "chcpu -r"
cmd_def_cpu = "vmcp def cpu 02 03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])
# exec_cmd.assert_called_once_with(userid, "vmcp def cpu 02 03")
rd = ("SMAPI testuid API Image_Definition_Update_DM --operands "
"-k COMMAND_DEFINE_CPU=\'CPUADDR=04 TYPE=IFL\' "
"-k COMMAND_DEFINE_CPU=\'CPUADDR=0A TYPE=IFL\'")
request.assert_called_once_with(rd)
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
@mock.patch.object(smtclient.SMTClient, 'get_active_cpu_offline_addrs')
Expand Down Expand Up @@ -4538,11 +4520,11 @@ def test_live_resize_cpus_rescan_failed(self, get_active,
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_def_cpu = "vmcp def cpu 02 03"
cmd_rescan_cpu = "chcpu -r"
cmd_uname = "uname -a"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])
request.assert_not_called()
cmd_enable_cpu = "chcpu -e 02,03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu),
mock.call(userid, cmd_enable_cpu)])
request.assert_called_once()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
@mock.patch.object(smtclient.SMTClient, 'get_active_cpu_offline_addrs')
Expand Down Expand Up @@ -4574,12 +4556,12 @@ def test_live_resize_cpus_redhat(self, get_active, resize, get_avail,
get_active.assert_called_once_with(userid)
resize.assert_called_once_with(userid, count)
get_avail.assert_called_once_with(['00', '01'], 32)
cmd_uname = "uname -a"
cmd_enable_cpu = "chcpu -e 02,03"
cmd_def_cpu = "vmcp def cpu 02 03"
cmd_rescan_cpu = "chcpu -r"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu)])
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu),
mock.call(userid, cmd_enable_cpu)])
request.assert_not_called()

@mock.patch.object(smtclient.SMTClient, '_get_defined_cpu_addrs')
Expand Down Expand Up @@ -4616,10 +4598,8 @@ def test_live_resize_cpus_ubuntu(self, get_active, resize, get_avail,

cmd_def_cpu = "vmcp def cpu 02 03"
cmd_rescan_cpu = "chcpu -r"
cmd_uname = "uname -a"
cmd_chcpu = "chcpu -e 02,03"
exec_cmd.assert_has_calls([mock.call(userid, cmd_uname),
mock.call(userid, cmd_def_cpu),
exec_cmd.assert_has_calls([mock.call(userid, cmd_def_cpu),
mock.call(userid, cmd_rescan_cpu),
mock.call(userid, cmd_chcpu)])
request.assert_not_called()
Expand Down

0 comments on commit d194948

Please sign in to comment.