<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@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;}
@font-face
        {font-family:"Lucida Console";
        panose-1:2 11 6 9 4 5 4 2 2 4;}
/* Style Definitions */
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";}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.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 Definitions */
@list l0
        {mso-list-id:2050491675;
        mso-list-template-ids:273157142;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D">This sounds great.&nbsp; Thanks Vojtech.<o:p></o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D"><o:p>&nbsp;</o:p></span></a></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> Tuesday, June 26, 2012 10:44 AM<br>
<b>To:</b> engine-devel@ovirt.org<br>
<b>Cc:</b> Costea, George; Schoenbrun, Dustin; Hopper, Ricky; Itamar Heim<br>
<b>Subject:</b> Re: oVirt UI Plugins feature: Ready for review<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
<div>
<p class="MsoNormal"><span style="font-size:13.5pt;color:black">Hi George,<br>
<br>
I've been thinking about developing plugins with GWT. There are some important issues that need to be addressed:</span><span style="color:black"><o:p></o:p></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">
<span style="font-size:13.5pt">GWT bootstrap sequence requires <em>permutation selector script</em> (</span><span style="font-family:&quot;Lucida Console&quot;">&lt;pluginApplication&gt;.nocache.js</span><span style="font-size:13.5pt">) to be invoked first.<br>
Selector script determines the correct permutation (</span><span style="font-family:&quot;Lucida Console&quot;">&lt;hashName&gt;.cache.html</span><span style="font-size:13.5pt">) and fetches it asynchronously from the same location.</span><o:p></o:p></li><li class="MsoNormal" style="color:black;mso-margin-top-alt:auto;margin-bottom:12.0pt;mso-list:l0 level1 lfo1">
<span style="font-size:13.5pt">GWT bootstrap sequence is asynchronous in nature.</span><o:p></o:p></li><li class="MsoNormal" style="color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo1">
<span style="font-size:13.5pt">GWT RPC (</span><span style="font-family:&quot;Lucida Console&quot;">XMLHttpRequest</span><span style="font-size:13.5pt">) is subject to Same Origin Policy [1].<br>
This means that <i>pluginApplication</i>'s server-side code should be deployed on oVirt JBoss AS instance (next to
</span><span style="font-family:&quot;Lucida Console&quot;">engine.ear</span><span style="font-size:13.5pt">).</span><o:p></o:p></li></ol>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:13.5pt;color:black"><br>
Given these limitations, I'd say the process could be like this:<br>
<br>
a) In <i>pluginApplication</i>'s </span><span style="font-family:&quot;Lucida Console&quot;;color:black">EntryPoint</span><span style="font-size:13.5pt;color:black">, use GWT JSNI [2] to register the plugin using native JavaScript code.<br>
<br>
&nbsp;&nbsp; You don't need to use <i>gwt-exporter</i> here, since plugin registration and logic is combined in one place.<br>
&nbsp;&nbsp; Using plugin-to-GWT delegate pattern with <i>gwt-exporter</i> is actually more complicated than going with plain JSNI.<br>
<br>
&nbsp;&nbsp; For example:<br>
<br>
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&nbsp;&nbsp; package com.myplugin;<br>
<br>
&nbsp;&nbsp; public class MyPluginApp implements com.google.gwt.core.client.EntryPoint {<br>
<br>
&nbsp;&nbsp; &nbsp; &nbsp;public void void onModuleLoad() {<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // Initialize plugin application, call registerPlugin() when ready<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; registerPlugin();<br>
&nbsp;&nbsp; &nbsp; &nbsp;}<br>
<br>
&nbsp;&nbsp; &nbsp; &nbsp;public static void tableContextMenu(com.google.gwt.core.client.JavaScriptObject eventContext) {<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // Consider using GWT overlay types [3] to easily work with JavaScriptObjects<br>
&nbsp;&nbsp; &nbsp; &nbsp;}<br>
<br>
&nbsp;&nbsp; &nbsp; &nbsp;private static native void registerPlugin() /*-{<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // Register 'myPlugin' into pluginApi.plugins object<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; $wnd.pluginApi.plugins.myPlugin = myPlugin = {<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;tableContextMenu: function(eventContext) {<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Call Java static method to handle this event<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @com.myplugin.MyPluginApp::tableContextMenu(Lcom/google/gwt/core/client/JavaScriptObject;)(eventContext);<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; };<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // Call the ready() function right away<br>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; $wnd.pluginApi.lifecycle(myPlugin).ready();<br>
&nbsp;&nbsp; &nbsp; &nbsp;}-*/;<br>
<br>
&nbsp;&nbsp; }</span><span style="font-size:13.5pt;color:black"><br>
<br>
b) Deploy the </span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;pluginApplication&gt;.war</span><span style="font-size:13.5pt;color:black"> file on JBoss AS instance, e.g.
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;JBOSS_HOME&gt;/standalone/deployments</span><span style="font-size:13.5pt;color:black">.<br>
<br>
&nbsp;&nbsp; This makes <i>pluginApplication</i>'s GWT RPC servlet(s) accessible from the same origin (protocol, domain, port).<br>
<br>
c) Modification of plugin lifecycle step #5:<br>
<br>
&nbsp;&nbsp; Instead of embedding </span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;pluginApplication&gt;.nocache.js</span><span style="font-size:13.5pt;color:black"> content into WebAdmin HTML page, just embed the link to it, e.g.
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">http(s)://127.0.0.1:&lt;port&gt;/path/to/&lt;pluginApplication&gt;.nocache.js</span><span style="font-size:13.5pt;color:black"><br>
<br>
d) Modification of plugin lifecycle step #6:<br>
<br>
&nbsp;&nbsp; During WebAdmin startup, for each plugin that is supposed to be loaded remotely, create an
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;iframe&gt;</span><span style="font-size:13.5pt;color:black"> that will fetch the plugin asynchronously.<br>
<br>
&nbsp;&nbsp; The </span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;iframe&gt;</span><span style="font-size:13.5pt;color:black"> is required in order for
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;pluginApplication&gt;.nocache.js</span><span style="font-size:13.5pt;color:black"> to appear from different (<i>pluginApplication</i>-specific) domain than WebAdmin HTML page.<br>
<br>
&nbsp;&nbsp; This way, fetching permutation (</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;hashName&gt;.cache.html</span><span style="font-size:13.5pt;color:black">) files, which are relative to
</span><span style="font-family:&quot;Lucida Console&quot;;color:black">&lt;pluginApplication&gt;.nocache.js</span><span style="font-size:13.5pt;color:black">, will work out-of-the-box.<br>
<br>
<br>
George, please let me know what you think, and I will update UI Plugins wiki accordingly.<br>
<br>
Vojtech<br>
<br>
<br>
[1] <a href="http://en.wikipedia.org/wiki/Same_origin_policy">http://en.wikipedia.org/wiki/Same_origin_policy</a><br>
[2] <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI">
https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI</a><br>
[3] <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsOverlay">
https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsOverlay</a><br>
<br>
</span><span style="color:black"><o:p></o:p></span></p>
<div class="MsoNormal" align="center" style="text-align:center"><span style="color:black">
<hr size="2" width="100%" align="center" id="zwchr">
</span></div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
From: &quot;George Costea&quot; &lt;<a href="mailto:George.Costea@netapp.com">George.Costea@netapp.com</a>&gt;<br>
To: &quot;Vojtech Szocs&quot; &lt;<a href="mailto:vszocs@redhat.com">vszocs@redhat.com</a>&gt;, <a href="mailto:engine-devel@ovirt.org">
engine-devel@ovirt.org</a><br>
Cc: &quot;Dustin Schoenbrun&quot; &lt;<a href="mailto:Dustin.Schoenbrun@netapp.com">Dustin.Schoenbrun@netapp.com</a>&gt;, &quot;Ricky Hopper&quot; &lt;<a href="mailto:Ricky.Hopper@netapp.com">Ricky.Hopper@netapp.com</a>&gt;, &quot;Itamar Heim&quot; &lt;<a href="mailto:iheim@redhat.com">iheim@redhat.com</a>&gt;<br>
Sent: Monday, June 25, 2012 9:11:33 PM<br>
Subject: RE: oVirt UI Plugins feature: Ready for review<br>
<br>
Thanks Vojtech.<br>
<br>
Since the plugins are embedded into the WebAdmin HTML page, that seems to simplify things; no external web service is needed. &nbsp;This approach ties into the issue over the freedom to decide which technology to use when developing a plugin. &nbsp;While I agree that
 jQuery is best for simple dialogs, a wizard-driven workflow is easier to develop in GWT. &nbsp;<br>
<br>
For example, if I want to step a user through the process of creating a new storage domain I would like to provide a workflow to select a storage array, provide credentials, and configure the details of the NFS export. &nbsp;This workflow could presumably have a
 GWT-RPC mechanism that relies on some additional libraries on the backend (libraries that allow me to communicate with the storage array). &nbsp;Using the GWT-Exporter, I could export the classes that would display the workflow which would then get launched as
 my extension is selected. &nbsp;You said that I would have my oVirt UI plugin depend on my compiled 'plugin support application'. &nbsp;My compiled plugin support application would normally be a war file containing my compiled GWT code and a web-inf folder containing
 my libraries. &nbsp;Is the plugin depending on the war file? &nbsp;Is that what I specify?<br>
<br>
-George<br>
<br>
-----Original Message-----<br>
From: Vojtech Szocs <a href="mailto:[mailto:vszocs@redhat.com]">[mailto:vszocs@redhat.com]</a>
<br>
Sent: Monday, June 25, 2012 1:12 PM<br>
To: Costea, George; <a href="mailto:engine-devel@ovirt.org">engine-devel@ovirt.org</a><br>
Cc: Schoenbrun, Dustin; Hopper, Ricky; Itamar Heim<br>
Subject: Re: oVirt UI Plugins feature: Ready for review<br>
<br>
Hi George,<br>
<br>
thanks for your feedback. Please find my answers below.<br>
<br>
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black">1) Are the plugins hosted by the same jboss server that hosts the engine? &nbsp;It would appear the answer is yes and that no separate container is required for the plugins.<br>
<br>
In short, yes.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
<br>
Plugins, along with their configuration and 3rd party dependencies, are meant to be embedded into final WebAdmin HTML page, see [http://www.ovirt.org/wiki/Features/UIPlugins#Plugin_lifecycle] step #5.
<br>
JBoss AS instance serves WebAdmin HTML page (WebadminDynamicHostingServlet), along with providing GWT RPC and REST endpoints that delegate to Engine business logic through EJB BackendLocal interface.<br>
<br>
However, plugins are not 'hosted' in a typical sense - WebadminDynamicHostingServlet reads and embeds all plugin data directly into final WebAdmin HTML page.<br>
<br>
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black">2) Does each plugin map to a unique extension within WebAdmin? &nbsp;Your example shows that I can extend the VM table to have a &quot;Show VM name and edit VM&quot; context-sensitive extension. &nbsp;This is named pluginApi.plugins.myPlugin.
 &nbsp;Can I safely assume that this is per extension? &nbsp;I would have pluginApi.plugins.myPlugin2 for extending a storage domain?<br>
<br>
Extension points are represented by application events, triggered by WebAdmin and consumed by plugins. For example, 'tableContextMenu' event gets triggered when a table context menu is about to be shown to the user, which gives plugins the ability to do something
 custom with the context menu before it's shown.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
<br>
There can be multiple plugins handling the same event (extension point). You can have two plugins, say 'pluginApi.plugins.One' and 'pluginApi.plugins.Two', each providing 'tableContextMenu' function for handling the above mentioned event. WebAdmin will invoke
 all plugins for the given event.<br>
<br>
To answer your question, in order to handle X events (extension points), you don't need to write X plugins. You can write one plugin that handles X events.<br>
<br>
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black">3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs?<br>
<br>
You can do anything you want in your plugin event handler function. Show a jQuery UI dialog, make oVirt REST API request, call arbitrary remote server using cross-domain technique like JSONP [1] or CORS [2], etc. Plugin authors are free to decide if they want
 to rely on 3rd party JavaScript libraries, or if they want to write entire plugin code by themselves.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
<br>
In my opinion, tools like jQuery are far more elegant for handling simple things such as UI dialogs. But if you really want to use GWT for this purpose, I suggest following approach:<br>
<br>
a, develop a 'plugin support application' in GWT, which implements the necessary dialog functionality b, export its main (e.g. dialog handling) classes for use in native JavaScript through gwt-exporter [3] c, have your oVirt UI plugin depend on your compiled
 'plugin support application' (this will cause your 'plugin support application' to be called during WebAdmin startup) d, in your oVirt UI plugin, invoke 'plugin support application' functionality through exported classes (plugin -&gt; GWT delegate pattern)<br>
<br>
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black">4) Is session info passed into the plugin so that I can invoke APIs into the engine? &nbsp;To power on a VM for instance? &nbsp;Or to mount a new NFS storage domain?<br>
<br>
Yes, this should be part of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] &quot;Plugin utility functions&quot; (global API).<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="color:black"><br>
<br>
Your plugin might access user session information in the following way: pluginApi.util().userInfo().* (replace * with id(), name(), domain(), etc.)<br>
<br>
As you pointed out, this could be used to authenticate oVirt REST API requests made from your plugin code.<br>
<br>
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black">BTW, the link to the original design notes on the wiki doesn't work.<br>
<br>
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to &quot;Public (Allow Internet guests)&quot; ... Does anybody know why this doesn't work?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black"><br>
<br>
<br>
Vojtech<br>
<br>
<br>
[1] <a href="http://en.wikipedia.org/wiki/JSONP">http://en.wikipedia.org/wiki/JSONP</a><br>
[2] <a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">http://en.wikipedia.org/wiki/Cross-origin_resource_sharing</a><br>
[3] <a href="http://code.google.com/p/gwt-exporter/">http://code.google.com/p/gwt-exporter/</a><br>
<br>
<br>
----- Original Message -----<br>
From: &quot;George Costea&quot; &lt;<a href="mailto:George.Costea@netapp.com">George.Costea@netapp.com</a>&gt;<br>
To: &quot;Vojtech Szocs&quot; &lt;<a href="mailto:vszocs@redhat.com">vszocs@redhat.com</a>&gt;, <a href="mailto:engine-devel@ovirt.org">
engine-devel@ovirt.org</a><br>
Cc: &quot;Dustin Schoenbrun&quot; &lt;<a href="mailto:Dustin.Schoenbrun@netapp.com">Dustin.Schoenbrun@netapp.com</a>&gt;, &quot;Ricky Hopper&quot; &lt;<a href="mailto:Ricky.Hopper@netapp.com">Ricky.Hopper@netapp.com</a>&gt;<br>
Sent: Monday, June 25, 2012 3:09:43 PM<br>
Subject: RE: oVirt UI Plugins feature: Ready for review<br>
<br>
Hi Vojtech,<br>
<br>
I have a few questions on this feature.<br>
<br>
1) Are the plugins hosted by the same jboss server that hosts the engine? &nbsp;It would appear the answer is yes and that no separate container is required for the plugins.<br>
2) Does each plugin map to a unique extension within WebAdmin? &nbsp;Your example shows that I can extend the VM table to have a &quot;Show VM name and edit VM&quot; context-sensitive extension. &nbsp;This is named pluginApi.plugins.myPlugin. &nbsp;Can I safely assume that this is
 per extension? &nbsp;I would have pluginApi.plugins.myPlugin2 for extending a storage domain?<br>
3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs?<br>
4) Is session info passed into the plugin so that I can invoke APIs into the engine? &nbsp;To power on a VM for instance? &nbsp;Or to mount a new NFS storage domain?<br>
<br>
BTW, the link to the original design notes on the wiki doesn't work.<br>
<br>
Thanks,<br>
George<br>
<br>
-----Original Message-----<br>
From: Vojtech Szocs <a href="mailto:[mailto:vszocs@redhat.com]">[mailto:vszocs@redhat.com]</a><br>
Sent: Thursday, June 21, 2012 11:03 AM<br>
To: <a href="mailto:engine-devel@ovirt.org">engine-devel@ovirt.org</a><br>
Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky<br>
Subject: oVirt UI Plugins feature: Ready for review<br>
<br>
Hi guys,<br>
<br>
I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application:<br>
<a href="http://www.ovirt.org/wiki/Features/UIPlugins">http://www.ovirt.org/wiki/Features/UIPlugins</a><br>
<br>
Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel.<br>
<br>
Cheers,<br>
Vojtech<o:p></o:p></span></p>
</div>
</div>
</body>
</html>