[Engine-devel] oVirt UI Plugins feature: Ready for review

Hi guys, I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel. Cheers, Vojtech

Hi Vojtech, I have a few questions on this feature. 1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain? BTW, the link to the original design notes on the wiki doesn't work. Thanks, George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Thursday, June 21, 2012 11:03 AM To: engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky Subject: oVirt UI Plugins feature: Ready for review Hi guys, I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel. Cheers, Vojtech

Hi George, thanks for your feedback. Please find my answers below.
1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins.
In short, yes. 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. 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. However, plugins are not 'hosted' in a typical sense - WebadminDynamicHostingServlet reads and embeds all plugin data directly into final WebAdmin HTML page.
2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain?
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. 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. 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.
3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs?
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. 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: 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 -> GWT delegate pattern)
4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain?
Yes, this should be part of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] "Plugin utility functions" (global API). Your plugin might access user session information in the following way: pluginApi.util().userInfo().* (replace * with id(), name(), domain(), etc.) As you pointed out, this could be used to authenticate oVirt REST API requests made from your plugin code.
BTW, the link to the original design notes on the wiki doesn't work.
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work? Vojtech [1] http://en.wikipedia.org/wiki/JSONP [2] http://en.wikipedia.org/wiki/Cross-origin_resource_sharing [3] http://code.google.com/p/gwt-exporter/ ----- Original Message ----- From: "George Costea" <George.Costea@netapp.com> To: "Vojtech Szocs" <vszocs@redhat.com>, engine-devel@ovirt.org Cc: "Dustin Schoenbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com> Sent: Monday, June 25, 2012 3:09:43 PM Subject: RE: oVirt UI Plugins feature: Ready for review Hi Vojtech, I have a few questions on this feature. 1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain? BTW, the link to the original design notes on the wiki doesn't work. Thanks, George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Thursday, June 21, 2012 11:03 AM To: engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky Subject: oVirt UI Plugins feature: Ready for review Hi guys, I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel. Cheers, Vojtech

Thanks Vojtech. Since the plugins are embedded into the WebAdmin HTML page, that seems to simplify things; no external web service is needed. This approach ties into the issue over the freedom to decide which technology to use when developing a plugin. While I agree that jQuery is best for simple dialogs, a wizard-driven workflow is easier to develop in GWT. 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. 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). Using the GWT-Exporter, I could export the classes that would display the workflow which would then get launched as my extension is selected. You said that I would have my oVirt UI plugin depend on my compiled 'plugin support application'. My compiled plugin support application would normally be a war file containing my compiled GWT code and a web-inf folder containing my libraries. Is the plugin depending on the war file? Is that what I specify? -George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Monday, June 25, 2012 1:12 PM To: Costea, George; engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Hopper, Ricky; Itamar Heim Subject: Re: oVirt UI Plugins feature: Ready for review Hi George, thanks for your feedback. Please find my answers below.
1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins.
In short, yes. 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. 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. However, plugins are not 'hosted' in a typical sense - WebadminDynamicHostingServlet reads and embeds all plugin data directly into final WebAdmin HTML page.
2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain?
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. 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. 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.
3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs?
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. 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: 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 -> GWT delegate pattern)
4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain?
Yes, this should be part of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] "Plugin utility functions" (global API). Your plugin might access user session information in the following way: pluginApi.util().userInfo().* (replace * with id(), name(), domain(), etc.) As you pointed out, this could be used to authenticate oVirt REST API requests made from your plugin code.
BTW, the link to the original design notes on the wiki doesn't work.
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work? Vojtech [1] http://en.wikipedia.org/wiki/JSONP [2] http://en.wikipedia.org/wiki/Cross-origin_resource_sharing [3] http://code.google.com/p/gwt-exporter/ ----- Original Message ----- From: "George Costea" <George.Costea@netapp.com> To: "Vojtech Szocs" <vszocs@redhat.com>, engine-devel@ovirt.org Cc: "Dustin Schoenbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com> Sent: Monday, June 25, 2012 3:09:43 PM Subject: RE: oVirt UI Plugins feature: Ready for review Hi Vojtech, I have a few questions on this feature. 1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain? BTW, the link to the original design notes on the wiki doesn't work. Thanks, George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Thursday, June 21, 2012 11:03 AM To: engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky Subject: oVirt UI Plugins feature: Ready for review Hi guys, I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel. Cheers, Vojtech

<font size=3D"4">Hi George,<br><br>I've been thinking about developing plu= gins with GWT. There are some important issues that need to be addressed:<b= r></font><ol><li><font size=3D"4">GWT bootstrap sequence requires <em>permu= tation selector script</em> (<font size=3D"3"><span style=3D"font-family: l= ucida console,sans-serif;"><pluginApplication>.nocache.js</span></fon= t>) to be invoked first.<br>Selector script determines the correct permutat= ion (<font style=3D"font-family: lucida console,sans-serif;" size=3D"3"><= ;hashName>.cache.html</font>) and fetches it asynchronously from the sam= e location.<br><br></font></li><li><font size=3D"4">GWT bootstrap sequence = is asynchronous in nature.<br><br></font></li><li><font size=3D"4">GWT RPC = (<font style=3D"font-family: lucida console,sans-serif;" size=3D"3">XMLHttp= Request</font>) is subject to Same Origin Policy [1].<br>This means that <s=
--=_8c1ef5c2-c775-4be9-be4e-f09c4448d600 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Hi George, I've been thinking about developing plugins with GWT. There are some important issues that need to be addressed: 1. GWT bootstrap sequence requires permutation selector script ( <pluginApplication>.nocache.js ) to be invoked first. Selector script determines the correct permutation ( <hashName>.cache.html ) and fetches it asynchronously from the same location. 2. GWT bootstrap sequence is asynchronous in nature. 3. GWT RPC ( XMLHttpRequest ) is subject to Same Origin Policy [1]. This means that pluginApplication 's server-side code should be deployed on oVirt JBoss AS instance (next to engine.ear ). Given these limitations, I'd say the process could be like this: a) In pluginApplication 's EntryPoint , use GWT JSNI [2] to register the plugin using native JavaScript code. You don't need to use gwt-exporter here, since plugin registration and logic is combined in one place. Using plugin-to-GWT delegate pattern with gwt-exporter is actually more complicated than going with plain JSNI. For example: package com.myplugin; public class MyPluginApp implements com.google.gwt.core.client.EntryPoint { public void void onModuleLoad() { // Initialize plugin application, call registerPlugin() when ready registerPlugin(); } public static void tableContextMenu(com.google.gwt.core.client.JavaScriptObject eventContext) { // Consider using GWT overlay types [3] to easily work with JavaScriptObjects } private static native void registerPlugin() /*-{ // Register 'myPlugin' into pluginApi.plugins object $wnd.pluginApi.plugins.myPlugin = myPlugin = { tableContextMenu: function(eventContext) { // Call Java static method to handle this event @com.myplugin.MyPluginApp::tableContextMenu(Lcom/google/gwt/core/client/JavaScriptObject;)(eventContext); } }; // Call the ready() function right away $wnd.pluginApi.lifecycle(myPlugin).ready(); }-*/; } b) Deploy the <pluginApplication>.war file on JBoss AS instance, e.g. <JBOSS_HOME>/standalone/deployments . This makes pluginApplication 's GWT RPC servlet(s) accessible from the same origin (protocol, domain, port). c) Modification of plugin lifecycle step #5: Instead of embedding <pluginApplication>.nocache.js content into WebAdmin HTML page, just embed the link to it, e.g. http(s)://127.0.0.1:<port>/path/to/<pluginApplication>.nocache.js d) Modification of plugin lifecycle step #6: During WebAdmin startup, for each plugin that is supposed to be loaded remotely, create an <iframe> that will fetch the plugin asynchronously. The <iframe> is required in order for <pluginApplication>.nocache.js to appear from different ( pluginApplication -specific ) domain than WebAdmin HTML page. This way, fetching permutation ( <hashName>.cache.html ) files, which are relative to <pluginApplication>.nocache.js , will work out-of-the-box. George, please let me know what you think, and I will update UI Plugins wiki accordingly. Vojtech [1] http://en.wikipedia.org/wiki/Same_origin_policy [2] https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSN... [3] https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsOve... ----- Original Message ----- From: "George Costea" <George.Costea@netapp.com> To: "Vojtech Szocs" <vszocs@redhat.com>, engine-devel@ovirt.org Cc: "Dustin Schoenbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com>, "Itamar Heim" <iheim@redhat.com> Sent: Monday, June 25, 2012 9:11:33 PM Subject: RE: oVirt UI Plugins feature: Ready for review Thanks Vojtech. Since the plugins are embedded into the WebAdmin HTML page, that seems to simplify things; no external web service is needed. This approach ties into the issue over the freedom to decide which technology to use when developing a plugin. While I agree that jQuery is best for simple dialogs, a wizard-driven workflow is easier to develop in GWT. 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. 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). Using the GWT-Exporter, I could export the classes that would display the workflow which would then get launched as my extension is selected. You said that I would have my oVirt UI plugin depend on my compiled 'plugin support application'. My compiled plugin support application would normally be a war file containing my compiled GWT code and a web-inf folder containing my libraries. Is the plugin depending on the war file? Is that what I specify? -George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Monday, June 25, 2012 1:12 PM To: Costea, George; engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Hopper, Ricky; Itamar Heim Subject: Re: oVirt UI Plugins feature: Ready for review Hi George, thanks for your feedback. Please find my answers below. 1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. In short, yes. 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. 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. However, plugins are not 'hosted' in a typical sense - WebadminDynamicHostingServlet reads and embeds all plugin data directly into final WebAdmin HTML page. <blockquote> 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 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. </blockquote> 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. 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. <blockquote> 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 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. </blockquote> 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: 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 -> GWT delegate pattern) <blockquote> 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain? Yes, this should be part of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] "Plugin utility functions" (global API). </blockquote> Your plugin might access user session information in the following way: pluginApi.util().userInfo().* (replace * with id(), name(), domain(), etc.) As you pointed out, this could be used to authenticate oVirt REST API requests made from your plugin code. <blockquote> BTW, the link to the original design notes on the wiki doesn't work. This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work? </blockquote> Vojtech [1] http://en.wikipedia.org/wiki/JSONP [2] http://en.wikipedia.org/wiki/Cross-origin_resource_sharing [3] http://code.google.com/p/gwt-exporter/ ----- Original Message ----- From: "George Costea" <George.Costea@netapp.com> To: "Vojtech Szocs" <vszocs@redhat.com>, engine-devel@ovirt.org Cc: "Dustin Schoenbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com> Sent: Monday, June 25, 2012 3:09:43 PM Subject: RE: oVirt UI Plugins feature: Ready for review Hi Vojtech, I have a few questions on this feature. 1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain? BTW, the link to the original design notes on the wiki doesn't work. Thanks, George -----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Thursday, June 21, 2012 11:03 AM To: engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky Subject: oVirt UI Plugins feature: Ready for review Hi guys, I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel. Cheers, Vojtech --=_8c1ef5c2-c775-4be9-be4e-f09c4448d600 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable <html><head><style type=3D'text/css'>p { margin: 0; }</style></head><body><= div style=3D'font-family: Times New Roman; font-size: 12pt; color: #000000'= pan style=3D"font-style: italic;">pluginApplication</span>'s server-side co= de should be deployed on oVirt JBoss AS instance (next to <font style=3D"fo= nt-family: lucida console,sans-serif;" size=3D"3">engine.ear</font>).<br></= font></li></ol><font size=3D"4"><br>Given these limitations, I'd say the pr= ocess could be like this:<br><br>a) In <span style=3D"font-style: italic;">= pluginApplication</span>'s <font style=3D"font-family: lucida console,sans-= serif;" size=3D"3">EntryPoint</font>, use GWT JSNI [2] to register the plug= in using native JavaScript code.<br><br> You don't need to use = <span style=3D"font-style: italic;">gwt-exporter</span> here, since plugin = registration and logic is combined in one place.<br> Using plug= in-to-GWT delegate pattern with <span style=3D"font-style: italic;">gwt-exp= orter</span> is actually more complicated than going with plain JSNI.<br><b= r> For example:<br><br><font style=3D"font-family: lucida conso= le,sans-serif;" size=3D"3"> package com.myplugin;<br><br> = public class MyPluginApp implements com.google.gwt.core.client.Entry= Point {<br><br> public void void onModuleLoad() {<= br> // Initialize plugin application, call= registerPlugin() when ready<br> registerP= lugin();<br> }<br><br> pu= blic static void tableContextMenu(com.google.gwt.core.client.JavaScriptObje= ct eventContext) {<br> // Consider using G= WT overlay types [3] to easily work with JavaScriptObjects<br> = }<br><br> private static native void = registerPlugin() /*-{<br> // Register 'myP= lugin' into pluginApi.plugins object<br> $= wnd.pluginApi.plugins.myPlugin =3D myPlugin =3D {<br> &n= bsp; tableContextMenu: function(eventContext) {<br>&nbs= p; // Call Java static meth= od to handle this event<br> = @com.myplugin.MyPluginApp::tableContextMenu(Lcom/google/gwt/core/cli= ent/JavaScriptObject;)(eventContext);<br> = }<br> };<br> &nbs= p; // Call the ready() function right away<br> &n= bsp; $wnd.pluginApi.lifecycle(myPlugin).ready();<br> &nb= sp; }-*/;<br><br> }</font><br><br>b) Deploy the <f= ont style=3D"font-family: lucida console,sans-serif;" size=3D"3"><plugin= Application>.war</font> file on JBoss AS instance, e.g. <font style=3D"f= ont-family: lucida console,sans-serif;" size=3D"3"><JBOSS_HOME>/stand= alone/deployments</font>.<br><br> This makes <span style=3D"fon= t-style: italic;">pluginApplication</span>'s GWT RPC servlet(s) accessible = from the same origin (protocol, domain, port).<br><br>c) Modification of pl= ugin lifecycle step #5:<br><br> Instead of embedding <font styl= e=3D"font-family: lucida console,sans-serif;" size=3D"3"><pluginApplicat= ion>.nocache.js</font> content into WebAdmin HTML page, just embed the l= ink to it, e.g. <font style=3D"font-family: lucida console,sans-serif;" siz= e=3D"3">http(s)://127.0.0.1:<port>/path/to/<pluginApplication>.= nocache.js</font><br><br>d) Modification of plugin lifecycle step #6:<br><b= r> During WebAdmin startup, for each plugin that is supposed to= be loaded remotely, create an <font size=3D"3"><span style=3D"font-family:= lucida console,sans-serif;"><iframe></span></font> that will fetch t= he plugin asynchronously.<br><br> The <font style=3D"font-famil= y: lucida console,sans-serif;" size=3D"3"><iframe></font> is required= in order for <font size=3D"3"><span style=3D"font-family: lucida console,s= ans-serif;"><pluginApplication>.nocache.js</span></font> to appear fr= om different (</font><font size=3D"4"><span style=3D"font-style: italic;">p= luginApplication</span>-specific</font><font size=3D"4">) domain than WebAd= min HTML page.<br><br> This way, fetching permutation (<font st= yle=3D"font-family: lucida console,sans-serif;" size=3D"3"><hashName>= .cache.html</font>) files, which are relative to <font style=3D"font-family= : lucida console,sans-serif;" size=3D"3"><pluginApplication>.nocache.= js</font>, 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>Vojte= ch<br><br><br>[1] http://en.wikipedia.org/wiki/Same_origin_policy<br>[2] ht= tps://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI= <br>[3] https://developers.google.com/web-toolkit/doc/latest/DevGuideCoding= BasicsOverlay<br><br></font><br><hr id=3D"zwchr"><br>From: "George Costea" = <George.Costea@netapp.com><br>To: "Vojtech Szocs" <vszocs@redhat.c= om>, engine-devel@ovirt.org<br>Cc: "Dustin Schoenbrun" <Dustin.Schoen= brun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com>, "Itama= r Heim" <iheim@redhat.com><br>Sent: Monday, June 25, 2012 9:11:33 PM<= br>Subject: RE: oVirt UI Plugins feature: Ready for review<br><br>Thanks Vo= jtech.<br><br>Since the plugins are embedded into the WebAdmin HTML page, t= hat seems to simplify things; no external web service is needed. This= approach ties into the issue over the freedom to decide which technology t= o use when developing a plugin. While I agree that jQuery is best for= simple dialogs, a wizard-driven workflow is easier to develop in GWT. &nbs= p;<br><br>For example, if I want to step a user through the process of crea= ting a new storage domain I would like to provide a workflow to select a st= orage array, provide credentials, and configure the details of the NFS expo= rt. This workflow could presumably have a GWT-RPC mechanism that reli= es on some additional libraries on the backend (libraries that allow me to = communicate with the storage array). Using the GWT-Exporter, I could = export the classes that would display the workflow which would then get lau= nched as my extension is selected. You said that I would have my oVir= t UI plugin depend on my compiled 'plugin support application'. My co= mpiled plugin support application would normally be a war file containing m= y compiled GWT code and a web-inf folder containing my libraries. Is = the plugin depending on the war file? Is that what I specify?<br><br>= -George<br><br>-----Original Message-----<br>From: Vojtech Szocs [mailto:vs= zocs@redhat.com] <br>Sent: Monday, June 25, 2012 1:12 PM<br>To: Costea, Geo= rge; engine-devel@ovirt.org<br>Cc: Schoenbrun, Dustin; Hopper, Ricky; Itama= r 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><br><blockquote> 1) Are the plugins hosted by the same jboss server tha= t hosts the engine? It would appear the answer is yes and that no sep= arate container is required for the plugins.<br><br>In short, yes.</blockqu= ote><br><br>Plugins, along with their configuration and 3rd party dependenc= ies, are meant to be embedded into final WebAdmin HTML page, see [http://ww= w.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><br><blockq= uote> 2) Does each plugin map to a unique extension within WebAdmin? = Your example shows that I can extend the VM table to have a "Show VM name a= nd edit VM" context-sensitive extension. This is named pluginApi.plug= ins.myPlugin. Can I safely assume that this is per extension? I= would have pluginApi.plugins.myPlugin2 for extending a storage domain?<br>= <br>Extension points are represented by application events, triggered by We= bAdmin 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 bef= ore it's shown.</blockquote><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 ha= ndle X events (extension points), you don't need to write X plugins. You ca= n write one plugin that handles X events.<br><br><br><blockquote> 3) Instea= d 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 RE= ST API request, call arbitrary remote server using cross-domain technique l= ike JSONP [1] or CORS [2], etc. Plugin authors are free to decide if they w= ant to rely on 3rd party JavaScript libraries, or if they want to write ent= ire plugin code by themselves.</blockquote><br><br>In my opinion, tools lik= e 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 a= pproach:<br><br>a, develop a 'plugin support application' in GWT, which imp= lements 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 applicati= on' (this will cause your 'plugin support application' to be called during = WebAdmin startup) d, in your oVirt UI plugin, invoke 'plugin support applic= ation' functionality through exported classes (plugin -> GWT delegate pa= ttern)<br><br><br><blockquote> 4) Is session info passed into the plugin so= that I can invoke APIs into the engine? To power on a VM for instanc= e? Or to mount a new NFS storage domain?<br><br>Yes, this should be p= art of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] = "Plugin utility functions" (global API).</blockquote><br><br>Your plugin mi= ght access user session information in the following way: pluginApi.util().= userInfo().* (replace * with id(), name(), domain(), etc.)<br><br>As you po= inted out, this could be used to authenticate oVirt REST API requests made = from your plugin code.<br><br><br><blockquote> BTW, the link to the origina= l design notes on the wiki doesn't work.<br><br>This is strange, [http://rh= evmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allo= w Internet guests)" ... Does anybody know why this doesn't work?</blockquot= e><br><br><br>Vojtech<br><br><br>[1] http://en.wikipedia.org/wiki/JSONP<br>= [2] http://en.wikipedia.org/wiki/Cross-origin_resource_sharing<br>[3] http:= //code.google.com/p/gwt-exporter/<br><br><br>----- Original Message -----<b= r>From: "George Costea" <George.Costea@netapp.com><br>To: "Vojtech Sz= ocs" <vszocs@redhat.com>, engine-devel@ovirt.org<br>Cc: "Dustin Schoe= nbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hoppe= r@netapp.com><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 s= ame jboss server that hosts the engine? 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? Your example = shows that I can extend the VM table to have a "Show VM name and edit VM" c= ontext-sensitive extension. This is named pluginApi.plugins.myPlugin.= Can I safely assume that this is per extension? I would have p= luginApi.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 disp= lay a dialog that fits my needs?<br>4) Is session info passed into the plug= in so that I can invoke APIs into the engine? To power on a VM for in= stance? 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>Geor= ge<br><br>-----Original Message-----<br>From: Vojtech Szocs [mailto:vszocs@= redhat.com]<br>Sent: Thursday, June 21, 2012 11:03 AM<br>To: engine-devel@o= virt.org<br>Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky<br>Subjec= t: oVirt UI Plugins feature: Ready for review<br><br>Hi guys,<br><br>I wrot= e a wiki page describing UI Plugins, a feature planned for oVirt web admini= stration (WebAdmin) application:<br>http://www.ovirt.org/wiki/Features/UIPl= ugins<br><br>Feature design is finished and ready for review. Please feel f= ree to add comments, ask questions or reach me directly on #ovirt channel.<= br><br>Cheers,<br>Vojtech<br></div></body></html> --=_8c1ef5c2-c775-4be9-be4e-f09c4448d600--

--_000_6C8AC8C50E170C4E9B44D47B39B24A48012080BASACEXCMBX04PRDh_ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 VGhpcyBzb3VuZHMgZ3JlYXQuICBUaGFua3MgVm9qdGVjaC4NCg0KRnJvbTogVm9qdGVjaCBTem9j cyBbbWFpbHRvOnZzem9jc0ByZWRoYXQuY29tXQ0KU2VudDogVHVlc2RheSwgSnVuZSAyNiwgMjAx MiAxMDo0NCBBTQ0KVG86IGVuZ2luZS1kZXZlbEBvdmlydC5vcmcNCkNjOiBDb3N0ZWEsIEdlb3Jn ZTsgU2Nob2VuYnJ1biwgRHVzdGluOyBIb3BwZXIsIFJpY2t5OyBJdGFtYXIgSGVpbQ0KU3ViamVj dDogUmU6IG9WaXJ0IFVJIFBsdWdpbnMgZmVhdHVyZTogUmVhZHkgZm9yIHJldmlldw0KDQpIaSBH ZW9yZ2UsDQoNCkkndmUgYmVlbiB0aGlua2luZyBhYm91dCBkZXZlbG9waW5nIHBsdWdpbnMgd2l0 aCBHV1QuIFRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBpc3N1ZXMgdGhhdCBuZWVkIHRvIGJlIGFk ZHJlc3NlZDoNCg0KICAxLiAgR1dUIGJvb3RzdHJhcCBzZXF1ZW5jZSByZXF1aXJlcyBwZXJtdXRh dGlvbiBzZWxlY3RvciBzY3JpcHQgKDxwbHVnaW5BcHBsaWNhdGlvbj4ubm9jYWNoZS5qcykgdG8g YmUgaW52b2tlZCBmaXJzdC4NClNlbGVjdG9yIHNjcmlwdCBkZXRlcm1pbmVzIHRoZSBjb3JyZWN0 IHBlcm11dGF0aW9uICg8aGFzaE5hbWU+LmNhY2hlLmh0bWwpIGFuZCBmZXRjaGVzIGl0IGFzeW5j aHJvbm91c2x5IGZyb20gdGhlIHNhbWUgbG9jYXRpb24uDQogIDIuICBHV1QgYm9vdHN0cmFwIHNl cXVlbmNlIGlzIGFzeW5jaHJvbm91cyBpbiBuYXR1cmUuDQogIDMuICBHV1QgUlBDIChYTUxIdHRw UmVxdWVzdCkgaXMgc3ViamVjdCB0byBTYW1lIE9yaWdpbiBQb2xpY3kgWzFdLg0KVGhpcyBtZWFu cyB0aGF0IHBsdWdpbkFwcGxpY2F0aW9uJ3Mgc2VydmVyLXNpZGUgY29kZSBzaG91bGQgYmUgZGVw bG95ZWQgb24gb1ZpcnQgSkJvc3MgQVMgaW5zdGFuY2UgKG5leHQgdG8gZW5naW5lLmVhcikuDQoN CkdpdmVuIHRoZXNlIGxpbWl0YXRpb25zLCBJJ2Qgc2F5IHRoZSBwcm9jZXNzIGNvdWxkIGJlIGxp a2UgdGhpczoNCg0KYSkgSW4gcGx1Z2luQXBwbGljYXRpb24ncyBFbnRyeVBvaW50LCB1c2UgR1dU IEpTTkkgWzJdIHRvIHJlZ2lzdGVyIHRoZSBwbHVnaW4gdXNpbmcgbmF0aXZlIEphdmFTY3JpcHQg Y29kZS4NCg0KICAgWW91IGRvbid0IG5lZWQgdG8gdXNlIGd3dC1leHBvcnRlciBoZXJlLCBzaW5j ZSBwbHVnaW4gcmVnaXN0cmF0aW9uIGFuZCBsb2dpYyBpcyBjb21iaW5lZCBpbiBvbmUgcGxhY2Uu DQogICBVc2luZyBwbHVnaW4tdG8tR1dUIGRlbGVnYXRlIHBhdHRlcm4gd2l0aCBnd3QtZXhwb3J0 ZXIgaXMgYWN0dWFsbHkgbW9yZSBjb21wbGljYXRlZCB0aGFuIGdvaW5nIHdpdGggcGxhaW4gSlNO SS4NCg0KICAgRm9yIGV4YW1wbGU6DQoNCiAgIHBhY2thZ2UgY29tLm15cGx1Z2luOw0KDQogICBw dWJsaWMgY2xhc3MgTXlQbHVnaW5BcHAgaW1wbGVtZW50cyBjb20uZ29vZ2xlLmd3dC5jb3JlLmNs aWVudC5FbnRyeVBvaW50IHsNCg0KICAgICAgcHVibGljIHZvaWQgdm9pZCBvbk1vZHVsZUxvYWQo KSB7DQogICAgICAgICAvLyBJbml0aWFsaXplIHBsdWdpbiBhcHBsaWNhdGlvbiwgY2FsbCByZWdp c3RlclBsdWdpbigpIHdoZW4gcmVhZHkNCiAgICAgICAgIHJlZ2lzdGVyUGx1Z2luKCk7DQogICAg ICB9DQoNCiAgICAgIHB1YmxpYyBzdGF0aWMgdm9pZCB0YWJsZUNvbnRleHRNZW51KGNvbS5nb29n bGUuZ3d0LmNvcmUuY2xpZW50LkphdmFTY3JpcHRPYmplY3QgZXZlbnRDb250ZXh0KSB7DQogICAg ICAgICAvLyBDb25zaWRlciB1c2luZyBHV1Qgb3ZlcmxheSB0eXBlcyBbM10gdG8gZWFzaWx5IHdv cmsgd2l0aCBKYXZhU2NyaXB0T2JqZWN0cw0KICAgICAgfQ0KDQogICAgICBwcml2YXRlIHN0YXRp YyBuYXRpdmUgdm9pZCByZWdpc3RlclBsdWdpbigpIC8qLXsNCiAgICAgICAgIC8vIFJlZ2lzdGVy ICdteVBsdWdpbicgaW50byBwbHVnaW5BcGkucGx1Z2lucyBvYmplY3QNCiAgICAgICAgICR3bmQu cGx1Z2luQXBpLnBsdWdpbnMubXlQbHVnaW4gPSBteVBsdWdpbiA9IHsNCiAgICAgICAgICAgIHRh YmxlQ29udGV4dE1lbnU6IGZ1bmN0aW9uKGV2ZW50Q29udGV4dCkgew0KICAgICAgICAgICAgICAg Ly8gQ2FsbCBKYXZhIHN0YXRpYyBtZXRob2QgdG8gaGFuZGxlIHRoaXMgZXZlbnQNCiAgICAgICAg ICAgICAgIEBjb20ubXlwbHVnaW4uTXlQbHVnaW5BcHA6OnRhYmxlQ29udGV4dE1lbnUoTGNvbS9n b29nbGUvZ3d0L2NvcmUvY2xpZW50L0phdmFTY3JpcHRPYmplY3Q7KShldmVudENvbnRleHQpOw0K ICAgICAgICAgICAgfQ0KICAgICAgICAgfTsNCiAgICAgICAgIC8vIENhbGwgdGhlIHJlYWR5KCkg ZnVuY3Rpb24gcmlnaHQgYXdheQ0KICAgICAgICAgJHduZC5wbHVnaW5BcGkubGlmZWN5Y2xlKG15 UGx1Z2luKS5yZWFkeSgpOw0KICAgICAgfS0qLzsNCg0KICAgfQ0KDQpiKSBEZXBsb3kgdGhlIDxw bHVnaW5BcHBsaWNhdGlvbj4ud2FyIGZpbGUgb24gSkJvc3MgQVMgaW5zdGFuY2UsIGUuZy4gPEpC T1NTX0hPTUU+L3N0YW5kYWxvbmUvZGVwbG95bWVudHMuDQoNCiAgIFRoaXMgbWFrZXMgcGx1Z2lu QXBwbGljYXRpb24ncyBHV1QgUlBDIHNlcnZsZXQocykgYWNjZXNzaWJsZSBmcm9tIHRoZSBzYW1l IG9yaWdpbiAocHJvdG9jb2wsIGRvbWFpbiwgcG9ydCkuDQoNCmMpIE1vZGlmaWNhdGlvbiBvZiBw bHVnaW4gbGlmZWN5Y2xlIHN0ZXAgIzU6DQoNCiAgIEluc3RlYWQgb2YgZW1iZWRkaW5nIDxwbHVn aW5BcHBsaWNhdGlvbj4ubm9jYWNoZS5qcyBjb250ZW50IGludG8gV2ViQWRtaW4gSFRNTCBwYWdl LCBqdXN0IGVtYmVkIHRoZSBsaW5rIHRvIGl0LCBlLmcuIGh0dHAocyk6Ly8xMjcuMC4wLjE6PHBv cnQ+L3BhdGgvdG8vPHBsdWdpbkFwcGxpY2F0aW9uPi5ub2NhY2hlLmpzDQoNCmQpIE1vZGlmaWNh dGlvbiBvZiBwbHVnaW4gbGlmZWN5Y2xlIHN0ZXAgIzY6DQoNCiAgIER1cmluZyBXZWJBZG1pbiBz dGFydHVwLCBmb3IgZWFjaCBwbHVnaW4gdGhhdCBpcyBzdXBwb3NlZCB0byBiZSBsb2FkZWQgcmVt b3RlbHksIGNyZWF0ZSBhbiA8aWZyYW1lPiB0aGF0IHdpbGwgZmV0Y2ggdGhlIHBsdWdpbiBhc3lu Y2hyb25vdXNseS4NCg0KICAgVGhlIDxpZnJhbWU+IGlzIHJlcXVpcmVkIGluIG9yZGVyIGZvciA8 cGx1Z2luQXBwbGljYXRpb24+Lm5vY2FjaGUuanMgdG8gYXBwZWFyIGZyb20gZGlmZmVyZW50IChw bHVnaW5BcHBsaWNhdGlvbi1zcGVjaWZpYykgZG9tYWluIHRoYW4gV2ViQWRtaW4gSFRNTCBwYWdl Lg0KDQogICBUaGlzIHdheSwgZmV0Y2hpbmcgcGVybXV0YXRpb24gKDxoYXNoTmFtZT4uY2FjaGUu aHRtbCkgZmlsZXMsIHdoaWNoIGFyZSByZWxhdGl2ZSB0byA8cGx1Z2luQXBwbGljYXRpb24+Lm5v Y2FjaGUuanMsIHdpbGwgd29yayBvdXQtb2YtdGhlLWJveC4NCg0KDQpHZW9yZ2UsIHBsZWFzZSBs ZXQgbWUga25vdyB3aGF0IHlvdSB0aGluaywgYW5kIEkgd2lsbCB1cGRhdGUgVUkgUGx1Z2lucyB3 aWtpIGFjY29yZGluZ2x5Lg0KDQpWb2p0ZWNoDQoNCg0KWzFdIGh0dHA6Ly9lbi53aWtpcGVkaWEu b3JnL3dpa2kvU2FtZV9vcmlnaW5fcG9saWN5DQpbMl0gaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2ds ZS5jb20vd2ViLXRvb2xraXQvZG9jL2xhdGVzdC9EZXZHdWlkZUNvZGluZ0Jhc2ljc0pTTkkNClsz XSBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS93ZWItdG9vbGtpdC9kb2MvbGF0ZXN0L0Rl dkd1aWRlQ29kaW5nQmFzaWNzT3ZlcmxheQ0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fXw0KDQpGcm9tOiAiR2VvcmdlIENvc3RlYSIgPEdlb3JnZS5Db3N0ZWFAbmV0YXBwLmNvbTxt YWlsdG86R2VvcmdlLkNvc3RlYUBuZXRhcHAuY29tPj4NClRvOiAiVm9qdGVjaCBTem9jcyIgPHZz em9jc0ByZWRoYXQuY29tPG1haWx0bzp2c3pvY3NAcmVkaGF0LmNvbT4+LCBlbmdpbmUtZGV2ZWxA b3ZpcnQub3JnPG1haWx0bzplbmdpbmUtZGV2ZWxAb3ZpcnQub3JnPg0KQ2M6ICJEdXN0aW4gU2No b2VuYnJ1biIgPER1c3Rpbi5TY2hvZW5icnVuQG5ldGFwcC5jb208bWFpbHRvOkR1c3Rpbi5TY2hv ZW5icnVuQG5ldGFwcC5jb20+PiwgIlJpY2t5IEhvcHBlciIgPFJpY2t5LkhvcHBlckBuZXRhcHAu Y29tPG1haWx0bzpSaWNreS5Ib3BwZXJAbmV0YXBwLmNvbT4+LCAiSXRhbWFyIEhlaW0iIDxpaGVp bUByZWRoYXQuY29tPG1haWx0bzppaGVpbUByZWRoYXQuY29tPj4NClNlbnQ6IE1vbmRheSwgSnVu ZSAyNSwgMjAxMiA5OjExOjMzIFBNDQpTdWJqZWN0OiBSRTogb1ZpcnQgVUkgUGx1Z2lucyBmZWF0 dXJlOiBSZWFkeSBmb3IgcmV2aWV3DQoNClRoYW5rcyBWb2p0ZWNoLg0KDQpTaW5jZSB0aGUgcGx1 Z2lucyBhcmUgZW1iZWRkZWQgaW50byB0aGUgV2ViQWRtaW4gSFRNTCBwYWdlLCB0aGF0IHNlZW1z IHRvIHNpbXBsaWZ5IHRoaW5nczsgbm8gZXh0ZXJuYWwgd2ViIHNlcnZpY2UgaXMgbmVlZGVkLiAg VGhpcyBhcHByb2FjaCB0aWVzIGludG8gdGhlIGlzc3VlIG92ZXIgdGhlIGZyZWVkb20gdG8gZGVj aWRlIHdoaWNoIHRlY2hub2xvZ3kgdG8gdXNlIHdoZW4gZGV2ZWxvcGluZyBhIHBsdWdpbi4gIFdo aWxlIEkgYWdyZWUgdGhhdCBqUXVlcnkgaXMgYmVzdCBmb3Igc2ltcGxlIGRpYWxvZ3MsIGEgd2l6 YXJkLWRyaXZlbiB3b3JrZmxvdyBpcyBlYXNpZXIgdG8gZGV2ZWxvcCBpbiBHV1QuDQoNCkZvciBl eGFtcGxlLCBpZiBJIHdhbnQgdG8gc3RlcCBhIHVzZXIgdGhyb3VnaCB0aGUgcHJvY2VzcyBvZiBj cmVhdGluZyBhIG5ldyBzdG9yYWdlIGRvbWFpbiBJIHdvdWxkIGxpa2UgdG8gcHJvdmlkZSBhIHdv cmtmbG93IHRvIHNlbGVjdCBhIHN0b3JhZ2UgYXJyYXksIHByb3ZpZGUgY3JlZGVudGlhbHMsIGFu ZCBjb25maWd1cmUgdGhlIGRldGFpbHMgb2YgdGhlIE5GUyBleHBvcnQuICBUaGlzIHdvcmtmbG93 IGNvdWxkIHByZXN1bWFibHkgaGF2ZSBhIEdXVC1SUEMgbWVjaGFuaXNtIHRoYXQgcmVsaWVzIG9u IHNvbWUgYWRkaXRpb25hbCBsaWJyYXJpZXMgb24gdGhlIGJhY2tlbmQgKGxpYnJhcmllcyB0aGF0 IGFsbG93IG1lIHRvIGNvbW11bmljYXRlIHdpdGggdGhlIHN0b3JhZ2UgYXJyYXkpLiAgVXNpbmcg dGhlIEdXVC1FeHBvcnRlciwgSSBjb3VsZCBleHBvcnQgdGhlIGNsYXNzZXMgdGhhdCB3b3VsZCBk aXNwbGF5IHRoZSB3b3JrZmxvdyB3aGljaCB3b3VsZCB0aGVuIGdldCBsYXVuY2hlZCBhcyBteSBl eHRlbnNpb24gaXMgc2VsZWN0ZWQuICBZb3Ugc2FpZCB0aGF0IEkgd291bGQgaGF2ZSBteSBvVmly dCBVSSBwbHVnaW4gZGVwZW5kIG9uIG15IGNvbXBpbGVkICdwbHVnaW4gc3VwcG9ydCBhcHBsaWNh dGlvbicuICBNeSBjb21waWxlZCBwbHVnaW4gc3VwcG9ydCBhcHBsaWNhdGlvbiB3b3VsZCBub3Jt YWxseSBiZSBhIHdhciBmaWxlIGNvbnRhaW5pbmcgbXkgY29tcGlsZWQgR1dUIGNvZGUgYW5kIGEg d2ViLWluZiBmb2xkZXIgY29udGFpbmluZyBteSBsaWJyYXJpZXMuICBJcyB0aGUgcGx1Z2luIGRl cGVuZGluZyBvbiB0aGUgd2FyIGZpbGU/ICBJcyB0aGF0IHdoYXQgSSBzcGVjaWZ5Pw0KDQotR2Vv cmdlDQoNCi0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQpGcm9tOiBWb2p0ZWNoIFN6b2NzIFtt YWlsdG86dnN6b2NzQHJlZGhhdC5jb21dPG1haWx0bzpbbWFpbHRvOnZzem9jc0ByZWRoYXQuY29t XT4NClNlbnQ6IE1vbmRheSwgSnVuZSAyNSwgMjAxMiAxOjEyIFBNDQpUbzogQ29zdGVhLCBHZW9y Z2U7IGVuZ2luZS1kZXZlbEBvdmlydC5vcmc8bWFpbHRvOmVuZ2luZS1kZXZlbEBvdmlydC5vcmc+ DQpDYzogU2Nob2VuYnJ1biwgRHVzdGluOyBIb3BwZXIsIFJpY2t5OyBJdGFtYXIgSGVpbQ0KU3Vi amVjdDogUmU6IG9WaXJ0IFVJIFBsdWdpbnMgZmVhdHVyZTogUmVhZHkgZm9yIHJldmlldw0KDQpI aSBHZW9yZ2UsDQoNCnRoYW5rcyBmb3IgeW91ciBmZWVkYmFjay4gUGxlYXNlIGZpbmQgbXkgYW5z d2VycyBiZWxvdy4NCg0KMSkgQXJlIHRoZSBwbHVnaW5zIGhvc3RlZCBieSB0aGUgc2FtZSBqYm9z cyBzZXJ2ZXIgdGhhdCBob3N0cyB0aGUgZW5naW5lPyAgSXQgd291bGQgYXBwZWFyIHRoZSBhbnN3 ZXIgaXMgeWVzIGFuZCB0aGF0IG5vIHNlcGFyYXRlIGNvbnRhaW5lciBpcyByZXF1aXJlZCBmb3Ig dGhlIHBsdWdpbnMuDQoNCkluIHNob3J0LCB5ZXMuDQoNCg0KUGx1Z2lucywgYWxvbmcgd2l0aCB0 aGVpciBjb25maWd1cmF0aW9uIGFuZCAzcmQgcGFydHkgZGVwZW5kZW5jaWVzLCBhcmUgbWVhbnQg dG8gYmUgZW1iZWRkZWQgaW50byBmaW5hbCBXZWJBZG1pbiBIVE1MIHBhZ2UsIHNlZSBbaHR0cDov L3d3dy5vdmlydC5vcmcvd2lraS9GZWF0dXJlcy9VSVBsdWdpbnMjUGx1Z2luX2xpZmVjeWNsZV0g c3RlcCAjNS4NCkpCb3NzIEFTIGluc3RhbmNlIHNlcnZlcyBXZWJBZG1pbiBIVE1MIHBhZ2UgKFdl YmFkbWluRHluYW1pY0hvc3RpbmdTZXJ2bGV0KSwgYWxvbmcgd2l0aCBwcm92aWRpbmcgR1dUIFJQ QyBhbmQgUkVTVCBlbmRwb2ludHMgdGhhdCBkZWxlZ2F0ZSB0byBFbmdpbmUgYnVzaW5lc3MgbG9n aWMgdGhyb3VnaCBFSkIgQmFja2VuZExvY2FsIGludGVyZmFjZS4NCg0KSG93ZXZlciwgcGx1Z2lu cyBhcmUgbm90ICdob3N0ZWQnIGluIGEgdHlwaWNhbCBzZW5zZSAtIFdlYmFkbWluRHluYW1pY0hv c3RpbmdTZXJ2bGV0IHJlYWRzIGFuZCBlbWJlZHMgYWxsIHBsdWdpbiBkYXRhIGRpcmVjdGx5IGlu dG8gZmluYWwgV2ViQWRtaW4gSFRNTCBwYWdlLg0KDQoyKSBEb2VzIGVhY2ggcGx1Z2luIG1hcCB0 byBhIHVuaXF1ZSBleHRlbnNpb24gd2l0aGluIFdlYkFkbWluPyAgWW91ciBleGFtcGxlIHNob3dz IHRoYXQgSSBjYW4gZXh0ZW5kIHRoZSBWTSB0YWJsZSB0byBoYXZlIGEgIlNob3cgVk0gbmFtZSBh bmQgZWRpdCBWTSIgY29udGV4dC1zZW5zaXRpdmUgZXh0ZW5zaW9uLiAgVGhpcyBpcyBuYW1lZCBw bHVnaW5BcGkucGx1Z2lucy5teVBsdWdpbi4gIENhbiBJIHNhZmVseSBhc3N1bWUgdGhhdCB0aGlz IGlzIHBlciBleHRlbnNpb24/ICBJIHdvdWxkIGhhdmUgcGx1Z2luQXBpLnBsdWdpbnMubXlQbHVn aW4yIGZvciBleHRlbmRpbmcgYSBzdG9yYWdlIGRvbWFpbj8NCg0KRXh0ZW5zaW9uIHBvaW50cyBh cmUgcmVwcmVzZW50ZWQgYnkgYXBwbGljYXRpb24gZXZlbnRzLCB0cmlnZ2VyZWQgYnkgV2ViQWRt aW4gYW5kIGNvbnN1bWVkIGJ5IHBsdWdpbnMuIEZvciBleGFtcGxlLCAndGFibGVDb250ZXh0TWVu dScgZXZlbnQgZ2V0cyB0cmlnZ2VyZWQgd2hlbiBhIHRhYmxlIGNvbnRleHQgbWVudSBpcyBhYm91 dCB0byBiZSBzaG93biB0byB0aGUgdXNlciwgd2hpY2ggZ2l2ZXMgcGx1Z2lucyB0aGUgYWJpbGl0 eSB0byBkbyBzb21ldGhpbmcgY3VzdG9tIHdpdGggdGhlIGNvbnRleHQgbWVudSBiZWZvcmUgaXQn cyBzaG93bi4NCg0KDQpUaGVyZSBjYW4gYmUgbXVsdGlwbGUgcGx1Z2lucyBoYW5kbGluZyB0aGUg c2FtZSBldmVudCAoZXh0ZW5zaW9uIHBvaW50KS4gWW91IGNhbiBoYXZlIHR3byBwbHVnaW5zLCBz YXkgJ3BsdWdpbkFwaS5wbHVnaW5zLk9uZScgYW5kICdwbHVnaW5BcGkucGx1Z2lucy5Ud28nLCBl YWNoIHByb3ZpZGluZyAndGFibGVDb250ZXh0TWVudScgZnVuY3Rpb24gZm9yIGhhbmRsaW5nIHRo ZSBhYm92ZSBtZW50aW9uZWQgZXZlbnQuIFdlYkFkbWluIHdpbGwgaW52b2tlIGFsbCBwbHVnaW5z IGZvciB0aGUgZ2l2ZW4gZXZlbnQuDQoNClRvIGFuc3dlciB5b3VyIHF1ZXN0aW9uLCBpbiBvcmRl ciB0byBoYW5kbGUgWCBldmVudHMgKGV4dGVuc2lvbiBwb2ludHMpLCB5b3UgZG9uJ3QgbmVlZCB0 byB3cml0ZSBYIHBsdWdpbnMuIFlvdSBjYW4gd3JpdGUgb25lIHBsdWdpbiB0aGF0IGhhbmRsZXMg WCBldmVudHMuDQoNCjMpIEluc3RlYWQgb2YgbGF1bmNoaW5nIGEgalF1ZXJ5IGRpYWxvZywgY2Fu IEkgcG9pbnQgdG8gYSBjb21waWxlZCBHV1QgaHRtbCBmaWxlIHRvIGRpc3BsYXkgYSBkaWFsb2cg dGhhdCBmaXRzIG15IG5lZWRzPw0KDQpZb3UgY2FuIGRvIGFueXRoaW5nIHlvdSB3YW50IGluIHlv dXIgcGx1Z2luIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb24uIFNob3cgYSBqUXVlcnkgVUkgZGlhbG9n LCBtYWtlIG9WaXJ0IFJFU1QgQVBJIHJlcXVlc3QsIGNhbGwgYXJiaXRyYXJ5IHJlbW90ZSBzZXJ2 ZXIgdXNpbmcgY3Jvc3MtZG9tYWluIHRlY2huaXF1ZSBsaWtlIEpTT05QIFsxXSBvciBDT1JTIFsy XSwgZXRjLiBQbHVnaW4gYXV0aG9ycyBhcmUgZnJlZSB0byBkZWNpZGUgaWYgdGhleSB3YW50IHRv IHJlbHkgb24gM3JkIHBhcnR5IEphdmFTY3JpcHQgbGlicmFyaWVzLCBvciBpZiB0aGV5IHdhbnQg dG8gd3JpdGUgZW50aXJlIHBsdWdpbiBjb2RlIGJ5IHRoZW1zZWx2ZXMuDQoNCg0KSW4gbXkgb3Bp bmlvbiwgdG9vbHMgbGlrZSBqUXVlcnkgYXJlIGZhciBtb3JlIGVsZWdhbnQgZm9yIGhhbmRsaW5n IHNpbXBsZSB0aGluZ3Mgc3VjaCBhcyBVSSBkaWFsb2dzLiBCdXQgaWYgeW91IHJlYWxseSB3YW50 IHRvIHVzZSBHV1QgZm9yIHRoaXMgcHVycG9zZSwgSSBzdWdnZXN0IGZvbGxvd2luZyBhcHByb2Fj aDoNCg0KYSwgZGV2ZWxvcCBhICdwbHVnaW4gc3VwcG9ydCBhcHBsaWNhdGlvbicgaW4gR1dULCB3 aGljaCBpbXBsZW1lbnRzIHRoZSBuZWNlc3NhcnkgZGlhbG9nIGZ1bmN0aW9uYWxpdHkgYiwgZXhw b3J0IGl0cyBtYWluIChlLmcuIGRpYWxvZyBoYW5kbGluZykgY2xhc3NlcyBmb3IgdXNlIGluIG5h dGl2ZSBKYXZhU2NyaXB0IHRocm91Z2ggZ3d0LWV4cG9ydGVyIFszXSBjLCBoYXZlIHlvdXIgb1Zp cnQgVUkgcGx1Z2luIGRlcGVuZCBvbiB5b3VyIGNvbXBpbGVkICdwbHVnaW4gc3VwcG9ydCBhcHBs aWNhdGlvbicgKHRoaXMgd2lsbCBjYXVzZSB5b3VyICdwbHVnaW4gc3VwcG9ydCBhcHBsaWNhdGlv bicgdG8gYmUgY2FsbGVkIGR1cmluZyBXZWJBZG1pbiBzdGFydHVwKSBkLCBpbiB5b3VyIG9WaXJ0 IFVJIHBsdWdpbiwgaW52b2tlICdwbHVnaW4gc3VwcG9ydCBhcHBsaWNhdGlvbicgZnVuY3Rpb25h bGl0eSB0aHJvdWdoIGV4cG9ydGVkIGNsYXNzZXMgKHBsdWdpbiAtPiBHV1QgZGVsZWdhdGUgcGF0 dGVybikNCg0KNCkgSXMgc2Vzc2lvbiBpbmZvIHBhc3NlZCBpbnRvIHRoZSBwbHVnaW4gc28gdGhh dCBJIGNhbiBpbnZva2UgQVBJcyBpbnRvIHRoZSBlbmdpbmU/ICBUbyBwb3dlciBvbiBhIFZNIGZv ciBpbnN0YW5jZT8gIE9yIHRvIG1vdW50IGEgbmV3IE5GUyBzdG9yYWdlIGRvbWFpbj8NCg0KWWVz LCB0aGlzIHNob3VsZCBiZSBwYXJ0IG9mIFtodHRwOi8vd3d3Lm92aXJ0Lm9yZy93aWtpL0ZlYXR1 cmVzL1VJUGx1Z2lucyNHbG9iYWxfQVBJX2Z1bmN0aW9uc10gIlBsdWdpbiB1dGlsaXR5IGZ1bmN0 aW9ucyIgKGdsb2JhbCBBUEkpLg0KDQoNCllvdXIgcGx1Z2luIG1pZ2h0IGFjY2VzcyB1c2VyIHNl c3Npb24gaW5mb3JtYXRpb24gaW4gdGhlIGZvbGxvd2luZyB3YXk6IHBsdWdpbkFwaS51dGlsKCku dXNlckluZm8oKS4qIChyZXBsYWNlICogd2l0aCBpZCgpLCBuYW1lKCksIGRvbWFpbigpLCBldGMu KQ0KDQpBcyB5b3UgcG9pbnRlZCBvdXQsIHRoaXMgY291bGQgYmUgdXNlZCB0byBhdXRoZW50aWNh dGUgb1ZpcnQgUkVTVCBBUEkgcmVxdWVzdHMgbWFkZSBmcm9tIHlvdXIgcGx1Z2luIGNvZGUuDQoN CkJUVywgdGhlIGxpbmsgdG8gdGhlIG9yaWdpbmFsIGRlc2lnbiBub3RlcyBvbiB0aGUgd2lraSBk b2Vzbid0IHdvcmsuDQoNClRoaXMgaXMgc3RyYW5nZSwgW2h0dHA6Ly9yaGV2bWYucGFkLmVuZ2lu ZWVyaW5nLnJlZGhhdC5jb20vNjhdIGhhcyBpdHMgdmlzaWJpbGl0eSBzZXQgdG8gIlB1YmxpYyAo QWxsb3cgSW50ZXJuZXQgZ3Vlc3RzKSIgLi4uIERvZXMgYW55Ym9keSBrbm93IHdoeSB0aGlzIGRv ZXNuJ3Qgd29yaz8NCg0KDQoNClZvanRlY2gNCg0KDQpbMV0gaHR0cDovL2VuLndpa2lwZWRpYS5v cmcvd2lraS9KU09OUA0KWzJdIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3Mtb3Jp Z2luX3Jlc291cmNlX3NoYXJpbmcNClszXSBodHRwOi8vY29kZS5nb29nbGUuY29tL3AvZ3d0LWV4 cG9ydGVyLw0KDQoNCi0tLS0tIE9yaWdpbmFsIE1lc3NhZ2UgLS0tLS0NCkZyb206ICJHZW9yZ2Ug Q29zdGVhIiA8R2VvcmdlLkNvc3RlYUBuZXRhcHAuY29tPG1haWx0bzpHZW9yZ2UuQ29zdGVhQG5l dGFwcC5jb20+Pg0KVG86ICJWb2p0ZWNoIFN6b2NzIiA8dnN6b2NzQHJlZGhhdC5jb208bWFpbHRv OnZzem9jc0ByZWRoYXQuY29tPj4sIGVuZ2luZS1kZXZlbEBvdmlydC5vcmc8bWFpbHRvOmVuZ2lu ZS1kZXZlbEBvdmlydC5vcmc+DQpDYzogIkR1c3RpbiBTY2hvZW5icnVuIiA8RHVzdGluLlNjaG9l bmJydW5AbmV0YXBwLmNvbTxtYWlsdG86RHVzdGluLlNjaG9lbmJydW5AbmV0YXBwLmNvbT4+LCAi Umlja3kgSG9wcGVyIiA8Umlja3kuSG9wcGVyQG5ldGFwcC5jb208bWFpbHRvOlJpY2t5LkhvcHBl ckBuZXRhcHAuY29tPj4NClNlbnQ6IE1vbmRheSwgSnVuZSAyNSwgMjAxMiAzOjA5OjQzIFBNDQpT dWJqZWN0OiBSRTogb1ZpcnQgVUkgUGx1Z2lucyBmZWF0dXJlOiBSZWFkeSBmb3IgcmV2aWV3DQoN CkhpIFZvanRlY2gsDQoNCkkgaGF2ZSBhIGZldyBxdWVzdGlvbnMgb24gdGhpcyBmZWF0dXJlLg0K DQoxKSBBcmUgdGhlIHBsdWdpbnMgaG9zdGVkIGJ5IHRoZSBzYW1lIGpib3NzIHNlcnZlciB0aGF0 IGhvc3RzIHRoZSBlbmdpbmU/ICBJdCB3b3VsZCBhcHBlYXIgdGhlIGFuc3dlciBpcyB5ZXMgYW5k IHRoYXQgbm8gc2VwYXJhdGUgY29udGFpbmVyIGlzIHJlcXVpcmVkIGZvciB0aGUgcGx1Z2lucy4N CjIpIERvZXMgZWFjaCBwbHVnaW4gbWFwIHRvIGEgdW5pcXVlIGV4dGVuc2lvbiB3aXRoaW4gV2Vi QWRtaW4/ICBZb3VyIGV4YW1wbGUgc2hvd3MgdGhhdCBJIGNhbiBleHRlbmQgdGhlIFZNIHRhYmxl IHRvIGhhdmUgYSAiU2hvdyBWTSBuYW1lIGFuZCBlZGl0IFZNIiBjb250ZXh0LXNlbnNpdGl2ZSBl eHRlbnNpb24uICBUaGlzIGlzIG5hbWVkIHBsdWdpbkFwaS5wbHVnaW5zLm15UGx1Z2luLiAgQ2Fu IEkgc2FmZWx5IGFzc3VtZSB0aGF0IHRoaXMgaXMgcGVyIGV4dGVuc2lvbj8gIEkgd291bGQgaGF2 ZSBwbHVnaW5BcGkucGx1Z2lucy5teVBsdWdpbjIgZm9yIGV4dGVuZGluZyBhIHN0b3JhZ2UgZG9t YWluPw0KMykgSW5zdGVhZCBvZiBsYXVuY2hpbmcgYSBqUXVlcnkgZGlhbG9nLCBjYW4gSSBwb2lu dCB0byBhIGNvbXBpbGVkIEdXVCBodG1sIGZpbGUgdG8gZGlzcGxheSBhIGRpYWxvZyB0aGF0IGZp dHMgbXkgbmVlZHM/DQo0KSBJcyBzZXNzaW9uIGluZm8gcGFzc2VkIGludG8gdGhlIHBsdWdpbiBz byB0aGF0IEkgY2FuIGludm9rZSBBUElzIGludG8gdGhlIGVuZ2luZT8gIFRvIHBvd2VyIG9uIGEg Vk0gZm9yIGluc3RhbmNlPyAgT3IgdG8gbW91bnQgYSBuZXcgTkZTIHN0b3JhZ2UgZG9tYWluPw0K DQpCVFcsIHRoZSBsaW5rIHRvIHRoZSBvcmlnaW5hbCBkZXNpZ24gbm90ZXMgb24gdGhlIHdpa2kg ZG9lc24ndCB3b3JrLg0KDQpUaGFua3MsDQpHZW9yZ2UNCg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdl LS0tLS0NCkZyb206IFZvanRlY2ggU3pvY3MgW21haWx0bzp2c3pvY3NAcmVkaGF0LmNvbV08bWFp bHRvOlttYWlsdG86dnN6b2NzQHJlZGhhdC5jb21dPg0KU2VudDogVGh1cnNkYXksIEp1bmUgMjEs IDIwMTIgMTE6MDMgQU0NClRvOiBlbmdpbmUtZGV2ZWxAb3ZpcnQub3JnPG1haWx0bzplbmdpbmUt ZGV2ZWxAb3ZpcnQub3JnPg0KQ2M6IFNjaG9lbmJydW4sIER1c3RpbjsgQ29zdGVhLCBHZW9yZ2U7 IEhvcHBlciwgUmlja3kNClN1YmplY3Q6IG9WaXJ0IFVJIFBsdWdpbnMgZmVhdHVyZTogUmVhZHkg Zm9yIHJldmlldw0KDQpIaSBndXlzLA0KDQpJIHdyb3RlIGEgd2lraSBwYWdlIGRlc2NyaWJpbmcg VUkgUGx1Z2lucywgYSBmZWF0dXJlIHBsYW5uZWQgZm9yIG9WaXJ0IHdlYiBhZG1pbmlzdHJhdGlv biAoV2ViQWRtaW4pIGFwcGxpY2F0aW9uOg0KaHR0cDovL3d3dy5vdmlydC5vcmcvd2lraS9GZWF0 dXJlcy9VSVBsdWdpbnMNCg0KRmVhdHVyZSBkZXNpZ24gaXMgZmluaXNoZWQgYW5kIHJlYWR5IGZv ciByZXZpZXcuIFBsZWFzZSBmZWVsIGZyZWUgdG8gYWRkIGNvbW1lbnRzLCBhc2sgcXVlc3Rpb25z IG9yIHJlYWNoIG1lIGRpcmVjdGx5IG9uICNvdmlydCBjaGFubmVsLg0KDQpDaGVlcnMsDQpWb2p0 ZWNoDQo= --_000_6C8AC8C50E170C4E9B44D47B39B24A48012080BASACEXCMBX04PRDh_ Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: base64 PGh0bWwgeG1sbnM6dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIHhtbG5zOm89InVy bjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgeG1sbnM6dz0idXJuOnNjaGVt YXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCIgeG1sbnM6bT0iaHR0cDovL3NjaGVtYXMubWlj cm9zb2Z0LmNvbS9vZmZpY2UvMjAwNC8xMi9vbW1sIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv VFIvUkVDLWh0bWw0MCI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIg Y29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjxtZXRhIG5hbWU9IkdlbmVyYXRv ciIgY29udGVudD0iTWljcm9zb2Z0IFdvcmQgMTQgKGZpbHRlcmVkIG1lZGl1bSkiPg0KPCEtLVtp ZiAhbXNvXT48c3R5bGU+dlw6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kb1w6KiB7 YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kd1w6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0 I1ZNTCk7fQ0KLnNoYXBlIHtiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKTt9DQo8L3N0eWxlPjwh W2VuZGlmXS0tPjxzdHlsZT48IS0tDQovKiBGb250IERlZmluaXRpb25zICovDQpAZm9udC1mYWNl DQoJe2ZvbnQtZmFtaWx5OkNhbGlicmk7DQoJcGFub3NlLTE6MiAxNSA1IDIgMiAyIDQgMyAyIDQ7 fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWlseTpUYWhvbWE7DQoJcGFub3NlLTE6MiAxMSA2IDQg MyA1IDQgNCAyIDQ7fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWlseToiTHVjaWRhIENvbnNvbGUi Ow0KCXBhbm9zZS0xOjIgMTEgNiA5IDQgNSA0IDIgMiA0O30NCi8qIFN0eWxlIERlZmluaXRpb25z ICovDQpwLk1zb05vcm1hbCwgbGkuTXNvTm9ybWFsLCBkaXYuTXNvTm9ybWFsDQoJe21hcmdpbjow aW47DQoJbWFyZ2luLWJvdHRvbTouMDAwMXB0Ow0KCWZvbnQtc2l6ZToxMi4wcHQ7DQoJZm9udC1m YW1pbHk6IlRpbWVzIE5ldyBSb21hbiIsInNlcmlmIjt9DQphOmxpbmssIHNwYW4uTXNvSHlwZXJs aW5rDQoJe21zby1zdHlsZS1wcmlvcml0eTo5OTsNCgljb2xvcjpibHVlOw0KCXRleHQtZGVjb3Jh dGlvbjp1bmRlcmxpbmU7fQ0KYTp2aXNpdGVkLCBzcGFuLk1zb0h5cGVybGlua0ZvbGxvd2VkDQoJ e21zby1zdHlsZS1wcmlvcml0eTo5OTsNCgljb2xvcjpwdXJwbGU7DQoJdGV4dC1kZWNvcmF0aW9u OnVuZGVybGluZTt9DQpwDQoJe21zby1zdHlsZS1wcmlvcml0eTo5OTsNCgltYXJnaW46MGluOw0K CW1hcmdpbi1ib3R0b206LjAwMDFwdDsNCglmb250LXNpemU6MTIuMHB0Ow0KCWZvbnQtZmFtaWx5 OiJUaW1lcyBOZXcgUm9tYW4iLCJzZXJpZiI7fQ0KcC5Nc29BY2V0YXRlLCBsaS5Nc29BY2V0YXRl LCBkaXYuTXNvQWNldGF0ZQ0KCXttc28tc3R5bGUtcHJpb3JpdHk6OTk7DQoJbXNvLXN0eWxlLWxp bms6IkJhbGxvb24gVGV4dCBDaGFyIjsNCgltYXJnaW46MGluOw0KCW1hcmdpbi1ib3R0b206LjAw MDFwdDsNCglmb250LXNpemU6OC4wcHQ7DQoJZm9udC1mYW1pbHk6IlRhaG9tYSIsInNhbnMtc2Vy aWYiO30NCnNwYW4uRW1haWxTdHlsZTE5DQoJe21zby1zdHlsZS10eXBlOnBlcnNvbmFsLXJlcGx5 Ow0KCWZvbnQtZmFtaWx5OiJDYWxpYnJpIiwic2Fucy1zZXJpZiI7DQoJY29sb3I6IzFGNDk3RDt9 DQpzcGFuLkJhbGxvb25UZXh0Q2hhcg0KCXttc28tc3R5bGUtbmFtZToiQmFsbG9vbiBUZXh0IENo YXIiOw0KCW1zby1zdHlsZS1wcmlvcml0eTo5OTsNCgltc28tc3R5bGUtbGluazoiQmFsbG9vbiBU ZXh0IjsNCglmb250LWZhbWlseToiVGFob21hIiwic2Fucy1zZXJpZiI7fQ0KLk1zb0NocERlZmF1 bHQNCgl7bXNvLXN0eWxlLXR5cGU6ZXhwb3J0LW9ubHk7DQoJZm9udC1zaXplOjEwLjBwdDt9DQpA cGFnZSBXb3JkU2VjdGlvbjENCgl7c2l6ZTo4LjVpbiAxMS4waW47DQoJbWFyZ2luOjEuMGluIDEu MGluIDEuMGluIDEuMGluO30NCmRpdi5Xb3JkU2VjdGlvbjENCgl7cGFnZTpXb3JkU2VjdGlvbjE7 fQ0KLyogTGlzdCBEZWZpbml0aW9ucyAqLw0KQGxpc3QgbDANCgl7bXNvLWxpc3QtaWQ6MjA1MDQ5 MTY3NTsNCgltc28tbGlzdC10ZW1wbGF0ZS1pZHM6MjczMTU3MTQyO30NCm9sDQoJe21hcmdpbi1i b3R0b206MGluO30NCnVsDQoJe21hcmdpbi1ib3R0b206MGluO30NCi0tPjwvc3R5bGU+PCEtLVtp ZiBndGUgbXNvIDldPjx4bWw+DQo8bzpzaGFwZWRlZmF1bHRzIHY6ZXh0PSJlZGl0IiBzcGlkbWF4 PSIxMDI2IiAvPg0KPC94bWw+PCFbZW5kaWZdLS0+PCEtLVtpZiBndGUgbXNvIDldPjx4bWw+DQo8 bzpzaGFwZWxheW91dCB2OmV4dD0iZWRpdCI+DQo8bzppZG1hcCB2OmV4dD0iZWRpdCIgZGF0YT0i MSIgLz4NCjwvbzpzaGFwZWxheW91dD48L3htbD48IVtlbmRpZl0tLT4NCjwvaGVhZD4NCjxib2R5 IGxhbmc9IkVOLVVTIiBsaW5rPSJibHVlIiB2bGluaz0icHVycGxlIj4NCjxkaXYgY2xhc3M9Ildv cmRTZWN0aW9uMSI+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iZm9udC1zaXpl OjExLjBwdDtmb250LWZhbWlseTomcXVvdDtDYWxpYnJpJnF1b3Q7LCZxdW90O3NhbnMtc2VyaWYm cXVvdDs7Y29sb3I6IzFGNDk3RCI+VGhpcyBzb3VuZHMgZ3JlYXQuJm5ic3A7IFRoYW5rcyBWb2p0 ZWNoLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxhIG5hbWU9 Il9NYWlsRW5kQ29tcG9zZSI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMS4wcHQ7Zm9udC1mYW1p bHk6JnF1b3Q7Q2FsaWJyaSZxdW90OywmcXVvdDtzYW5zLXNlcmlmJnF1b3Q7O2NvbG9yOiMxRjQ5 N0QiPjxvOnA+Jm5ic3A7PC9vOnA+PC9zcGFuPjwvYT48L3A+DQo8ZGl2Pg0KPGRpdiBzdHlsZT0i Ym9yZGVyOm5vbmU7Ym9yZGVyLXRvcDpzb2xpZCAjQjVDNERGIDEuMHB0O3BhZGRpbmc6My4wcHQg MGluIDBpbiAwaW4iPg0KPHAgY2xhc3M9Ik1zb05vcm1hbCI+PGI+PHNwYW4gc3R5bGU9ImZvbnQt c2l6ZToxMC4wcHQ7Zm9udC1mYW1pbHk6JnF1b3Q7VGFob21hJnF1b3Q7LCZxdW90O3NhbnMtc2Vy aWYmcXVvdDsiPkZyb206PC9zcGFuPjwvYj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEwLjBwdDtm b250LWZhbWlseTomcXVvdDtUYWhvbWEmcXVvdDssJnF1b3Q7c2Fucy1zZXJpZiZxdW90OyI+IFZv anRlY2ggU3pvY3MgW21haWx0bzp2c3pvY3NAcmVkaGF0LmNvbV0NCjxicj4NCjxiPlNlbnQ6PC9i PiBUdWVzZGF5LCBKdW5lIDI2LCAyMDEyIDEwOjQ0IEFNPGJyPg0KPGI+VG86PC9iPiBlbmdpbmUt ZGV2ZWxAb3ZpcnQub3JnPGJyPg0KPGI+Q2M6PC9iPiBDb3N0ZWEsIEdlb3JnZTsgU2Nob2VuYnJ1 biwgRHVzdGluOyBIb3BwZXIsIFJpY2t5OyBJdGFtYXIgSGVpbTxicj4NCjxiPlN1YmplY3Q6PC9i PiBSZTogb1ZpcnQgVUkgUGx1Z2lucyBmZWF0dXJlOiBSZWFkeSBmb3IgcmV2aWV3PG86cD48L286 cD48L3NwYW4+PC9wPg0KPC9kaXY+DQo8L2Rpdj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxvOnA+ Jm5ic3A7PC9vOnA+PC9wPg0KPGRpdj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0eWxl PSJmb250LXNpemU6MTMuNXB0O2NvbG9yOmJsYWNrIj5IaSBHZW9yZ2UsPGJyPg0KPGJyPg0KSSd2 ZSBiZWVuIHRoaW5raW5nIGFib3V0IGRldmVsb3BpbmcgcGx1Z2lucyB3aXRoIEdXVC4gVGhlcmUg YXJlIHNvbWUgaW1wb3J0YW50IGlzc3VlcyB0aGF0IG5lZWQgdG8gYmUgYWRkcmVzc2VkOjwvc3Bh bj48c3BhbiBzdHlsZT0iY29sb3I6YmxhY2siPjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjxvbCBz dGFydD0iMSIgdHlwZT0iMSI+DQo8bGkgY2xhc3M9Ik1zb05vcm1hbCIgc3R5bGU9ImNvbG9yOmJs YWNrO21zby1tYXJnaW4tdG9wLWFsdDphdXRvO21hcmdpbi1ib3R0b206MTIuMHB0O21zby1saXN0 OmwwIGxldmVsMSBsZm8xIj4NCjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTMuNXB0Ij5HV1QgYm9v dHN0cmFwIHNlcXVlbmNlIHJlcXVpcmVzIDxlbT5wZXJtdXRhdGlvbiBzZWxlY3RvciBzY3JpcHQ8 L2VtPiAoPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtMdWNpZGEgQ29uc29s ZSZxdW90OyI+Jmx0O3BsdWdpbkFwcGxpY2F0aW9uJmd0Oy5ub2NhY2hlLmpzPC9zcGFuPjxzcGFu IHN0eWxlPSJmb250LXNpemU6MTMuNXB0Ij4pIHRvIGJlIGludm9rZWQgZmlyc3QuPGJyPg0KU2Vs ZWN0b3Igc2NyaXB0IGRldGVybWluZXMgdGhlIGNvcnJlY3QgcGVybXV0YXRpb24gKDwvc3Bhbj48 c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7THVjaWRhIENvbnNvbGUmcXVvdDsiPiZsdDto YXNoTmFtZSZndDsuY2FjaGUuaHRtbDwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVw dCI+KSBhbmQgZmV0Y2hlcyBpdCBhc3luY2hyb25vdXNseSBmcm9tIHRoZSBzYW1lIGxvY2F0aW9u Ljwvc3Bhbj48bzpwPjwvbzpwPjwvbGk+PGxpIGNsYXNzPSJNc29Ob3JtYWwiIHN0eWxlPSJjb2xv cjpibGFjazttc28tbWFyZ2luLXRvcC1hbHQ6YXV0bzttYXJnaW4tYm90dG9tOjEyLjBwdDttc28t bGlzdDpsMCBsZXZlbDEgbGZvMSI+DQo8c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdCI+R1dU IGJvb3RzdHJhcCBzZXF1ZW5jZSBpcyBhc3luY2hyb25vdXMgaW4gbmF0dXJlLjwvc3Bhbj48bzpw PjwvbzpwPjwvbGk+PGxpIGNsYXNzPSJNc29Ob3JtYWwiIHN0eWxlPSJjb2xvcjpibGFjazttc28t bWFyZ2luLXRvcC1hbHQ6YXV0bzttc28tbWFyZ2luLWJvdHRvbS1hbHQ6YXV0bzttc28tbGlzdDps MCBsZXZlbDEgbGZvMSI+DQo8c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdCI+R1dUIFJQQyAo PC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtMdWNpZGEgQ29uc29sZSZxdW90 OyI+WE1MSHR0cFJlcXVlc3Q8L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMy41cHQiPikg aXMgc3ViamVjdCB0byBTYW1lIE9yaWdpbiBQb2xpY3kgWzFdLjxicj4NClRoaXMgbWVhbnMgdGhh dCA8aT5wbHVnaW5BcHBsaWNhdGlvbjwvaT4ncyBzZXJ2ZXItc2lkZSBjb2RlIHNob3VsZCBiZSBk ZXBsb3llZCBvbiBvVmlydCBKQm9zcyBBUyBpbnN0YW5jZSAobmV4dCB0bw0KPC9zcGFuPjxzcGFu IHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtMdWNpZGEgQ29uc29sZSZxdW90OyI+ZW5naW5lLmVh cjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdCI+KS48L3NwYW4+PG86cD48L286 cD48L2xpPjwvb2w+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIiBzdHlsZT0ibWFyZ2luLWJvdHRvbTox Mi4wcHQiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTMuNXB0O2NvbG9yOmJsYWNrIj48YnI+DQpH aXZlbiB0aGVzZSBsaW1pdGF0aW9ucywgSSdkIHNheSB0aGUgcHJvY2VzcyBjb3VsZCBiZSBsaWtl IHRoaXM6PGJyPg0KPGJyPg0KYSkgSW4gPGk+cGx1Z2luQXBwbGljYXRpb248L2k+J3MgPC9zcGFu PjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtMdWNpZGEgQ29uc29sZSZxdW90Oztjb2xv cjpibGFjayI+RW50cnlQb2ludDwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdDtj b2xvcjpibGFjayI+LCB1c2UgR1dUIEpTTkkgWzJdIHRvIHJlZ2lzdGVyIHRoZSBwbHVnaW4gdXNp bmcgbmF0aXZlIEphdmFTY3JpcHQgY29kZS48YnI+DQo8YnI+DQombmJzcDsmbmJzcDsgWW91IGRv bid0IG5lZWQgdG8gdXNlIDxpPmd3dC1leHBvcnRlcjwvaT4gaGVyZSwgc2luY2UgcGx1Z2luIHJl Z2lzdHJhdGlvbiBhbmQgbG9naWMgaXMgY29tYmluZWQgaW4gb25lIHBsYWNlLjxicj4NCiZuYnNw OyZuYnNwOyBVc2luZyBwbHVnaW4tdG8tR1dUIGRlbGVnYXRlIHBhdHRlcm4gd2l0aCA8aT5nd3Qt ZXhwb3J0ZXI8L2k+IGlzIGFjdHVhbGx5IG1vcmUgY29tcGxpY2F0ZWQgdGhhbiBnb2luZyB3aXRo IHBsYWluIEpTTkkuPGJyPg0KPGJyPg0KJm5ic3A7Jm5ic3A7IEZvciBleGFtcGxlOjxicj4NCjxi cj4NCjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7THVjaWRhIENvbnNvbGUm cXVvdDs7Y29sb3I6YmxhY2siPiZuYnNwOyZuYnNwOyBwYWNrYWdlIGNvbS5teXBsdWdpbjs8YnI+ DQo8YnI+DQombmJzcDsmbmJzcDsgcHVibGljIGNsYXNzIE15UGx1Z2luQXBwIGltcGxlbWVudHMg Y29tLmdvb2dsZS5nd3QuY29yZS5jbGllbnQuRW50cnlQb2ludCB7PGJyPg0KPGJyPg0KJm5ic3A7 Jm5ic3A7ICZuYnNwOyAmbmJzcDtwdWJsaWMgdm9pZCB2b2lkIG9uTW9kdWxlTG9hZCgpIHs8YnI+ DQombmJzcDsmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgLy8gSW5pdGlhbGl6ZSBwbHVnaW4g YXBwbGljYXRpb24sIGNhbGwgcmVnaXN0ZXJQbHVnaW4oKSB3aGVuIHJlYWR5PGJyPg0KJm5ic3A7 Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IHJlZ2lzdGVyUGx1Z2luKCk7PGJyPg0KJm5ic3A7 Jm5ic3A7ICZuYnNwOyAmbmJzcDt9PGJyPg0KPGJyPg0KJm5ic3A7Jm5ic3A7ICZuYnNwOyAmbmJz cDtwdWJsaWMgc3RhdGljIHZvaWQgdGFibGVDb250ZXh0TWVudShjb20uZ29vZ2xlLmd3dC5jb3Jl LmNsaWVudC5KYXZhU2NyaXB0T2JqZWN0IGV2ZW50Q29udGV4dCkgezxicj4NCiZuYnNwOyZuYnNw OyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAvLyBDb25zaWRlciB1c2luZyBHV1Qgb3ZlcmxheSB0eXBl cyBbM10gdG8gZWFzaWx5IHdvcmsgd2l0aCBKYXZhU2NyaXB0T2JqZWN0czxicj4NCiZuYnNwOyZu YnNwOyAmbmJzcDsgJm5ic3A7fTxicj4NCjxicj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7 cHJpdmF0ZSBzdGF0aWMgbmF0aXZlIHZvaWQgcmVnaXN0ZXJQbHVnaW4oKSAvKi17PGJyPg0KJm5i c3A7Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IC8vIFJlZ2lzdGVyICdteVBsdWdpbicgaW50 byBwbHVnaW5BcGkucGx1Z2lucyBvYmplY3Q8YnI+DQombmJzcDsmbmJzcDsgJm5ic3A7ICZuYnNw OyAmbmJzcDsgJHduZC5wbHVnaW5BcGkucGx1Z2lucy5teVBsdWdpbiA9IG15UGx1Z2luID0gezxi cj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7dGFibGVD b250ZXh0TWVudTogZnVuY3Rpb24oZXZlbnRDb250ZXh0KSB7PGJyPg0KJm5ic3A7Jm5ic3A7ICZu YnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IC8vIENhbGwgSmF2YSBzdGF0 aWMgbWV0aG9kIHRvIGhhbmRsZSB0aGlzIGV2ZW50PGJyPg0KJm5ic3A7Jm5ic3A7ICZuYnNwOyAm bmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IEBjb20ubXlwbHVnaW4uTXlQbHVnaW5B cHA6OnRhYmxlQ29udGV4dE1lbnUoTGNvbS9nb29nbGUvZ3d0L2NvcmUvY2xpZW50L0phdmFTY3Jp cHRPYmplY3Q7KShldmVudENvbnRleHQpOzxicj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7 ICZuYnNwOyAmbmJzcDsgJm5ic3A7fTxicj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZu YnNwOyB9Ozxicj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAvLyBDYWxsIHRo ZSByZWFkeSgpIGZ1bmN0aW9uIHJpZ2h0IGF3YXk8YnI+DQombmJzcDsmbmJzcDsgJm5ic3A7ICZu YnNwOyAmbmJzcDsgJHduZC5wbHVnaW5BcGkubGlmZWN5Y2xlKG15UGx1Z2luKS5yZWFkeSgpOzxi cj4NCiZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7fS0qLzs8YnI+DQo8YnI+DQombmJzcDsmbmJz cDsgfTwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdDtjb2xvcjpibGFjayI+PGJy Pg0KPGJyPg0KYikgRGVwbG95IHRoZSA8L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiZx dW90O0x1Y2lkYSBDb25zb2xlJnF1b3Q7O2NvbG9yOmJsYWNrIj4mbHQ7cGx1Z2luQXBwbGljYXRp b24mZ3Q7Lndhcjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVwdDtjb2xvcjpibGFj ayI+IGZpbGUgb24gSkJvc3MgQVMgaW5zdGFuY2UsIGUuZy4NCjwvc3Bhbj48c3BhbiBzdHlsZT0i Zm9udC1mYW1pbHk6JnF1b3Q7THVjaWRhIENvbnNvbGUmcXVvdDs7Y29sb3I6YmxhY2siPiZsdDtK Qk9TU19IT01FJmd0Oy9zdGFuZGFsb25lL2RlcGxveW1lbnRzPC9zcGFuPjxzcGFuIHN0eWxlPSJm b250LXNpemU6MTMuNXB0O2NvbG9yOmJsYWNrIj4uPGJyPg0KPGJyPg0KJm5ic3A7Jm5ic3A7IFRo aXMgbWFrZXMgPGk+cGx1Z2luQXBwbGljYXRpb248L2k+J3MgR1dUIFJQQyBzZXJ2bGV0KHMpIGFj Y2Vzc2libGUgZnJvbSB0aGUgc2FtZSBvcmlnaW4gKHByb3RvY29sLCBkb21haW4sIHBvcnQpLjxi cj4NCjxicj4NCmMpIE1vZGlmaWNhdGlvbiBvZiBwbHVnaW4gbGlmZWN5Y2xlIHN0ZXAgIzU6PGJy Pg0KPGJyPg0KJm5ic3A7Jm5ic3A7IEluc3RlYWQgb2YgZW1iZWRkaW5nIDwvc3Bhbj48c3BhbiBz dHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7THVjaWRhIENvbnNvbGUmcXVvdDs7Y29sb3I6YmxhY2si PiZsdDtwbHVnaW5BcHBsaWNhdGlvbiZndDsubm9jYWNoZS5qczwvc3Bhbj48c3BhbiBzdHlsZT0i Zm9udC1zaXplOjEzLjVwdDtjb2xvcjpibGFjayI+IGNvbnRlbnQgaW50byBXZWJBZG1pbiBIVE1M IHBhZ2UsIGp1c3QgZW1iZWQgdGhlIGxpbmsgdG8gaXQsIGUuZy4NCjwvc3Bhbj48c3BhbiBzdHls ZT0iZm9udC1mYW1pbHk6JnF1b3Q7THVjaWRhIENvbnNvbGUmcXVvdDs7Y29sb3I6YmxhY2siPmh0 dHAocyk6Ly8xMjcuMC4wLjE6Jmx0O3BvcnQmZ3Q7L3BhdGgvdG8vJmx0O3BsdWdpbkFwcGxpY2F0 aW9uJmd0Oy5ub2NhY2hlLmpzPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTMuNXB0O2Nv bG9yOmJsYWNrIj48YnI+DQo8YnI+DQpkKSBNb2RpZmljYXRpb24gb2YgcGx1Z2luIGxpZmVjeWNs ZSBzdGVwICM2Ojxicj4NCjxicj4NCiZuYnNwOyZuYnNwOyBEdXJpbmcgV2ViQWRtaW4gc3RhcnR1 cCwgZm9yIGVhY2ggcGx1Z2luIHRoYXQgaXMgc3VwcG9zZWQgdG8gYmUgbG9hZGVkIHJlbW90ZWx5 LCBjcmVhdGUgYW4NCjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6JnF1b3Q7THVjaWRh IENvbnNvbGUmcXVvdDs7Y29sb3I6YmxhY2siPiZsdDtpZnJhbWUmZ3Q7PC9zcGFuPjxzcGFuIHN0 eWxlPSJmb250LXNpemU6MTMuNXB0O2NvbG9yOmJsYWNrIj4gdGhhdCB3aWxsIGZldGNoIHRoZSBw bHVnaW4gYXN5bmNocm9ub3VzbHkuPGJyPg0KPGJyPg0KJm5ic3A7Jm5ic3A7IFRoZSA8L3NwYW4+ PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O0x1Y2lkYSBDb25zb2xlJnF1b3Q7O2NvbG9y OmJsYWNrIj4mbHQ7aWZyYW1lJmd0Ozwvc3Bhbj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEzLjVw dDtjb2xvcjpibGFjayI+IGlzIHJlcXVpcmVkIGluIG9yZGVyIGZvcg0KPC9zcGFuPjxzcGFuIHN0 eWxlPSJmb250LWZhbWlseTomcXVvdDtMdWNpZGEgQ29uc29sZSZxdW90Oztjb2xvcjpibGFjayI+ Jmx0O3BsdWdpbkFwcGxpY2F0aW9uJmd0Oy5ub2NhY2hlLmpzPC9zcGFuPjxzcGFuIHN0eWxlPSJm b250LXNpemU6MTMuNXB0O2NvbG9yOmJsYWNrIj4gdG8gYXBwZWFyIGZyb20gZGlmZmVyZW50ICg8 aT5wbHVnaW5BcHBsaWNhdGlvbjwvaT4tc3BlY2lmaWMpIGRvbWFpbiB0aGFuIFdlYkFkbWluIEhU TUwgcGFnZS48YnI+DQo8YnI+DQombmJzcDsmbmJzcDsgVGhpcyB3YXksIGZldGNoaW5nIHBlcm11 dGF0aW9uICg8L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OiZxdW90O0x1Y2lkYSBDb25z b2xlJnF1b3Q7O2NvbG9yOmJsYWNrIj4mbHQ7aGFzaE5hbWUmZ3Q7LmNhY2hlLmh0bWw8L3NwYW4+ PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMy41cHQ7Y29sb3I6YmxhY2siPikgZmlsZXMsIHdoaWNo IGFyZSByZWxhdGl2ZSB0bw0KPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTomcXVvdDtM dWNpZGEgQ29uc29sZSZxdW90Oztjb2xvcjpibGFjayI+Jmx0O3BsdWdpbkFwcGxpY2F0aW9uJmd0 Oy5ub2NhY2hlLmpzPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTMuNXB0O2NvbG9yOmJs YWNrIj4sIHdpbGwgd29yayBvdXQtb2YtdGhlLWJveC48YnI+DQo8YnI+DQo8YnI+DQpHZW9yZ2Us IHBsZWFzZSBsZXQgbWUga25vdyB3aGF0IHlvdSB0aGluaywgYW5kIEkgd2lsbCB1cGRhdGUgVUkg UGx1Z2lucyB3aWtpIGFjY29yZGluZ2x5Ljxicj4NCjxicj4NClZvanRlY2g8YnI+DQo8YnI+DQo8 YnI+DQpbMV0gPGEgaHJlZj0iaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TYW1lX29yaWdp bl9wb2xpY3kiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2FtZV9vcmlnaW5fcG9saWN5 PC9hPjxicj4NClsyXSA8YSBocmVmPSJodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS93ZWIt dG9vbGtpdC9kb2MvbGF0ZXN0L0Rldkd1aWRlQ29kaW5nQmFzaWNzSlNOSSI+DQpodHRwczovL2Rl dmVsb3BlcnMuZ29vZ2xlLmNvbS93ZWItdG9vbGtpdC9kb2MvbGF0ZXN0L0Rldkd1aWRlQ29kaW5n QmFzaWNzSlNOSTwvYT48YnI+DQpbM10gPGEgaHJlZj0iaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2ds ZS5jb20vd2ViLXRvb2xraXQvZG9jL2xhdGVzdC9EZXZHdWlkZUNvZGluZ0Jhc2ljc092ZXJsYXki Pg0KaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vd2ViLXRvb2xraXQvZG9jL2xhdGVzdC9E ZXZHdWlkZUNvZGluZ0Jhc2ljc092ZXJsYXk8L2E+PGJyPg0KPGJyPg0KPC9zcGFuPjxzcGFuIHN0 eWxlPSJjb2xvcjpibGFjayI+PG86cD48L286cD48L3NwYW4+PC9wPg0KPGRpdiBjbGFzcz0iTXNv Tm9ybWFsIiBhbGlnbj0iY2VudGVyIiBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPjxzcGFuIHN0 eWxlPSJjb2xvcjpibGFjayI+DQo8aHIgc2l6ZT0iMiIgd2lkdGg9IjEwMCUiIGFsaWduPSJjZW50 ZXIiIGlkPSJ6d2NociI+DQo8L3NwYW4+PC9kaXY+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIiBzdHls ZT0ibWFyZ2luLWJvdHRvbToxMi4wcHQiPjxzcGFuIHN0eWxlPSJjb2xvcjpibGFjayI+PGJyPg0K RnJvbTogJnF1b3Q7R2VvcmdlIENvc3RlYSZxdW90OyAmbHQ7PGEgaHJlZj0ibWFpbHRvOkdlb3Jn ZS5Db3N0ZWFAbmV0YXBwLmNvbSI+R2VvcmdlLkNvc3RlYUBuZXRhcHAuY29tPC9hPiZndDs8YnI+ DQpUbzogJnF1b3Q7Vm9qdGVjaCBTem9jcyZxdW90OyAmbHQ7PGEgaHJlZj0ibWFpbHRvOnZzem9j c0ByZWRoYXQuY29tIj52c3pvY3NAcmVkaGF0LmNvbTwvYT4mZ3Q7LCA8YSBocmVmPSJtYWlsdG86 ZW5naW5lLWRldmVsQG92aXJ0Lm9yZyI+DQplbmdpbmUtZGV2ZWxAb3ZpcnQub3JnPC9hPjxicj4N CkNjOiAmcXVvdDtEdXN0aW4gU2Nob2VuYnJ1biZxdW90OyAmbHQ7PGEgaHJlZj0ibWFpbHRvOkR1 c3Rpbi5TY2hvZW5icnVuQG5ldGFwcC5jb20iPkR1c3Rpbi5TY2hvZW5icnVuQG5ldGFwcC5jb208 L2E+Jmd0OywgJnF1b3Q7Umlja3kgSG9wcGVyJnF1b3Q7ICZsdDs8YSBocmVmPSJtYWlsdG86Umlj a3kuSG9wcGVyQG5ldGFwcC5jb20iPlJpY2t5LkhvcHBlckBuZXRhcHAuY29tPC9hPiZndDssICZx dW90O0l0YW1hciBIZWltJnF1b3Q7ICZsdDs8YSBocmVmPSJtYWlsdG86aWhlaW1AcmVkaGF0LmNv bSI+aWhlaW1AcmVkaGF0LmNvbTwvYT4mZ3Q7PGJyPg0KU2VudDogTW9uZGF5LCBKdW5lIDI1LCAy MDEyIDk6MTE6MzMgUE08YnI+DQpTdWJqZWN0OiBSRTogb1ZpcnQgVUkgUGx1Z2lucyBmZWF0dXJl OiBSZWFkeSBmb3IgcmV2aWV3PGJyPg0KPGJyPg0KVGhhbmtzIFZvanRlY2guPGJyPg0KPGJyPg0K U2luY2UgdGhlIHBsdWdpbnMgYXJlIGVtYmVkZGVkIGludG8gdGhlIFdlYkFkbWluIEhUTUwgcGFn ZSwgdGhhdCBzZWVtcyB0byBzaW1wbGlmeSB0aGluZ3M7IG5vIGV4dGVybmFsIHdlYiBzZXJ2aWNl IGlzIG5lZWRlZC4gJm5ic3A7VGhpcyBhcHByb2FjaCB0aWVzIGludG8gdGhlIGlzc3VlIG92ZXIg dGhlIGZyZWVkb20gdG8gZGVjaWRlIHdoaWNoIHRlY2hub2xvZ3kgdG8gdXNlIHdoZW4gZGV2ZWxv cGluZyBhIHBsdWdpbi4gJm5ic3A7V2hpbGUgSSBhZ3JlZSB0aGF0DQogalF1ZXJ5IGlzIGJlc3Qg Zm9yIHNpbXBsZSBkaWFsb2dzLCBhIHdpemFyZC1kcml2ZW4gd29ya2Zsb3cgaXMgZWFzaWVyIHRv IGRldmVsb3AgaW4gR1dULiAmbmJzcDs8YnI+DQo8YnI+DQpGb3IgZXhhbXBsZSwgaWYgSSB3YW50 IHRvIHN0ZXAgYSB1c2VyIHRocm91Z2ggdGhlIHByb2Nlc3Mgb2YgY3JlYXRpbmcgYSBuZXcgc3Rv cmFnZSBkb21haW4gSSB3b3VsZCBsaWtlIHRvIHByb3ZpZGUgYSB3b3JrZmxvdyB0byBzZWxlY3Qg YSBzdG9yYWdlIGFycmF5LCBwcm92aWRlIGNyZWRlbnRpYWxzLCBhbmQgY29uZmlndXJlIHRoZSBk ZXRhaWxzIG9mIHRoZSBORlMgZXhwb3J0LiAmbmJzcDtUaGlzIHdvcmtmbG93IGNvdWxkIHByZXN1 bWFibHkgaGF2ZSBhDQogR1dULVJQQyBtZWNoYW5pc20gdGhhdCByZWxpZXMgb24gc29tZSBhZGRp dGlvbmFsIGxpYnJhcmllcyBvbiB0aGUgYmFja2VuZCAobGlicmFyaWVzIHRoYXQgYWxsb3cgbWUg dG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgc3RvcmFnZSBhcnJheSkuICZuYnNwO1VzaW5nIHRoZSBH V1QtRXhwb3J0ZXIsIEkgY291bGQgZXhwb3J0IHRoZSBjbGFzc2VzIHRoYXQgd291bGQgZGlzcGxh eSB0aGUgd29ya2Zsb3cgd2hpY2ggd291bGQgdGhlbiBnZXQgbGF1bmNoZWQgYXMNCiBteSBleHRl bnNpb24gaXMgc2VsZWN0ZWQuICZuYnNwO1lvdSBzYWlkIHRoYXQgSSB3b3VsZCBoYXZlIG15IG9W aXJ0IFVJIHBsdWdpbiBkZXBlbmQgb24gbXkgY29tcGlsZWQgJ3BsdWdpbiBzdXBwb3J0IGFwcGxp Y2F0aW9uJy4gJm5ic3A7TXkgY29tcGlsZWQgcGx1Z2luIHN1cHBvcnQgYXBwbGljYXRpb24gd291 bGQgbm9ybWFsbHkgYmUgYSB3YXIgZmlsZSBjb250YWluaW5nIG15IGNvbXBpbGVkIEdXVCBjb2Rl IGFuZCBhIHdlYi1pbmYgZm9sZGVyIGNvbnRhaW5pbmcNCiBteSBsaWJyYXJpZXMuICZuYnNwO0lz IHRoZSBwbHVnaW4gZGVwZW5kaW5nIG9uIHRoZSB3YXIgZmlsZT8gJm5ic3A7SXMgdGhhdCB3aGF0 IEkgc3BlY2lmeT88YnI+DQo8YnI+DQotR2VvcmdlPGJyPg0KPGJyPg0KLS0tLS1PcmlnaW5hbCBN ZXNzYWdlLS0tLS08YnI+DQpGcm9tOiBWb2p0ZWNoIFN6b2NzIDxhIGhyZWY9Im1haWx0bzpbbWFp bHRvOnZzem9jc0ByZWRoYXQuY29tXSI+W21haWx0bzp2c3pvY3NAcmVkaGF0LmNvbV08L2E+DQo8 YnI+DQpTZW50OiBNb25kYXksIEp1bmUgMjUsIDIwMTIgMToxMiBQTTxicj4NClRvOiBDb3N0ZWEs IEdlb3JnZTsgPGEgaHJlZj0ibWFpbHRvOmVuZ2luZS1kZXZlbEBvdmlydC5vcmciPmVuZ2luZS1k ZXZlbEBvdmlydC5vcmc8L2E+PGJyPg0KQ2M6IFNjaG9lbmJydW4sIER1c3RpbjsgSG9wcGVyLCBS aWNreTsgSXRhbWFyIEhlaW08YnI+DQpTdWJqZWN0OiBSZTogb1ZpcnQgVUkgUGx1Z2lucyBmZWF0 dXJlOiBSZWFkeSBmb3IgcmV2aWV3PGJyPg0KPGJyPg0KSGkgR2VvcmdlLDxicj4NCjxicj4NCnRo YW5rcyBmb3IgeW91ciBmZWVkYmFjay4gUGxlYXNlIGZpbmQgbXkgYW5zd2VycyBiZWxvdy48YnI+ DQo8YnI+DQo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3Bh biBzdHlsZT0iY29sb3I6YmxhY2siPjEpIEFyZSB0aGUgcGx1Z2lucyBob3N0ZWQgYnkgdGhlIHNh bWUgamJvc3Mgc2VydmVyIHRoYXQgaG9zdHMgdGhlIGVuZ2luZT8gJm5ic3A7SXQgd291bGQgYXBw ZWFyIHRoZSBhbnN3ZXIgaXMgeWVzIGFuZCB0aGF0IG5vIHNlcGFyYXRlIGNvbnRhaW5lciBpcyBy ZXF1aXJlZCBmb3IgdGhlIHBsdWdpbnMuPGJyPg0KPGJyPg0KSW4gc2hvcnQsIHllcy48bzpwPjwv bzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIiBzdHlsZT0ibWFyZ2luLWJvdHRv bToxMi4wcHQiPjxzcGFuIHN0eWxlPSJjb2xvcjpibGFjayI+PGJyPg0KPGJyPg0KUGx1Z2lucywg YWxvbmcgd2l0aCB0aGVpciBjb25maWd1cmF0aW9uIGFuZCAzcmQgcGFydHkgZGVwZW5kZW5jaWVz LCBhcmUgbWVhbnQgdG8gYmUgZW1iZWRkZWQgaW50byBmaW5hbCBXZWJBZG1pbiBIVE1MIHBhZ2Us IHNlZSBbaHR0cDovL3d3dy5vdmlydC5vcmcvd2lraS9GZWF0dXJlcy9VSVBsdWdpbnMjUGx1Z2lu X2xpZmVjeWNsZV0gc3RlcCAjNS4NCjxicj4NCkpCb3NzIEFTIGluc3RhbmNlIHNlcnZlcyBXZWJB ZG1pbiBIVE1MIHBhZ2UgKFdlYmFkbWluRHluYW1pY0hvc3RpbmdTZXJ2bGV0KSwgYWxvbmcgd2l0 aCBwcm92aWRpbmcgR1dUIFJQQyBhbmQgUkVTVCBlbmRwb2ludHMgdGhhdCBkZWxlZ2F0ZSB0byBF bmdpbmUgYnVzaW5lc3MgbG9naWMgdGhyb3VnaCBFSkIgQmFja2VuZExvY2FsIGludGVyZmFjZS48 YnI+DQo8YnI+DQpIb3dldmVyLCBwbHVnaW5zIGFyZSBub3QgJ2hvc3RlZCcgaW4gYSB0eXBpY2Fs IHNlbnNlIC0gV2ViYWRtaW5EeW5hbWljSG9zdGluZ1NlcnZsZXQgcmVhZHMgYW5kIGVtYmVkcyBh bGwgcGx1Z2luIGRhdGEgZGlyZWN0bHkgaW50byBmaW5hbCBXZWJBZG1pbiBIVE1MIHBhZ2UuPGJy Pg0KPGJyPg0KPG86cD48L286cD48L3NwYW4+PC9wPg0KPHAgY2xhc3M9Ik1zb05vcm1hbCI+PHNw YW4gc3R5bGU9ImNvbG9yOmJsYWNrIj4yKSBEb2VzIGVhY2ggcGx1Z2luIG1hcCB0byBhIHVuaXF1 ZSBleHRlbnNpb24gd2l0aGluIFdlYkFkbWluPyAmbmJzcDtZb3VyIGV4YW1wbGUgc2hvd3MgdGhh dCBJIGNhbiBleHRlbmQgdGhlIFZNIHRhYmxlIHRvIGhhdmUgYSAmcXVvdDtTaG93IFZNIG5hbWUg YW5kIGVkaXQgVk0mcXVvdDsgY29udGV4dC1zZW5zaXRpdmUgZXh0ZW5zaW9uLiAmbmJzcDtUaGlz IGlzIG5hbWVkIHBsdWdpbkFwaS5wbHVnaW5zLm15UGx1Z2luLg0KICZuYnNwO0NhbiBJIHNhZmVs eSBhc3N1bWUgdGhhdCB0aGlzIGlzIHBlciBleHRlbnNpb24/ICZuYnNwO0kgd291bGQgaGF2ZSBw bHVnaW5BcGkucGx1Z2lucy5teVBsdWdpbjIgZm9yIGV4dGVuZGluZyBhIHN0b3JhZ2UgZG9tYWlu Pzxicj4NCjxicj4NCkV4dGVuc2lvbiBwb2ludHMgYXJlIHJlcHJlc2VudGVkIGJ5IGFwcGxpY2F0 aW9uIGV2ZW50cywgdHJpZ2dlcmVkIGJ5IFdlYkFkbWluIGFuZCBjb25zdW1lZCBieSBwbHVnaW5z LiBGb3IgZXhhbXBsZSwgJ3RhYmxlQ29udGV4dE1lbnUnIGV2ZW50IGdldHMgdHJpZ2dlcmVkIHdo ZW4gYSB0YWJsZSBjb250ZXh0IG1lbnUgaXMgYWJvdXQgdG8gYmUgc2hvd24gdG8gdGhlIHVzZXIs IHdoaWNoIGdpdmVzIHBsdWdpbnMgdGhlIGFiaWxpdHkgdG8gZG8gc29tZXRoaW5nDQogY3VzdG9t IHdpdGggdGhlIGNvbnRleHQgbWVudSBiZWZvcmUgaXQncyBzaG93bi48bzpwPjwvbzpwPjwvc3Bh bj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIiBzdHlsZT0ibWFyZ2luLWJvdHRvbToxMi4wcHQi PjxzcGFuIHN0eWxlPSJjb2xvcjpibGFjayI+PGJyPg0KPGJyPg0KVGhlcmUgY2FuIGJlIG11bHRp cGxlIHBsdWdpbnMgaGFuZGxpbmcgdGhlIHNhbWUgZXZlbnQgKGV4dGVuc2lvbiBwb2ludCkuIFlv dSBjYW4gaGF2ZSB0d28gcGx1Z2lucywgc2F5ICdwbHVnaW5BcGkucGx1Z2lucy5PbmUnIGFuZCAn cGx1Z2luQXBpLnBsdWdpbnMuVHdvJywgZWFjaCBwcm92aWRpbmcgJ3RhYmxlQ29udGV4dE1lbnUn IGZ1bmN0aW9uIGZvciBoYW5kbGluZyB0aGUgYWJvdmUgbWVudGlvbmVkIGV2ZW50LiBXZWJBZG1p biB3aWxsIGludm9rZQ0KIGFsbCBwbHVnaW5zIGZvciB0aGUgZ2l2ZW4gZXZlbnQuPGJyPg0KPGJy Pg0KVG8gYW5zd2VyIHlvdXIgcXVlc3Rpb24sIGluIG9yZGVyIHRvIGhhbmRsZSBYIGV2ZW50cyAo ZXh0ZW5zaW9uIHBvaW50cyksIHlvdSBkb24ndCBuZWVkIHRvIHdyaXRlIFggcGx1Z2lucy4gWW91 IGNhbiB3cml0ZSBvbmUgcGx1Z2luIHRoYXQgaGFuZGxlcyBYIGV2ZW50cy48YnI+DQo8YnI+DQo8 bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0i Y29sb3I6YmxhY2siPjMpIEluc3RlYWQgb2YgbGF1bmNoaW5nIGEgalF1ZXJ5IGRpYWxvZywgY2Fu IEkgcG9pbnQgdG8gYSBjb21waWxlZCBHV1QgaHRtbCBmaWxlIHRvIGRpc3BsYXkgYSBkaWFsb2cg dGhhdCBmaXRzIG15IG5lZWRzPzxicj4NCjxicj4NCllvdSBjYW4gZG8gYW55dGhpbmcgeW91IHdh bnQgaW4geW91ciBwbHVnaW4gZXZlbnQgaGFuZGxlciBmdW5jdGlvbi4gU2hvdyBhIGpRdWVyeSBV SSBkaWFsb2csIG1ha2Ugb1ZpcnQgUkVTVCBBUEkgcmVxdWVzdCwgY2FsbCBhcmJpdHJhcnkgcmVt b3RlIHNlcnZlciB1c2luZyBjcm9zcy1kb21haW4gdGVjaG5pcXVlIGxpa2UgSlNPTlAgWzFdIG9y IENPUlMgWzJdLCBldGMuIFBsdWdpbiBhdXRob3JzIGFyZSBmcmVlIHRvIGRlY2lkZSBpZiB0aGV5 IHdhbnQNCiB0byByZWx5IG9uIDNyZCBwYXJ0eSBKYXZhU2NyaXB0IGxpYnJhcmllcywgb3IgaWYg dGhleSB3YW50IHRvIHdyaXRlIGVudGlyZSBwbHVnaW4gY29kZSBieSB0aGVtc2VsdmVzLjxvOnA+ PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiIHN0eWxlPSJtYXJnaW4tYm90 dG9tOjEyLjBwdCI+PHNwYW4gc3R5bGU9ImNvbG9yOmJsYWNrIj48YnI+DQo8YnI+DQpJbiBteSBv cGluaW9uLCB0b29scyBsaWtlIGpRdWVyeSBhcmUgZmFyIG1vcmUgZWxlZ2FudCBmb3IgaGFuZGxp bmcgc2ltcGxlIHRoaW5ncyBzdWNoIGFzIFVJIGRpYWxvZ3MuIEJ1dCBpZiB5b3UgcmVhbGx5IHdh bnQgdG8gdXNlIEdXVCBmb3IgdGhpcyBwdXJwb3NlLCBJIHN1Z2dlc3QgZm9sbG93aW5nIGFwcHJv YWNoOjxicj4NCjxicj4NCmEsIGRldmVsb3AgYSAncGx1Z2luIHN1cHBvcnQgYXBwbGljYXRpb24n IGluIEdXVCwgd2hpY2ggaW1wbGVtZW50cyB0aGUgbmVjZXNzYXJ5IGRpYWxvZyBmdW5jdGlvbmFs aXR5IGIsIGV4cG9ydCBpdHMgbWFpbiAoZS5nLiBkaWFsb2cgaGFuZGxpbmcpIGNsYXNzZXMgZm9y IHVzZSBpbiBuYXRpdmUgSmF2YVNjcmlwdCB0aHJvdWdoIGd3dC1leHBvcnRlciBbM10gYywgaGF2 ZSB5b3VyIG9WaXJ0IFVJIHBsdWdpbiBkZXBlbmQgb24geW91ciBjb21waWxlZA0KICdwbHVnaW4g c3VwcG9ydCBhcHBsaWNhdGlvbicgKHRoaXMgd2lsbCBjYXVzZSB5b3VyICdwbHVnaW4gc3VwcG9y dCBhcHBsaWNhdGlvbicgdG8gYmUgY2FsbGVkIGR1cmluZyBXZWJBZG1pbiBzdGFydHVwKSBkLCBp biB5b3VyIG9WaXJ0IFVJIHBsdWdpbiwgaW52b2tlICdwbHVnaW4gc3VwcG9ydCBhcHBsaWNhdGlv bicgZnVuY3Rpb25hbGl0eSB0aHJvdWdoIGV4cG9ydGVkIGNsYXNzZXMgKHBsdWdpbiAtJmd0OyBH V1QgZGVsZWdhdGUgcGF0dGVybik8YnI+DQo8YnI+DQo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8 cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iY29sb3I6YmxhY2siPjQpIElzIHNlc3Np b24gaW5mbyBwYXNzZWQgaW50byB0aGUgcGx1Z2luIHNvIHRoYXQgSSBjYW4gaW52b2tlIEFQSXMg aW50byB0aGUgZW5naW5lPyAmbmJzcDtUbyBwb3dlciBvbiBhIFZNIGZvciBpbnN0YW5jZT8gJm5i c3A7T3IgdG8gbW91bnQgYSBuZXcgTkZTIHN0b3JhZ2UgZG9tYWluPzxicj4NCjxicj4NClllcywg dGhpcyBzaG91bGQgYmUgcGFydCBvZiBbaHR0cDovL3d3dy5vdmlydC5vcmcvd2lraS9GZWF0dXJl cy9VSVBsdWdpbnMjR2xvYmFsX0FQSV9mdW5jdGlvbnNdICZxdW90O1BsdWdpbiB1dGlsaXR5IGZ1 bmN0aW9ucyZxdW90OyAoZ2xvYmFsIEFQSSkuPG86cD48L286cD48L3NwYW4+PC9wPg0KPHAgY2xh c3M9Ik1zb05vcm1hbCIgc3R5bGU9Im1hcmdpbi1ib3R0b206MTIuMHB0Ij48c3BhbiBzdHlsZT0i Y29sb3I6YmxhY2siPjxicj4NCjxicj4NCllvdXIgcGx1Z2luIG1pZ2h0IGFjY2VzcyB1c2VyIHNl c3Npb24gaW5mb3JtYXRpb24gaW4gdGhlIGZvbGxvd2luZyB3YXk6IHBsdWdpbkFwaS51dGlsKCku dXNlckluZm8oKS4qIChyZXBsYWNlICogd2l0aCBpZCgpLCBuYW1lKCksIGRvbWFpbigpLCBldGMu KTxicj4NCjxicj4NCkFzIHlvdSBwb2ludGVkIG91dCwgdGhpcyBjb3VsZCBiZSB1c2VkIHRvIGF1 dGhlbnRpY2F0ZSBvVmlydCBSRVNUIEFQSSByZXF1ZXN0cyBtYWRlIGZyb20geW91ciBwbHVnaW4g Y29kZS48YnI+DQo8YnI+DQo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9y bWFsIj48c3BhbiBzdHlsZT0iY29sb3I6YmxhY2siPkJUVywgdGhlIGxpbmsgdG8gdGhlIG9yaWdp bmFsIGRlc2lnbiBub3RlcyBvbiB0aGUgd2lraSBkb2Vzbid0IHdvcmsuPGJyPg0KPGJyPg0KVGhp cyBpcyBzdHJhbmdlLCBbaHR0cDovL3JoZXZtZi5wYWQuZW5naW5lZXJpbmcucmVkaGF0LmNvbS82 OF0gaGFzIGl0cyB2aXNpYmlsaXR5IHNldCB0byAmcXVvdDtQdWJsaWMgKEFsbG93IEludGVybmV0 IGd1ZXN0cykmcXVvdDsgLi4uIERvZXMgYW55Ym9keSBrbm93IHdoeSB0aGlzIGRvZXNuJ3Qgd29y az88bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHls ZT0iY29sb3I6YmxhY2siPjxicj4NCjxicj4NCjxicj4NClZvanRlY2g8YnI+DQo8YnI+DQo8YnI+ DQpbMV0gPGEgaHJlZj0iaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9KU09OUCI+aHR0cDov L2VuLndpa2lwZWRpYS5vcmcvd2lraS9KU09OUDwvYT48YnI+DQpbMl0gPGEgaHJlZj0iaHR0cDov L2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy1vcmlnaW5fcmVzb3VyY2Vfc2hhcmluZyI+aHR0 cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy1vcmlnaW5fcmVzb3VyY2Vfc2hhcmluZzwv YT48YnI+DQpbM10gPGEgaHJlZj0iaHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL2d3dC1leHBvcnRl ci8iPmh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9nd3QtZXhwb3J0ZXIvPC9hPjxicj4NCjxicj4N Cjxicj4NCi0tLS0tIE9yaWdpbmFsIE1lc3NhZ2UgLS0tLS08YnI+DQpGcm9tOiAmcXVvdDtHZW9y Z2UgQ29zdGVhJnF1b3Q7ICZsdDs8YSBocmVmPSJtYWlsdG86R2VvcmdlLkNvc3RlYUBuZXRhcHAu Y29tIj5HZW9yZ2UuQ29zdGVhQG5ldGFwcC5jb208L2E+Jmd0Ozxicj4NClRvOiAmcXVvdDtWb2p0 ZWNoIFN6b2NzJnF1b3Q7ICZsdDs8YSBocmVmPSJtYWlsdG86dnN6b2NzQHJlZGhhdC5jb20iPnZz em9jc0ByZWRoYXQuY29tPC9hPiZndDssIDxhIGhyZWY9Im1haWx0bzplbmdpbmUtZGV2ZWxAb3Zp cnQub3JnIj4NCmVuZ2luZS1kZXZlbEBvdmlydC5vcmc8L2E+PGJyPg0KQ2M6ICZxdW90O0R1c3Rp biBTY2hvZW5icnVuJnF1b3Q7ICZsdDs8YSBocmVmPSJtYWlsdG86RHVzdGluLlNjaG9lbmJydW5A bmV0YXBwLmNvbSI+RHVzdGluLlNjaG9lbmJydW5AbmV0YXBwLmNvbTwvYT4mZ3Q7LCAmcXVvdDtS aWNreSBIb3BwZXImcXVvdDsgJmx0OzxhIGhyZWY9Im1haWx0bzpSaWNreS5Ib3BwZXJAbmV0YXBw LmNvbSI+Umlja3kuSG9wcGVyQG5ldGFwcC5jb208L2E+Jmd0Ozxicj4NClNlbnQ6IE1vbmRheSwg SnVuZSAyNSwgMjAxMiAzOjA5OjQzIFBNPGJyPg0KU3ViamVjdDogUkU6IG9WaXJ0IFVJIFBsdWdp bnMgZmVhdHVyZTogUmVhZHkgZm9yIHJldmlldzxicj4NCjxicj4NCkhpIFZvanRlY2gsPGJyPg0K PGJyPg0KSSBoYXZlIGEgZmV3IHF1ZXN0aW9ucyBvbiB0aGlzIGZlYXR1cmUuPGJyPg0KPGJyPg0K MSkgQXJlIHRoZSBwbHVnaW5zIGhvc3RlZCBieSB0aGUgc2FtZSBqYm9zcyBzZXJ2ZXIgdGhhdCBo b3N0cyB0aGUgZW5naW5lPyAmbmJzcDtJdCB3b3VsZCBhcHBlYXIgdGhlIGFuc3dlciBpcyB5ZXMg YW5kIHRoYXQgbm8gc2VwYXJhdGUgY29udGFpbmVyIGlzIHJlcXVpcmVkIGZvciB0aGUgcGx1Z2lu cy48YnI+DQoyKSBEb2VzIGVhY2ggcGx1Z2luIG1hcCB0byBhIHVuaXF1ZSBleHRlbnNpb24gd2l0 aGluIFdlYkFkbWluPyAmbmJzcDtZb3VyIGV4YW1wbGUgc2hvd3MgdGhhdCBJIGNhbiBleHRlbmQg dGhlIFZNIHRhYmxlIHRvIGhhdmUgYSAmcXVvdDtTaG93IFZNIG5hbWUgYW5kIGVkaXQgVk0mcXVv dDsgY29udGV4dC1zZW5zaXRpdmUgZXh0ZW5zaW9uLiAmbmJzcDtUaGlzIGlzIG5hbWVkIHBsdWdp bkFwaS5wbHVnaW5zLm15UGx1Z2luLiAmbmJzcDtDYW4gSSBzYWZlbHkgYXNzdW1lIHRoYXQgdGhp cyBpcw0KIHBlciBleHRlbnNpb24/ICZuYnNwO0kgd291bGQgaGF2ZSBwbHVnaW5BcGkucGx1Z2lu cy5teVBsdWdpbjIgZm9yIGV4dGVuZGluZyBhIHN0b3JhZ2UgZG9tYWluPzxicj4NCjMpIEluc3Rl YWQgb2YgbGF1bmNoaW5nIGEgalF1ZXJ5IGRpYWxvZywgY2FuIEkgcG9pbnQgdG8gYSBjb21waWxl ZCBHV1QgaHRtbCBmaWxlIHRvIGRpc3BsYXkgYSBkaWFsb2cgdGhhdCBmaXRzIG15IG5lZWRzPzxi cj4NCjQpIElzIHNlc3Npb24gaW5mbyBwYXNzZWQgaW50byB0aGUgcGx1Z2luIHNvIHRoYXQgSSBj YW4gaW52b2tlIEFQSXMgaW50byB0aGUgZW5naW5lPyAmbmJzcDtUbyBwb3dlciBvbiBhIFZNIGZv ciBpbnN0YW5jZT8gJm5ic3A7T3IgdG8gbW91bnQgYSBuZXcgTkZTIHN0b3JhZ2UgZG9tYWluPzxi cj4NCjxicj4NCkJUVywgdGhlIGxpbmsgdG8gdGhlIG9yaWdpbmFsIGRlc2lnbiBub3RlcyBvbiB0 aGUgd2lraSBkb2Vzbid0IHdvcmsuPGJyPg0KPGJyPg0KVGhhbmtzLDxicj4NCkdlb3JnZTxicj4N Cjxicj4NCi0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tPGJyPg0KRnJvbTogVm9qdGVjaCBTem9j cyA8YSBocmVmPSJtYWlsdG86W21haWx0bzp2c3pvY3NAcmVkaGF0LmNvbV0iPlttYWlsdG86dnN6 b2NzQHJlZGhhdC5jb21dPC9hPjxicj4NClNlbnQ6IFRodXJzZGF5LCBKdW5lIDIxLCAyMDEyIDEx OjAzIEFNPGJyPg0KVG86IDxhIGhyZWY9Im1haWx0bzplbmdpbmUtZGV2ZWxAb3ZpcnQub3JnIj5l bmdpbmUtZGV2ZWxAb3ZpcnQub3JnPC9hPjxicj4NCkNjOiBTY2hvZW5icnVuLCBEdXN0aW47IENv c3RlYSwgR2VvcmdlOyBIb3BwZXIsIFJpY2t5PGJyPg0KU3ViamVjdDogb1ZpcnQgVUkgUGx1Z2lu cyBmZWF0dXJlOiBSZWFkeSBmb3IgcmV2aWV3PGJyPg0KPGJyPg0KSGkgZ3V5cyw8YnI+DQo8YnI+ DQpJIHdyb3RlIGEgd2lraSBwYWdlIGRlc2NyaWJpbmcgVUkgUGx1Z2lucywgYSBmZWF0dXJlIHBs YW5uZWQgZm9yIG9WaXJ0IHdlYiBhZG1pbmlzdHJhdGlvbiAoV2ViQWRtaW4pIGFwcGxpY2F0aW9u Ojxicj4NCjxhIGhyZWY9Imh0dHA6Ly93d3cub3ZpcnQub3JnL3dpa2kvRmVhdHVyZXMvVUlQbHVn aW5zIj5odHRwOi8vd3d3Lm92aXJ0Lm9yZy93aWtpL0ZlYXR1cmVzL1VJUGx1Z2luczwvYT48YnI+ DQo8YnI+DQpGZWF0dXJlIGRlc2lnbiBpcyBmaW5pc2hlZCBhbmQgcmVhZHkgZm9yIHJldmlldy4g UGxlYXNlIGZlZWwgZnJlZSB0byBhZGQgY29tbWVudHMsIGFzayBxdWVzdGlvbnMgb3IgcmVhY2gg bWUgZGlyZWN0bHkgb24gI292aXJ0IGNoYW5uZWwuPGJyPg0KPGJyPg0KQ2hlZXJzLDxicj4NClZv anRlY2g8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8L2Rpdj4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9o dG1sPg0K --_000_6C8AC8C50E170C4E9B44D47B39B24A48012080BASACEXCMBX04PRDh_--

Hi guys, as a follow-up to an excellent discussion with Michal, here are some ideas that could prove useful when implementing robust UI plugin infrastructure. (Please let me know what you think.) 1. Implement WebAdmin dialog that lists active plugins, with the ability to turn them on/off (during WebAdmin runtime). 2. Implement WebAdmin 'plugin-safe' mode, which disables all plugins during WebAdmin startup (could be controlled via HTTP parameter) 3. Introduce WebAdmin plugin API compliance version, so that plugins can be made against specific version of WebAdmin Cheers, Vojtech

All of these are excellent ideas! -----Original Message----- From: engine-devel-bounces@ovirt.org [mailto:engine-devel-bounces@ovirt.org] On Behalf Of Vojtech Szocs Sent: Tuesday, June 26, 2012 11:19 AM To: engine-devel@ovirt.org Cc: Michal Skrivanek Subject: [Engine-devel] oVirt UI Plugins: some more ideas Hi guys, as a follow-up to an excellent discussion with Michal, here are some ideas that could prove useful when implementing robust UI plugin infrastructure. (Please let me know what you think.) 1. Implement WebAdmin dialog that lists active plugins, with the ability to turn them on/off (during WebAdmin runtime). 2. Implement WebAdmin 'plugin-safe' mode, which disables all plugins during WebAdmin startup (could be controlled via HTTP parameter) 3. Introduce WebAdmin plugin API compliance version, so that plugins can be made against specific version of WebAdmin Cheers, Vojtech _______________________________________________ Engine-devel mailing list Engine-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-devel

On 06/25/2012 10:11 PM, Costea, George wrote:
Thanks Vojtech.
Since the plugins are embedded into the WebAdmin HTML page, that seems to simplify things; no external web service is needed. This approach ties into the issue over the freedom to decide which technology to use when developing a plugin. While I agree that jQuery is best for simple dialogs, a wizard-driven workflow is easier to develop in GWT.
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. 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). Using the GWT-Exporter, I could export the classes that would display the workflow which would then get launched as my extension is selected. You said that I would have my oVirt UI plugin depend on my compiled 'plugin support application'. My compiled plugin support application would normally be a war file containing my compiled GWT code and a web-inf folder containing my libraries. Is the plugin depending on the war file? Is that what I specify?
-George
-----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Monday, June 25, 2012 1:12 PM To: Costea, George; engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Hopper, Ricky; Itamar Heim Subject: Re: oVirt UI Plugins feature: Ready for review
Hi George,
thanks for your feedback. Please find my answers below.
1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins.
In short, yes.
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. 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.
However, plugins are not 'hosted' in a typical sense - WebadminDynamicHostingServlet reads and embeds all plugin data directly into final WebAdmin HTML page.
2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain?
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.
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.
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.
3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs?
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.
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:
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 -> GWT delegate pattern)
4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain?
Yes, this should be part of [http://www.ovirt.org/wiki/Features/UIPlugins#Global_API_functions] "Plugin utility functions" (global API).
Your plugin might access user session information in the following way: pluginApi.util().userInfo().* (replace * with id(), name(), domain(), etc.)
As you pointed out, this could be used to authenticate oVirt REST API requests made from your plugin code.
BTW, the link to the original design notes on the wiki doesn't work.
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work?
Vojtech
[1] http://en.wikipedia.org/wiki/JSONP [2] http://en.wikipedia.org/wiki/Cross-origin_resource_sharing [3] http://code.google.com/p/gwt-exporter/
----- Original Message ----- From: "George Costea" <George.Costea@netapp.com> To: "Vojtech Szocs" <vszocs@redhat.com>, engine-devel@ovirt.org Cc: "Dustin Schoenbrun" <Dustin.Schoenbrun@netapp.com>, "Ricky Hopper" <Ricky.Hopper@netapp.com> Sent: Monday, June 25, 2012 3:09:43 PM Subject: RE: oVirt UI Plugins feature: Ready for review
Hi Vojtech,
I have a few questions on this feature.
1) Are the plugins hosted by the same jboss server that hosts the engine? It would appear the answer is yes and that no separate container is required for the plugins. 2) Does each plugin map to a unique extension within WebAdmin? Your example shows that I can extend the VM table to have a "Show VM name and edit VM" context-sensitive extension. This is named pluginApi.plugins.myPlugin. Can I safely assume that this is per extension? I would have pluginApi.plugins.myPlugin2 for extending a storage domain? 3) Instead of launching a jQuery dialog, can I point to a compiled GWT html file to display a dialog that fits my needs? 4) Is session info passed into the plugin so that I can invoke APIs into the engine? To power on a VM for instance? Or to mount a new NFS storage domain?
BTW, the link to the original design notes on the wiki doesn't work.
Thanks, George
-----Original Message----- From: Vojtech Szocs [mailto:vszocs@redhat.com] Sent: Thursday, June 21, 2012 11:03 AM To: engine-devel@ovirt.org Cc: Schoenbrun, Dustin; Costea, George; Hopper, Ricky Subject: oVirt UI Plugins feature: Ready for review
Hi guys,
I wrote a wiki page describing UI Plugins, a feature planned for oVirt web administration (WebAdmin) application: http://www.ovirt.org/wiki/Features/UIPlugins
Feature design is finished and ready for review. Please feel free to add comments, ask questions or reach me directly on #ovirt channel.
Cheers, Vojtech
reviewed the wiki, some notes: 1. nit: plugin is in {} - should only be function call there so not all of plugin needs such a deep indentation. 2. what are deps? 3. sorting/ordering of plugins. either part of their conf, or part of their name (nn-pluginname...) which is a normal linux convention 4. Proposed configuration file location: /etc/ovirt/webadmin add /extensions 5. events - should have before and after event calls 6. missing in api - api to perform a rest call (say using json) 7. future: provide a javascript sdk like the python one, rather than just a rest api level integration - not sure worth the hassle 8. reminder - extensions need can't use internal API, only the REST API. this goes to *entities* as well - either you expose a REST-like entity for the important fields, or we start moving parts of the UI to the REST entities to match (I'm not sure you want to go with latter yet, as it is a huge undertaking, but you need to expose matching entities to begin with, or extensions will break on upgrade since internal entities aren't backward compatible. to sum it up: ui plugins must get an SDK of what they can do, which will include entry points, entities and relevant methods. UI code should be as simple as possible to write for the main use cases (i.e., i think the SDK should provide very simple objets for adding subtabs, context menu items, etc.) - right now it is very java script oriented.

On Mon, Jun 25, 2012 at 01:11:41PM -0400, Vojtech Szocs wrote:
BTW, the link to the original design notes on the wiki doesn't work.
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work?
The DNS records aren't public.

Looks like rhevmf.pad.engineering.redhat.com is on internal network :( You can find original UI plugin design notes here: http://www.ovirt.org/wiki/Features/UIPluginsOriginalDesignNotes (I've also updated UI plugin main wiki page to reflect the link above.) Vojtech ----- Original Message ----- From: "Ewoud Kohl van Wijngaarden" <ewoud+ovirt@kohlvanwijngaarden.nl> To: engine-devel@ovirt.org Sent: Tuesday, June 26, 2012 4:15:21 PM Subject: Re: [Engine-devel] oVirt UI Plugins feature: Ready for review On Mon, Jun 25, 2012 at 01:11:41PM -0400, Vojtech Szocs wrote:
BTW, the link to the original design notes on the wiki doesn't work.
This is strange, [http://rhevmf.pad.engineering.redhat.com/68] has its visibility set to "Public (Allow Internet guests)" ... Does anybody know why this doesn't work?
The DNS records aren't public. _______________________________________________ Engine-devel mailing list Engine-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-devel
participants (4)
-
Costea, George
-
Ewoud Kohl van Wijngaarden
-
Itamar Heim
-
Vojtech Szocs