Bug 1804781 - [TLS everywhere] test_novnc failed with "Not a valid html document" error
Summary: [TLS everywhere] test_novnc failed with "Not a valid html document" error
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat OpenStack
Classification: Red Hat
Component: openstack-tempest
Version: 13.0 (Queens)
Hardware: Unspecified
OS: Unspecified
low
low
Target Milestone: ---
: ---
Assignee: Chandan Kumar
QA Contact: Martin Kopec
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-02-19 15:55 UTC by Archit Modi
Modified: 2024-05-03 12:14 UTC (History)
14 users (show)

Fixed In Version: openstack-tempest-18.0.0-14.el7ost
Doc Type: No Doc Update
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-06-24 11:41:26 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
OpenStack gerrit 655827 0 None MERGED Handle 'path' query parameter for test_novnc 2020-11-19 00:38:02 UTC
Red Hat Issue Tracker OSP-32007 0 None None None 2024-05-03 12:14:43 UTC

Description Archit Modi 2020-02-19 15:55:42 UTC
Description of problem: Running RHOS 13 tempest tests with TLS everywhere enabled, test_novnc tempest test failed with "Not a valid html document in the response" error


How reproducible:
always

Steps to Reproduce:
1. Deploy RHOS 13 with TLS everywhere
2. Run tempest.api.compute.servers.test_novnc.NoVNCConsoleTestJSON.test_novnc tempest test

Actual results:
testtools.matchers._impl.MismatchError: '<html>' not in u'<!DOCTYPE html>\n<html lang="en">\n<head>\n\n    <!--\n    noVNC example: lightweight example using minimal UI and features\n\n    This is a self-contained file which doesn\'t import WebUtil or external CSS.\n\n    Copyright (C) 2018 The noVNC Authors\n    noVNC is licensed under the MPL 2.0 (see LICENSE.txt)\n    This file is licensed under the 2-Clause BSD license (see LICENSE.txt).\n\n    Connect parameters are provided in query string:\n        http://example.com/?host=HOST&port=PORT&scale=true\n    -->\n    <title>noVNC</title>\n\n    <meta charset="utf-8">\n\n    <style>\n\n        body {\n            margin: 0;\n            background-color: dimgrey;\n            height: 100%;\n            display: flex;\n            flex-direction: column;\n        }\n        html {\n            height: 100%;\n        }\n\n        #top_bar {\n            background-color: #6e84a3;\n            color: white;\n            font: bold 12px Helvetica;\n            padding: 6px 5px 4px 5px;\n            border-bottom: 1px outset;\n        }\n        #status {\n            text-align: center;\n        }\n        #sendCtrlAltDelButton {\n            position: fixed;\n            top: 0px;\n            right: 0px;\n            border: 1px outset;\n            padding: 5px 5px 4px 5px;\n            cursor: pointer;\n        }\n\n        #screen {\n            flex: 1; /* fill remaining space */\n            overflow: hidden;\n        }\n\n    </style>\n\n    <!-- Promise polyfill for IE11 -->\n    <script src="vendor/promise.js"></script>\n\n    <!-- ES2015/ES6 modules polyfill -->\n    <script type="module">\n        window._noVNC_has_module_support = true;\n    </script>\n    <script>\n        window.addEventListener("load", function() {\n            if (window._noVNC_has_module_support) return;\n            const loader = document.createElement("script");\n            loader.src = "vendor/browser-es-module-loader/dist/" +\n                "browser-es-module-loader.js";\n            document.head.appendChild(loader);\n        });\n    </script>\n\n    <!-- actual script modules -->\n    <script type="module" crossorigin="anonymous">\n        // RFB holds the API to connect and communicate with a VNC server\n        import RFB from \'./core/rfb.js\';\n\n        let rfb;\n        let desktopName;\n\n        // When this function is called we have\n        // successfully connected to a server\n        function connectedToServer(e) {\n            status("Connected to " + desktopName);\n        }\n\n        // This function is called when we are disconnected\n        function disconnectedFromServer(e) {\n            if (e.detail.clean) {\n                status("Disconnected");\n            } else {\n                status("Something went wrong, connection is closed");\n            }\n        }\n\n        // When this function is called, the server requires\n        // credentials to authenticate\n        function credentialsAreRequired(e) {\n            const password = prompt("Password Required:");\n            rfb.sendCredentials({ password: password });\n        }\n\n        // When this function is called we have received\n        // a desktop name from the server\n        function updateDesktopName(e) {\n            desktopName = e.detail.name;\n        }\n\n        // Since most operating systems will catch Ctrl+Alt+Del\n        // before they get a chance to be intercepted by the browser,\n        // we provide a way to emulate this key sequence.\n        function sendCtrlAltDel() {\n            rfb.sendCtrlAltDel();\n            return false;\n        }\n\n        // Show a status text in the top bar\n        function status(text) {\n            document.getElementById(\'status\').textContent = text;\n        }\n\n        // This function extracts the value of one variable from the\n        // query string. If the variable isn\'t defined in the URL\n        // it returns the default value instead.\n        function readQueryVariable(name, defaultValue) {\n            // A URL with a query parameter can look like this:\n            // https://www.example.com?myqueryparam=myvalue\n            //\n            // Note that we use location.href instead of location.search\n            // because Firefox < 53 has a bug w.r.t location.search\n            const re = new RegExp(\'.*[?&]\' + name + \'=([^&#]*)\'),\n                  match = document.location.href.match(re);\n            if (typeof defaultValue === \'undefined\') { defaultValue = null; }\n\n            if (match) {\n                // We have to decode the URL since want the cleartext value\n                return decodeURIComponent(match[1]);\n            }\n\n            return defaultValue;\n        }\n\n        document.getElementById(\'sendCtrlAltDelButton\')\n            .onclick = sendCtrlAltDel;\n\n        // Read parameters specified in the URL query string\n        // By default, use the host and port of server that served this file\n        const host = readQueryVariable(\'host\', window.location.hostname);\n        let port = readQueryVariable(\'port\', window.location.port);\n        const password = readQueryVariable(\'password\', \'\');\n        const path = readQueryVariable(\'path\', \'websockify\');\n\n        // | | |         | | |\n        // | | | Connect | | |\n        // v v v         v v v\n\n        status("Connecting");\n\n        // Build the websocket URL used to connect\n        let url;\n        if (window.location.protocol === "https:") {\n            url = \'wss\';\n        } else {\n            url = \'ws\';\n        }\n        url += \'://\' + host;\n        if(port) {\n            url += \':\' + port;\n        }\n        url += \'/\' + path;\n\n        // Creating a new RFB object will start a new connection\n        rfb = new RFB(document.getElementById(\'screen\'), url,\n                      { credentials: { password: password } });\n\n        // Add listeners to important events from the RFB module\n        rfb.addEventListener("connect",  connectedToServer);\n        rfb.addEventListener("disconnect", disconnectedFromServer);\n        rfb.addEventListener("credentialsrequired", credentialsAreRequired);\n        rfb.addEventListener("desktopname", updateDesktopName);\n\n        // Set parameters that can be changed on an active connection\n        rfb.viewOnly = readQueryVariable(\'view_only\', false);\n        rfb.scaleViewport = readQueryVariable(\'scale\', false);\n    </script>\n</head>\n\n<body>\n    <div id="top_bar">\n        <div id="status">Loading</div>\n        <div id="sendCtrlAltDelButton">Send CtrlAltDel</div>\n    </div>\n    <div id="screen">\n        <!-- This is where the remote screen will appear -->\n    </div>\n</body>\n</html>\n': Not a valid html document in the response.



Expected results:
Test passed

Additional info:

Comment 3 Stephen Finucane 2020-02-21 10:04:17 UTC
This is simply a bad Tempest test. Tempest is checking for a '<html>' tag, but the response contains a '<html lang="en">' tag. The matcher should just be cleverer. Then again you shouldn't parse [1] HTML [2] with regex [3] so... :) In any case, reassigning component.

[1] https://blog.codinghorror.com/parsing-html-the-cthulhu-way/
[2] http://web.archive.org/web/20060505114433/http://www.alpha-geek.com/2004/01/12/bring_me_your_regexs_i_will_create_html_to_break_them
[3] https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454

Comment 4 Stephen Finucane 2020-02-21 10:09:24 UTC
This was already resolved upstream [1]. You need a newer version of Tempest.

[1] https://review.opendev.org/#/c/655827/

Comment 5 Martin Kopec 2020-02-21 11:59:59 UTC
The fix will need to be backported in order to get it packaged for RHOS-13.

Comment 17 Martin Kopec 2020-05-26 13:29:43 UTC
The issue is fixed in the Fixed in version package. Currently even the newer version of the package (openstack-tempest-18.0.0-15.el7ost) is present via latest symlink in the rhos-13 repositories.
I confirmed the test is passing in a job using the openstack-tempest-18.0.0-14.el7ost or newer.

Comment 19 errata-xmlrpc 2020-06-24 11:41:26 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2020:2719

Comment 20 Angela Huey 2024-05-03 12:14:16 UTC
Great post. Thanks for sharing this my bug query is finally resolved today thanks for sharing this. https://www.dollartree-compass.com


Note You need to log in before you can comment on or make changes to this bug.