[Kimchi-devel] [PATCH V4] Add the front end support for SPICE

Yu Xin Huo huoyuxin at linux.vnet.ibm.com
Thu Jan 9 11:43:57 UTC 2014


On 1/7/2014 12:45 PM, zhoumeina wrote:
> v3-v4 restructure js code to drop redundance code.
>        replace tabs with 4 spaces
> v2-v3 Add related make files
> v1-v2 add spice.html.tmpl
> This patch add the front end support of spice.
>
> 1 If there were a spice vm in host, show a "spice" button
> but not "vnc" in guest page.
>
> 2 click "spice" we can show a screen just like the demo
> http://www.spice-space.org/spice-html5/spice.html
>
> Signed-off-by: zhoumeina <zhoumein at linux.vnet.ibm.com>
> ---
>   configure.ac                   |    1 +
>   contrib/kimchi.spec.fedora.in  |    1 +
>   contrib/kimchi.spec.suse.in    |    1 +
>   ui/css/spice/spice.css         |  115 ++++
>   ui/js/Makefile.am              |    2 +-
>   ui/js/spice/Makefile.am        |   25 +
>   ui/js/spice/atKeynames.js      |  183 ++++++
>   ui/js/spice/bitmap.js          |   51 ++
>   ui/js/spice/cursor.js          |   92 +++
>   ui/js/spice/display.js         |  806 ++++++++++++++++++++++++
>   ui/js/spice/enums.js           |  282 +++++++++
>   ui/js/spice/inputs.js          |  251 ++++++++
>   ui/js/spice/jsbn.js            |  589 ++++++++++++++++++
>   ui/js/spice/lz.js              |  166 +++++
>   ui/js/spice/main.js            |  176 ++++++
>   ui/js/spice/png.js             |  256 ++++++++
>   ui/js/spice/prng4.js           |   79 +++
>   ui/js/spice/quic.js            | 1335 ++++++++++++++++++++++++++++++++++++++++
>   ui/js/spice/rng.js             |  102 +++
>   ui/js/spice/rsa.js             |  146 +++++
>   ui/js/spice/sha1.js            |  346 +++++++++++
>   ui/js/spice/spiceconn.js       |  447 ++++++++++++++
>   ui/js/spice/spicedataview.js   |   96 +++
>   ui/js/spice/spicemsg.js        |  883 ++++++++++++++++++++++++++
>   ui/js/spice/spicetype.js       |  480 +++++++++++++++
>   ui/js/spice/ticket.js          |  250 ++++++++
>   ui/js/spice/utils.js           |  261 ++++++++
>   ui/js/spice/wire.js            |  123 ++++
>   ui/js/src/kimchi.api.js        |   21 +
>   ui/js/src/kimchi.guest_main.js |   24 +-
>   ui/pages/guest.html.tmpl       |    1 +
>   ui/pages/spice.html.tmpl       |  138 +++++
>   32 files changed, 7724 insertions(+), 5 deletions(-)
>   create mode 100644 ui/css/spice/spice.css
>   create mode 100644 ui/js/spice/Makefile.am
>   create mode 100644 ui/js/spice/atKeynames.js
>   create mode 100644 ui/js/spice/bitmap.js
>   create mode 100644 ui/js/spice/cursor.js
>   create mode 100644 ui/js/spice/display.js
>   create mode 100644 ui/js/spice/enums.js
>   create mode 100644 ui/js/spice/inputs.js
>   create mode 100644 ui/js/spice/jsbn.js
>   create mode 100644 ui/js/spice/lz.js
>   create mode 100644 ui/js/spice/main.js
>   create mode 100644 ui/js/spice/png.js
>   create mode 100644 ui/js/spice/prng4.js
>   create mode 100644 ui/js/spice/quic.js
>   create mode 100644 ui/js/spice/rng.js
>   create mode 100644 ui/js/spice/rsa.js
>   create mode 100644 ui/js/spice/sha1.js
>   create mode 100644 ui/js/spice/spiceconn.js
>   create mode 100644 ui/js/spice/spicedataview.js
>   create mode 100644 ui/js/spice/spicemsg.js
>   create mode 100644 ui/js/spice/spicetype.js
>   create mode 100644 ui/js/spice/ticket.js
>   create mode 100644 ui/js/spice/utils.js
>   create mode 100644 ui/js/spice/wire.js
>   create mode 100644 ui/pages/spice.html.tmpl
>
> diff --git a/configure.ac b/configure.ac
> index 0d04d51..68855f8 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -66,6 +66,7 @@ AC_CONFIG_FILES([
>       ui/images/theme-default/Makefile
>       ui/js/Makefile
>       ui/js/novnc/Makefile
> +    ui/js/spice/Makefile
>       ui/js/novnc/web-socket-js/Makefile
>       ui/libs/Makefile
>       ui/libs/themes/Makefile
> diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in
> index 577516c..9f92044 100644
> --- a/contrib/kimchi.spec.fedora.in
> +++ b/contrib/kimchi.spec.fedora.in
> @@ -133,6 +133,7 @@ rm -rf $RPM_BUILD_ROOT
>   %{_datadir}/kimchi/ui/js/jquery.min.js
>   %{_datadir}/kimchi/ui/js/modernizr.custom.2.6.2.min.js
>   %{_datadir}/kimchi/ui/js/novnc/*.js
> +%{_datadir}/kimchi/ui/js/spice/*.js
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/WebSocketMain.swf
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/swfobject.js
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/web_socket.js
> diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in
> index 12d02ec..369fac2 100644
> --- a/contrib/kimchi.spec.suse.in
> +++ b/contrib/kimchi.spec.suse.in
> @@ -80,6 +80,7 @@ rm -rf $RPM_BUILD_ROOT
>   %{_datadir}/kimchi/ui/js/jquery.min.js
>   %{_datadir}/kimchi/ui/js/modernizr.custom.2.6.2.min.js
>   %{_datadir}/kimchi/ui/js/novnc/*.js
> +%{_datadir}/kimchi/ui/js/spice/*.js
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/WebSocketMain.swf
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/swfobject.js
>   %{_datadir}/kimchi/ui/js/novnc/web-socket-js/web_socket.js
>
> diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
> index fbcf4a2..a18288f 100644
> --- a/ui/js/src/kimchi.api.js
> +++ b/ui/js/src/kimchi.api.js
> @@ -309,6 +309,27 @@ var kimchi = {
>           });
>       },
>
> +    spiceToVM : function(vm) {
> +        kimchi.requestJSON({
> +            url : '/config',
> +            type : 'GET',
> +            dataType : 'json'
> +        }).done(function(data, textStatus, xhr) {
> +            http_port = data['http_port'];
> +            kimchi.requestJSON({
> +                url : "/vms/" + encodeURIComponent(vm) + "/connect",
> +                type : "POST",
> +                dataType : "json"
> +            }).done(function(data, textStatus, xhr) {
> +                url = 'http://' + location.hostname + ':' + http_port;
> +                url += "/spice.html?port=" + data.graphics.port + "&listen=" + data.graphics.listen;
> +                window.open(url);
> +            });
> +        }).error(function() {
> +            kimchi.message.error(i18n['msg.fail.get.config']);
> +        });
> +    },
> +
>       listVMs : function(suc, err) {
>           kimchi.requestJSON({
>               url : kimchi.url + 'vms',
> diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
> index a36c59c..d14cda9 100644
> --- a/ui/js/src/kimchi.guest_main.js
> +++ b/ui/js/src/kimchi.guest_main.js
> @@ -119,6 +119,10 @@ kimchi.initVmButtonsAction = function() {
>           kimchi.vncToVM($(this).data('vm'));
>       });
>
> +    $(".vm-spice").on("click", function(event) {
> +        kimchi.spiceToVM($(this).data('vm'));
> +    });
> +
>       kimchi.init_button_stat();
>
>   };
> @@ -127,11 +131,23 @@ kimchi.init_button_stat = function() {
>       $('.vm-action').each(function() {
>           var vm_action = $(this);
>           var vm_vnc = vm_action.find('.vm-vnc');
> -        if ((vm_action.data('graphics') === 'vnc')
> -                && (vm_action.data('vmstate') === 'running')) {
> -            vm_vnc.removeAttr('disabled');
> +        var vm_spice = vm_action.find('.vm-spice');
> +        var vm_graphics = vm_vnc;
> +        if (vm_action.data('graphics') === 'vnc') {
> +            vm_spice.hide();
> +            vm_graphics = vm_vnc;
> +        } else if (vm_action.data('graphics') === 'spice') {
> +            vm_vnc.hide();
> +            vm_graphics = vm_spice
> +        } else {
> +            vm_vnc.hide();
> +            vm_spice.hide();
> +        }
> +
> +        if (vm_action.data('vmstate') === 'running') {
> +            vm_graphics.removeAttr('disabled');
>           } else {
> -            vm_vnc.attr('disabled', 'disabled');
> +            vm_graphics.attr('disabled', 'disabled');
>           }
Seems like this section of code has some logical issue.
Originally, it checkes vm_action.data('graphics') === 'vnc' && 
vm_action.data('vmstate') === 'running', then enable something.
Now it only checks vm_action.data('vmstate') === 'running', then enabled 
it.
>
>           var editButton = vm_action.find('.vm-edit');
> diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
> index 6bd6853..6d83d57 100644
> --- a/ui/pages/guest.html.tmpl
> +++ b/ui/pages/guest.html.tmpl
> @@ -58,6 +58,7 @@
>                           <span class="text">$_("Actions")</span><span class="arrow"></span>
>                           <div class="popover actionsheet right-side" style="width: 250px">
>                               <button class="button-big vm-vnc" data-vm="{name}"><span class="text">VNC</span></button>
> +                            <button class="button-big vm-spice" data-vm="{name}"><span class="text">SPICE</span></button>
>                               <button class="button-big vm-edit" data-vm="{name}"><span class="text">$_("Edit")</span></button>
>                               <a class="button-big red vm-delete" data-vm="{name}">$_("Delete")</a>
>                           </div>
> diff --git a/ui/pages/spice.html.tmpl b/ui/pages/spice.html.tmpl
> new file mode 100644
> index 0000000..fd839ab
> --- /dev/null
> +++ b/ui/pages/spice.html.tmpl
> @@ -0,0 +1,138 @@
> +<!--
> +   Copyright (C) 2012 by Jeremy P. White <jwhite at codeweavers.com>
> +
> +   This file is part of spice-html5.
> +
> +   spice-html5 is free software: you can redistribute it and/or modify
> +   it under the terms of the GNU Lesser General Public License as published by
> +   the Free Software Foundation, either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   spice-html5 is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public License
> +   along with spice-html5.  If not, see <http://www.gnu.org/licenses/>.
> +
> +   --------------------------------------------------
> +    Spice Javascript client template.
> +    Refer to main.js for more detailed information
> +   --------------------------------------------------
> +
> +-->
> +<!DOCTYPE html>
> +<html>
> +    <head>
> +        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
> +        <title>Spice Javascript client</title>
> +        <script src="js/spice/enums.js"></script>
> +        <script src="js/spice/atKeynames.js"></script>
> +        <script src="js/spice/utils.js"></script>
> +        <script src="js/spice/png.js"></script>
> +        <script src="js/spice/lz.js"></script>
> +        <script src="js/spice/quic.js"></script>
> +        <script src="js/spice/bitmap.js"></script>
> +        <script src="js/spice/spicedataview.js"></script>
> +        <script src="js/spice/spicetype.js"></script>
> +        <script src="js/spice/spicemsg.js"></script>
> +        <script src="js/spice/wire.js"></script>
> +        <script src="js/spice/spiceconn.js"></script>
> +        <script src="js/spice/display.js"></script>
> +        <script src="js/spice/main.js"></script>
> +        <script src="js/spice/inputs.js"></script>
> +        <script src="js/spice/cursor.js"></script>
> +        <script src="js/spice/jsbn.js"></script>
> +        <script src="js/spice/rsa.js"></script>
> +        <script src="js/spice/prng4.js"></script>
> +        <script src="js/spice/rng.js"></script>
> +        <script src="js/spice/sha1.js"></script>
> +        <script src="js/spice/ticket.js"></script>
> +        <link rel="stylesheet" type="text/css" href="css/spice/spice.css">
> +    </head>
> +    <script>
> +        var host = null, port = null;
> +        var sc;
> +        function spice_error(e) {
> +            disconnect();
> +        }
> +
> +        function connect() {
> +            var host, port, password, scheme = "ws://", uri;
> +            host = getParameter("listen");
> +            port = getParameter("port");
> +            document.getElementById("host").value = host;
> +            document.getElementById("port").value = port;
> +            if ((!host) || (!port)) {
> +                console.log("must set host and port");
> +                return;
> +            }
> +
> +            if (sc) {
> +                sc.stop();
> +            }
> +
> +            uri = scheme + host + ":" + port;
> +            try {
> +                sc = new SpiceMainConn({
> +                    uri : uri,
> +                    screen_id : "spice-screen",
> +                    dump_id : "debug-div",
> +                    message_id : "message-div",
> +                    password : "",
> +                    onerror : spice_error
> +                });
> +            } catch (e) {
> +                alert(e.toString());
> +                disconnect();
> +            }
> +
> +        }
> +
> +        function disconnect()
> +        {
> +            console.log(">> disconnect");
> +            if (sc) {
> +                sc.stop();
> +            }
> +            console.log("<< disconnect");
> +        }
> +
> +        function getParameter(name) {
> +            var paramStr = location.search;
> +            if (paramStr.length == 0)
> +                return null;
> +            if (paramStr.charAt(0) != '?')
> +                return null;
> +            paramStr = unescape(paramStr);
> +            paramStr = paramStr.substring(1);
> +            if (paramStr.length == 0)
> +                return null;
> +            var params = paramStr.split('&');
> +            for ( var i = 0; i < params.length; i++) {
> +                var parts = params[i].split('=', 2);
> +                if (parts[0] == name) {
> +                    if (parts.length < 2 || typeof (parts[1]) == "undefined" || parts[1] == "undefined" || parts[1] == "null")
> +                        return "";
> +                    return parts[1];
> +                }
> +            }
> +            return null;
> +        }
> +    </script>
> +    <body onload="connect();" onunload="disconnect();">
> +        <div id="login">
> +            <span class="logo">SPICE</span>
> +            <label for="host">Host:</label> <input id="host" value="localhost" type="text" disabled="disabled"> <!-- localhost -->
> +            <label for="port">Port:</label> <input id="port" value="5959" type="text" disabled="disabled">
> +        </div>
> +        <div id="spice-area">
> +            <div id="spice-screen" class="spice-screen"></div>
> +        </div>
> +        <div id="message-div" class="spice-message"></div>
> +        <div id="debug-div">
> +        <!-- If DUMPXXX is turned on, dumped images will go here -->
> +        </div>
> +    </body>
> +</html>
> \ No newline at end of file




More information about the Kimchi-devel mailing list