RFC – Hypervisor Performance Manager for s390x (KVM IBM z Systems)
by Chandra Shekhar Reddy Potula
Proposal of introducing a new plugin – Hypervisor Performance
Manager(HPM) for s390x (KVM IBM z Systems).
*Abstract*
z Systems Hypervisor Performance Manager (zHPM) can be used to bring a
goal-oriented approach to the performance management of a hypervisor.
zHPM dynamically manages resource allocation when contention occurs
based on user-specified policies associated with performance objectives.
*Introduction about HPM:*
zHPM provides the following capabilities:
·APIs to enable a virtualization management solution for fully operating
zHPM.
·These APIs are provided using RESTful web services. The zHPM APIs
provide the following functions:
–Definition of workload resource groups and performance policy.
–Collection of virtual server and hypervisor performance metrics related
to understanding of performance goal achievement.
–Operational controls.
·A command line interface that provides similar functions as the zHPM APIs.
·Collection of hypervisor level and virtual server level performance
metrics to help set up performance goals, and support virtual server CPU
management.
·Management of CPU resource allocation to virtual servers in order to
meet goals
Workload resource groups
A workload resource group is a collection of virtual servers that host a
business application. The workload resource group provides a "management
view" of these virtual servers. By defining a workload resource group
you can manage hypervisor resources based on the requirements of the
business applications deployed on the KVM for IBM z Systems hypervisor.
Performance policies
In zHPM, a performance policy defines goals for virtual servers in a
workload resource group. You can define performance policies and express
a business goal and an importance level for the virtual servers that are
part of a workload resource group. zHPM then monitors and manages
hypervisor resources allocated to the virtual servers based on these
performance policies.
Service class
the service class a virtual server is associated with.
*Use Cases:*
New plugin Hypervisor Performance Manager(HPM) UI toprovide the
following operations support:
1.Performance Policies
a.List
b.Add/Update/Remove
c.Import/Export
2.Workload Resource Group (WRG) configuration
a.List WRG’s
b.Get/Create/Edit/Delete WRG
c.Add/Remove Virtual Server from WRG
3.Service Classes
a.Details of Service Class
b.Fetch or update Virtual Server information
4.Virtual Server CPU Management
a.Get/Enable/Disable CPU management
b.Report dynamic CPU resource adjustments
REST API’s Supported by HPM.
1.Workload Resource Group
a.GET /zhpm/wsapi/v1/workload-resource-groups
b.GET /zhpm/wsapi/v1/workload-resource-groups/detail
c.GET /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-id}
d.POST /zhpm/wsapi/v1/workload-resource-groups
e.DELETE /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-id}
f.POST /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-id}/actions
2.Performance Policies
a.POST /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-id}
b.POST /zhpm/wsapi/v1/workload-resource-groups/default
c.POST /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-ids
d.GET /zhpm/wsapi/v1/workload-resource-groups/{wrg-resource-id}
e.GET /zhpm/wsapi/v1/workload-resource-groups/detail
3.Virtual Servers
a.GET /zhpm/wsapi/v1/virtual-servers
b.GET /zhpm/wsapi/v1/virtual-servers/{vs-resource-id}
c.POST /zhpm/wsapi/v1/virtual-servers/{vs-resource-id}
d.GET /zhpm/wsapi/v1/virtual-servers/detail
4.Metrics
a.GET /zhpm/wsapi/v1/metrics/raw/hypervisor
b.GET /zhpm/wsapi/v1/metrics/calculated/hypervisor
c.GET /zhpm/wsapi/v1/metrics/raw/workload-resource-groups
d.GET /zhpm/wsapi/v1/metrics/calculated/workload-resource-groups
e.GET /zhpm/wsapi/v1/metrics/raw/workload-resource-groups/default
f.GET /zhpm/wsapi/v1/metrics/calculated/workload-resource-groups/default
g.GET /zhpm/wsapi/v1/metrics/raw/workload-resource-groups/{wrg-resource-id}
a.GET
/zhpm/wsapi/v1/metrics/calculated/workload-resource-groups/{wrg-resource-id}
5.CPU Management
a.GET /zhpm/wsapi/v1/mgmt-levels
b.POST /zhpm/wsapi/v1/mgmt-levels
c.GET /zhpm/wsapi/v1/dynamic-resource-adjustments
6.Memory Management
TBD
The following code changes will be made in support of plugin:
1.Plugin infrastructure
2.Backend python code support for Kimchi/Ginger for the REST API development
3.Frontend HTML5/JavaScript code.
More details to be followed like detailed use cases, REST API and
mock-ups ...
Further documentation can be found @
http://www.ibm.com/support/knowledgecenter/SSNW54_1.1.1/com.ibm.kvm.v111....
Please feel free to comment !!!
Thanks and Regards
Chandra
7 years, 12 months
[PATCH] [Wok] Fix to provide date convertion as per locale
by jkatta@linux.vnet.ibm.com
From: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
This fix provides template and utils methods for the date convertion
as per the locale settings from UI login page
Signed-off-by: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
---
src/wok/template.py | 26 +++++++++++++++++++++++++-
src/wok/utils.py | 10 ++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/src/wok/template.py b/src/wok/template.py
index 43a34db..e8d083e 100644
--- a/src/wok/template.py
+++ b/src/wok/template.py
@@ -22,10 +22,13 @@
import cherrypy
import errno
import json
+import threading
import time
+import locale
+
from Cheetah.Template import Template
from glob import iglob
-
+from contextlib import contextmanager
from wok import config as config
from wok.config import paths
@@ -133,3 +136,24 @@ def render(resource, data):
return render_cheetah_file(resource, data)
else:
raise cherrypy.HTTPError(406)
+
+
+def get_locale():
+ cookie = cherrypy.request.cookie
+ if "wokLocale" in cookie.keys():
+ return [cookie["wokLocale"].value]
+ langs = get_lang()
+ return langs
+
+
+LOCALE_LOCK = threading.Lock()
+
+
+@contextmanager
+def setlocale(name):
+ with LOCALE_LOCK:
+ saved = locale.setlocale(locale.LC_TIME)
+ try:
+ yield locale.setlocale(locale.LC_TIME, name)
+ finally:
+ locale.setlocale(locale.LC_TIME, saved)
diff --git a/src/wok/utils.py b/src/wok/utils.py
index 9a08001..807893d 100644
--- a/src/wok/utils.py
+++ b/src/wok/utils.py
@@ -42,6 +42,7 @@ from threading import Timer
from wok.config import paths, PluginPaths
from wok.exception import InvalidParameter, TimeoutExpired
from wok.stringutils import decode_value
+from wok.template import get_locale, setlocale
wok_log = cherrypy.log.error_log
@@ -619,3 +620,12 @@ def upgrade_objectstore_schema(objstore=None, field=None):
wok_log.error("Cannot upgrade objectstore schema: %s" % e.args[0])
return False
return True
+
+
+def dateNtime_to_locale(dateNtime):
+ dt = datetime.strptime(dateNtime, "%Y-%m-%d %H:%M:%S")
+ cokies_locale = get_locale()
+ cokies_locale = cokies_locale[0].replace("-", "_")
+ with setlocale(cokies_locale):
+ dt_locale = (dt.strftime('%c'))
+ return dt_locale
--
2.7.4
7 years, 12 months
[PATCH] [Wok] Fix non-relative paths
by Lucio Correia
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
ui/js/wok.user-log.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/js/wok.user-log.js b/ui/js/wok.user-log.js
index bac5439..f7659ee 100644
--- a/ui/js/wok.user-log.js
+++ b/ui/js/wok.user-log.js
@@ -173,7 +173,7 @@ wok.initUserLog = function() {
$(".content-area", "#wokSettings").css("height", "100%");
wok.initUserLogConfig();
$('#advanced-search-button').on('click',function(){
- wok.window.open('/tabs/settings-search.html');
+ wok.window.open('tabs/settings-search.html');
});
$("#download-button").on('click',function(){
--
2.7.4
7 years, 12 months
[PATCH] [Wok] Fix ip-address.js directory
by Lucio Correia
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
ui/libs/datatables/js/plugins/ip-address/Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/libs/datatables/js/plugins/ip-address/Makefile.am b/ui/libs/datatables/js/plugins/ip-address/Makefile.am
index f823bae..b48f817 100644
--- a/ui/libs/datatables/js/plugins/ip-address/Makefile.am
+++ b/ui/libs/datatables/js/plugins/ip-address/Makefile.am
@@ -16,6 +16,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-datatablesipaddressjsdir = $(datadir)/wok/ui/libs/datatables/js/plugins/ip-address/ip-address.js
+datatablesipaddressjsdir = $(datadir)/wok/ui/libs/datatables/js/plugins/ip-address
dist_datatablesipaddressjs_DATA = $(wildcard *.js) $(NULL)
--
2.7.4
7 years, 12 months
[PATCH] Do not install firewalld conf in Debian
by Lucio Correia
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
Makefile.am | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index e7ab86e..5f91a62 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,9 +95,6 @@ install-deb: install
$(DESTDIR)/etc/init/wokd.conf; \
fi
$(MKDIR_P) $(DESTDIR)/$(localstatedir)/lib/wok/
- $(MKDIR_P) $(DESTDIR)/usr/lib/firewalld/services
- cp -R $(top_srcdir)/src/firewalld.xml \
- $(DESTDIR)/usr/lib/firewalld/services/wokd.xml
deb: contrib/make-deb.sh
--
2.7.4
7 years, 12 months
[PATCH] [Kimchi] Issue #1063: Upon migrating guest to remote server, password less ssh is permanent
by archus@linux.vnet.ibm.com
From: Archana Singh <archus(a)linux.vnet.ibm.com>
Changes to ensure that password less login is removed if its setup by kimchi.
It also provide option for user to specify if user want to keep
the password less login setup by kimchi, if not specified password
less login setup by kimchi will be removed.
However if password less login is not setup by kimchi,
code does not remove the password less login.
Signed-off-by: Archana Singh <archus(a)linux.vnet.ibm.com>
---
model/vms.py | 180 ++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 129 insertions(+), 51 deletions(-)
diff --git a/model/vms.py b/model/vms.py
index bff7ed2..28aab76 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -1747,58 +1747,59 @@ class VMModel(object):
if password is None:
raise OperationFailed("KCHVM0056E",
{'host': remote_host, 'user': user})
- else:
- self._set_password_less_login(remote_host, user, password)
+ return False
+ return True
- def _set_password_less_login(self, remote_host, user, passwd):
- home_dir = '/root' if user is 'root' else '/home/%s' % user
+ def _read_id_rsa_pub_file(self, id_rsa_pub_file):
+ data = None
+ with open(id_rsa_pub_file, "r") as id_file:
+ data = id_file.read()
+ return data
- id_rsa_file = "%s/.ssh/id_rsa" % home_dir
- id_rsa_pub_file = id_rsa_file + '.pub'
- ssh_port = 22
- ssh_client = None
+ def _create_root_ssh_key_if_required(self, user, id_rsa_pub_file,
+ id_rsa_file):
+ if os.path.isfile(id_rsa_pub_file):
+ return
- def read_id_rsa_pub_file():
- data = None
- with open(id_rsa_pub_file, "r") as id_file:
- data = id_file.read()
- return data
+ with open("/dev/zero") as zero_input:
+ cmd = ['ssh-keygen', '-q', '-N', '', '-f', id_rsa_file]
+ proc = subprocess.Popen(
+ cmd,
+ stdin=zero_input,
+ stdout=open(os.devnull, 'wb')
+ )
+ out, err = proc.communicate()
- def create_root_ssh_key_if_required():
- if os.path.isfile(id_rsa_pub_file):
- return
+ if not os.path.isfile(id_rsa_pub_file):
+ raise OperationFailed("KCHVM0070E")
- with open("/dev/zero") as zero_input:
- cmd = ['ssh-keygen', '-q', '-N', '', '-f', id_rsa_file]
- proc = subprocess.Popen(
- cmd,
- stdin=zero_input,
- stdout=open(os.devnull, 'wb')
+ if user != 'root':
+ id_rsa_content = self._read_id_rsa_pub_file(id_rsa_pub_file)
+ updated_content = id_rsa_content.replace(
+ ' root@', ' %s@' % user
)
- out, err = proc.communicate()
+ with open(id_rsa_pub_file, 'w+') as f:
+ f.write(updated_content)
- if not os.path.isfile(id_rsa_pub_file):
- raise OperationFailed("KCHVM0070E")
+ user_uid = pwd.getpwnam(user).pw_uid
+ user_gid = pwd.getpwnam(user).pw_gid
+ os.chown(id_rsa_pub_file, user_uid, user_gid)
+ os.chown(id_rsa_file, user_uid, user_gid)
- if user is not 'root':
- id_rsa_content = read_id_rsa_pub_file()
- updated_content = id_rsa_content.replace(
- ' root@', ' %s@' % user
- )
- with open(id_rsa_pub_file, 'w+') as f:
- f.write(updated_content)
+ def _get_ssh_client(self, remote_host, user, passwd, ssh_port):
+ ssh_client = paramiko.SSHClient()
+ ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ ssh_client.connect(remote_host, ssh_port, username=user,
+ password=passwd, timeout=4)
+ return ssh_client
- user_uid = pwd.getpwnam(user).pw_uid
- user_gid = pwd.getpwnam(user).pw_gid
- os.chown(id_rsa_pub_file, user_uid, user_gid)
- os.chown(id_rsa_file, user_uid, user_gid)
+ def _set_password_less_login(self, remote_host, user, passwd):
+ home_dir = '/root' if user == 'root' else '/home/%s' % user
- def get_ssh_client(remote_host, user, passwd):
- ssh_client = paramiko.SSHClient()
- ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- ssh_client.connect(remote_host, ssh_port, username=user,
- password=passwd, timeout=4)
- return ssh_client
+ id_rsa_file = "%s/.ssh/id_rsa" % home_dir
+ id_rsa_pub_file = id_rsa_file + '.pub'
+ ssh_port = 22
+ ssh_client = None
def append_id_rsa_to_remote_authorized_keys(ssh_client, id_rsa_data):
sftp_client = ssh_client.open_sftp()
@@ -1824,9 +1825,11 @@ class VMModel(object):
sftp_client.close()
try:
- create_root_ssh_key_if_required()
- id_rsa_data = read_id_rsa_pub_file()
- ssh_client = get_ssh_client(remote_host, user, passwd)
+ self._create_root_ssh_key_if_required(user, id_rsa_pub_file,
+ id_rsa_file)
+ id_rsa_data = self._read_id_rsa_pub_file(id_rsa_pub_file)
+ ssh_client = self._get_ssh_client(remote_host, user, passwd,
+ ssh_port)
append_id_rsa_to_remote_authorized_keys(
ssh_client,
id_rsa_data
@@ -1865,17 +1868,21 @@ class VMModel(object):
def migration_pre_check(self, remote_host, user, password):
self._check_if_host_not_localhost(remote_host)
- self._check_if_password_less_login_enabled(
+ default_passless_status = self._check_if_password_less_login_enabled(
remote_host,
user,
password
)
- self._check_remote_libvirt_conn(remote_host, user)
+ if not default_passless_status:
+ self._set_password_less_login(remote_host, user, password)
+
self._check_if_migrating_same_arch_hypervisor(remote_host, user)
if platform.machine() in ['ppc64', 'ppc64le']:
self._check_ppc64_subcores_per_core(remote_host, user)
+ return default_passless_status
+
def _check_if_path_exists_in_remote_host(self, path, remote_host, user):
username_host = "%s@%s" % (user, remote_host)
cmd = ['ssh', '-oStrictHostKeyChecking=no', username_host,
@@ -1957,15 +1964,22 @@ class VMModel(object):
user
)
- def migrate(self, name, remote_host, user=None, password=None):
+ def migrate(self, name, remote_host, user=None, password=None,
+ remove_passless_login=True):
name = name.decode('utf-8')
remote_host = remote_host.decode('utf-8')
if user is None:
user = 'root'
+ user = user.encode('utf-8')
+
+ default_passless_status = self.migration_pre_check(remote_host, user,
+ password)
- self.migration_pre_check(remote_host, user, password)
- dest_conn = self._get_remote_libvirt_conn(remote_host, user)
+ if default_passless_status:
+ remove_passless_login = False
+
+ dest_conn = self._get_remote_libvirt_conn(remote_host)
non_shared = self._check_if_nonshared_migration(
name,
@@ -1977,18 +1991,80 @@ class VMModel(object):
'dest_conn': dest_conn,
'non_shared': non_shared,
'remote_host': remote_host,
- 'user': user}
+ 'user': user,
+ 'password': password,
+ 'remove_passless_login': remove_passless_login}
task_id = AsyncTask('/plugins/kimchi/vms/%s/migrate' % name,
self._migrate_task, params).id
return self.task.lookup(task_id)
+ def _remove_password_less_login(self, remote_host, user, passwd):
+ home_dir = '/root' if user == 'root' else '/home/%s' % user
+
+ id_rsa_file = "%s/.ssh/id_rsa" % home_dir
+ id_rsa_pub_file = id_rsa_file + '.pub'
+ ssh_port = 22
+ ssh_client = None
+
+ def remove_id_rsa_to_remote_authorized_keys(ssh_client, id_rsa_data):
+ sftp_client = ssh_client.open_sftp()
+ ssh_dir = '%s/.ssh' % home_dir
+
+ try:
+ sftp_client.chdir(ssh_dir)
+ except IOError:
+ raise OperationFailed(
+ "KCHVM0089E",
+ {'host': remote_host, 'user': user, 'sshdir': ssh_dir}
+ )
+ file_handler = sftp_client.file(
+ '%s/.ssh/authorized_keys' % home_dir,
+ mode='r',
+ bufsize=1
+ )
+ lines = file_handler.readlines()
+ try:
+ lines.remove(id_rsa_data)
+ except ValueError:
+ pass
+ file_handler = sftp_client.file(
+ '%s/.ssh/authorized_keys' % home_dir,
+ mode='w',
+ bufsize=1
+ )
+ file_handler.writelines(lines)
+ file_handler.flush()
+ file_handler.close()
+ sftp_client.close()
+
+ try:
+ self._create_root_ssh_key_if_required(user, id_rsa_pub_file,
+ id_rsa_file)
+ id_rsa_data = self._read_id_rsa_pub_file(id_rsa_pub_file)
+ ssh_client = self._get_ssh_client(remote_host, user, passwd,
+ ssh_port)
+ remove_id_rsa_to_remote_authorized_keys(
+ ssh_client,
+ id_rsa_data
+ )
+ except Exception, e:
+ raise OperationFailed(
+ "KCHVM0068E",
+ {'host': remote_host, 'user': user, 'error': e}
+ )
+ finally:
+ if ssh_client:
+ ssh_client.close()
+
def _migrate_task(self, cb, params):
name = params['name'].decode('utf-8')
dest_conn = params['dest_conn']
non_shared = params['non_shared']
remote_host = params['remote_host']
user = params['user']
+ password = params['password']
+ remove_passless_login = params['remove_passless_login']
cb('starting a migration')
@@ -2022,6 +2098,8 @@ class VMModel(object):
raise OperationFailed('KCHVM0058E', {'err': e.message,
'name': name})
finally:
+ if remove_passless_login:
+ self._remove_password_less_login(remote_host, user, password)
dest_conn.close()
cb('Migrate finished', True)
--
2.7.4
7 years, 12 months
[PATCH v2] [Kimchi 0/4] CPU Hot plug/unplug feature
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
v2:
- standardized i18n messages to use CPUs instead of vCPUs
This patch set implements CPU Hot plug/unplug capabilities
in Kimchi.
To test it, simply add/remove CPUs in a running guest via the
'Edit' menu. Note that all restrictions on the current CPU value
(can't exceed max number of CPUs, must be a number that makes
sense in the topology if one is set) still applies.
For Power systems, the hot unplug requires additional software
running in the guest to work: powerpc-utils, ppc64-diag and
librtas. The service 'rtas_err' must be running too.
*** BLURB HERE ***
Daniel Henrique Barboza (4):
CPU Hot plug/unplug: i18n changes
CPU Hot plug/unplug: model changes
CPU Hot plug/unplug: test changes
CPU Hot plug/unplug: ui changes
i18n.py | 5 +++
model/vms.py | 50 ++++++++++++++++++++++-
tests/test_model.py | 80 +++++++++++++++++++++++++++++++++++++
ui/js/src/kimchi.guest_edit_main.js | 12 +++---
ui/pages/guest-edit.html.tmpl | 1 +
ui/pages/help/en_US/guests.dita | 8 ++++
6 files changed, 148 insertions(+), 8 deletions(-)
--
2.7.4
8 years
[PATCH v2] [Kimchi 0/5] CPU Hot plug/unplug feature
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
** DEPENDS ON 'CPU topology setup enhancements' PATCH SET **
v3:
- rebased the patch set with the 'CPU topology setup enhancements' changes
- added new test on test_rest.py
v2:
- standardized i18n messages to use CPUs instead of vCPUs
This patch set implements CPU Hot plug/unplug capabilities
in Kimchi.
To test it, simply add/remove CPUs in a running guest via the
'Edit' menu. Note that all restrictions on the current CPU value
(can't exceed max number of CPUs, must be a number that makes
sense in the topology if one is set) still applies.
For Power systems, the hot unplug requires additional software
running in the guest to work: powerpc-utils, ppc64-diag and
librtas. The service 'rtas_err' must be running too.
Daniel Henrique Barboza (5):
CPU Hot plug/unplug: i18n changes
CPU Hot plug/unplug: model changes
CPU Hot plug/unplug: test changes
CPU Hot plug/unplug: ui changes
CPU Hot plug/unplug: test_rest.py changes
i18n.py | 3 +
model/vms.py | 66 ++++++++++++++++++---
tests/test_model.py | 112 ++++++++++++++++++++++++++++++++++++
tests/test_rest.py | 33 +++++++++--
ui/js/src/kimchi.guest_edit_main.js | 44 +++++++++-----
ui/pages/guest-edit.html.tmpl | 5 +-
ui/pages/help/en_US/guests.dita | 8 +++
7 files changed, 242 insertions(+), 29 deletions(-)
--
2.7.4
8 years
[PATCH] [Kimchi 0/9] (STABLE-2.3.x VERSION) CPU topology setup enhancements
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
This patch set is a backport of the patch set
'[PATCH v3] [Kimchi 0/8] CPU topology setup enhancements'
that were accepted and pushed to the master branch.
Daniel Henrique Barboza (9):
Bug fix #1072 - changing vpus verification
Adding 'sockets' field in the topology of Templates
template_edit_main.js: initProcessor now a global function
Adding 'Processor' tab in Edit Guest dialog
CPU configuration UI: several improvements
Adding CPU setup help text in Edit Guest/Template
Edit Guest dialog: fixing 'Save' button on Processor tab
Changing 'threads' to be a free number field
Edit Guest: block CPU settings when guest is running or paused
i18n.py | 3 +-
model/cpuinfo.py | 4 +-
tests/test_model.py | 12 +--
ui/css/kimchi.css | 36 +++++--
ui/css/src/modules/_edit-guests.scss | 28 ++++-
ui/css/src/modules/_templates.scss | 3 -
ui/js/src/kimchi.guest_edit_main.js | 109 ++++++++++---------
ui/js/src/kimchi.template_edit_main.js | 187 ++++++++++++++++++++++-----------
ui/pages/guest-edit.html.tmpl | 58 ++++++++--
ui/pages/i18n.json.tmpl | 2 +-
ui/pages/template-edit.html.tmpl | 27 +++--
11 files changed, 315 insertions(+), 154 deletions(-)
--
2.7.4
8 years
[PATCH] [Kimchi] Bug fix #1072 - changing vpus verification
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
This patch changes the vcpu verification when
editing a turned off VM, if the VM has a topology
set, to comply with the current libvirt schema: vcpus
must be a multiple of the 'threads' value.
Unit tests were adapted to reflect these changes.
Signed-off-by: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
---
i18n.py | 2 +-
model/cpuinfo.py | 2 +-
tests/test_model.py | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/i18n.py b/i18n.py
index 03929e5..2ec0e78 100644
--- a/i18n.py
+++ b/i18n.py
@@ -357,7 +357,7 @@ messages = {
"KCHCPUINF0002E": _("When CPU topology is defined, maximum number of vCPUs must be a product of sockets, cores, and threads."),
"KCHCPUINF0003E": _("This host (or current configuration) does not allow CPU topology."),
"KCHCPUINF0004E": _("The maximum number of vCPUs is too large for this system."),
- "KCHCPUINF0005E": _("When CPU topology is defined, vCPUs must be a multiple of a product of cores and threads."),
+ "KCHCPUINF0005E": _("When CPU topology is defined, vCPUs must be a multiple of the 'threads' number defined."),
"KCHCPUINF0006E": _("The number of threads is too large for this system."),
"KCHCPUINF0007E": _("When CPU topology is specified, sockets, cores and threads are required paramaters."),
"KCHCPUINF0008E": _("Parameter 'cpu_info' expects an object with fields among: 'vcpus', 'maxvcpus', 'topology'."),
diff --git a/model/cpuinfo.py b/model/cpuinfo.py
index 3707a02..5f82320 100644
--- a/model/cpuinfo.py
+++ b/model/cpuinfo.py
@@ -138,7 +138,7 @@ class CPUInfoModel(object):
raise InvalidParameter("KCHCPUINF0006E")
if maxvcpus != sockets * cores * threads:
raise InvalidParameter("KCHCPUINF0002E")
- if vcpus % (cores * threads) != 0:
+ if vcpus % threads != 0:
raise InvalidParameter("KCHCPUINF0005E")
if maxvcpus > self.get_host_max_vcpus():
diff --git a/tests/test_model.py b/tests/test_model.py
index 05d7415..1246be6 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -1298,23 +1298,23 @@ class ModelTests(unittest.TestCase):
# define CPU topology
inst.vm_update(u'kimchi-vm1', {'cpu_info': {'topology': {
- 'sockets': 4, 'cores': 2, 'threads': 1}}})
+ 'sockets': 2, 'cores': 2, 'threads': 2}}})
vm_info = inst.vm_lookup(u'kimchi-vm1')
- self.assertEquals({'sockets': 4, 'cores': 2, 'threads': 1},
+ self.assertEquals({'sockets': 2, 'cores': 2, 'threads': 2},
vm_info['cpu_info']['topology'])
- # vcpus not a multiple of (cores * threads)
+ # vcpus not a multiple of threads
self.assertRaises(InvalidParameter, inst.vm_update, u'kimchi-vm1',
- {'cpu_info': {'vcpus': 1}})
+ {'cpu_info': {'vcpus': 5}})
# maxvcpus different of (sockets * cores * threads)
self.assertRaises(InvalidParameter, inst.vm_update, u'kimchi-vm1',
{'cpu_info': {'maxvcpus': 4}})
- # topology does not match maxvcpus (8 != 2 * 2 * 1)
+ # topology does not match maxvcpus (8 != 3 * 2 * 2)
self.assertRaises(InvalidParameter, inst.vm_update, u'kimchi-vm1',
{'cpu_info': {'topology': {
- 'sockets': 2, 'cores': 2, 'threads': 1}}})
+ 'sockets': 3, 'cores': 2, 'threads': 2}}})
# undefine CPU topology
inst.vm_update(u'kimchi-vm1', {'cpu_info': {'topology': {}}})
--
2.7.4
8 years