
Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 03/25/2014 04:53 AM, zhshzhou@linux.vnet.ibm.com wrote:
From: Zhou Zheng Sheng <zhshzhou@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@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) {