--
Reviewed-by: Paulo Vital <pvital(a)linux.vnet.ibm.com>
On Tue, 2014-03-25 at 15:53 +0800, zhshzhou(a)linux.vnet.ibm.com wrote:
From: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
On some architecture of hosts, such as ppc64 hosts, QEMU is not compiled
with Spice. So we'd like to disable Spice on these hosts. Unfortunately
even QEMU is not compiled with Spice, 'qemu --help' still prints Spice
related help. In this patch we use ldd to determine if QEMU is linked to
libspice-server.so, and provide this information through the
/config/capabilities URI. The front-end code then checks the capabilities
and add or remove Spice from the graphic options respectively.
Signed-off-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
---
docs/API.md | 1 +
src/kimchi/config.py.in | 10 +++++++---
src/kimchi/mockmodel.py | 1 +
src/kimchi/model/config.py | 15 ++++++++++++++-
tests/test_rest.py | 1 +
ui/js/src/kimchi.api.js | 6 ++++--
ui/js/src/kimchi.template_edit_main.js | 13 +++++++++++--
7 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/docs/API.md b/docs/API.md
index a380558..3711fbe 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -573,6 +573,7 @@ creation.
* **GET**: Retrieve capabilities information
* libvirt_stream_protocols: list of which network protocols are accepted
for iso streaming by libvirt
+ * qemu_spice: True, if QEMU supports Spice; False, otherwise
* qemu_stream: True, if QEMU supports ISO streaming; False, otherwise
* screenshot: True, if libvirt stream functionality can create screenshot
file without problems; False, otherwise or None if the functionality was
diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in
index cf8497a..d15a6b5 100644
--- a/src/kimchi/config.py.in
+++ b/src/kimchi/config.py.in
@@ -54,15 +54,19 @@ def get_debugreports_path():
return os.path.join(paths.state_dir, 'debugreports')
-def find_qemu_binary():
+def find_qemu_binary(find_emulator=False):
try:
connect = libvirt.open('qemu:///system')
except Exception, e:
raise Exception("Unable to get qemu binary location: %s" % e)
try:
xml = connect.getCapabilities()
- expr = "/capabilities/guest/arch[@name='%s']\
- /domain[@type='kvm']/emulator" % platform.machine()
+ if find_emulator:
+ expr = "/capabilities/guest/arch[@name='%s']\
+ /emulator" % platform.machine()
+ else:
+ expr = "/capabilities/guest/arch[@name='%s']\
+ /domain[@type='kvm']/emulator" % platform.machine()
res = xpath_get_text(xml, expr)
location = res[0]
except Exception, e:
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index faf1049..7b567cb 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -65,6 +65,7 @@ class MockModel(object):
def capabilities_lookup(self, *ident):
return {'libvirt_stream_protocols':
['http', 'https', 'ftp', 'ftps',
'tftp'],
+ 'qemu_spice': True,
'qemu_stream': True,
'screenshot': True,
'system_report_tool': True,
diff --git a/src/kimchi/model/config.py b/src/kimchi/model/config.py
index a6a25e4..7f553ea 100644
--- a/src/kimchi/model/config.py
+++ b/src/kimchi/model/config.py
@@ -23,6 +23,7 @@ import cherrypy
from kimchi.basemodel import Singleton
from kimchi.config import config as kconfig
+from kimchi.config import find_qemu_binary
from kimchi.distroloader import DistroLoader
from kimchi.exception import NotFoundError
from kimchi.featuretests import FeatureTests
@@ -30,7 +31,7 @@ from kimchi.model.debugreports import DebugReportsModel
from kimchi.repositories import Repositories
from kimchi.screenshot import VMScreenshot
from kimchi.swupdate import SoftwareUpdate
-from kimchi.utils import check_url_path, kimchi_log
+from kimchi.utils import check_url_path, kimchi_log, run_command
class ConfigModel(object):
@@ -72,6 +73,17 @@ class CapabilitiesModel(object):
kimchi_log.info("*** Feature tests completed ***")
_set_capabilities.priority = 90
+ def _qemu_support_spice(self):
+ qemu_path = find_qemu_binary(find_emulator=True)
+ out, err, rc = run_command(['ldd', qemu_path])
+ if rc != 0:
+ kimchi_log.error('Failed to find qemu binary dependencies: %s',
err)
+ return False
+ for line in out.split('\n'):
+ if line.lstrip().startswith('libspice-server.so'):
+ return True
+ return False
+
def lookup(self, *ident):
report_tool = DebugReportsModel.get_system_report_tool()
try:
@@ -89,6 +101,7 @@ class CapabilitiesModel(object):
repo_mngt_tool = repo._pkg_mnger.TYPE
return {'libvirt_stream_protocols': self.libvirt_stream_protocols,
+ 'qemu_spice': self._qemu_support_spice(),
'qemu_stream': self.qemu_stream,
'screenshot': VMScreenshot.get_stream_test_result(),
'system_report_tool': bool(report_tool),
diff --git a/tests/test_rest.py b/tests/test_rest.py
index 3f2e449..ca4eeed 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -1346,6 +1346,7 @@ class RestTests(unittest.TestCase):
conf = json.loads(resp)
self.assertIn('libvirt_stream_protocols', conf)
self.assertIn('qemu_stream', conf)
+ self.assertIn('qemu_spice', conf)
self.assertIn('screenshot', conf)
self.assertIn('system_report_tool', conf)
self.assertIn('update_tool', conf)
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 4310435..075b9d0 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -49,14 +49,16 @@ var kimchi = {
* Get host capabilities
* suc: callback if succeed err: callback if failed
*/
- getCapabilities : function(suc, err) {
+ getCapabilities : function(suc, err, done) {
+ done = typeof done !== 'undefined' ? done: function(){};
kimchi.requestJSON({
url : "/config/capabilities",
type : "GET",
contentType : "application/json",
dataType : "json",
success: suc,
- error: err
+ error: err,
+ complete: done
});
},
diff --git a/ui/js/src/kimchi.template_edit_main.js
b/ui/js/src/kimchi.template_edit_main.js
index 58f4506..9c429c4 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -30,8 +30,17 @@ kimchi.template_edit_main = function() {
}
var disks = template.disks;
$('input[name="disks"]').val(disks[0].size);
- var options = [{label: 'VNC', value: 'vnc'}, {label:
'Spice', value: 'spice'}];
- kimchi.select('template-edit-graphics-list', options);
+
+ var options = [{label: 'VNC', value: 'vnc'}];
+ kimchi.getCapabilities(function(result) {
+ if (result.qemu_spice == true) {
+ options.push({label: 'Spice', value: 'spice'})
+ }
+ }, function() {
+ }, function(){
+ kimchi.select('template-edit-graphics-list', options);
+ });
+
kimchi.listStoragePools(function(result) {
var options = [];
if (result && result.length) {