------=_Part_3896354_1791016925.1349203611679
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Hi Chris,=20
many thanks for your feedback and suggestions :)=20
Adding context-sensitive button with corresponding menu item sounds good! I=
n fact, this is the proper way how context menu items should be handled, si=
nce WebAdmin data grids work with context-sensitive "action buttons" which =
are reflected within the context menu. I agree that this is a very useful f=
eature to have in plugin API, it should be implemented as part of next majo=
r PoC revision.=20
I have a question though: when the user clicks the custom button or corresp=
onding context menu item, will your plugin handle common dialog UI (everyth=
ing except actual content) on its own, or do you prefer to have some kind o=
f "dialog UI" API to create the standard-looking dialog frame for you? I li=
ke the idea of using iframe to present custom content though :)=20
As for grouping multiple context-sensitive buttons and corresponding contex=
t menu items, this makes sense and we have something like this already impl=
emented in WebAdmin (in Host main tab, Power Management drop-down group but=
ton, but this is defined not to appear in context menu though). I think thi=
s should be part of "custom context-sensitive button / menu item" plugin AP=
I feature.=20
If needed we can help work on an implementation for the dialog popup
plug=
in framework as we=E2=80=99d like to get it in relatively quickly so we can=
move forward on the content side of our plugin.=20
If I understand correctly, this is about providing "dialog UI" API to creat=
e the standard-looking dialog frame + custom content iframe. I'd like to he=
lp with this as well, but you can play with the code and propose a patch on=
top of PoC rev.5 [
http://gerrit.ovirt.org/8120].=20
For the reverse proxy, would it be easier from a customer standpoint
to j=
ust include a reverse proxy servlet such as this one?=20
Actually, I was under the impression that oVirt Engine (3.1) package (ovirt=
-engine) takes care of setting up Apache web server, which redirects all tr=
affic to Engine JBoss AS by default (but maybe I am wrong here). However, i=
f this is the case, an efficient way to work around same-origin policy (cro=
ss-origin issues) is to configure Apache's reverese proxy module (mod_proxy=
), as discussed in another thread on engine-devel:
http://lists.ovirt.org/p=
ipermail/engine-devel/2012-September/002511.html=20
This way, you could use Apache to bring Engine and arbitrary (local or remo=
te) web services on same origin. What do you think?=20
On the other hand, using a special-purpose reverse proxy servlet directly i=
n Engine, not sure if that's a good idea though.. (I'd prefer configuring "=
front-end" web server, such as Apache, for this purpose)=20
I'm also sending a couple of updates:=20
UI Plugins Follow-Up Meeting: scheduled for Tuesday, October 9 at 4pm GMT+1=
(I'll send a meeting invitation soon, also planning to re-write oVirt UI P=
lugins wiki soon after that)=20
PoC rev.5 patch update: many thanks to Juan and Doron for reviewing the rec=
ent patch [
http://gerrit.ovirt.org/8120]! I'll update the patch accordingly=
as revision 5.1=20
Planned items to be included in PoC revision 6:=20
* adding custom context-sensitive button (either separately or within a=
button group), along with corresponding context menu item representation=
=20
* update custom main tab to show the actual content (iframe) from the g=
iven URL=20
* adding custom sub tab that shows content from the given URL=20
More items to consider having in PoC revision 6:=20
* "dialog UI" API to create the standard-looking dialog frame + custom =
content iframe=20
* Engine REST API exposed through plugin API=20
* integration with Tasks pane to provide visual feedback on custom oper=
ations=20
* extending existing dialogs (e.g. Edit Cluster Policy - custom propert=
ies)=20
Let me know what you think.=20
Regards,=20
Vojtech=20
----- Original Message -----
From: "Christopher Morrissey" <Christopher.Morrissey(a)netapp.com>=20
To: vszocs(a)redhat.com=20
Cc: "George Costea" <George.Costea(a)netapp.com>, "Dustin
Schoenbrun" <Dustin=
.Schoenbrun(a)netapp.com>, engine-devel(a)ovirt.org=20
Sent: Tuesday, October 2, 2012 6:15:34 PM=20
Subject: RE: [Engine-devel] UI Plugins: PoC patch revision 5 is here=20
Hi Vojtech,=20
The patch is great and has cleared up some questions I had about the implem=
entation. I=E2=80=99ve been able to get the sample plugins working and wade=
d through the code changes, so feel like I have a good understanding of wha=
t was delivered. Thanks a lot for putting this all together. I do have a fe=
w questions and suggestions for you, though.=20
Will there eventually be a way to add one or more buttons to the context se=
nsitive buttons and menus throughout the interface? For example, we=E2=80=
=99d like to allow a button to provision a datastore when a data center, cl=
uster, or host is selected. When the button is clicked, it would open a dia=
log with an iframe in which we would load our interface to perform the asso=
ciated action. Some contexts would have several buttons, such as a storage =
domain (provision, resize, dedupe management, destroy) so it would probably=
make sense for a drop down menu to be available as well so that the number=
of buttons above the table doesn=E2=80=99t get too cluttered. We=E2=80=99d=
also like to add these same actions to the menus that popup when a context=
ual object is right clicked.=20
If needed we can help work on an implementation for the dialog popup plugin=
framework as we=E2=80=99d like to get it in relatively quickly so we can m=
ove forward on the content side of our plugin.=20
For the reverse proxy, would it be easier from a customer standpoint to jus=
t include a reverse proxy servlet such as this one?
http://sourceforge.net/=
projects/j2ep/=20
I=E2=80=99m just thinking that setting up and managing a plugin for the HTT=
P server may be more complex than including one internally that would be tr=
ansparent to a customer.=20
Thanks,=20
Chris=20
From: Vojtech Szocs < vszocs(a)redhat.com >=20
Date: September 21, 2012 4:37:31 PM EDT=20
To: engine-devel < engine-devel(a)ovirt.org >=20
Subject: [Engine-devel] UI Plugins: PoC patch revision 5 is here=20
<blockquote>
Hi guys,=20
it's been a while but here comes the latest revision of UI Plugins proof-of=
-concept patch (please find it attached).=20
This revision was originally meant to focus solely on server-side component=
s of the plugin infrastructure. However, I ended up implementing all the ma=
jor concepts and ideas as discussed on engine-devel mailing list, impacting=
both client-side and server-side parts of the plugin infrastructure. As a =
result, UI plugin infrastructure should be pretty much complete now, so we =
can focus on specific plugin API features in upcoming PoC revisions.=20
There's a whole bunch of changes and improvements in this revision, so I'll=
try to cover all the relevant parts step by step. If you have any comments=
, questions or ideas, please let me know!=20
So here we go... (or if you just want to get the patch, find the link at th=
e end of this message)=20
0. Added new Engine configuration values=20
UI plugin data path is represented by ConfigValues.UIPluginDataPath enum op=
tion ("UIPluginDataPath" in vdc_options table), and resolved relative to Co=
nfigValues.DataDir if possible. Following (default) values:=20
* UIPluginDataPath =3D ui-plugins=20
* DataDir =3D /usr/share/ovirt-engine=20
result in UI plugin data path: /usr/share/ovirt-engine/ui-plugins=20
UI plugin config path is represented by ConfigValues.UIPluginConfigPath enu=
m option ("UIPluginConfigPath" in vdc_options table), and resolved relative=
to ConfigValues.ConfigDir if possible. Following (default) values:=20
* UIPluginConfigPath =3D ui-plugins=20
* ConfigDir =3D /etc/ovirt-engine=20
result in UI plugin config path: /etc/ovirt-engine/ui-plugins=20
1. Processing UI plugin data on the server=20
PluginDataManager is the class responsible for reading, validating and cach=
ing UI plugin descriptor/configuration data on the server (Engine). It has =
two main responsibilities:=20
* return a snapshot of currently valid plugin data ( getCurrentData met=
hod)=20
* reload plugin data from local file system if necessary ( reloadData m=
ethod)=20
The reloadData method doesn't modify "live" plugin data directly. Instead,
=
it creates a local working copy of current plugin data, updates this copy a=
s it reads/validates plugin descriptor and configuration files, and attempt=
s to update "live" plugin data through conditional reference re-assignment =
(using java.util.concurrent.atomic.AtomicReference.compareAndSet method).=
=20
In other words, reloadData method makes no attempts with regard to Java loc=
k-based synchronization, in favor of dealing with "live" data through Atomi=
cReference (reference that involves atomic volatile reads and writes):=20
* In the best case, a thread will succeed in updating "live" data ( Ato=
micReference.compareAndSet =3D=3D true), which means that "live" data remai=
ned unchanged since this thread acquired a reference of current plugin data=
.=20
* In the worst case, a thread will NOT succeed in updating "live" data =
( AtomicReference.compareAndSet =3D=3D false), which means that "live" data=
was already changed by another thread since this thread acquired a referen=
ce of current plugin data.=20
In my opinion, when dealing with external resources like the local file sys=
tem, this is a good compromise between performance and up-to-date data. Whi=
le we might not get "completely-up-to-date" data at the given point in time=
( reloadData + getCurrentData ), we are guaranteed to get "recently-up-to-=
date" and consistent data. In other words, the requirement of "completely-u=
p-to-date" data would involve synchronized statements that would hurt perfo=
rmance. In my (very humble) opinion, the benefit of having "completely-up-t=
o-date" data, at the cost of reduced performance, is not really worth it, e=
specially in our case when the user can just hit refresh (F5) to reload Web=
Admin and its plugin data.=20
Plugin descriptor files are expected to be placed in UI plugin data path, f=
or example: /usr/share/ovirt-engine/ui-plugins/foo.json=20
Following descriptor file attributes are implemented and recognized by the =
plugin infrastructure:=20
* name : A name that uniquely identifies the plugin (required attribute=
).=20
* url : URL of plugin host page that invokes the plugin code (required =
attribute).=20
* config : Default configuration object associated with the plugin (opt=
ional attribute).=20
* resourcePath : Path to plugin static resources, relative to UI plugin=
data path (optional attribute). This is used when serving plugin files thr=
ough Engine PluginResourceServlet (more on this below).=20
Plugin configuration files are expected to be placed in UI plugin config pa=
th, for example: /etc/engine/ui-plugins/foo-config.json=20
Note that plugin configuration files follow the "<descriptorFileName>-confi=
g.json" convention.=20
Following configuration file attributes are implemented and recognized by t=
he plugin infrastructure:=20
* config : Custom configuration object associated with the plugin (opti=
onal attribute). This overrides the default plugin descriptor configuration=
, if any.=20
* enabled : Indicates whether the plugin should be loaded on WebAdmin s=
tartup (optional attribute). Default value is 'true'.=20
* order : Defines the relative order in which the plugin will be loaded=
on WebAdmin startup (optional attribute). Default value is Integer.MAX_VAL=
UE (lowest order).=20
The concept of merging custom configuration ( config attribute in foo-confi=
g.json ), if any, on top of default configuration ( config attribute in foo=
.json ), if any, remains unchanged. This makes the plugin configuration qui=
te flexible - in my opinion, the added complexity of handling/merging such =
configuration is definitely worth the effort.=20
The enabled attribute is straight-forward, allowing users to turn the given=
plugin off, if necessary. In future, users should still be able to load su=
ch plugins through WebAdmin GUI.=20
The order attribute controls the order in which plugins are loaded on WebAd=
min startup. Since plugin resources are fetched asynchronously by the brows=
er, this is basically a way of imposing some degree of determinism in the "=
generally-non-deterministic" plugin environment, which is helpful when trou=
bleshooting problems with multiple plugins. This attribute is also helpful =
due to file listing methods in java.io.File giving no guarantees that files=
would be listed in any particular order (otherwise we could just go for th=
e "NN-<descriptorFileName>.json" convention, with NN being the order
number=
).=20
2. Modified behavior of WebadminDynamicHostingServlet=20
WebadminDynamicHostingServlet is the servlet used to serve WebAdmin applica=
tion host page (HTML page that bootstraps WebAdmin JavaScript code).=20
In addition to its former behavior, as part of handling the given request, =
WebadminDynamicHostingServlet :=20
* reloads descriptor/configuration data from local file system if neces=
sary, and obtains a snapshot of currently valid plugin data ( PluginDataMan=
ager.reloadAndGetCurrentData )=20
* embeds all plugin meta-data, suitable for use in client-side plugin i=
nfrastructure, into WebAdmin host page as "pluginDefinitions" JavaScript ar=
ray ( PluginDefinitions )=20
As a result, reloading UI plugin descriptor/configuration data is as simple=
as refreshing (F5) WebAdmin application in the browser (no need to restart=
Engine).=20
3. Added servlet for serving plugin static resources=20
PluginResourceServlet is the servlet used to serve UI plugin static files (=
plugin host page, 3rd party JavaScript, etc.) from the local file system.=
=20
For example, requesting URL:=20
* http://<EngineManagerHost>:8700/webadmin/webadmin/plugin/foo/content/=
start.html=20
will send the content of:=20
* /usr/share/ovirt-engine/ui-plugins/<resourcePath>/content/start.html=
=20
to the client.=20
As shown in the above example:=20
* /webadmin/webadmin/plugin/ is the servlet root path for PluginResourc=
eServlet=20
* in the extra path beyond the servlet root path ( /foo/content/start.h=
tml ):=20
* /foo represents the name of the plugin=20
* /content/start.html represents the path to requested resource, re=
lative to "UIPluginDataPath / <resourcePath>"=20
Note that each plugin using PluginResourceServlet to serve its static files=
must declare non-empty resourcePath attribute in within the plugin descrip=
tor.=20
Also note that PluginResourceServlet , unlike WebadminDynamicHostingServlet=
, does NOT reload descriptor/configuration data from local file system as =
part of handling the given request. In other words, it's assumed that plugi=
n data has already been (re)loaded when serving WebAdmin application host p=
age, with subsequent requests to PluginResourceServlet reading the current =
plugin information.=20
Until we solve the cross-origin issue in a clean way, PluginResourceServlet=
should be used to serve all plugin resources from local file system.=20
4. Plugin lifecycle improved to deal with misbehaving plugins=20
PluginState enum has been modified to deal with plugins that allow uncaught=
exceptions to escape from plugin event handler functions (e.g. "UiInit"):=
=20
* removed state INITIALIZED=20
* added state INITIALIZING : The plugin is (currently) being initialize=
d by calling UiInit event handler function.=20
* added state IN_USE : Plugin's UiInit event handler function has compl=
eted successfully, we can now call other event handler functions as necessa=
ry. The plugin is in use now.=20
* added state FAILED : An uncaught exception escaped while calling an e=
vent handler function, which indicates internal error within the plugin cod=
e. The plugin is removed from service.=20
I've attached a simple state diagram that illustrates different states and =
transitions between them (green color is initial state, red color is end st=
ate).=20
Uncaught exceptions in plugin event handler functions will be caught and ha=
ndled by the plugin infrastructure. This prevents a misbehaving plugin from=
breaking WebAdmin application, since WebAdmin is the caller (initiator) of=
the function call. In such case, the plugin will be removed from service.=
=20
Update on cross-origin issue (consequence of same-origin policy)=20
In order for the plugin to access WebAdmin plugin API, plugin host page (e.=
g. start.html ) must be served from URL on same origin as Engine origin. Ot=
herwise, plugin code running in the context of an iframe'd host page will f=
ail to evaluate "parent.pluginApi" expression, with "parent" being
top-leve=
l (WebAdmin) window, and "pluginApi" being the global plugin API object exp=
osed by WebAdmin.=20
This is why PluginResourceServlet , available on Engine origin, should be u=
sed to serve all plugin resources from local file system.=20
There's only one issue that remains to be solved: cross-origin "plugin vs. =
remote service" communication, with "remote service" being anything other
t=
han Engine (REST API). In future, we'll address this with Apache reverse pr=
oxy configuration, so that users can configure Apache server (placed in fro=
nt of Engine JBoss AS) to put arbitrary (local or remote non-Engine) servic=
es on same origin. However, this requires a change in current Apache config=
uration. Until then, users can manually edit the Engine Apache configuratio=
n file ( /etc/httpd/conf.d/ovirt-engine.conf ).=20
I've attached some sample plugin files for you to experiment with. Instead =
of attaching actual patch file (92 kB) to this email, I've submitted the pa=
tch to oVirt Gerrit:
http://gerrit.ovirt.org/8120=20
Let me know what you think!=20
Cheers,=20
Vojtech=20
</blockquote>
<blockquote>
<ui-plugin-sample-files.tar.gz>=20
</blockquote>
<blockquote>
<ui-plugin-lifecycle.png>=20
</blockquote>
<blockquote>
_______________________________________________=20
Engine-devel mailing list=20
Engine-devel(a)ovirt.org=20
http://lists.ovirt.org/mailman/listinfo/engine-devel=20
</blockquote>
------=_Part_3896354_1791016925.1349203611679
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,new york,times,serif; font-size: =
12pt; color: #000000'>Hi Chris,<br><br>many thanks for your feedback
and su=
ggestions :)<br><br>Adding context-sensitive button with corresponding menu=
item sounds good! In fact, this is the proper way how context menu items s=
hould be handled, since WebAdmin data grids work with context-sensitive "ac=
tion buttons" which are reflected within the context menu. I agree that thi=
s is a very useful feature to have in plugin API, it should be implemented =
as part of next major PoC revision.<br><br>I have a question though: when t=
he user clicks the custom button or corresponding context menu item, will y=
our plugin handle common dialog UI (everything except actual content) on it=
s own, or do you prefer to have some kind of "dialog UI" API to create the =
standard-looking dialog frame for you? I like the idea of using iframe to p=
resent custom content though :)<br><br>As for grouping multiple context-sen=
sitive buttons and corresponding context menu items, this makes sense and w=
e have something like this already implemented in WebAdmin (in Host main ta=
b, Power Management drop-down group button, but this is defined not to appe=
ar in context menu though). I think this should be part of "custom context-=
sensitive button / menu item" plugin API feature.<br><br>>
<span style=
=3D"font-size:11.0pt;font-family:"Calibri","sans-serif"=
;color:#1F497D">If
needed we can help work on an implementation for the dialog popup=20
plugin framework as we=E2=80=99d like to get it in relatively quickly so we=
can=20
move forward on
the content side of our plugin.</span><br><br>If I understand
correctly, t=
his is about providing "dialog UI" API to create the standard-looking dialo=
g frame + custom content iframe. I'd like to help with this as well, =
but you can play with the code and propose a patch on top of PoC rev.5 [htt=
p://gerrit.ovirt.org/8120].<br><br>> <span
style=3D"font-size:11.0pt;fon=
t-family:"Calibri","sans-serif";color:#1F497D">For
the =
reverse proxy, would it be easier from a customer standpoint to just includ=
e a reverse proxy servlet such as this one?<br></span><br>Actually, I
was u=
nder the impression that oVirt Engine (3.1) package (ovirt-engine) takes ca=
re of setting up Apache web server, which redirects all traffic to Engine J=
Boss AS by default (but maybe I am wrong here). However, if this is the cas=
e, an efficient way to work around same-origin policy (cross-origin issues)=
is to configure Apache's reverese proxy module (mod_proxy), as discussed i=
n another thread on engine-devel:
http://lists.ovirt.org/pipermail/engine-d=
evel/2012-September/002511.html<br><br>This way, you could use Apache to br=
ing Engine and arbitrary (local or remote) web services on same origin. Wha=
t do you think?<br><br>On the other hand, using a special-purpose reverse p=
roxy servlet directly in Engine, not sure if that's a good idea though.. (I=
'd prefer configuring "front-end" web server, such as Apache, for this
purp=
ose)<br><br>I'm also sending a couple of
updates:<br><br><strong>UI Plugins=
Follow-Up Meeting:</strong> scheduled for Tuesday, October 9 at 4pm GMT+1 =
(I'll send a meeting invitation soon, also planning to re-write oVirt UI Pl=
ugins wiki soon after that)<br><br><span style=3D"font-weight:
bold;">PoC r=
ev.5 patch update:</span> many thanks to Juan and Doron for reviewing the r=
ecent patch [
http://gerrit.ovirt.org/8120]! I'll update the patch according=
ly as revision 5.1<br><br><span style=3D"font-weight:
bold;">Planned items =
to be included in PoC revision 6:</span><br><ul><li>adding custom
context-s=
ensitive button (either separately or within a button group), along with co=
rresponding context menu item representation</li><li>update custom main tab=
to show the actual content (iframe) from the given URL</li><li>adding cust=
om sub tab that shows content from the given
URL</li></ul><p><br></p><p><sp=
an style=3D"font-weight: bold;">More items to consider having in PoC revisi=
on 6:</span><br></p><ul><li>"dialog UI" API to
create the standard-looking =
dialog frame + custom content iframe</li><li>Engine REST API exposed throug=
h plugin API</li><li>integration with Tasks pane to provide visual feedback=
on custom operations</li><li>extending existing dialogs (e.g. Edit Cluster=
Policy - custom
properties)<br></li></ul><p><br></p><p>Let me
know what yo=
u
think.<br></p><p><br></p><p></p>Regards,<br>Vojtech<br><br><br><hr
id=3D"=
zwchr"><div
style=3D"color:#000;font-weight:normal;font-style:normal;text-d=
ecoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>F=
rom: </b>"Christopher Morrissey"
&lt;Christopher.Morrissey(a)netapp.com&gt;<b=
r><b>To: </b>vszocs(a)redhat.com<br><b>Cc: </b>"George
Costea" <George.Cos=
tea(a)netapp.com&gt;, "Dustin Schoenbrun"
&lt;Dustin.Schoenbrun(a)netapp.com&gt=
;, engine-devel(a)ovirt.org<br><b>Sent: </b>Tuesday, October 2, 2012
6:15:34 =
PM<br><b>Subject: </b>RE: [Engine-devel] UI Plugins: PoC patch revision
5 i=
s here<br><br>
<style><!--
@font-face
=09{font-family:Wingdings;
=09panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
=09{font-family:Wingdings;
=09panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
=09{font-family:Calibri;
=09panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
=09{font-family:Tahoma;
=09panose-1:2 11 6 4 3 5 4 4 2 4;}
p.MsoNormal, li.MsoNormal, div.MsoNormal
=09{margin:0in;
=09margin-bottom:.0001pt;
=09font-size:12.0pt;
=09font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
=09{mso-style-priority:99;
=09color:blue;
=09text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
=09{mso-style-priority:99;
=09color:purple;
=09text-decoration:underline;}
p
=09{mso-style-priority:99;
=09mso-margin-top-alt:auto;
=09margin-right:0in;
=09mso-margin-bottom-alt:auto;
=09margin-left:0in;
=09font-size:12.0pt;
=09font-family:"Times New Roman","serif";}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
=09{mso-style-priority:99;
=09mso-style-link:"Balloon Text Char";
=09margin:0in;
=09margin-bottom:.0001pt;
=09font-size:8.0pt;
=09font-family:"Tahoma","sans-serif";}
span.BalloonTextChar
=09{mso-style-name:"Balloon Text Char";
=09mso-style-priority:99;
=09mso-style-link:"Balloon Text";
=09font-family:"Tahoma","sans-serif";}
span.EmailStyle20
=09{mso-style-type:personal;
=09font-family:"Calibri","sans-serif";
=09color:#1F497D;}
span.EmailStyle23
=09{mso-style-type:personal-reply;
=09font-family:"Calibri","sans-serif";
=09color:#1F497D;}
.MsoChpDefault
=09{mso-style-type:export-only;
=09font-size:10.0pt;}
@page WordSection1
=09{size:8.5in 11.0in;
=09margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
=09{page:WordSection1;}
@list l0
=09{mso-list-id:180434570;
=09mso-list-template-ids:-282402880;}
@list l0:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l0:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l0:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l0:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1
=09{mso-list-id:259874230;
=09mso-list-template-ids:-1105409970;}
@list l1:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l1:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l1:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l1:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2
=09{mso-list-id:580258439;
=09mso-list-template-ids:-6366690;}
@list l2:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l2:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l2:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l2:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3
=09{mso-list-id:713581435;
=09mso-list-template-ids:2069783976;}
@list l3:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l3:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l3:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l3:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4
=09{mso-list-id:765921994;
=09mso-list-template-ids:400719310;}
@list l4:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l4:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l4:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l4:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5
=09{mso-list-id:843908114;
=09mso-list-template-ids:-1243547606;}
@list l5:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l5:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l5:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l5:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6
=09{mso-list-id:964771435;
=09mso-list-template-ids:-2000783132;}
@list l6:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l6:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l6:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l6:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7
=09{mso-list-id:1176848642;
=09mso-list-template-ids:1223565722;}
@list l7:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l7:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l7:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l7:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8
=09{mso-list-id:1311206220;
=09mso-list-template-ids:314224160;}
@list l8:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l8:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l8:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l8:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9
=09{mso-list-id:1434012829;
=09mso-list-template-ids:-690447050;}
@list l9:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l9:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l9:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l9:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10
=09{mso-list-id:2135564416;
=09mso-list-template-ids:728504136;}
@list l10:level1
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0B7;
=09mso-level-tab-stop:.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Symbol;}
@list l10:level2
=09{mso-level-number-format:bullet;
=09mso-level-text:o;
=09mso-level-tab-stop:1.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:"Courier New";
=09mso-bidi-font-family:"Times New Roman";}
@list l10:level3
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:1.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level4
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level5
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:2.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level6
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level7
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:3.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level8
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.0in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
@list l10:level9
=09{mso-level-number-format:bullet;
=09mso-level-text:\F0A7;
=09mso-level-tab-stop:4.5in;
=09mso-level-number-position:left;
=09text-indent:-.25in;
=09mso-ansi-font-size:10.0pt;
=09font-family:Wingdings;}
ol
=09{margin-bottom:0in;}
ul
=09{margin-bottom:0in;}
--></style>
<div class=3D"WordSection1">
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Hi
Vojtech,</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">The patch is great
and ha=
s cleared up some questions I had about the implementation. I=E2=80=99ve be=
en able to get the sample plugins working and waded through the
code changes, so feel like I have a good understanding of what was deliver=
ed. Thanks a lot for putting this all together. I do have a few questions a=
nd suggestions for you, though.</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Will there
eventually be =
a way to add one or more buttons to the context sensitive buttons and menus=
throughout the interface? For example, we=E2=80=99d like to allow
a button to provision a datastore when a data center, cluster, or host is =
selected. When the button is clicked, it would open a dialog with an iframe=
in which we would load our interface to perform the associated action. Som=
e contexts would have several buttons,
such as a storage domain (provision, resize, dedupe management, destroy) s=
o it would probably make sense for a drop down menu to be available as well=
so that the number of buttons above the table doesn=E2=80=99t get too clut=
tered. We=E2=80=99d also like to add these same
actions to the menus that popup when a contextual object is right clicked.=
</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">If needed we can
help wor=
k on an implementation for the dialog popup plugin framework as we=E2=80=99=
d like to get it in relatively quickly so we can move forward on
the content side of our plugin.</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">For the reverse
proxy, wo=
uld it be easier from a customer standpoint to just include a reverse proxy=
servlet such as this one? </span><a
href=3D"http://sourceforge.net/p=
rojects/j2ep/"
target=3D"_blank">http://sourceforge.net/projects/j2ep/</...
</p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I=E2=80=99m just
thinking=
that setting up and managing a plugin for the HTTP server may be more comp=
lex than including one internally that would be transparent to a
customer.</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Thanks,</span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Chris</span></p>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class=3D"MsoNormal"
style=3D"margin-bottom:12.0pt"><b>From:</b> Vojtech =
Szocs <<a href=3D"mailto:vszocs@redhat.com"
target=3D"_blank">vszocs@red=
hat.com</a>><br>
<b>Date:</b> September 21, 2012 4:37:31 PM EDT<br>
<b>To:</b> engine-devel <<a
href=3D"mailto:engine-devel@ovirt.org" targe=
t=3D"_blank">engine-devel(a)ovirt.org</a>&gt;<br>
<b>Subject:</b> <b>[Engine-devel] UI Plugins: PoC patch revision 5 is
here<=
/b></p>
</div>
</blockquote>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<div>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt"><span
style=3D"color:=
black">Hi guys,<br>
<br>
it's been a while but here comes the latest revision of UI Plugins proof-of=
-concept patch (please find it attached).<br>
<br>
This revision was originally meant to focus solely on server-side component=
s of the plugin infrastructure. However, I ended up implementing all the ma=
jor concepts and ideas as discussed on engine-devel mailing list, impacting=
both client-side and server-side
parts of the plugin infrastructure. As a result, UI plugin infrastructure =
should be pretty much complete now, so we can focus on specific plugin API =
features in upcoming PoC revisions.<br>
<br>
There's a whole bunch of changes and improvements in this revision, so I'll=
try to cover all the relevant parts step by step. If you have any comments=
, questions or ideas, please let me know!<br>
<br>
So here we go... (or if you just want to get the patch, find the link at th=
e end of this message)</span></p>
<div class=3D"MsoNormal" style=3D"text-align:center"
align=3D"center"><span=
style=3D"color:black">
<hr align=3D"center" size=3D"2" width=3D"100%">
</span></div>
<p class=3D"MsoNormal"><span
style=3D"color:black"><br>
<strong>0. Added new Engine configuration values</strong><b><br>
</b><br>
<u>UI plugin data path</u> is represented by
<em>ConfigValues.UIPluginDataP=
ath</em> enum option ("UIPluginDataPath" in
<i>vdc_options</i> table), and resolved relative to
<i>ConfigValues.DataDir=
</i> if possible. Following (default) values:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l0 level1 lfo1">
<i>UIPluginDataPath =3D ui-plugins</i></li><li
class=3D"MsoNormal" style=3D=
"color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0=
level1 lfo1">
<i>DataDir =3D /usr/share/ovirt-engine</i></li></ul>
<p class=3D"MsoNormal"><span style=3D"color:black">result
in UI plugin data=
path: <i>
/usr/share/ovirt-engine/ui-plugins</i><br>
<br>
<u>UI plugin config path</u> is represented by
<i>ConfigValues.UIPluginConf=
igPath</i> enum option ("UIPluginConfigPath" in
<i>vdc_options</i> table), and resolved relative to
<i>ConfigValues.ConfigD=
ir</i> if possible. Following (default) values:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l3 level1 lfo2">
<i>UIPluginConfigPath =3D ui-plugins</i></li><li
class=3D"MsoNormal" style=
=3D"color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list=
:l3 level1 lfo2">
<i>ConfigDir =3D /etc/ovirt-engine</i></li></ul>
<p><span style=3D"color:black">result in UI plugin config path:
<i>/etc/ovi=
rt-engine/ui-plugins</i></span></p>
<p class=3D"MsoNormal"><span
style=3D"color:black"><br>
<b>1. Processing UI plugin data on the server<br>
</b><br>
<i>PluginDataManager</i> is the class responsible for reading, validating a=
nd caching UI plugin descriptor/configuration data on the server (Engine). =
It has two main responsibilities:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l2 level1 lfo3">
return a snapshot of currently valid plugin data (<i>getCurrentData</i> met=
hod)</li><li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:au=
to;mso-margin-bottom-alt:auto;mso-list:l2 level1 lfo3">
reload plugin data from local file system if necessary (<i>reloadData</i> m=
ethod)</li></ul>
<p><span style=3D"color:black">The <i>reloadData</i>
method doesn't modify =
"live" plugin data directly. Instead, it creates a local working copy of cu=
rrent plugin data, updates this copy as it reads/validates plugin descripto=
r and configuration files, and attempts
to update "live" plugin data through conditional reference re-assignment (=
using <i>
java.util.concurrent.atomic.AtomicReference.compareAndSet</i> method).</spa=
n></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">In other words,
<i>reloadData</i> method mak=
es no attempts with regard to Java lock-based synchronization, in favor of =
dealing with "live" data through
<i>AtomicReference</i> (reference that involves atomic
<i>volatile</i> read=
s and writes):</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l4 level1 lfo4">
In the best case, a thread will succeed in updating "live" data
(<i>AtomicR=
eference.compareAndSet</i> =3D=3D true), which means that "live" data
remai=
ned unchanged since this thread acquired a reference of current plugin data=
.</li><li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;=
mso-margin-bottom-alt:auto;mso-list:l4 level1 lfo4">
In the worst case, a thread will NOT succeed in updating "live" data
(<i>At=
omicReference.compareAndSet</i> =3D=3D false), which means that "live"
data=
was already changed by another thread since this thread acquired a referen=
ce of current plugin data.</li></ul>
<p><span style=3D"color:black">In my opinion, when dealing with
external re=
sources like the local file system, this is a good compromise between perfo=
rmance and up-to-date data. While we might not get "completely-up-to-date" =
data at the given point in time (<i>reloadData
+ getCurrentData</i>), we are guaranteed to get "recently-up-to-date" and
=
consistent data. In other words, the requirement of "completely-up-to-date"=
data would involve
<i>synchronized</i> statements that would hurt performance. In my (very hum=
ble) opinion, the benefit of having "completely-up-to-date" data, at the co=
st of reduced performance, is not really worth it, especially in our case w=
hen the user can just hit refresh
(F5) to reload WebAdmin and its plugin data.</span></p>
<p><span style=3D"color:black"> </span></p>
<p><u><span style=3D"color:black">Plugin descriptor
files</span></u><span s=
tyle=3D"color:black"> are expected to be placed in UI plugin data path, for=
example:
<i>/usr/share/ovirt-engine/ui-plugins/foo.json</i></span></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">Following descriptor file attributes
are imp=
lemented and recognized by the plugin infrastructure:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l9 level1 lfo5">
<i>name</i>: A name that uniquely identifies the plugin (required attribute=
).</li><li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto=
;mso-margin-bottom-alt:auto;mso-list:l9 level1 lfo5">
<i>url</i>: URL of plugin host page that invokes the plugin code (required =
attribute).</li><li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top=
-alt:auto;mso-margin-bottom-alt:auto;mso-list:l9 level1 lfo5">
<i>config</i>: Default configuration object associated with the plugin (opt=
ional attribute).</li><li class=3D"MsoNormal"
style=3D"color:black;mso-marg=
in-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l9 level1 lfo5">
<i>resourcePath</i>: Path to plugin static resources, relative to UI plugin=
data path (optional attribute). This is used when serving plugin files thr=
ough Engine
<i>PluginResourceServlet</i> (more on this below).</li></ul>
<p><u><span style=3D"color:black">Plugin configuration
files</span></u><spa=
n style=3D"color:black"> are expected to be placed in UI plugin config path=
, for example:
<i>/etc/engine/ui-plugins/foo-config.json</i></span></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">Note that plugin configuration files
follow =
the "<descriptorFileName>-config.json"
convention.</span></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">Following configuration file
attributes are =
implemented and recognized by the plugin infrastructure:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l8 level1 lfo6">
<i>config</i>: Custom configuration object associated with the plugin (opti=
onal attribute). This overrides the default plugin descriptor configuration=
, if any.</li><li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-a=
lt:auto;mso-margin-bottom-alt:auto;mso-list:l8 level1 lfo6">
<i>enabled</i>: Indicates whether the plugin should be loaded on WebAdmin s=
tartup (optional attribute). Default value is 'true'.</li><li
class=3D"MsoN=
ormal" style=3D"color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:a=
uto;mso-list:l8 level1 lfo6">
<i>order</i>: Defines the relative order in which the plugin will be loaded=
on WebAdmin startup (optional attribute). Default value is
<i>Integer.MAX_VALUE</i> (lowest order).</li></ul>
<p><span style=3D"color:black">The concept of merging custom
configuration =
(<i>config</i> attribute in
<i>foo-config.json</i>), if any, on top of default configuration
(<i>config=
</i> attribute in
<i>foo.json</i>), if any, remains unchanged. This makes the plugin configur=
ation quite flexible - in my opinion, the added complexity of handling/merg=
ing such configuration is definitely worth the effort.</span></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">The <i>enabled</i>
attribute is straight-for=
ward, allowing users to turn the given plugin off, if necessary. In future,=
users should still be able to load such plugins through WebAdmin GUI.</spa=
n></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">The <i>order</i>
attribute controls the orde=
r in which plugins are loaded on WebAdmin startup. Since plugin resources a=
re fetched asynchronously by the browser, this is basically a way of imposi=
ng some degree of determinism in the
"generally-non-deterministic" plugin environment, which is helpful when tr=
oubleshooting problems with multiple plugins. This attribute is also helpfu=
l due to file listing methods in
<i>java.io.File</i> giving no guarantees that files would be listed in any =
particular order (otherwise we could just go for the "NN-<descriptorFile=
Name>.json" convention, with NN being the order
number).</span></p>
<p class=3D"MsoNormal"><span
style=3D"color:black"><br>
<b>2. Modified behavior of WebadminDynamicHostingServlet<br>
</b><br>
<i>WebadminDynamicHostingServlet</i> is the servlet used to serve WebAdmin =
application host page (HTML page that bootstraps WebAdmin JavaScript code).=
<br>
<br>
In addition to its former behavior, as part of handling the given request, =
<i>WebadminDynamicHostingServlet</i>:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l7 level1 lfo7">
reloads descriptor/configuration data from local file system if necessary, =
and obtains a snapshot of currently valid plugin data (<i>PluginDataManager=
.reloadAndGetCurrentData</i>)</li><li class=3D"MsoNormal"
style=3D"color:bl=
ack;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l7 level1 l=
fo7">
embeds all plugin meta-data, suitable for use in client-side plugin infrast=
ructure, into WebAdmin host page as "pluginDefinitions" JavaScript array (<=
i>PluginDefinitions</i>)</li></ul>
<p class=3D"MsoNormal"><span style=3D"color:black">As a
result, reloading U=
I plugin descriptor/configuration data is as simple as refreshing (F5) WebA=
dmin application in the browser (no need to restart Engine).<br>
<br>
<b>3. Added servlet for serving plugin static resources<br>
</b><br>
<i>PluginResourceServlet</i> is the servlet used to serve UI plugin static =
files (plugin host page, 3rd party JavaScript, etc.) from the local file sy=
stem.<br>
<br>
For example, requesting URL:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l5 level1 lfo8">
<i><a>http://<EngineManagerHost>:8700/webadmin/webadmin/plugin/foo/co=
ntent/start.html</a></i></li></ul>
<p><span style=3D"color:black">will send the content
of:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l1 level1 lfo9">
<i>/usr/share/ovirt-engine/ui-plugins/<resourcePath>/content/start.ht=
ml</i></li></ul>
<p><span style=3D"color:black">to the
client.</span></p>
<p><span style=3D"color:black"> </span></p>
<p><span style=3D"color:black">As shown in the above
example:</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l10 level1 lfo10">
<i>/webadmin/webadmin/plugin/</i> is the servlet root path for
<i>PluginRes=
ourceServlet</i></li><li class=3D"MsoNormal"
style=3D"color:black;mso-margi=
n-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l10 level1 lfo10">
in the extra path beyond the servlet root path (<i>/foo/content/start.html<=
/i>):</li></ul>
<ul type=3D"disc">
<ul type=3D"circle">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l10 level2 lfo10">
<i>/foo</i> represents the name of the plugin</li><li
class=3D"MsoNormal" s=
tyle=3D"color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-=
list:l10 level2 lfo10">
<i>/content/start.html</i> represents the path to requested resource, relat=
ive to "UIPluginDataPath / <resourcePath>"</li></ul>
</ul>
<p class=3D"MsoNormal"><span style=3D"color:black">Note
that each plugin us=
ing <i>PluginResourceServlet</i> to serve its static files must declare non=
-empty
<i>resourcePath</i> attribute in within the plugin descriptor.<br>
<br>
Also note that <i>PluginResourceServlet</i>, unlike
<i>WebadminDynamicHosti=
ngServlet</i>, does NOT reload descriptor/configuration data from local fil=
e system as part of handling the given request. In other words, it's assume=
d that plugin data has already been
(re)loaded when serving WebAdmin application host page, with subsequent re=
quests to
<i>PluginResourceServlet</i> reading the current plugin
information.<br>
<br>
Until we solve the cross-origin issue in a clean way, <i>PluginResourceServ=
let</i> should be used to serve all plugin resources from local file system=
.<br>
<br>
<b>4. Plugin lifecycle improved to deal with misbehaving
plugins</b><br>
<br>
<i>PluginState</i> enum has been modified to deal with plugins that allow u=
ncaught exceptions to escape from plugin event handler functions (e.g. "UiI=
nit"):</span></p>
<ul type=3D"disc">
<li class=3D"MsoNormal"
style=3D"color:black;mso-margin-top-alt:auto;mso-ma=
rgin-bottom-alt:auto;mso-list:l6 level1 lfo11">
removed state <i>INITIALIZED</i></li><li
class=3D"MsoNormal" style=3D"color=
:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l6 level=
1 lfo11">
added state <i>INITIALIZING</i>: The plugin is (currently) being initialize=
d by calling UiInit event handler function.</li><li class=3D"MsoNormal"
sty=
le=3D"color:black;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-li=
st:l6 level1 lfo11">
added state <i>IN_USE</i>: Plugin's UiInit event handler function has
compl=
eted successfully, we can now call other event handler functions as necessa=
ry. The plugin is in use now.</li><li class=3D"MsoNormal"
style=3D"color:bl=
ack;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l6 level1 l=
fo11">
added state <i>FAILED</i>: An uncaught exception escaped while calling an e=
vent handler function, which indicates internal error within the plugin cod=
e. The plugin is removed from service.</li></ul>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt"><span
style=3D"color:=
black">I've attached a simple state diagram that illustrates different stat=
es and transitions between them (green color is initial state, red color is=
end state).<br>
<br>
Uncaught exceptions in plugin event handler functions will be caught and ha=
ndled by the plugin infrastructure. This prevents a misbehaving plugin from=
breaking WebAdmin application, since WebAdmin is the caller (initiator) of=
the function call. In such case,
the plugin will be removed from service.<br>
<br>
<b>Update on cross-origin issue (consequence of same-origin
policy)</b><br>
<br>
In order for the plugin to access WebAdmin plugin API, plugin host page (e.=
g. <i>
start.html</i>) must be served from URL on same origin as Engine origin. Ot=
herwise, plugin code running in the context of an iframe'd host page will f=
ail to evaluate "parent.pluginApi" expression, with "parent" being
top-leve=
l (WebAdmin) window, and "pluginApi"
being the global plugin API object exposed by WebAdmin.<br>
<br>
This is why <i>PluginResourceServlet</i>, available on Engine origin, shoul=
d be used to serve all plugin resources from local file system.<br>
<br>
There's only one issue that remains to be solved: cross-origin "plugin vs. =
remote service" communication, with "remote service" being anything other
t=
han Engine (REST API). In future, we'll address this with Apache reverse pr=
oxy configuration, so that users
can configure Apache server (placed in front of Engine JBoss AS) to put ar=
bitrary (local or remote non-Engine) services on same origin. However, this=
requires a change in current Apache configuration. Until then, users can m=
anually edit the Engine Apache configuration
file (<i>/etc/httpd/conf.d/ovirt-engine.conf</i>).</span></p>
<div class=3D"MsoNormal" style=3D"text-align:center"
align=3D"center"><span=
style=3D"color:black">
<hr align=3D"center" size=3D"2" width=3D"100%">
</span></div>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt"><span
style=3D"color:=
black"><br>
I've attached some sample plugin files for you to experiment with. Instead =
of attaching actual patch file (92 kB) to this email, I've submitted the pa=
tch to oVirt Gerrit:
<a
href=3D"http://gerrit.ovirt.org/8120"
target=3D"_blank">http://gerrit.ov=
irt.org/8120</a><br>
<br>
Let me know what you think!<br>
<br>
Cheers,<br>
Vojtech</span></p>
</div>
</div>
</blockquote>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p
class=3D"MsoNormal"><ui-plugin-sample-files.tar.gz></p>
</div>
</blockquote>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class=3D"MsoNormal"><ui-plugin-lifecycle.png></p>
</div>
</blockquote>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p
class=3D"MsoNormal">_______________________________________________<br>
Engine-devel mailing list<br>
<a href=3D"mailto:Engine-devel@ovirt.org"
target=3D"_blank">Engine-devel@ov=
irt.org</a><br>
<a
href=3D"http://lists.ovirt.org/mailman/listinfo/engine-devel"
target=3D"=
_blank">http://lists.ovirt.org/mailman/listinfo/engine-devel</...
</div>
</blockquote>
</div>
</div><br></div></body></html>
------=_Part_3896354_1791016925.1349203611679--