<html><head><style type='text/css'>p { margin: 0; }</style></head><body><div style='font-family: times new roman,new york,times,serif; font-size: 12pt; color: #000000'>Hi Chris,<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; Your
 assumption about the structure of the pluginDefinitions object is 
correct.&nbsp; It’s no longer a String-&gt;String mapping , but a String to 
Object mapping.</span><br><br>Yes :) but maybe we could also formalize some terms, for example:<br><br><em>Plugin descriptor</em> is the JSON file that contains important plugin meta-data (including the plugin source page URL), e.g. <span style="color: black;"><i>/usr/share/ovirt-engine/ui-plugins/test.json<br><span style="font-style: italic;"><span style="font-style: italic;"></span></span></i><br><span style="font-style: italic;">Plugin definition</span> is the JavaScript object representing plugin descriptor meta-data suitable for use on client (GWT WebAdmin). Plugin definition is embedded into WebAdmin host page within <span style="font-style: italic;">pluginDefinitions</span> object, and read by <span style="font-style: italic;">PluginManager</span> during WebAdmin startup.<br><i><span style="font-style: italic;"><span style="font-style: italic;"></span><br>Plugin configuration</span></i> is the JSON file that contains <strong>optional</strong> plugin configuration, e.g. </span><span style="color:black"><i>/etc/ovirt-engine/ui-plugins/test-config.json</i></span><br><span style="color: black;"><i><span style="font-style: italic;"><br></span></i>I think we can combine two things here:<br>1) allow plugin authors to define standard (fallback) configuration directly inside plugin descriptor<br>2) allow plugin users to override standard configuration by modifying dedicated plugin configuration file<br><br>Finally, <span style="font-style: italic;">plugin source page</span> is the HTML page used to invoke actual plugin code (this page is referenced by plugin descriptor's "url" attribute). Plugin source page can also load external resources required by the plugin, e.g. 3rd party JavaScript libraries, CSS, images, etc.<br><br></span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; I
 liked the original IIFE approach, except that it seemed that having 
additional static resources (jquery, images, html templates, etc) was 
going to be more
 cumbersome.&nbsp; I don’t think having the plugin author write a basic 
start.html is that big of a burden :).</span><br><br>You're right, for such additional plugin resources, even more configuration/parsing/logic would be required. Even though plugin authors need to write the plugin source page themselves, they have full control over it, which is a good thing in general.<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; I
 agree that the plugin configuration was always going to be a resource 
(probably a local file) that the end user could customize.&nbsp; I’m not sure
 it I really
 needs to be separate from the plugin definition file 
(/usr/share/ovirt-engine/ui-plugins/test.json).&nbsp; I suppose it depends on
 how complex the configuration is going to be and on some of the 
implementation details surrounding the plugin definition file.</span><br><br>Yeah, let's make the concept of the plugin configuration file optional for now (standard plugin configuration can be part of plugin descriptor).<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; In
 my patch, I simply used Jackson to parse the file into a tree of 
JsonNodes. &nbsp;Should the plugin definition be a java object of some sort? 
(please please please
 don’t make me learn about java beans…).&nbsp; I stuck with the JsonNodes 
because Jackson makes them easy to work with and they’re really easy to 
re-serialize back to json to give to the webadmin.</span><br><br>I think using Jackson's JSON representation in Java (JsonNode) is perfectly suitable in this situation. No need to have separate Java bean for that :)<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; We
 should probably turn on JsonParser.Feature.ALLOW_COMMENTS.&nbsp; The 
definition and config files will difficult for end-users (or even 
developers) to understand
 without comments.</span><br><br>Agreed.<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; We need to formalize the structure of the plugin definition and decide which fields are mandatory and which are optional</span><br><br>Sounds good, but I'd skip some attributes for now (enabled, apiVersion, author, license) for the sake of simplicity.<br><br>As you wrote, when loading plugin descriptor, we should enforce mandatory attributes (name, version, url).<br><br>As for plugin configuration, there could be two different attributes:<br>- "config" for standard (fallback) plugin configuration (JSON object)<br>- "configFile" for external plugin configuration file (path to file, relative to <span style="color:black">/etc/ovirt-engine/ui-plugins/)</span>, that overrides the standard configuration<br><br>Note that when loading plugin descriptor, the loader should also "merge" the configuration together (custom config on top of standard config).<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; I
 can work on the plugin Definition loader some more and make it enforce 
mandatory/optional fields. &nbsp;I’ll also investigate the directory climbing
 issue I mentioned
 in my previous mail.</span><br><br>Sounds good! I was planning to incorporate your original patch in next PoC revision, but of course, you can work on the loader some more and send another patch :)<br><br>For the directory climbing issue, see <span style="font-style: italic;">&lt;OVIRT_ROOT&gt;/backend/manager/modules/root/src/main/java/org/ovirt/engine/core/FileServlet.java</span> (there's a method called isSane for dealing with such issue).<br><br><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&gt; Also,
 I’m curious how things are going to work when the “url” points to a 
foreign resource as the plugin start page.&nbsp; I don’t think the plugin’s 
iframe is going
 to be able to access parent.pluginApi.&nbsp; Perhaps there is some aspect of
 CORS that I don’t understand?</span><br><br>When the plugin iframe references a resource on different origin (protocol, domain, port) than WebAdmin main page origin, JavaScript code running inside that iframe will not be able to access parent (top-level) <span style="font-style: italic;">pluginApi</span> object. You're right, the statement "parent.pluginApi" will not work, because of Same-Origin Policy enforced by the browser.<br><br>CORS is just one alternative, see http://stackoverflow.com/questions/3076414/ways-to-circumvent-the-same-origin-policy for more. However, CORS needs to be supported by the browser (a special HTTP response header is used to tell that the iframe is allowed to access resources from another - WebAdmin main page - origin). We need to investigate this a bit more I guess.<br><br>Regards,<br>Vojtech<br><br><br><hr id="zwchr"><div style="color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Chris Frantz" &lt;Chris.Frantz@hp.com&gt;<br><b>To: </b>"Vojtech Szocs" &lt;vszocs@redhat.com&gt;<br><b>Cc: </b>"engine-devel" &lt;engine-devel@ovirt.org&gt;<br><b>Sent: </b>Thursday, August 23, 2012 5:12:02 PM<br><b>Subject: </b>RE: UI Plugins configuration<br><br>



<style><!--

@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}

p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p
        {mso-style-priority:99;
        margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}

@list l0
        {mso-list-id:135345730;
        mso-list-template-ids:-1544269566;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style>


<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">Vojtech,</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">Your assumption about the structure of the pluginDefinitions object is correct.&nbsp; It’s no longer a String-&gt;String mapping , but a String to Object mapping.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">I liked the original IIFE approach, except that it seemed that having additional static resources (jquery, images, html templates, etc) was going to be more
 cumbersome.&nbsp; I don’t think having the plugin author write a basic start.html is that big of a burden :).</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">I agree that the plugin configuration was always going to be a resource (probably a local file) that the end user could customize.&nbsp; I’m not sure it I really
 needs to be separate from the plugin definition file (/usr/share/ovirt-engine/ui-plugins/test.json).&nbsp; I suppose it depends on how complex the configuration is going to be and on some of the implementation details surrounding the plugin definition file.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">In my patch, I simply used Jackson to parse the file into a tree of JsonNodes. &nbsp;Should the plugin definition be a java object of some sort? (please please please
 don’t make me learn about java beans…).&nbsp; I stuck with the JsonNodes because Jackson makes them easy to work with and they’re really easy to re-serialize back to json to give to the webadmin.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">We should probably turn on JsonParser.Feature.ALLOW_COMMENTS.&nbsp; The definition and config files will difficult for end-users (or even developers) to understand
 without comments.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">We need to formalize the structure of the plugin definition and decide which fields are mandatory and which are optional:</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">{</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Mandatory fields: name, enabled, version, url, apiversion, author, license<br>
&nbsp; # Name of the plugin&nbsp; </span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"name": "test",<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Whether or not plugin is enabed</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"enabled": true,<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # version of the plugin</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"version": "1.0",<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # How to load the plugin</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"url": "/webadmin/webadmin/plugin/test/start.html",<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Which version of engine plugin is meant to work with</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"apiversion": "3.1.0",<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Who wrote the plugin and how is it licensed?</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; "author": "SuperBig Corporation",<br>
&nbsp; "license": "Proprietary",<br>
<br>
</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Optional fields path, config</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Where to locate plugin (if loaded by webadmin/plugin)</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"path": "/tmp",</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp; # Plugin configuration information (if any)</span></p>
<p class="MsoNormal"><span style="font-family:&quot;Courier New&quot;;color:black">&nbsp;&nbsp;"config": "test-config.json",<br>
}</span><span style="color:black"><br>
</span><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;;color:#1F497D">&nbsp;&nbsp;&nbsp;&nbsp;
</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">I can work on the plugin Definition loader some more and make it enforce mandatory/optional fields. &nbsp;I’ll also investigate the directory climbing issue I mentioned
 in my previous mail.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">Also, I’m curious how things are going to work when the “url” points to a foreign resource as the plugin start page.&nbsp; I don’t think the plugin’s iframe is going
 to be able to access parent.pluginApi.&nbsp; Perhaps there is some aspect of CORS that I don’t understand?</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">Thanks,</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">--Chris</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">&nbsp;</span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:&quot;Tahoma&quot;,&quot;sans-serif&quot;">From:</span></b><span style="font-size:10.0pt;font-family:&quot;Tahoma&quot;,&quot;sans-serif&quot;"> Vojtech Szocs [mailto:vszocs@redhat.com]
<br>
<b>Sent:</b> Thursday, August 23, 2012 7:14 AM<br>
<b>To:</b> Frantz, Chris<br>
<b>Cc:</b> engine-devel<br>
<b>Subject:</b> Re: UI Plugins configuration</span></p>
</div>
</div>
<p class="MsoNormal">&nbsp;</p>
<div>
<p class="MsoNormal"><span style="color:black">Hi Chris,<br>
<br>
thanks for taking the time to make this patch, these are some excellent ideas! (CC'ing engine-devel so that we can discuss this with other guys as well)<br>
<br>
First of all, I really like the way you designed plugin source page URLs (going through
<em>PluginSourcePageServlet</em>), e.g. "/webadmin/webadmin/plugin/&lt;pluginName&gt;/&lt;pluginSourcePage&gt;.html", plus the concept of "path" JSON attribute.<br>
<br>
<i>WebadminDynamicHostingServlet</i> loads and caches all plugin definitions (<i>*.json</i> files), and directly embeds them into WebAdmin host page as
<i>pluginDefinitions</i> JavaScript object. I'm assuming that <i>pluginDefinitions</i> object will now look like this:<br>
<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black">var pluginDefinitions = {<br>
&nbsp;&nbsp;"test": {<br>
&nbsp;&nbsp; &nbsp;"name": "test",<br>
&nbsp;&nbsp; &nbsp;"version": "1.0",<br>
&nbsp;&nbsp; &nbsp;"url": "/webadmin/webadmin/plugin/test/foo.html",<br>
&nbsp;&nbsp; &nbsp;"path": "/tmp",<br>
&nbsp;&nbsp; &nbsp;"config": {"a":1, "b":2, "c":3}<br>
&nbsp;&nbsp;}<br>
}</span><span style="color:black"><br>
<br>
Originally, the <i>pluginDefinitions</i> object looked like this:<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black"><br>
var pluginDefinitions = {<br>
&nbsp;&nbsp;"test": "/webadmin/webadmin/plugin/test/foo.html" // Simple pluginName -&gt; pluginSourcePageUrl mappings<br>
}</span><span style="color:black"><br>
<br>
This is because PluginManager (WebAdmin) only needs <i>pluginName</i> ("name") and
<i>pluginSourcePageUrl</i> ("url") during startup, when creating plugin iframe. But this can be changed :)<br>
<br>
Plugin "version" makes sense, plus the plugin configuration object ("config") can be useful directly on the client. Let me explain:<br>
<br>
Originally, plugin configuration was supposed to be passed to actual plugin code (through immediately-invoked-function-expression, or IIFE), just like this:<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black"><br>
(function (pluginApi, pluginConfig) { // JavaScript IIFE<br>
&nbsp;&nbsp;// ... actual plugin code ...<br>
})(<br>
&nbsp;&nbsp;parent.pluginApi, /* reference to global pluginApi object */<br>
&nbsp;&nbsp;{"a":1, "b":2, "c":3} /* embedded plugin configuration as JavaScript object */<br>
);</span><span style="color:black"><br>
<br>
The whole purpose of <i>PluginSourcePageServlet</i> was to "wrap" actual plugin code into HTML, so that users don't need to write HTML pages for their plugins manually.
<i>PluginSourcePageServlet</i> would handle any plugin dependencies (placed into HTML head), with actual plugin code being wrapped into IIFE, as shown above. Plugin configuration was meant to be stored in a separate file, e.g.
<i>&lt;pluginName&gt;-config.json</i>, so that users could change the default plugin configuration to suit their needs.<br>
<br>
Inspired by your patch, rather than reading/embedding plugin configuration when serving plugin HTML page (<i>PluginSourcePageServlet</i>), it's even better to have the plugin configuration embedded directly into WebAdmin host page, along with introducing new
<i>pluginApi</i> function to retrieve the plugin configuration object.<br>
<br>
Based on this, I suggest following modifications to the original concept:<br>
<br>
- modify original <i>pluginDefinitions</i> structure, from <i>pluginName -&gt; pluginSourcePageUrl</i>, to
<i>pluginName -&gt; pluginDefObject</i><br>
- <i>pluginDefObject</i> is basically a subset of physical plugin definition (<i>test.json</i>, see below), suitable for use on the client<br>
- add following attributes to <i>pluginDefObject</i>: <i>version</i>, <i>url</i>,
<i>config</i><br>
&nbsp;&nbsp;* note #1: <i>name</i> is not needed, since it's already the key of <i>pluginName -&gt; pluginDefObject</i> mapping<br>
&nbsp;&nbsp;* note #2: <i>path</i> is not needed on the client (more on this below)<br>
- introduce <i>pluginApi.config(pluginName)</i> function for plugins to retrieve their configuration object, and remove
<i>pluginConfig</i> parameter from main IIFE (as shown above)<br>
<br>
[a] Physical plugin definition file (JSON) might be located at oVirt "DataDir", e.g.
<i>/usr/share/ovirt-engine/ui-plugins/test.json</i>, for example:<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black"><br>
{<br>
&nbsp;&nbsp;"name": "test",<br>
&nbsp;&nbsp;"version": "1.0",<br>
&nbsp;&nbsp;"url": "/webadmin/webadmin/plugin/test/start.html",<br>
&nbsp;&nbsp;"path": "/tmp",<br>
&nbsp;&nbsp;"config": "test-config.json"<br>
}</span><span style="color:black"><br>
<br>
[b] Plugin configuration file (JSON) might be located at oVirt "ConfigDir", e.g. <i>
/etc/ovirt-engine/ui-plugins/test-config.json</i>, for example:<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black"><br>
{<br>
&nbsp;&nbsp;"a":1, "b":2, "c":3<br>
}</span><span style="color:black"><br>
<br>
[c] Finally, plugin static resources (plugin source page, actual plugin code, plugin dependencies, CSS/images, etc.) would be located at
<i>/tmp</i> (as shown in [a]), for example:<br>
</span><span style="font-family:&quot;Courier New&quot;;color:black"><br>
/tmp/start.html -&gt; plugin source page, used to load actual plugin code<br>
/tmp/test.js -&gt; actual plugin code<br>
/tmp/deps/jquery-min.js -&gt; simulate 3rd party plugin dependency</span><span style="color:black"><br>
<br>
For example:<br>
"/webadmin/webadmin/plugin/test/start.html" will be mapped to <i>/tmp/start.html</i><br>
"/webadmin/webadmin/plugin/test/deps/jquery-min.js" will be mapped to <i>/tmp/deps/jquery-min.js</i><br>
<br>
This approach has some pros and cons:<br>
(+) plugin static resources can be served through <i>PluginSourcePageServlet</i> (pretty much like oVirt documentation resources, served through oVirt Engine root war's
<i>FileServlet</i>)<br>
(+) plugin author has complete control over plugin source page<br>
(-) plugin author actually needs to write plugin source page<br>
<br>
Overall, I think this approach is better than the previous one (where <i>PluginSourcePageServlet</i> took care of rendering plugin source page, but sacrificed some flexibility).<br>
<br>
By the way, here's what would happen behind the scenes:</span></p>
<ol start="1" type="1">
<li class="MsoNormal" style="color:black;mso-margin-top-alt:auto;margin-bottom:12.0pt;mso-list:l0 level1 lfo1">
user requests WebAdmin host page, <i>WebadminDynamicHostingServlet</i> loads and caches all plugin definitions [a] + plugin configurations [b] and constructs/embeds appropriate
<i>pluginDefinitions</i> JavaScript object</li><li class="MsoNormal" style="color:black;mso-margin-top-alt:auto;margin-bottom:12.0pt;mso-list:l0 level1 lfo1">
during WebAdmin startup, <i>PluginManager</i> registers the plugin (name/version/url/config), and creates/attaches the iframe to fetch plugin source page ansynchronously</li><li class="MsoNormal" style="color:black;mso-margin-top-alt:auto;margin-bottom:12.0pt;mso-list:l0 level1 lfo1">
<i>PluginSourcePageServlet</i> handles plugin source page request, resolves the correct path [c] and just streams the file content back to client</li></ol>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black">&gt; 1. &nbsp;The plugin configuration files should probably have an "enabled" field and an "apiVersion" field that should be examined to determine whether or not to use the plugin.<br>
<br>
Sounds good, we can implement these later on :)<br>
<br>
&gt; 2. &nbsp;I suspect the way I've modified PluginSourcePage makes it vulnerable to directory climbing attacks.<br>
<br>
Yes, but we can defend against these, restricting access only to plugin's "path" and its sub-directories.<br>
<br>
&gt; 3. &nbsp;Is /usr/share/ovirt-engine the right place for the plugin config files?<br>
<br>
I suppose you mean plugin definition files [a], cannot tell for sure, but we can change this anytime :)<br>
<br>
<br>
Chris, please let me know what you think, and again - many thanks for sending the patch!<br>
<br>
<br>
Regards,<br>
Vojtech<br>
<br>
</span></p>
<div class="MsoNormal" style="text-align:center" align="center"><span style="color:black">
<hr id="zwchr" size="2" width="100%" align="center">
</span></div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
From: "Chris Frantz" &lt;<a href="mailto:Chris.Frantz@hp.com" target="_blank">Chris.Frantz@hp.com</a>&gt;<br>
To: <a href="mailto:vszocs@redhat.com" target="_blank">vszocs@redhat.com</a><br>
Sent: Wednesday, August 22, 2012 7:56:45 PM<br>
Subject: UI Plugins configuration<br>
<br>
Vojtech,<br>
<br>
I decided to work on making the plugin patch a bit more configurable, following some of the ideas expressed by Itamar and others in the meeting yesterday. &nbsp;The attached patch is a simple first-attempt.<br>
<br>
Plugin configurations are stored in /usr/share/ovirt-engine/ui-plugins/*.json.<br>
<br>
Example:<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "test",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"version": "1.0",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"url": "/webadmin/webadmin/plugin/test/foo.html",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"path": "/tmp",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"config": {"a":1, "b":2, "c": 3}<br>
}<br>
<br>
The engine reads all of the *.json files in that directory to build the list of known plugins and gives that list to the webadmin.<br>
<br>
When webadmin loads a plugin, it requests the URL given in the plugin config file. &nbsp;The "plugin" URL is mapped to PluginSourcePage, which will translate the first part of the path ("test") into whatever path is stored in pluginConfig ("/tmp") in this case,
 and then serve the static file (e.g. "/tmp/foo.html").<br>
<br>
I didn't use the renderPluginSourcePage() method in favor of just serving a static file, but I have no strong opinion on the matter. &nbsp;However, a plugin may want to store static resources at "path" and have the engine serve those resources. &nbsp;By just serving
 files through PluginSourcePage, we don't need any other servlets to provide those resources.<br>
<br>
There is still a bit of work to do:<br>
<br>
1. &nbsp;The plugin configuration files should probably have an "enabled" field and an "apiVersion" field that should be examined to determine whether or not to use the plugin.<br>
<br>
2. &nbsp;I suspect the way I've modified PluginSourcePage makes it vulnerable to directory climbing attacks.<br>
<br>
3. &nbsp;Is /usr/share/ovirt-engine the right place for the plugin config files?<br>
<br>
Let me know what you think,<br>
--Chris</span></p>
</div>
</div>


</div><br></div></body></html>