Enable OSProfiler support in Ironic

This patch does the following:
* Adds osprofiler wsgi middleware
  This middleware is used for 2 things:
  - It checks that person who wants to trace is trusted and knows
    secret HMAC key.
  - It starts tracing in case of proper trace headers
    and adds first wsgi trace point, with info about HTTP request.

* Adds initialization of osprofiler at start of service
  - Initialize and set an oslo.messaging based notifier instance
    to osprofiler, which will be used to send notifications to Ceilometer.

* Traces HTTP/RPC/DB API calls and SQL requests

NOTE to test this patch:
1) Make the following changes in localrc to configure DevStack to enable
   OSProfiler:

   enable_plugin panko https://git.openstack.org/openstack/panko
   enable_plugin ceilometer https://git.openstack.org/openstack/ceilometer
   enable_plugin osprofiler https://git.openstack.org/openstack/osprofiler

   # Enable the following services
   CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler
   ENABLED_SERVICES+=,ceilometer-acompute,ceilometer-acentral
   ENABLED_SERVICES+=,ceilometer-anotification,ceilometer-collector
   ENABLED_SERVICES+=,ceilometer-alarm-evaluator,ceilometer-alarm-notifier
   ENABLED_SERVICES+=,ceilometer-api

NOTE: the order of enabling plugins matters.

2) Run stack.sh. Once DevStack environment is setup, enable profiler options
   in ironic.conf and restart ironic services:
   [profiler]
   enabled = true
   hmac_keys = SECRET_KEY
   trace_sqlalchemy = true

3) Use openstackclient and run baremetal command with
   --os-profile SECRET_KEY
   [--profile can be used, but it is deprecated.]
   For example, the following will cause the <trace-id> to be printed
   after node list:

   $ openstack --os-profile SECRET_KEY baremetal node list
   .....
   .....
   Trace ID: <trace-id>
   Display trace with command:
   osprofiler trace show --html <trace-id>

4) The trace results can be saved using this command:

   $ osprofiler trace show --html <trace-id> --out trace.html

OSprofiler spec: https://review.openstack.org/#/c/103825/

Co-Authored-By: Tovin Seven <vinhnt@vn.fujitsu.com>
Co-Authored-By: Hieu LE <hieulq@vn.fujitsu.com>

Partial-Bug: #1560704

Change-Id: Icd3d7c62cf7442de8a77fc67f119ae9b03725f02
This commit is contained in:
Ramamani Yeleswarapu 2016-08-18 16:55:56 -07:00
parent 8e48156488
commit 3773f17403
17 changed files with 2298 additions and 3 deletions

View File

@ -711,6 +711,16 @@ For more information about the supported parameters see::
Always be careful when running debuggers in time sensitive code, Always be careful when running debuggers in time sensitive code,
they may cause timeout errors that weren't there before. they may cause timeout errors that weren't there before.
OSProfiler Tracing in Ironic
============================
OSProfiler is an OpenStack cross-project profiling library. It is being
used among OpenStack projects to look at performance issues and detect
bottlenecks. For details on how OSProfiler works and how to use it in ironic,
please refer to `OSProfiler Support Documentation <osprofiler-support>`_.
Building developer documentation Building developer documentation
================================ ================================

View File

@ -25,6 +25,7 @@ primarily for developers.
Ironic System Architecture <architecture> Ironic System Architecture <architecture>
Provisioning State Machine <states> Provisioning State Machine <states>
Developing New Notifications <notifications> Developing New Notifications <notifications>
OSProfiler Tracing <osprofiler-support>
These pages contain information for PTLs, cross-project liaisons, and core These pages contain information for PTLs, cross-project liaisons, and core
reviewers. reviewers.

View File

@ -0,0 +1,120 @@
.. _OSProfiler-support:
================
About OSProfiler
================
OSProfiler is an OpenStack cross-project profiling library. Its API
provides different ways to add a new trace point. Trace points contain
two messages (start and stop). Messages like below are sent to a collector::
{
"name": <point_name>-(start|stop),
"base_id": <uuid>,
"parent_id": <uuid>,
"trace_id": <uuid>,
"info": <dict>
}
The fields are defined as follows:
``base_id`` - <uuid> that is same for all trace points that belong to
one trace. This is used to simplify the process of retrieving all
trace points (related to one trace) from the collector.
``parent_id`` - <uuid> of parent trace point.
``trace_id`` - <uuid> of current trace point.
``info`` - the dictionary that contains user information passed when
calling profiler start() & stop() methods.
The profiler uses ceilometer as a centralized collector. Two other
alternatives for ceilometer are pure MongoDB driver and Elasticsearch.
A notifier is setup to send notifications to ceilometer using oslo.messaging
and ceilometer API is used to retrieve all messages related to one trace.
OSProfiler has entry point that allows the user to retrieve information
about traces and present it in HTML/JSON using CLI.
For more details see `OSProfiler Cross-project profiling library`_.
How to Use OSProfiler with Ironic in Devstack
=============================================
To use or test OSProfiler in ironic, the user needs to setup Devstack
with OSProfiler and ceilometer. In addition to the setup described at
`Deploying Ironic with DevStack`_, the user needs to do the following:
Add the following to ``localrc`` to enable OSProfiler and ceilometer::
enable_plugin panko https://git.openstack.org/openstack/panko
enable_plugin ceilometer https://git.openstack.org/openstack/ceilometer
enable_plugin osprofiler https://git.openstack.org/openstack/osprofiler
# Enable the following services
CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler
ENABLED_SERVICES+=,ceilometer-acompute,ceilometer-acentral
ENABLED_SERVICES+=,ceilometer-anotification,ceilometer-collector
ENABLED_SERVICES+=,ceilometer-alarm-evaluator,ceilometer-alarm-notifier
ENABLED_SERVICES+=,ceilometer-api
Run stack.sh.
Once Devstack environment is setup, edit ``ironic.conf`` to set the following
profiler options and restart ironic services::
[profiler]
enabled = True
hmac_keys = SECRET_KEY # default value used across several OpenStack projects
In order to trace ironic using OSProfiler, use openstackclient to run
baremetal commands with
``--os-profile SECRET_KEY``
For example, the following will cause a <trace-id> to be printed after node list:
``$ openstack --os-profile SECRET_KEY baremetal node list``
Output of the above command will include the following::
Trace ID: <trace-id>
Display trace with command:
osprofiler trace show --html <trace-id>
The trace results can be seen using this command::
$ osprofiler trace show --html <trace-id>
The trace results can be saved in a file with ``--out file-name`` option::
$ osprofiler trace show --html <trace-id> --out trace.html
Sample Trace:
.. figure:: ../images/sample_trace.svg
:width: 660px
:align: left
:alt: Sample Trace
.. figure:: ../images/sample_trace_details.svg
:width: 660px
:align: left
:alt: Sample Trace Details
References
==========
- `OSProfiler Cross-project profiling library`_
- `Deploying Ironic with DevStack`_
.. _OSProfiler Cross-project profiling library: http://docs.openstack.org/osprofiler/latest/index.html
.. _Deploying Ironic with DevStack: http://docs.openstack.org/ironic/latest/contributor/dev-quickstart.html#deploying-ironic-with-devstack

View File

@ -0,0 +1,793 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg3336"
version="1.1"
inkscape:version="0.91 r13725"
width="1187.8125"
height="352.5"
viewBox="0 0 1187.8125 352.5"
sodipodi:docname="sample trace.svg">
<metadata
id="metadata3342">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3340" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1053"
inkscape:window-height="405"
id="namedview3338"
showgrid="false"
inkscape:zoom="1.0195212"
inkscape:cx="593.90625"
inkscape:cy="176.25"
inkscape:window-x="104"
inkscape:window-y="104"
inkscape:window-maximized="0"
inkscape:current-layer="svg3336" />
<image
width="1187.8125"
height="352.5"
preserveAspectRatio="none"
style="image-rendering:optimizeQuality"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABPMAAAF4CAIAAAC+TStFAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAKIOSURBVHhe7f3/cxvHvfcL7v+EHxJUpcItVSLW
2Ye8lZBV8WWtcvHU3Yq8DnFOKvTmnoflkmhrL47kEKJrodAlKZKpZAVGN8RJZERF42ht0VobtklC
IjUQQ6xoEiJoCpJAmiAhkeAXGds90zPoGcyAGAJoA4P3q7rkmZ5Pd48xb/R83pzBzP9pCwAAAAAA
AAAAaGaosx2/NY6CgoKCgoKCgoKCgoKC0qSFOtsCaGa+/fZbtgSAKKA6IB6oDogHqgPigeqAeByj
OjjbpgczIBAPVAfEA9UB8UB1QDxQHRCPY1QHZ9v0YAYE4oHqgHigOiAeqA6IB6oD4nGM6uBsmx7M
gEA8UB0QD1QHxAPVAfFAdUA8jlEdnG3TgxkQiAeqA+KB6oB4oDogHqgOiMcxqoOzbXowAwLxQHVA
PFAdEA9UB8QD1QHxOEZ1cLZND2ZAIB6oDogHqgPigeqAeKA6IB7HqI53tpLfRfBLbLUeCBii5eC0
qHy8Rdq6+kZiGbaxJmwlwj5fhHWJo9m64LwLODJhrzzjGKnx5FBmrnMf9/jCyTzbWiHVzWC6yRA4
FuNcl0+E+j1tVDk1PMHiZAp0lMx1vDaU+dYbPrL2MHcBM2rgJiqSFi/pukx9cLZNTxktyri94VW2
vVqqnk+BUzBme6Cl+f6drYy7f0LYLUiYDFsF/Vy3NdHvVtTG6BpJsE0A1IySuY6fS6ucfDB3AXOq
dhNHkFZdXGHFznZLCvZ10b9Ttml/Gs9HfWTdE1L/TxMjHS5XB5vmTeIJuiG0kKP9vR0oWM+A+dVY
wEPOwu4BOd/Tb5XXVAEqmwb8gR63q80bWS0emuJfanTJq9zQMFwmFlT+lC0fzoRRV+EJn+c42Zs2
jz+KGbXZ0Wd7ACjwJzbiAbRlbZPiPdmEEwz76IzhPu4NSkVLan7uoJSb6yZ85PQjVxhns0OnJtaJ
1bj5JNlNOnUVN5ROhsCx6OY6RdQ9QTnNWQ1RGVSS8yhq/PH/9Q2ybJoy6aVoIjkZ668GcBjWcx3B
4B+s5jfTHBtzF7CkYjdhOheZSKuoQN1FX75z3UBmij0KFTrbxEgX3aahGPd8zEf+T9V5mje25vG6
IbYmBujEXcTti2GmPgJlZ0DlqLj8MbKo3yqvqfOasknB7f/K+Fdply+aN1Et32Fe8usPuasrICnH
k+9cAYe66dFlewAwdCmX4gLYdVTdSumcoM1FVucOSrnzbkSetGiFfjaTDp2alE6sxs1EvLrZUL4u
jOywhdDNdcrf8909AyFpVXcSK5/zKLjf/atVysRL0VRyhHJfDeAwyuZ1/DRrPb+Z59iYu4AlFbsJ
07moRFolN7jIVoLAd84t184VVuRsFQfbE5D/rJ5P0r9TKtMxb225Wdoynh9C+RD6cat/tZTXIjcF
6rfKa+q8pmzq8FMVbW3xUkoGe4px/HxK4DpcDXnIYpdPuRqbUa6fsEC18yiRQz7m57aApkWX7QHA
0E8RipuVT2bKYl9EOd0oc0KXP0ZXt2JyatYTSpY7d1BK5joDynlQP5slD52a6AxmOa5yMvcG5Qsh
yjU6pbFhMgSORT/X5aWAltO5j3v9EVkZh+U8qho3zVMmXopWkiv/1QAO47C5jiBPPmVSL8scG3MX
MKdCN2E9F1lLS2cl+M65ZUvF2qYiZ6sMp0fbQTZPy7OxnJuUi+eHWA0rf5h0H+852R8IS9X/z7Qm
FWrRuFVeUwXINtG/xTC2klIk5O8/qdwYwOIMqi12qKStJ4t/Qk6GqIqVsfTjxvhxQbOiz/YAUDBM
EVuRPsVvKpe69FMHO10QitNFmXMNwTrbI2cR7VYn3WxW4dRkNW5Jcw3D/ylwLCVzHX1GivIIKRn6
Q1tr3erUSDBNmXgpWkmu/FcDOAzruU7DdILi5zerHBtzFzCnQjdhPReVSsvUSvCd88s1c4VHdrbq
V0menr3hCfof9SYb63jDEPnVRCTk6+tR/p/V5sAW5bWo/P239G5kZUJUBahvmIn0tbk6+kOxZGYr
yQvVoNpiKyVvtZhe9Z3La7zwQTNSku0BQDCe2BRr64/FaD5frJZngeIVp/LOtjivlJ/rVHSbKpya
rMaFswVWc91WMhYaoNdv3QHJWrclQjVLmfgwO87WTJjAEZSd64qTT9n5jWCaY2PuAuZU6Cas5yK9
tCytBN+5YaDauMLK7kaWvzyeEfnSsxH5f7ajg5+lreOthkjwF6qBLcpocSsRon8BYfeqK1u98lFi
fxpRP3FdQ1Wbsk6VX6+xOGWLNotyrUxviWG3Hur3Sl7DkW52rLI90NqU5Eyyte3weHRpPJsTOnwT
NE53N3K5c80h510V/abKpibLcZWTuXrf9AS9Ccstd22YDIFj4ec6RSdMuEQEVN3U2drJeUxSJl2Y
heTKfzWAwyg713HTbLn5jYfPsTF3AXMqdBPWc5FOWqpM6YreSvCdl8pboSpXWOpsDcjj8T8tUfBo
N5KxvxHp9sAynvt/MP4CWTfNg8op0aIB7Tndyt+CdajHTKctfZzbTfTI4opb5MstfCsidapbDtPH
tLC1I6oVNAx8tgeACpdyMWRrSynefGw2U7m9yo9ryp5rymZ7GoZNlU1NluMaH+ej1hsmQ+BYdHNd
XpKfFMEjy6mSnEfFJGXShVlIruxXAziMsnMdP81az2+WOTbmLmBOpW7Cci7SScvaSvCS5pZr5wor
c7aETGyEPYy5zdMf0ll15Y9Ghr8SmcfrvqI0pEd+sn0t33jeclhr0X3c0x/kP9bVCfUlGyOxCI1V
T62648LHBaWM/NcZdnTzieBJelDbZBkbWsmPnqfHs+yrNeQ1/pQOmhFdtgcAo9TZqtaWN7ZsTvCF
ItpEk1C8JsX6XFM229Mo3VTZ1GQ1LvcKlq6+4uuJ9JMhcCzGua6oE33iUkHOwzBJmfRhFpIr89UA
DqPsXGeYZq3mN1kvZjk25i5gig03YTEX6aVlZSV4SevkbaVYu/DOFjQl8BhAPFAdqBDlD7c6Y2uS
q1VEjVWXjw6U7BkABjDXAfFAdUA8jlEdnG3TgxkQiAeqA5WxKl9eMNxU9P072+KNUuw2aADMwVwH
xAPVAfE4RnVwtk0PZkAgHqgOHI5iYNs8vgnDj2W+f2ebDHnku/d090EDUArmOiAeqA6IxzGqg7Nt
ejADAvFAdUA8UB0QD1QHxAPVAfE4RnVwtk0PZkAgHqgOiAeqA+KB6oB4oDogHseoDs626cEMCMQD
1QHxQHVAPFAdEA9UB8TjGNXB2TY9mAGBeKA6IB6oDogHqgPigeqAeByjOups3wbNDNEiWwJAFFAd
EA9UB8QD1QHxQHVAPI5RHa7ZNj1Ei2wJAFFAdUA8UB0QD1QHxAPVAfE4RnVwtk0PZkAgHqgOiAeq
A+KB6oB4oDogHseojjnbdDr98OHDWB0g3ZLOlcFAPeC1uL63/zC3PZnNfbGBglLLQnS1uX/AdIbz
Lvg+gOqAeKA6IB6oDojHMaqjzvbp06dff/31y5cvv6sDpNuFhQWY2/qhaZHYWoMbQUGpbdHMLc67
QDxQHRAPVAfEA9UB8ThGddTZxuNx4j9f1Y0XL16QIcgCGxPUFE2LD3PbBh+CglLbQjSmiA3nXSAe
qA6IB6oD4oHqgHgcozrqbGOx2H6dIUMcHBRvZQQ1RNOiwYSgoNS8TGZzithw3gXigeqAeKA6IB6o
DojHMapjznZvb293d7d+/yrmmY0JaoqmRYMJQUGpR1HEhvMuEA9UB8QD1QHxQHVAPI5RHXO2+ToD
Z1s/NC0aHAgKSj2KIjacd4F4oDogHqgOiAeqA+Kpger219JZtvg9wpztzs7O9vb20f/dmP7jL9tc
LvdP/7e/zG+YxMDZ1g9NiwYHgoJSj6KIDeddYMJWIuzzRTJsrRwVRUp+F8EvsdWKVZcM9fRP4HV2
oCZAdUA8UB0QD6e6tfClqWODxdI5PHt55lBNfktaDcXZigXLQ4NKjLZQe5izfVkVTyP/m7t3bJVk
K7HBjv/2x1lWzQFnWz80LRocSAuWyI03aCbMeOPCIqlcuDjwyx+RtR//8s3by1zwwtDr7jej2ipK
pUURW6XnXdBCZMJe8k3zhg93thVGHtHZkt77Ikj2QG2A6oB4oDogHk511NlytnN7/dF87+D0UJxl
gBYYWpWn/s72xYsXuVzuiP+uf/q/u7wfPtt9+WJnf36ko+PKbEkMnG390LRocCAtXebH3vzzHFn4
+NbvTvx5gdasfPLmz84H1YC/vv/aD37ogrM9QlHEVuF5F7QMilllqJ41Ewv2e9pIhfu4xxdOKBmY
SeSWFOzronEuV1tX30iMOd4yzpZs8gYjQe9xN+3cG0zk2QbS2UQ/Gz+fDPs8NILtQLIYBECFQHVA
PFAdEA+nOhOPmpuROofm5pSVF+nw9Xvt8uXc3huLy9TeFS/z9t5eI+u5pcSZ4SklpnNYCi8p2WPp
Ndvcwm3JYwyrCuZsNzc3yYL+3y//g35JTPmPL/nI5b/3ugZnduTl1Zte1/+4vcr3Q/+Fs60fmhYN
DqSFy9zv+4N/L6n0vX7pr/Ly3ejZ13yTV3wlzjZ69oRv5Ne/cLt+/JsLDyb/nSz88LV3outfzH/0
bydo2v2jE+9cpNeBW7ooYuNmQAAIpX41L/m72DqjKyCRfKskkqRnckZWxBeV87Lyztbl9oZks7wa
9ro7RhLKBtpbTygpLwy4u/wxxU7TGJe3ohulAeCB6oB4oDogHk51pldfk+cGp0dTZCFDtvaOP6Hp
4P7anevT7dcX5dSQa5X9+tTg9NDMJl3efxYipvfSo3W6UuJsl+a6B2fvZPcKhb30J7PtmnmugqKz
zWaz+n/v/V7OMcz4/T0+cun/8Gg13xBn23szxfdD/4WzrR+aFg0OpGXLx3/73b99uq6vXBj611++
STwqWZ4f++//OvaPjVzQzNm6Xg+STXdvv6UsfBE9/1PfZOTGGyf+PPfxM31wqxZFbNwMCICCYlnZ
NYTCashD1rp8UXk1M+HrKG7UR/Ikgz3FLYc4W3+MrdDu1M7yUV8x8+PgYwCoHKgOiAeqA+LhVGfq
bNXKR3OdgfllVlko7CyeodaULJm2oqRv3zt2KZGmiyXONh4/NiRNZmvpEJmzJf8/Gxsb+n9jZZwt
aVCMTBE3q9ak/u51/Y//z1O+H/ovnG39IJ+wsmBwIK1aFn6vXptlZfGTN0/87vcPmNc1/BZ3iL8G
Gz372g351mVicX2TdGFx7ARZeDbj+9ef/8jl+tHPfndhnotvyaKITVMdACo0odJc6dZEP1k5GV6V
NxGSIepZFZuqi5TZSkqRkL//pHJPMttymLNVN/CZnOTv4pI9udtAwNfXQztGtgfsA9UB8UB1QDyc
6kw9aiY0TCupTZVvHuaKci1X32o/uxD/enQsfubqdDeJsXK2RNRXaSedl6TRu0/SOzWwikVnu76+
rv83f8BiSjnI6yL/vz5X762v5eXZKx0dHzzM8Vvpv3C29YN8wsqCwYG0aHkQ7FZMqVJWPvr1/3op
uMIFqMX0mu2JG/JTpgzOVg34+NZbPxjkOm/JoohNUx0AKjq/mo/6yEpFzjYT6WtzdfSHYsnMVpLf
cgRnmxjpUqvzUqDLfdzrC4ajUjKTDOE6BjgKUB0QD1QHxMOpztTZsruRuQuwBrhWO8tDAWpWL99e
nFn6dmHc+potZX939UlkXOodIhZ39g79lW5VMGebyWTW1taO+G8280m/+9fBh2trjz8519ExMrdd
EgNnWz80LRocSGuWu7ffYe5ULn99/7/R3JhxVnuCFCmVO9u70UvdP6E/BKS/s8U1WxluBgRAQfGr
qpk1vRuZPcdTF6mseOWVTET+yS1Ly+w728RIB/uNrmytDcYa2R6wD1QHxAPVAfFwqjNxtrnYbHtg
boEsxePtg9JnO0o1T7HVbmz22HDR/S6PT5d1thrpy4Gp396t9pW4zNk+r4rN3efRwf+lzeX64U//
Ryj5YnuN1ReBs60fmhYNDgQFpR5FERs3AwKgoNyATJF//UXSLcODoZQnSBkjiysUt5s0YmmZbWdL
Urriyx0lv9vtU9a2pBEP6VZ52goAdoDqgHigOiAeTnUGZ2t46096dHiq+/pimrq67fRXUncgPkON
Lm116isSsy+7X/ZcqPX43K8Gp46xn+Yane1uTGoPxCdpZKGQSvQO3gvRG5urgjnbp0+fPnv27Mj/
Zjbz+9/J/R3svtwwiYGzrR+aFg0OBAWlHkURGzcDAsDIJ4In24gXbfOwtEp+64/ysoriW38o+sjV
CR99NxB9o4WUke9iVq7t2nW25L/FZE8ehL0pw9MfkmIjXeozlwGoHKgOiAeqA+LhVEc9Kv9L2u5h
KfxIftCxQjY1eo299af7anxyjfm79N37tPIG8bC5ufD9TjnAc21+ZoY+AFm+zFt6zTY3Nz6rvPWn
fej+H2ZqkFsyZ5uuM3C29UPTosGBoKDUoyhi42ZAAAQB1QHxQHVAPFAdEI9jVMec7erq6pMnT+r3
L5xt/dC0aHAgKCj1KIrYcN4F4oHqgHigOiAeqA6IxzGqY872mzoDZ1s/NC0aHAgKSs3LJJwt+P6A
6oB4oDogHqgOiMcxqqPO9sGDB8lkMlU3lpaWyBBwtnVC0+LD3LbBh6Cg1LYQjSliw3kXiAeqA+KB
6oB4oDogHseojjpbYj7j8fji4uJyHSDdSpJEFg4OrN+PC6pA0+L63r7Bh6Cg1LZs7rNvMc67QDxQ
HRAPVAfEA9UB8ThGddTZvnz58vHjx8R/xuoA6ZZ0vr29/erVKzYmqCm8Fom5fZjbniwxJCgoVRai
K83WEnDeBeKB6oB4oDogHqgOiMcxqqPOdn9/n5hbsrBZBxTnjFuR6wdmQCAeqA6IB6oD4oHqgHig
OiAex6iOOlvyn1evXh0cHBD/WQ9wtbauYAYE4oHqgHigOiAeqA6IB6oD4nGM6pizBc0LZkAgHqgO
iAeqA+KB6oB4oDogHseoDs626cEMCMQD1QHxQHVAPFAdEA9UB8TjGNWZO9tsNqu8rafmLC8vk87Z
MKAWaFpU3vqjvZcFgPqB8y4QD1QHxAPVAfFAdUA8jlGdibMlznNlZeXZs2eZOkC6JZ1vbGywwUDV
aFrUHmOrrAJQP3DeBeKB6oB4oDogHqgOiMcxqjNxtqlUqk62VoF0ToZgg4Gq0bQIZwuEgfMuEA9U
B8QD1QHxQHVAPI5RnYmzXVpaYh60bpAh2GCgajQtwtkCYeC8C8QD1QHxQHVAPFAdEI9jVAdn2/Ro
WoSzBcLAeReIB6oD4oHqgHigOiAex6jOhrNNpVJjY2NnZMjC48eP2Qb7wNnWEE2LcLZAGDjvAvEI
UV0mYzwlgpYGcx0Qj1jVYdIDlBqobn8t3QDPCK7U2RJbe+XKlbc4Ll68WMbcPn/+/NNPP/373//O
1vXA2dYQTYtwtkAYyPZA/ZH8LoJfYqu86uim4oaakYl469EtaGJqNNfVSbHAmVSgulopCpMeYHCq
Wwtfmjo2WCydw7OXZw7V5Lek1VCcrViwPDSoxGgLtadSZzs1NcUcLcfbb799+vTpsbEx4ntZnMzT
p08/+eQTsumjjz5iVXrgbGuIpsUvNpav+H75I5erzeObWFXqAKgLNcr2ALABp7p6OdswkjygB3Md
EE8FqquZs8WkBxQ41VFny9nO7fVH872D00Px8lfODK3K0wDOdnx8nNlZM4i5TafTLFQODofDn332
GZytADQt3v30nX8Z+CiykSushr0nQ/C2oH4g2wMcWxP9Lperf0I+mdBLAPRSa0zelAz1uFxumjht
ScG+rja6yX3c4wsn8/J2QiY24j3udrl7BiZWYyRbc3nDGXkDTd345I1THZfVkenO3eWPyWPnk2Gf
h47hPu71R5U5UPK7O0YS8iKB7KpHnhy5ULY3NMNTYDvA9zYSU/ZJHtobjATpLtMNwYT2P2I2Omh2
9KrzBqPKQXYf7w8nMwlFB/xfk2UV0EpOWgRNsdb6AUDFfK5TJik2PdH6gRFNgNqMWia+VHiGSc+q
LWgJONWZeNTcjNQ5NDenrLxIh6/fa5cv5/beWFzeJ1XFy7y9t9fIem4pcWZ4SonpHJbCS4orLr1m
m1u4LXmMYVVxuLN9/vz5559//u677zIXa8b58+cXFxdZg0xme3v74OBgcnISzlYAmhYjN954M6rc
jUxmJJZlMiS/1x8c6HG72voiSSlAFtw9I1K+sDqhZGL0xIwJDFQMNwMCoORHsn8t5KM+OVFS3KS2
YWtiQE72Ndy+mJyJJUMeVkPweOiKmk3RNItLtMyyvdVIX1uXL6rEE4/b5g0lFH8d9XW5fVE6BG9t
NWObDJLNqhXvVwPo7qrjEYeuOmZiVshygMyYBDq0mw1DXbXat8XooMkxqM7tlS1EPubvcLnb+sJU
TFt0RTncVOfq31lkebi8EVmdmmew0g8ARUzmOhnObdJ6F9OaPOGwpK9cvJnw+EnPqi1oCTjVmV59
TZ4bnB6l72zNkK2940+oB91fu3N9uv36ouxHuVbZr08NTg/NbNLl/WchYnovPVqnKyXOdmmue3D2
TnavUNhLfzLbrpnnKjjc2SaTyQsXLjALawFxtvwNyRsbG+Tfr776Cs5WAJoWP7711v/k++xj4mxp
pqafkMh85aX5XD46oCwUpECHXyIzlzeU3EL+BWzCzYAAsEuzcqokBZiDPUmSfuViLs35aZbkcvUr
WT5HYqSD1LP8THYClTvbCEnnuga0i2Wkq55Qkq0oFlvJ9YrWVjO2tIMO1YAU4ZI80ptqvin0f1Dt
jQytXJDmkz/L0UFzY1SdeujJivK3HEqMnGFNPADnDeS2NNxCPwBwGFVn4jZ1AixsRfrYH1HKxJsK
jy6q8VZtQUvAqc7U2aqVj+Y6A/PLrLJQ2Fk8Q60pWTJtRUnfvnfsUiJNF0ucbTx+bEiazNLLvrXi
cGe7srLy3nvvMQtrwc2bNzc3N1kDFThbMWha/GJj4WL/az+gd0kF/Ce1GUxG8tM0U15g8xaZtMhC
PqHcINjW1R9R80MADoWbAQEgyA6VWDvZ4vb7/fTfiS355mLF4DHXSuannpP9gbCkJEyK9WWzE8HO
3cgyHs1N0jzMCPOaxNrKS8Ruau6TXu2le+P1hSKJVeZgi0ke3TFdVkdGVNbNk78yo4OmxspjaIIo
WdlKSpFQIODr66EnV1avtTXXDwA8VqrjBKPTXAUCs6qni2q9VQxoCTjVmXrUTGiYVlKbKt88zBXl
Wq6+1X52If716Fj8zNXpbhJj5WyJ0K7STjovSaN3n6R3amBxD3e2uVzuwYMHZ8+eZS5Wz+nTp2/d
ukU6Ua7T8sDZikHT4hfRs//i++yucs22P6I7rpK/OLkp8xaZtLQJjKZxA+5AcRWA8nAzIAAU2dp6
AwFi8IhRJV7S5faPyHVabpRfTURCLN+nnpTY2WqcrTe8Sm9lJv+Rq8rlYWR3yHC8sZVRdoj+8Kxt
QLbfxSTvKM7WanTQzFh5DE0QupW8FOiify4JhqNSMpMMaarQ2prrBwAeK9VxgtEJUF5Vkrgy8ab1
dFGtt4oBLQGnOlNny+5G5i7AGuBa7SwPBahZvXx7cWbp24Vx62u2lP3d1SeRcal3iFjc2Tv0V7pV
UdETpHZ3d9k2Mw4ODkgnLJQDzlYMmhbVa7auNo+f/e5Mw8LZ5qUR5VEXeJwysAU3AwIgQ82sDL3z
V/21LW9siySCPeoW2RAf8W5kuiEx0uXWfsno5u8f5snHfG5vKGQwthpJsj99tBMuySt/N3Jp8ldm
dNDMWHkMslLUtrpCdV/8O42sGhaktbXQDwAcVqrTK4r7jTZVkskEZaZACic8btKzbAtaAk51Js42
F5ttD8wtkKV4vH1Q+mxHqeYpttqNzR4bLrrf5fHpss5WI305MPXbu9W+ErciZ3s04GzFoGkR77MF
wuBmQABkNDMr/xKCPSFZuyOXOFB5vQj7wesq9wQpt9dLW6nZFE2zuETLPNvLS/4O9uwUegVXfZxU
fpX+CJc99Emxtm538dZluq570I+yNzTJG2APfir3BCmzBLHM6KCJsfIYZKWY9msr8h84ZDUWtqQR
j5u7I561tdIPAEU41VGNqA+KmvB1uVXBUCFpT4SK9Hd0+JX5ply8mfDoojbpWbQFLQGnOoOzNbz1
Jz06PNV9fTFNbxzeTn8ldQfiM9To0lanviIx+7L7Zc+FWo/P/Wpw6hj7aa7R2e7GpPZAfJJGFgqp
RO/gvRC9sbkq6uhs9/b2Dg4O2IoeONsaomkRzhYIg5sBAVBQ7ixWn5tE/+CvPiFZJhMb6euRbxFx
tXX1Fd+iU8hE/fQJ7W2eEYnYVLJZzabklWIyZuUxiKUmbkJ5Mq0U6pef9m4YQrGyuiu2+YQa6ube
6ZORf33Lutbe4qPrzCpBLDc6aF4sVEdXiml/cSXPXgTkPu7pD0mxkS720GStrbV+AFDRnWHZOyzk
V/VENaVRzalv8dHfdWcZby483aRn3ha0BJzqqEflf0nbPSyFH8kPOlbIpkavsbf+dF+NT66xH8em
796nlTeIh83Nhe93ygGea/MzM/QByPJl3tJrtrm58VnlrT/tQ/f/MFOD3LKOzrYMcLY1RNMinC0Q
hu68C8CRoRkWQb4XmLoC+TblkicoK1SlOsnfVXTZAFQK5jogHqgOiMcxqoOzbXo0LcLZAmHgvAtq
hOVtyqVUobqtmN8TNP2NLQBlwVwHxAPVAfE4RnVwtk2PpkU4WyAMnHdBzViN+uV3jxHK38V7RNXR
n/y6e/CjV3AkMNcB8UB1QDyOUZ2Js11eXn727BnzoHWAdJ5KVf0DYaCiaRHOFggD510gHqgOiAeq
A+KB6oB4HKM6E2ebzWZXVlbqZG5Jt6TzjY0NNhioGk2LcLZAGDjvAvFAdUA8UB0QD1QHxOMY1Zk4
WwJxnqlUaqkOLC8vw9bWFk2LD3PbxNaSf5VVAOoHzrtAPFAdEA9UB8QD1QHxOEZ15s4WNBGYAYF4
oDogHqgOiAeqA+KB6oB4HKM6ONumBzMgEA9UB8QD1QHxQHVAPFAdEI9jVAdn2/RgBgTigeqAeKA6
IB6oDogHqgPicYzq4GybHsyAQDxQHRAPVAfEA9UB8UB1QDyOUZ25s81ms/V7ghTpnA0DakElWlzf
23+Y257Msocnt1Qh/+Ob+wfsgwA1AuddIB6oDogHqgPigeqAeByjOhNni7f+NBeHapHYWoPZa8EC
c1tbcN4F4oHqgHigOiAeqA6IxzGqM3G2qVSqTrZWgXROhmCDgao5VIvK24BavOBlSLUF510gHqgO
iAeqA+KB6oB4HKM6E2e7tLTEPGjdIEOwwUDVHKpFg8drzTKZzbGPA9QCnHeBeKA6IB6oDogHqgPi
cYzq4GybnkO1aPB4LVvYxwFqAc67QDxQHRAPVAfEA9UB8ThGdTacbSqVGhsbOyNDFh4/fsw22AfO
toYcqkWDwWvZwj4OUAtw3gXiEaK6TMZ4SgQtDeY6IB6xqsOkByg1UN3+WroBnhFcqbMltvbKlStv
cVy8eLGMuX3+/Pmnn37697//na3rgbOtIYdq0WDwWrawjwPUAmR7oP5IfhfBL7FVXnV0U3FDzchE
vPXoFjQxNZrr6qRY4EwqUF2tFIVJDzA41a2FL00dGyyWzuHZyzOHavJb0moozlYsWB4aVGK0hdpT
qbOdmppijpbj7bffPn369NjYGPG9LE7m6dOnn3zyCdn00UcfsSo9cLY15NAZ0GDwalGWr/h++SOX
60cn3rk4z9XPj514fSyirZrWfH+FfRygFtQo2wPABpzq6uVsw0jygB7MdUA8FaiuZs4Wkx5Q4FRH
nS1nO7fXH833Dk4Pxcsn0oZW5WkAZzs+Ps7srBnE3KbTaRYqB4fD4c8++wzOVgCHzoAGg1d9ufvp
O6+9P/kxXTj7L4OTcuX6P26ff+0XP/9p0ceW1nzPhX0coBYg2wMcWxP9Lperf0I+mdBLAPRSa0ze
lAz1uFxumjhtScG+rja6yX3c4wsn8/J2QiY24j3udrl7BiZWYyRbc3nDGXkDTd345I1THZfVrYa9
7i5/TB47nwz7PHQM93GvP7oqb5f87o6RhLxIILvqCdENXCjbG5rhKbAd4HsbiSn7JA/tDUaCdJfp
hmBC+x8xGx00O3rVeYNR5SC7j/eHk5mEooM2j29CPd6yCmglJy2Cplhr/QCgYj7XKZMUm55o/cCI
JkBtRi0TXyo8w6Rn1Ra0BJzqTDxqbkbqHJqbU1ZepMPX77XLl3N7bywu75Oq4mXe3ttrZD23lDgz
PKXEdA5L4SUlCS+9ZptbuC15jGFVcbizff78+eeff/7uu+8yF2vG+fPnFxcXWYNMZnt7++DgYHJy
Es5WAId6DIPBq2H5+NOz3Vfm5OX036NzH+uu0JbWqCV69oRv5Ne/cLt+/JsLDyb/nSz88LV3outf
zH/0bydoWkgvBS/qm9SisI8D1IJDVQdaCjk/kv1rIR/1yYmS4ia1DVsTA3Kyr+H2xeRMLBnysBqC
x0NX1GyKpllcomWW7a1G+tq6fFElnnjcNm8oofjrqK/L7YvSIXhrqxnbZJBsVq14vxpAd1cdjzh0
1TETs0KWA5K8w3RoNxuGumq1b4vRQZNjUJ3bK1uIfMzf4XK39YWpmLboinK4qc7Vv7PI8nB5I6qv
UKRlpR8AipjMdTKc26T1LqY1ecJhf1osF28mPH7Ss2oLWgJOdaZXX5PnBqdH6TtbM2Rr7/gTmlXv
r925Pt1+fVHOsLlW2a9PDU4PzWzS5f1nIWJ6Lz1apyslznZprntw9k52r1DYS38y266Z5yo43Nkm
k8kLFy4wC2sBcbb8DckbGxvk36+++grOVgCHegyDwatRSV980+X6yW9+P50uVi6W+NjSGlKiZ12v
B/+xkbt7+y1l4Yvo+Z/6JiM33jjx57mPn+mDa1fYxwFqwaGqA62FfGlWTpWkAHOwJ0nSr1zMpTk/
zZJcrn4ly+dIjHSQepafyU6gcmcbIelc14B2sYx01RNKshXFYiu5XtHaasaWdtChGpAiXJJHelPN
N4X+D6q9kaGVC9J88mc5OmhujKpTDz1ZUf6WQ4n5TT0A5w3ktjTcQj8AcBhVZ+I2dQIsbEX62B9R
ysSbCo8uqvFWbUFLwKnO1NmqlY/mOgPzy6yyUNhZPEOtKVkybUVJ37537FIiTRdLnG08fmxImszS
y7614nBnu7Ky8t577zELa8HNmzc3NzdZAxU4WzEc6jEMBq+mZcZ34p0/aV60Ymf72o0FZcHlk29m
JmFk4dmM719/Tn+++7PfXeB/vlujwj4OUAsOVR1oMWSHSqydbHH7/X7678SWfHOxYvCYa3W5j/ec
7A+EJSVhUqwvNcEKdu5GlvFobpLmYUaY1yTWVl4idlNzn/RqL90bry8USawyB1tM8uiO6bI6MqKy
bp78lRkdNDVWHkMTRMnKVlKKhAIBX18Pvfue1WttzfUDAI+V6jjB6DRXgcCs6umiWm8VA1oCTnWm
HjUTGqaV1KbKNw9zRbmWq2+1n12Ifz06Fj9zdbqbxFg5WyK0q7STzkvS6N0n6Z0aWNzDnW0ul3vw
4MHZs2eZi9Vz+vTpW7dukU6U67Q8cLZiONRjGAxe9eXjW7/rvjJzlyyvfPLmz47ibE/cWFYWdM5W
Dfj41ls/YD/frWVhHweoBYeqDrQasrX1BgLE4BGjSryky+0fkeu03Ci/moiEWL5PPSmxs9U4W294
ld7KTP4jV5XLw8jukOF4Yyuj7BD94VnbgGy/i0neUZyt1eigmbHyGJogdCt5KdBF/1wSDEelZCYZ
0lShtTXXDwA8VqrjBKMToLzqDpQTmFU9XVTrrWJAS8CpztTZsruRuQuwBrhWO8tDAWpWL99enFn6
dmHc+potZX939UlkXOodIhZ39g79lW5VVPQEqd3dXbbNjIODA9IJC+WAsxXDoR7DYPBqURYuDtBn
I//gJ2/4pteL9dU527vRS90/oVd1jI9crlFhHweoBYeqDrQc1MzK0Dt/1V/b8sa2SCLYo26RDfER
70amGxIjXW7tl4xu/v5hnnzM5/aGQgZjq5Ek+9NHO+GSvPJ3I5cmf2VGB82MlccgK0VtqytU98W/
08iqYUFaWwv9AMBhpTq9orjfaFMlmUxQZgqkcMLjJj3LtqAl4FRn4mxzsdn2wNwCWYrH2welz3aU
ap5iq93Y7LHhovtdHp8u62w10pcDU7+9W+0rcStytkcDzlYMh3oMg8Fr2cI+DlALDlUdaDk0Myv/
los9IVm7I5c4UHm9CPvB6yr3BCm310tbqdkUTbO4RMs828tL/g727BR6BVd9nFR+lf4Ilz30SbG2
bnfx1mW6rnvQj7I3NMkbYA9+KvcEKbMEsczooImx8hhkpZj2ayvyHzhkNRa2pBGPm7sjnrW10g8A
RTjVUY2oD4qa8HW5VcFQIWlPhIr0d3T4lfmmXLyZ8OiiNulZtAUtAac6g7M1vPUnPTo81X19MU1v
HN5OfyV1B+Iz1OjSVqe+IjH7svtlz4Vaj8/9anDqGPtprtHZ7sak9kB8kkYWCqlE7+C9EL2xuSrq
6Gz39vYODg7Yih442xpyqMcwGLyWLezjALXgUNWB1kO5s1h9bhL9g7/6hGSZTGykr0d5G0pbV1/x
LTqFTNRPX6PS5hmRiE0lm9VsSl4pJmNWHoNYauImlCfTSqF++b07hiEUK6u7YptPqKFu7p0+GfnX
t6xr7S0+us6sEsRyo4PmxUJ1dKWY9hdX8uxFQO7jnv6QFBvpYg9N1tpa6wcAFd0ZdnWCvWjKG0xE
NaVRzalv8eFfO1Um3lx4uknPvC1oCTjVUY/K/5K2e1gKP5IfdKyQTY1eY2/96b4an1xjP45N371P
K28QD5ubC9/vlAM81+ZnZugDkOXLvKXXbHNz47PKW3/ah+7/YaYGuWUdnW0Z4GxryKEew2DwWraw
jwPUgkNVB0BF0AyLIN8LTF2BfJtyyROUFapSneTvKrpsACoFcx0QD1QHxOMY1cHZNj2HatFg8Fq2
sI8D1AKcd0GNsLxNuZQqVLcV83uCpr+xBaAsmOuAeKA6IB7HqA7Otuk5VIsGg9eaZRLOtqbgvAtq
xmrU36c8LvmQu3iPqDr6k193D370Co4E5jogHqgOiMcxqjNxtsvLy8+ePWMetA6QzlOpqn8gDFQO
1eLD3LbB5rVgIR8C+zhALcB5F4gHqgPigeqAeKA6IB7HqM7E2Waz2ZWVlTqZW9It6XxjY4MNBqrm
UC2u7+0bbF4Lls39A/ZxgFqA8y4QD1QHxAPVAfFAdUA8jlGdibMlEOeZSqWW6sDy8jJsbW2pRIvE
3D7MbU+W+L1WKOR/HLa25uC8C8QD1QHxQHVAPFAdEI9jVGfubEETgRkQiAeqA+KB6oB4oDogHqgO
iMcxqoOzbXowAwLxQHVAPFAdEA9UB8QD1QHxOEZ1cLZND2ZAIB6oDogHqgPigeqAeKA6IB7HqA7O
tunBDAjEA9UB8UB1QDxQHRAPVAfE4xjVmTvbdDr98OHDWB0g3ZLO2TCgFmAGPDLswVpZ40OnUEqL
4UFcUB0QD1QHxAPVAfFAdUA8jlGdibMlznNhYeHly5ff1QHSLekc5raGYAY8GngZ0hGKZm6hOiAe
qA6IB6oD4oHqgHgcozqjs3316lU8Hn/x4gVZqBOkczIEWWBDgurADHg0Hua2DbYN5dBCPjTl04Pq
gHigOiAeqA6IB6oD4nGM6ozOdn9/PxaLkX/rChni4ACvGK0NmAGPhsGzoVRSJrM55dOD6oB4oDog
HqgOiAeqA+JxjOrMne3e3t7u7m79/lXMMxsSVAdmwKNh8GwoFRbl04PqgHigOiAeqA6IB6oD4nGM
6sydbb7OwNnWEMyAR8Ng2FAqLMqnB9UB8UB1QDxQHRCPWNVlMsbn7YBWpAaq219LZ9ni94i5s93Z
2dne3q7y38XQG+5zMdOtcLY1BOfdo2EwbCgVFuXTg+pA/ZH8LoJfYqu86uim4oajU6t+gGNpWtVB
201MBWfYWh3fTMQLnQAKp7q18KWpY4PF0jk8e3nmUE1+S1oNxdmKBctDg0qMtlB7zJ3ty2r59p+j
v2kjOcngDKvQA2dbQ+AxjobBsNWzLF/x/fJHLtePTrxzcV6pWf/rlTf+zz90uX78f/NNr5OayI03
aA7PeOPCota24Yry6UF1QDxQHRAPVAfEU4HqauZsw3C2QIZTHXW2nO3cXn803zs4PRRnGaAFhlbl
Ee5sX7x4kcvljvzv5KWf/s+nP4qFvK7B+6YxcLY1BOfdo2EwbPUrdz9957X3Jz+mC2f/ZXCSVk5f
+tWVGVLzxeKHvzoR/DsX/MX82Jt/niuuNl5RPj2oDnBsTfS7XK7+CflkQi8BEPwxeVMy1ONyuWni
tCUF+7roHzxd7uMeXziZl7cTMrER73G3y90zMLEaI9mayxvOyBto6sYnb5zqtKyOLPjDkT7Sr3sg
SsfPJ8M+Dx3Gfdw7ElM6ksO8wUiQjkM3BBNsdC473JJC/aUNQavTOKqTB6F90ejiV0geJRrqp1va
uG8WNwpoNsxUR6E2lM2PtH5gRFGX5XHXx5eqkW5XkKOs2oKWgFOdiUfNzUidQ3NzysqLdPj6vXb5
cm7vjcVl6ueKl3l7b6+R9dxS4szwlBLTOSyFl5TssfSabW7htuQxhlWFubPd3Nwk9fp/v/wPpv9S
/uNLffzuy/x3r/bTN72u398r6Yf+C2dbQ+AxjobBsAkoH396tvsKda1/ff83/37lbPePi9ds1TL3
+3690SUlevaEb+TXv3C7fvybCw8m/50s/PC1d6LrX8x/9G8naEZELwULvMarfHpQHeCR8yPZvxby
UZ98WugYSfAbtiYG5JRcw+2LyZlYMuRhNQSPh67YdLauDn+MnMbycqIW8bq75FXqA8hyQJJHoWFu
byhBN6ySemXvuH5WyW6QZE9pGPK6PKFVOQC0Oo2iOvoNYoMovbm8Ec3huNiWTNTX5WZ/YtJGAc2H
meooeqd6+HE3xJupkYao8VZtQUvAqc706mvy3OD0aIosZMjW3vEnNB3cX7tzfbr9+qKcGnKtsl+f
Gpwemtmky/vPQsT0Xnq0TldKnO3SXPfg7J3sXqGwl/5ktl0zz1Vg6Wyz2az+33u/p0mGKb+/p4/f
yuWIhV2RnW1JP/RfONsaAo9xNAyGrc4lffFNl+snv/n9dJqsBn2uE9o1259d+qsa9vHffvdvn/JG
Vy7Rs67Xg//YyN29/Zay8EX0/E99k5Ebb5z489zHz/TB9S/KpwfVAR3ypVk5VZICzMGeDK+yi7m+
aF7OklyufiUX50iMdJB6lp/J+bp9Z8suDxNIb6pjptC9UtI9XZgh26P90IbFgQDQaEzV6Xvjht+K
9PGjQ9PNiZnqKIbjXjy+9Lgrf+ooE2+qRrqoxlu1BS0BpzpTZ6tWPprrDMwvs8pCYWfxDLWmZMm0
FSV9+96xS4k0XSxxtvH4sSFpMltLS2jubMn/3sbGhv7fWBlnSxqUxH8rO9tYaT35F862hpCPlC0B
OxgMm5Ay4zvxzp+e5YKDbwyxH9wuD73+xhC74rrw+9eLLrdYomdfu7GgLLh88s3Mi2MnyMKzGd+/
/pz+fPdnv7vAehNRlE8PqgN6ZIfaE0rKFrff76f/TmzJNxcreTZzrS738Z6T/YGwpCRMivWlJljh
KHcjFyNob7pUjGxV1q0yNlZf0hAARiOpbispRUKBgK+vh97XX+yN70UbVDc6aC7MVEfRq+jw416q
OgWuni6q9VYxoCXgVGfqUTOhYVpJbap88zBXlGu5+lb72YX416Nj8TNXp7tJjJWzJUK7SjvpvCSN
3n2S3qmBN7R0tuvr6/p/8wcspJSDvEn8t8t/7yXOtrSe/AtnW0PIR8qWgB0Mhq1+5eNbv+u+MnOX
LK988ubPqLO9++k7/5PvM3rNdn7sxC9G2O3HD4LdinE1lOjZEzeWlQWds1UDPr711g+Un+8KKcqn
B9UBA7K19QYCXtmoSn63y+0fkeu03Ci/moiEWFbuUu68hLMFDU6jqC4vBbrcx72+YDgqJTP03uVi
b3wvZNUdKNlJ0FyYqY6iV9Hhx71UdQpcPV1U661iQEvAqc7U2bK7kbkLsAa4VjvLQwFqVi/fXpxZ
+nZh3PqaLWV/d/VJZFzqHSIWd/YO/ZVuVZg720wms7a2VuW/irM13QpnW0PgMY6GwbDVsyxcHKDP
Rv7BT95Qf1WbDsrPRuZqcndvv8McrKFYONu70UvdP6EXwbhHLosoyqcH1QEj1MzK0JuS1V/b8sa2
SCLYo26RDXG1dyNrEeXvCzXJ2NT6Ku4LBc6mQVRHv1HFvwDJgxR7M9yViruRmx4z1VH0x139qSyB
ysvkuOvjTdVIF9V6q7agJeBUZ+Jsc7HZ9sDcAlmKx9sHpc92lGqeYqvd2Oyx4aL7XR6fLutsNdKX
A1O/vVvtK3HNne3zWrD8N+ps2YoeONsaAo9xNAyGDaXConx6UB0woplZ+bdc7AnJ9AZleWtipEte
L8KelkMfoqPi9nppKzWbomkWl2hV4DHKPstHCzPxGLROfbpKYSvm7+KtCmhlGkV1kt/t9snWpbAl
jXjc2neL9qb2Qp8kZDo6aC441VHhqA+KmvB1uXkVaU+EivR3dPiV414u3kyNdHEgqujOqi1oCTjV
GZyt4a0/6dHhqe7ri2lq47bTX0ndgfgMNbq01amvSMy+7H7Zc6HW43O/Gpw6xn6aa3S2uzGpPRCf
pJGFQirRO3gvRG9srgpzZ/v06dNnz55V+e/W7qvC/rbpVjjbGgKPcTR4t4ZSeVE+PagOlKDcWcwu
HMh/8FefkCyTiY309SjvLGnr6uPecJKJ+ul7T9o8I1KeZl9aNiWvcMl5BR5DthbK+1d0g1hldVx9
PqG9f0X3UiLQ2jSM6vIJ9Y0tnv6QFBvpkh/NpvTG3v7iPu71R9XruiU7CZoH3Rl2dUIWl/yqnqh2
DzI5vtpbfNo8vgnter51vKkaCxn5/VVsm3lb0BJwqqMelf8lbfewFH4kP+hYIZsavcbe+tN9NT65
xgxd+u59WnmDeNjcXPh+pxzguTY/M0MfgCxf5i29ZpubG59V3vrTPnT/DzM1yC3NnW26zsDZ1hB4
jKNhMGwoFRbl04PqQG2gGRahT36qJ8nd5duUS56grADVAfE0vOrgYB0I5jogHseoztzZrq6uPnny
pH7/wtnWEMyAR8Ng2FAqLMqnB9WBGmF5m3IpUB0QT8OrDs7WgWCuA+JxjOrMne03dQbOtoZgBjwa
BsOGUkmZhLMFNWc16u9THpdsuE3ZCFQHxCNUdewWhlLKWFc4WweCuQ6IxzGqM3G2Dx48WFpaStUN
0jkZAs62VmAGPBoPc9sG24ZyaCEfmvLpQXVAPFAdEA9UB8QD1QHxOEZ1Js52eXlZkqTFxUWyUHNI
t6RzsnBwYP1+XGAHzIBHY31v32DbUA4tm/vsawvVAfFAdUA8UB0QD1QHxOMY1Rmd7atXr16+fPn4
8WPiP2N1gHRLOt/e3iYDsSFBdWAGPDLE3D7MbU+W+DeU0kI+KM3WEqA6IB6oDogHqgPigeqAeByj
OqOzJezv7xNzS+o36wDplnSOW5FrCGZAIB6oDogHqgPigeqAeKA6IB7HqM7E2RJevXp1cHBA/Gc9
wNXa2oIZEIgHqgPigeqAeKA6IB6oDojHMaozd7agicAMCMQD1QHxQHVAPFAdEA9UB8TjGNXB2TY9
mAGBeKA6IB6oDogHqgPigeqAeByjuoqcbTabVd7WU3OWl5dJ52wYcCQwA1YPe5RU1vjYpEOL4blK
rQNUB8QD1QHxQHVAPFAdEI9jVHe4syXOc2Vl5dmzZ5k6QLolnW9sbLDBgH0wA1ZJ9a//aUFzC9UB
8UB1QDxQHRAPVAfE4xjVHe5sU6lUnWytAumcDMEGA/bBDFglD3PbBqdqt5AeWF8tA1QHxAPVAfFA
dUA8UB0Qj2NUd7izXVpaYh60bpAh2GDAPpgBq8RgU49QJrM51lfLANUB8UB1QDxQHRAPVAfE4xjV
wdk2PZgBq8RgU49WWF8tA1QHxAPVAfFAdUA8UB0Qj2NUd3Rnm0qlxsbGzsiQhcePH7MN9oGzrQbM
gFVi8KhHK6yvlgGqA+IRorpM5pBTImgtMNcB8YhVHSY9QKmB6vbX0g3wUOAjOltia69cufIWx8WL
F03N7dOnT//rv/7L5/OdOnXqT3/6k2kMnG014LxbJQaPerTC+moZoDpQfyS/i+CX2CqvOrqpuKFm
ZCLeenQLmhi7c10m7HV5wxm2dih1UjJobipQXa2Ug0kPMDjVrYUvTR0bLJbO4dnLM4dq8lvSaijO
VixYHhpUYrSF2nNEZzs1NcUcLcfbb799+vTpsbEx4ntZXCZz7969//zP/9zd3d3b2/voo49u3rxJ
vC7bpgJnWw3wGFXyxcZ68P1f/sjl+sEv3ro4z/nV+bETr49FtNWyhfXVMkB1QDyc6urlbIkrQZIH
eOzOdTadLQAmVKC6mjlbTHpAgVMddbac7dxefzTfOzg9FC+f6xpalafxnO34+Dizs2YQc5tOp5XI
fD5/cHCQlVlYWLh8+fI333yjbNKAs60GeIwq+WL60r8MfPIxMagPRrrf/IgubKz/4/b5137x85/C
2VoA1QGOrYl+l8vVPyGfTOglAHqpNSZvSoZ6XC43TZy2pGBfVxvd5D7u8YWTeXk7IRMb8R53u9w9
AxOrMZKtab6Apm588sapjsvqVsNed5c/Jo+dT4Z9HjqG+7jXH12Vt0t+d8dIQl4kkF31hOgGLpTt
Dc3wFNgO8L2NxFSvQob2BiNBust0QzCh/Y+YjQ6aHX6uk48wPfCcbGSYhl1tHn8ocFIVkCyVqCIK
9/H+cDKTUHTT5vFNMH1oSrbWFWg9zOc6ZZIqqss1MKIJShNjmfhSgRkmPau2oCXgVGfiUXMzUufQ
3Jyy8iIdvn6vXb6c23tjcXmfVBUv8/beXiPruaXEmeEpJaZzWAovKXly6TXb3MJtyWMMqwrbzvb5
8+eff/75u+++y1ysGefPn19cXGQNOD777LO//e1vGxsbbF0FzrYa4DGq5Iv54Guqs31t4LO71Kmm
/x6d+9j0mm307AnfyK9/4Xb9+DcXHkz+O1n44WvvRNcLqxNKTktTlhY4FUB1gEfOj2T/WshHfXKi
pLhJbcPWxABJqDjcvpiciSVDHlZD8HjoippN0TSLS7TMsr3VSF9bly+qxBOP2+YNJRR/HfV1uX1R
OgRvbTVjmwySzaoV71cD6O6q4xGHrjpmYmjIckCSd5gO7WbDUFet9m0xOmhyiqqjGlb/hiIfepc3
IisvMdLl9srOQlaKpmBFKsqGmL/D5W7rC1PxbdEVJg/NS1jpCrQiJnOdDOc2ab2L6VGecNifFsvF
mwmMn/Ss2oKWgFOd6dXX5LnB6VH6ktYM2do7/oR60P21O9en268vyn6Ua5X9+tTg9NDMJl3efxYi
pvfSo3W6UuJsl+a6B2fvZPcKhb30J7PtmnmuAtvONplMXrhwgVlYC4iz5W9IVpifn798+fKTJ0/g
bGsLPEaVEB/7J99rNIX+yRtDDzgTu2jubF2vB/+xkbt7+y1l4Yvo+Z/6Jsk5wBtKbrVMJgvVAR3y
pVk5VZICzMGeJEm8cjGX5vA0S3K5+hUnwJEY6SD1LD+T3ULlzjZC0rmuAfXiF+2qJ5RkK4rFVnK9
orXVjC3toEM1KUW4JI/0pppvCv0fVHsjQysXpPnkz3J00NxYzXXFQ08kz9lQqhTOS2hSISvK334o
Mb8uhlZb6Aq0JMa5zsRt6gRV2Ir0sT+0lIk3FRhdVOOt2oKWgFOdqbNVKx/NdQbml1llobCzeIZa
U7Jk2oqSvn3v2KVEmi6WONt4/NiQNJmll31rhW1nu7Ky8t577zELa8HNmzc3NzdZA5l//vOfxA8v
LCy8fPmSVXHA2VYDPEaVfHzrdyf+vEBd68onb5649FfNxFo429duyMHE4vom6QIJ800W8gnlVsu2
rv6Immk7GKgO6JEdKrF2ssXt9/vpvxNb8s3FisFjrtXlPt5zsj8QlpSESbG+1AQr2LkbWcajuUma
hxlhXpNYW3mJ2E3NfdKrvXRvvL5QJLHKHGwxyaM7psvqyIjKunnyV2Z00NTo57qtpBQJBQK+vh46
3WuHnpMK/ZsGW9VJRROQfkWLMdcVaE0Mc52ZMHSCqkBIVvV0Ua23igEtAac6U4+aCQ3TSmpT5ZuH
uaJcy9W32s8uxL8eHYufuTrdTWKsnC0R2lXaSeclafTuk/RODSyubWeby+UePHhw9uxZ5mL1nD59
+tatW6RP/sLs7Ozs+++/n0ql8vk8q9IDZ1sN8BhVEvnbGyf+PEdvQl757M2fnQ8qDlaxrKZ3I99Y
VhZ0zlaF3rAWUM8MzgWqAwZka+sNBIjBI0aVeEmX2z8i12m5UX41EQkxT0A9KbGz1Thbb3iV3spM
/iNXlcvDyO6Q4XhjK6PsEP3hWduAbL+LSd5RnK3V6KCZKaouLwW66J9CguGolMwkQxaH3uR6LFsp
RhVXtBhzXYHWxDDXmQlDJyh5VUk9ysSb1tNFtd4qBrQEnOpMnS27G5m7AGuAa7WzPBSgZvXy7cWZ
pW8Xxq2v2VL2d1efRMal3iFicWfv0F/pVsVRniC1u7vLtplxcHBA+mShmczCwsIf//jHp0+fbm9v
s6oS4GyrAR6jSr7YWLg4ID8b+Sdv+KbXiybWjrPNSyPKg0W4R4M4GagOGKFmVobemUkvXCmYpUaJ
YI+6RTbER7wbmW6Qf+Ko3ONMdoC/f5gnH/O5vaGQwdhqJMn+9NFOuCSv/N3IpclfmdFBM6Opjmq6
+DcY7q7j8ncjq1IhK6qw+RUtxkJXoCUxm+soenVxsqOKMZmgrNTICYyb9CzbgpaAU52Js83FZtsD
cwtkKR5vH5Q+21GqeYqtdmOzx4aL7nd5fLqss9VIXw5M/fZuta/EPYqztcXExAS7nitz4cKF0p/g
wtlWAzxGlRRdaxWF9dUyQHXAiGZm5d9ysScka3fkEgcqrxdhP3hd5Z4g5fZ6aSs1m6JpFpdomWd7
ecnfwZ6dQq/gqo+Tyq/SH+Gyhz4p1tbtLt66TNd1DwNS9oYmeQPswU/lniBlliCWGR00MUXVyX+8
kJVW2JJGPG5N3eTQ84/m0RSskwpZKdqE4ooWY6Ur0Ipwcx3VgvqgqAlfl5tXjia7SH9Hh1+Zb8rF
mwmMLmqTnkVb0BJwqjM4W8Nbf9Kjw1Pd1xfT9Mbh7fRXUncgPkONLm116isSsy+7X/ZcqPX43K8G
p46xn+Yane1uTGoPxCdpZKGQSvQO3gvRG5urou7Odm9P3l2V7777jr+iqwBnWw3wGFVi8KhHK6yv
lgGqAyUodxarz02if/BXn5Ask4mN9PXINza42rr6im/RKWSifvpc8TbPiERsKtmsZlPySjEZ41XH
Z2nEUhPHIadmW1KoX35GuWEIxcrqrtjmE2qom3unT0b+9S3rWnuLj64zqwSx3OigeeFUl2cv7XEf
9/SHpNhIl/qAY/pKK/b2FcNbf4pSIStFm1Bc0WKsdQVaD90Zlr15QX5VT5RXjvYWH/29Ypbx5gLT
TXrmbUFLwKmOelT+l7Tdw1L4kfygY4VsavQae+tP99X45Br7cWz67n1aeYN42Nxc+H6nHOC5Nj8z
Qx+ALF/mLb1mm5sbn1Xe+tM+dP8PMzXILevubCsBzrYa4DGqxOBRj1ZYXy0DVAdqA82wCPK9wNQ5
yLcplzxBWaEq1Un+rqLLBqBSMNcB8UB1QDyOUR2cbdODGbBKDB71aIX11TJAdaBGWN6mXEoVqtuK
+T1B09/YAlAWzHVAPFAdEI9jVAdn2/RgBqwSg0c9QpmEswXgyKxG/fIbswjl7+I9ouroT37dPfjR
KzgSmOuAeKA6IB7HqO5wZ7u8vPzs2TPmQesA6TyVqvr3wi0MZsAqeZjbNjhVu4X0wPpqGaA6IB6o
DogHqgPigeqAeByjusOdbTabXVlZqZO5Jd2Szjc2NthgwD6YAatkfW/f4FTtls39A9ZXywDVAfFA
dUA8UB0QD1QHxOMY1R3ubAnEeaZSqaU6sLy8DFtbJZgBq4eY24e57ckSy3poIa1a0NYSoDogHqgO
iAeqA+KB6oB4HKO6ipwtaGQwAwLxQHVAPFAdEA9UB8QD1QHxOEZ1cLZND2ZAIB6oDogHqgPigeqA
eKA6IB7HqA7OtunBDAjEA9UB8UB1QDxQHRAPVAfE4xjVwdk2PZgBgXigOiAeqA6IB6oD4oHqgHgc
o7qKnG02m63fE6RI52wYcCQwAzYaB98VFl7uTGbZU6bIMqlxGFAdEA9UB8QD1QHxQHVAPI5R3eHO
Fm/9aXAwAzYa8y92tIcna+aWbXMKUB0QD1QHxAPVAfFAdUA8jlHd4c42lUrVydYqkM7JEGwwYB/M
gI2GwdaSMpnNsW1OAaoD4oHqgHigOiAeqA6IxzGqO9zZLi0tMQ9aN8gQbDBgH8yAjYbB1iqFbXMK
UB0QD1QHxAPVAfFAdUA8jlEdnG3Tgxmw0TB4WqWwbU4BqgPigeqAeKA6IB6oDojHMao7urNNpVJj
Y2NnZMjC48eP2Qb7wNlWA2bARsPgaZXCtjkFqA6IB6oD4oHqgHjEqi6TOcQHgJagBqrbX0s3wEOB
j+hsia29cuXKWxwXL140NbdPnz79r//6L5/Pd+rUqT/96U+mMXC21YDzbqNh8LRKYducAlQHFDJh
r8sbztBFye9y+SW5tmbo+uRUV6ux6rHPwFE0reqg7SamgjNsrY5vJuKFTgCFU91a+NLUscFi6Rye
vTxzqCa/Ja2G4mzFguWhQSVGW6g9R3S2U1NTzNFyvP3226dPnx4bGyO+l8VlMvfu3fvP//zP3d3d
vb29jz766ObNm8Trsm0qcLbVAI/RaHyxsXBx4Jc/crlcP/7lm7eXOWe7Gva6nXEKgeqAQp2drQ6o
DogHqgPiqUB1NXO2ZAqHswUETnXU2XK2c3v90Xzv4PRQvPxFGkOr8jSesx0fH2d21gxibtPptBKZ
z+cPDg6yMgsLC5cvX/7mm2+UTRpwttWA826j8fGt35348wI1tCufvPmz80HV2SZGetxuh5xCoLqW
JhMb8R53u1xtHn8ocJJ3tgMjQbbFF07m5WA9+WTY56ERLpf7eDGItPUGo6F+Y1td9sapTqsnC/5w
pK+NdDcQpSczeQCySrr3jsTkHSPI/UeUfSMbgonS/rekUH9pQ9DqNI7qqvnugObCTHUUw18Szebb
MvGlaqTbFeQoq7agJeBUZ+JRczNS59DcnLLyIh2+fq9dvpzbe2NxeZ9UFS/z9t5eI+u5pcSZ4Skl
pnNYCi8prrj0mm1u4bbkMYZVhW1n+/z5888///zdd99lLtaM8+fPLy4usgYcn3322d/+9reNjQ22
rgJnWw3wGI2GcpFWLnO+1y/9VV7OS/6TfilKEiJDqiH5vf7gQI/b1dYXSUoBsuDuGZHyhdUJJVMi
p6yJxju3QHUtTGKky+2V8yiSantJmsRlWq4uf4yeUjJRX5e7f8J4dtmaGHCzCOUWBpc3UratLtOy
8BiuDrldXk7UIl51AHnnugLku8TC3N5Qgm6g43aMJGh1sZ/VkIfkffL2fDLkdXlCq3IAaHUaRXXV
fXdAc2GmOorB2R563A3xZmqkIWq8VVvQEnCqM736mjw3OD1KX9KaIVt7x59QD7q/duf6dPv1RdmP
cq2yX58anB6a2aTL+89CxPReerROV0qc7dJc9+DsnexeobCX/mS2XTPPVWDb2SaTyQsXLjALawFx
tvwNyQrz8/OXL19+8uQJnG1tgcdoNFRbuzD0r798M7pOl+fH+vrCJGch5w1jqkGqvDSdyUcHlIWC
FOjwS+Sk4g0lt+T8qAGB6loXKaDlRIRkqIfLnLib7bcifWrqbYU+63L7YqrcaVslTdNlWlYewx9T
Kqnp7uC6kXeO60cNM2R7tB/a0PjVBIDQmKqz+90BzYWZ6iiG4148vsX5tky8qRrpohpv1Ra0BJzq
TJ2tWvlorjMwv8wqC4WdxTPUmpIl01aU9O17xy4l0nSxxNnG48eGpMksvexbK2w725WVlffee49Z
WAtu3ry5ubnJGsj885//JH54YWHh5cuXrIoDzrYa4DEaDWplFz9588Tvfv9AtrUbuciNN1xF9OcK
yX+Sel75nKKcUsj5hCzkE8G+rjaXq62rP2L9d/zvC6iuZTGkO/moj8uceG3rkiSOraQUCQUCvr4e
qu9D2uo6sfQYasDWRL+um2K3ujDuf4HVlzQEgNFIqjv6dwc0F2aqo+hVdPhxL1WdAldPF9V6qxjQ
EnCqM/WomdAwraQ2Vb55mCvKtVx9q/3sQvzr0bH4mavT3STGytkSoV2lnXRekkbvPknv1MDi2na2
uVzuwYMHZ8+eZS5Wz+nTp2/dukX65C/Mzs7Ovv/++6lUKp/Psyo9cLbVAI/RaHyx8tGv/9dLwRXl
yi0ryiZy3tBOGwzJXzzvKNvI+YQLovegBQxtvn+gupbFmO7EtPyKKJjfQFZLlJuXAl3u415fMByV
khl6/+UhbclC8SvTSB4DtAqNorrqvjuguTBTHUWvosOPe6nqFLh6uqjWW8WAloBTnamzZXcjcxdg
DXCtdpaHAtSsXr69OLP07cK49TVbyv7u6pPIuNQ7RCzu7B36K92qOMoTpHZ3d9k2Mw4ODkifLDST
WVhY+OMf//j06dPt7W1WVQKcbTXAYzQaf33/v7Grs5Sz2hOkCOS8oZ02GBbONi+NKM8Kob+zxTVb
0DiUuxuZ20DTIvbDLw16gZfdokApeyeznbuRtYbl7wtVw7iMTa3H3cjAggZRXZXfHdBcmKmOUsF8
WybeVI10Ua23agtaAk51Js42F5ttD8wtkKV4vH1Q+mxHqeYpttqNzR4bLrrf5fHpss5WI305MPXb
u9W+EvcoztYWExMT7HquzIULF0p/ggtnWw3wGI0Gf6lWK2ybU4DqWphkyMM/iET3BCltQ6S/o8Ov
PEeHQ/K73T45/SpsSSMe0rYnlFQ2FNvSp6Hwz+DRMq3DPUbZZ/loYSYeg9ap4xe2Yv4u3qqAVqZR
VFfddwc0F5zqqHDUB0VN+Lrch8235eLN1EgXB6KK7qzagpaAU53B2Rre+pMeHZ7qvr6YpjcOb6e/
kroD8RlqdGmrU1+RmH3Z/bLnQq3H5341OHWM/TTX6Gx3Y1J7ID5JIwuFVKJ38F6I3thcFXV3tnt7
8u6qfPfdd/wVXQU422qAx2g0DJ5WKWybU4DqWpotSX3XhOGtP9pbJaxuNcgn1LdOePpDUmyky+WT
cyqadbE3WLiPe/1Rta0uG6vAY8jWgj1VvKtP9/4V06yOq88ntPevcK/QAK1Ow6iuqu8OaC50Z1j2
ogT5VT1R7R5kcnwt5lvLeFM1FjLy+6vYNvO2oCXgVEc9Kv9L2u5hKfxIftCxQjY1eo299af7anxy
jf04Nn33Pq28QTxsbi58v1MO8Fybn5mhD0CWL/OWXrPNzY3PKm/9aR+6/4eZGuSWdXe2lQBnWw3w
GI2GwdMqhW1zClAdqCkVZeFQHRBPw6sODtaBYK4D4nGM6uBsmx7MgI2GwdMqhW1zClAdqClwtqBB
aXjVwdk6EMx1QDyOUR2cbdODGbDRMHhapbBtTgGqAzUFzhY0KEJVR28SNaXMlwPO1oFgrgPicYzq
Dne2y8vLz549Yx60DpDOU6mqfy/cwmAGbDQMnpaUSThbAKoGqgPigeqAeKA6IB7HqO5wZ5vNZldW
Vupkbkm3pPONjQ02GLAPZsBGY/7FjsHZLrw0eT56UwPVAfFAdUA8UB0QD1QHxOMY1R3ubAnEeaZS
qaU6sLy8DFtbJZgBG42D76i5neRsLalxGFAdEA9UB8QD1QHxQHVAPI5RXUXOFjQymAGBeKA6IB6o
DogHqgPigeqAeByjOjjbpgczIBAPVAfEA9UB8UB1QDxQHRCPY1QHZ9v0YAYE4oHqgHigOiAeqA6I
B6oD4nGM6uBsmx7MgEA8UB0QD1QHxAPVAfFAdUA8jlFdRc42m83W7wlSpHM2DDgSmAGbhfW9/dmt
l/c2X5AFVtW0QHVAPFAdEA9UB8QD1QHxOEZ1hztbvPWnwcEM2CwQT6s8LZn4W1bVtEB1QDxQHRAP
VAfEA9UB8ThGdYc721QqVSdbq0A6J0OwwYB9MAM2C4qtVQqralqgOiAeqA6IB6oD4oHqgHgco7rD
ne3S0hLzoHWDDMEGA/bBDNgswNkCUA1QHRAPVAfEA9UB8ThGdXC2TQ9mwGYBzhaAaoDqgHigOiAe
qA6IxzGqO7qzTaVSY2NjZ2TIwuPHj9kG+8DZVgNmwGYBzhaAaoDqgHigOiAesarLZA7xAaAlqIHq
9tfSDfBQ4CM6W2Jrr1y58hbHxYsXTc3t06dP/+u//svn8506depPf/qTaQycbTXgvNsswNkC55EJ
e13ecIYuSn6Xyy/JtTVD1yenulqNVY99Bo6iaVUHbTcxFZxha3V8MxEvdAIonOrWwpemjg0WS+fw
7OWZQzX5LWk1FGcrFiwPDSox2kLtOaKznZqaYo6W4+233z59+vTY2BjxvSwuk7l3795//ud/7u7u
7u3tffTRRzdv3iRel21TgbOtBniMZoHZ2vmxE6+PyU6AsDrh87S5XK42jz+q1jUDUB1QqLOz1QHV
AfFAdUA8FaiuZs6WTOFwtoDAqY46W852bq8/mu8dnB6Kl78qY2hVnsZztuPj48zOmkHMbTqdViLz
+fzBwUFWZmFh4fLly998842ySQPOthpw3m0WvthY/8ft86/94uc/VZ3t1kS/N7QqL0X9XYEmOrlA
dS1NJjbiPe6W/yATCpzkne3ASJBt8YWTeTlYTz4Z9nlohMvlPl4MIm29wWio39hWl71xqtPqyYI/
HOlrI90NROnJTB6A/rXIfdw7ElP/XCT3H1H2jWwIJkr735JC/aUNQavTOKqr5rsDmgsz1VEMf0k0
m2/LxJeqkW5XkKOs2oKWgFOdiUfNzUidQ3NzysqLdPj6vXb5cm7vjcXlfVJVvMzbe3uNrOeWEmeG
p5SYzmEpvKS44tJrtrmF25LHGFYVtp3t8+fPP//883fffZe5WDPOnz+/uLjIGnB89tlnf/vb3zY2
Nti6CpxtNcBjNAtfbKT/Hp37WHfNViMZ9I4k2LKM5Pf6gwM9bldbXyQpBciCu2dEynNXeX0T3985
B6prYRIjXW6vnEeRVNtL0iQu03J1+WP0lJKJ+rrc/RPGs8vWxICbRRQKq7SxN1K2rS7TsvAYrg65
XV5O1CJedQB557oC5DvDwtzeUIJuoON2sG+b1s9qyEPyPnl7PhnyujzKn5xAy9MoqqvuuwOaCzPV
UQzO9tDjbog3UyMNUeOt2oKWgFOd6dXX5LnB6VH6ktYM2do7/oR60P21O9en268vyn6Ua5X9+tTg
9NDMJl3efxYipvfSo3W6UuJsl+a6B2fvZPcKhb30J7PtmnmuAtvONplMXrhwgVlYC4iz5W9IVpif
n798+fKTJ0/gbGsLPEazwO5GXix1tqvhPo9fyYU0yClGvp6bjw4oCwUp0OGXyMnGG0pu6WPFA9W1
LlJAy4kIyVAPlzm5i5n0VqRPTb2t0Gddbl9MlTVtq6RpukzLymP4Y0olNd0dXDfyznH9qGGGbI/2
QxsW9x0AjcZUnd3vDmguzFRHMRz34vEtzrdl4k3VSBfVeKu2oCXgVGfqbNXKR3OdgfllVlko7Cye
odaULJm2oqRv3zt2KZGmiyXONh4/NiRNZull31ph29murKy89957zMJacPPmzc3NTdZA5p///Cfx
wwsLCy9fvmRVHHC21QCP0SyYO9tM1O/pD6k3EhWR/CfD8t/vyblGOdWQ8wxZyCeCfV1tLldbV3/k
+7uqBNW1LIZ0Jx/1cZkTnwfpkiSOraQUCQUCvr4equND2uo6sfQYasDWRL+um2K3ujDuf4HVlzQE
gNFIqjv6dwc0F2aqo+hVdPhxL1WdAldPF9V6qxjQEnCqM/WomdAwraQ2Vb55mCvKtVx9q/3sQvzr
0bH4mavT3STGytkSoV2lnXRekkbvPknv1MDi2na2uVzuwYMHZ8+eZS5Wz+nTp2/dukX65C/Mzs7O
vv/++6lUKp/Psyo9cLbVAI/RLJg4262JgZMjkulXUPIXz0fKqYacZ7RzjtzU/f39Mheqa1mM6U5M
y6+IUvkNZLVEoXkp0OU+7vUFw1EpmaH3Xx7SliwUM61G8higVWgU1VX33QHNhZnqKHoVHX7cS1Wn
wNXTRbXeKga0BJzqTJ0tuxuZuwBrgGu1szwUoGb18u3FmaVvF8atr9lS9ndXn0TGpd4hYnFn79Bf
6VbFUZ4gtbu7y7aZcXBwQPpkoZnMwsLCH//4x6dPn25vb7OqEuBsqwEeo1kodbaJkQ5XEe2EImPh
bPPSiPIMEfo7W1yzBeIpdzcyt4GmReyHXxr0Ai+7FYFS9k5mO3cjaw3L3xeqhnEZm1qPu5GBBQ2i
uiq/O6C5MFMdpYL5tky8qRrpolpv1Ra0BJzqTJxtLjbbHphbIEvxePug9NmOUs1TbLUbmz02XHS/
y+PTZZ2tRvpyYOq3d6t9Je5RnK0tJiYm2PVcmQsXLpT+BBfOthrgMZoF5mzlwqqaFqiuhUmGPPyD
SHRPkNI2RPo7Ooy/HachbrdPTr8KW9KIh7TtCSWVDcW29Gko/DN4tEzrcI9R9lk+WpiJx6B16viF
rZi/i7cqoJVpFNVV990BzQWnOioc9UFRE74u92Hzbbl4MzXSxYGoojurtqAl4FRncLaGt/6kR4en
uq8vpumNw9vpr6TuQHyGGl3a6tRXJGZfdr/suVDr8blfDU4dYz/NNTrb3ZjUHohP0shCIZXoHbwX
ojc2V0Xdne3enry7Kt999x1/RVcBzrYa4DGaBThb4BC2JPVdE4a3/mhvlbC6pSCfUN864ekPSbGR
LpdPzqlo1sXeYOE+7vVH1ba6bKwCjyFbC/b08K4+3ftXTLM6rj6f0N6/wr1CA7Q6DaO6qr47oLnQ
nWHZCxHkV/VEtXuQyfG1mG8t403VWMjI769i28zbgpaAUx31qPwvabuHpfAj+UHHCtnU6DX21p/u
q/HJNfbj2PTd+7TyBvGwubnw/U45wHNtfmaGPgBZvsxbes02Nzc+q7z1p33o/h9mapBb1t3ZVgKc
bTXAYzQLcLYAWFBRFg7VAfE0vOrgYB0I5jogHseoDs626cEM2CzA2QJgAZwtaFAaXnVwtg4Ecx0Q
j2NUB2fb9GAGbBbgbAGwAM4WNChCVUdvEjWlzJcDztaBYK4D4nGM6g53tsvLy8+ePWMetA6QzlOp
qn8v3MJgBmwW4GwBqAaoDogHqgPigeqAeByjusOdbTabXVlZqZO5Jd2Szjc2NthgwD6YAZuFe5sv
FFs7u/WSVTUtUB0QD1QHxAPVAfFAdUA8jlHd4c6WQJxnKpVaqgPLy8uwtVWCGbBZWN/bJ56W+Fuy
wKqaFqgOiAeqA+KB6oB4oDogHseoriJnCxoZzIBAPFAdEA9UB8QD1QHxQHVAPI5RHZxt04MZEIgH
qgPigeqAeKA6IB6oDojHMaqDs216MAMC8UB1QDxQHRAPVAfEA9UB8ThGdXC2TQ9mQCAeqA6IB6oD
4oHqgHigOiAex6iuImebTqcfPnwYqwOkW9I5GwYcCcyATmJ9b/9hbnsyW3w/0PdeyP5s7h+w/VOB
6oB4oDogHqgOiAeqA+JxjOoOd7bEeS4sLLx8+fK7OkC6JZ3D3FYDZkDHQGytwVU2TjGYW6gOiAeq
A+KB6oB4oDogHseo7hBn++rVq3g8/uLFC7JQJ0jnZAiywIYENsEM6Bge5rYNfrJxCtk3tpcyUB0Q
D1QHxAPVAfFAdUA8jlHdIc52f38/FouRf+sKGeLgwHi7I6gQzICOwWAmG6pMZnNsL2WgOiAeqA6I
B6oD4oHqgHgco7qKnO3e3t7u7m79/lXMMxsS2AQzoGMwmMlGK2wvZaA6IB6oDogHqgPigeqAeByj
uoqcbb7OwNlWA2ZAx2Bwko1W2F7KQHVAPFAdEA9UZ0Ymc8gTWkBViFUdjiag1EB1+2vpLFv8HqnI
2e7s7Gxvbx/13+yDa7/5eZvL5XL/9Nd/erBhEgNnWw047zoGg5NstML2UgaqA+LhVCf5XS6/xFaq
oFb9AMfiYNVlwl6XN5xha5WTiXjxrakvFZxha6UiHE3A4FS3Fr40dWywWDqHZy/PHKrJb0mroThb
sWB5aFCJ0RZqT0XO9mUVfPv5mbb/EXlOO9uKDna4z3z+LdtSBM62GuAxHIPBSZqU+bETr49F2Op6
8P1f/sjl+sEv3ro4b1VTy8L2UgaqA+KB6oB4HKy6Iztb0g5eqK5UoLqaOVscTaDAqY46W852bq8/
mu8dnB6K6/LAEgytyvN9O9sXL17kcrmj/bu9/6rwaj+//SL3cmd/1u9quzJdEgNnWw3I9hyDwUnq
y/o/bp9/7Rc//6nmbKcv/cvAJx+ThQcj3W9+RBdKa2pa2F7KQHXADjQJc7kG/IEet6vNG7mjrAbD
Pk+by+U+7g1KxfNQPkmqj7tJQJvHF07mWTWBU52W1ZEFfzjSR7sZiNJO5ObyTULHvSMxNWsnYd5g
JOil/dLxEqxbLjvckkL9pQ1Bq9NAqjMNtjc0MTKxEbm2zeMPBU6qzpbbJYPjNQ5KNyqwEMsd0H9E
wA5mqqNwh4bWD4woh5ifKsvEl0rCcDSt2oKWgFOdiUfNzUidQ3NzysqLdPj6vXb5cm7vjcVlauCK
l3l7b6+R9dxS4szwlBLTOSyFl5QcsvSabW7htuQxhlVFRc52c3OThOn//fI/2NehlP/40iSe/vv/
u/G/uPo/WSuph7OtBngMx2BwkvqS/nt07mP+mu188DXVx7428Nld0xqtRM+e8I38+hdu149/c+HB
5L+ThR++9k50/Yv5j/7tBM1JfnTinYuLXLxZYXspA9UBO9CEScXtl/hVhppBZSJekngVcfdPaKco
C4/h6vDHSExeTtRI8y55lSbcZDkgyfkeDXN7Qwm6YZXUd4wkaHWxn9WQh+R98vZ8MuR1eUKrcgBo
dRpGdabBdodOjHS5vbIJksO1L562SxTO0pgPSrarweV2gPuIgD3MVEfRO1WXi330maivS50qy8Wb
SYI/mlZtQUvAqc706mvy3OD0aIosZMjW3vEnNCncX7tzfbr9+qKcIHKtsl+fGpwemtmky/vPQsT0
Xnq0TldKnO3SXPfg7J3sXqGwl/5ktl0zz1VQqbPNZrP6f+/9Xsk7TPj9PZP4zWzi//h1mze8svey
ZCucbTXAYzgGg5M0KYv83cjpP/leo1+4n7wx9MCqRi3Rs67Xg//YyN29/Zay8EX0/E99k5Ebb5z4
89zHz/TBFoXtpQxUB+wgJ2E00SVJ7tZWXlllSdlWzN9F1npCSbKSGOkgyyyVXiWZdNHzWnsMf0yp
lJu7fXQQhWSox6Wke7owQ7ZH+6ENtYwOgCKNojrTYLtDSwHN0BBouGGXZIrx5ntIt7PaynYA2MVM
dRS9irhjsxXpc3kj8jG2jjdVI3c0LduCloBTnamzVSsfzXUG5pdZZaGws3iGWlOyZNqKkr5979il
RJouljjbePzYkDSZraUHrMjZkv/bjY0N/b+xMs6WNDDG//Mv//e2//n/JW3vb2+W9gZnWw3kM2RL
oMkxOEmTwjnbj2/97sSfF2jlyidvnrj0V7Ma1oqU6NnXbsibiMX1TdIF0hVZeDbj+9ef/8jl+tHP
fnfhsJ/msr2UgeqAHWjCxKVV8qpiZSk0HVYSqq2JfrJ0Mmx+5YpTnZaB6VIx2lyXipGtyrouzJjt
SaUNAWA0iOpMg+0ObfAq+ahPXTWPt9hDul0JrnAHgF3MVEfRq4j/6LWwMvGm9cWjaR0DWgJOdaYe
NRMappXUpso3D3NFuZarb7WfXYh/PToWP3N1upvEWDlbIrSrtJPOS9Lo3SfpnRqYwUqd7fr6uv7f
/AELKeUgr49PTw2faPv1X5M7B/mtkn7ov3C21UA+Q7YEmhyDkzQpnLON/I1ebqW3HK989ubPzgfN
aooNo2dP3FhWFnTOVg34+NZbPxgsrpoWtpcyUB2wA02YuJRJXi1eO4KzBY1Lg6jONNju0EavEtPM
kXm8xR7S7UpwhTsA7GKmOopeRfxHT1bdARpWJt60vng0rWNAS8CpztTZsruRuQuwBrhWO8tDAWpW
L99enFn6dmHc+potZX939UlkXOodIhZ39g79lW5VVORsM5nM2traEf9Nfvj/aOv9cPXV3vamVQyc
bTXAYzgGg5M0Kbq7kRcuDshPQv7JG77pdYsatVg427vRS90/oT9rpL+zxTVbUC9owsSlTMpqh2+C
Zk0mdyOr9ylP+OjDTrRmh3qMQ+6NNMnY1Hrzuy4BaBjVmQbbHbqyu5GL9eZ7yHmhynYA2MVMdRT9
IeOOJT0mJp+81SHm1MgdTcu2oCXgVGfibHOx2fbA3AJZisfbB6XPdpRqnmKr3djsseGi+10eny7r
bDXSlwNTv71b7StxK3K2z6vg3v/7f6Y5TJH/5122pQicbTXAYzgGg5NstML2UgaqA3agCROXMimr
PG7lJ2IkzTI8Qcrl0W5arsBjlH2ejRbGZXVaPalTn64ie20+XQetTMOozjTY7tDJkId/ipD2M3Ya
wvrJTPi63Fy9yaAkeCCq7GlFOwDswqnO6tDQT1g7lpH+jg6/8smXizeThO5oWrQFLQGnOoOzNbz1
Jz06PNV9fTFNfdt2+iupOxCfoUaXtjr1FYnZl90vey7UenzuV4NTx9hPc43OdjcmtQfikzSyUEgl
egfvheiNzVVRkbN9+vTps2fPjvbvi93vWF+M/e2SGDjbaoDHcAwGJ9lohe2lDFQH7ECTKi6tUlZ9
oYj21p/iS0lofqy+9aerj38dUCUegzWnz/smrXXvIDHN6rj6fEJ7u4nhbUOglWkg1ZkG2xua+FNJ
fVEM/9YfYo4mit/GKHejq9mgGfl1PmyACnYA2EV3hjU/NOQT1t7i0+bxTRR/wmEZby4J3dG0kgFo
ATjVUY/K/5K2e1gKP5IfdKyQTY1eY2/96b4an1xjDi599z6tvEE8bG4ufL9TDvBcm5+ZoQ9Ali/z
ll6zzc2Nzypv/Wkfuv+HmRrklhU523SdgbOtBngMx2Bwko1W2F7KQHWgCmiOdYS8F6oD4oHqgHig
OiAex6iuIme7urr65MmT+v0LZ1sNmAEdg8FJNlpheykD1YEqgLMFTQNUB8QD1QHxOEZ1FTnbb+oM
nG01YAZ0DAYn2VBlEs4W1Aw4W9A0CFUdvUnUFNtfFtDUYK4D4nGM6g53tg8ePFhaWkrVDdI5GQLO
9shgBnQMD3PbBj/ZOIXsG9tLGagOiAeqA+KB6oB4oDogHseo7nBnu7y8LEnS4uIiWag5pFvSOVk4
OLB+Py4oC2ZAx7C+t2/wk41TNvd131CoDogHqgPigeqAeKA6IB7HqO4QZ/vq1auXL18+fvyY+M9Y
HSDdks63t7fJQGxIYBPMgE6CmNuHue3JEmP5PRayPwZbS4DqgHigOiAeqA6IB6oD4nGM6g5xtoT9
/X1ibknYZh0g3ZLOcStyNWAGBOKB6oB4oDogHqgOiAeqA+JxjOoOd7aEV69eHRwcEP9ZD3C1tkow
AwLxQHVAPFAdEA9UB8QD1QHxOEZ1FTlb0MhgBgTigeqAeKA6IB6oDogHqgPicYzq4GybHsyAQDxQ
HRAPVAfEA9UB8UB1QDyOUd1RnG02m1Xe1lNzlpeXSedsGFAZmAGdB3uOVPaQxzh9j0B1QDxQHRAP
VAfEA9UB8ThGdbadLXGeKysrz549y9QB0i3pfGNjgw0GKgAzoMMo8+6fxjG3UB0QD1QHxAPVAfFA
dUA8jlGdbWebSqXqZGsVSOdkCDYYqADMgA7jYW7bYGi1QjaxoO8bqA6IB6oD4oHqgHigOiAex6jO
trNdWlpiHrRukCHYYKACMAM6DIOb5ctkNseCvm+gOiAeqA6IB6oD4oHqgHgcozo426YHM6DDMLhZ
Q2FB3zdQHRAPVAfEA9UB8UB1QDyOUV3NnG0qlRobGzsjQxYeP37MNtgHztYWmAEdhsHKGgoL+r6B
6oB4oDogHqjOjEzGXuYI7CFWdTiagFID1e2vpRvgKcC1cbbE1l65cuUtjosXL5qa2+fPn3/++efn
zp07ffr0hx9++OTJE7aBA87WFjjvOgyDlTUUFvR9A9UBhUzY6/KGM3RR8rtcfkmurRm6PjnV1Wqs
euwzcBQOVh335bVFJuLFt6a+VHCGrZWKcDQBg1PdWvjS1LHBYukcnr08c6gmvyWthuJsxYLloUEl
RluoPbVxtlNTU8zRcrz99tvEvo6NjRHfy+Iymfn5+WAwuLm5ubOzMzo6+uWXX7INHHC2toDHcBhf
bCxf8f3yRy7Xj068c3FeMbTpi2+6GEdJRGoPVAcU6uxsdUB1QDwOVt2RnS1pBy9UVypQXc2cLY4m
UOBUR50tZzu31x/N9w5OD8XLX1wxtCpPwzvb8fFxZmfNIOY2nU4rkdvb269evcrlcsTcEltLGir1
PHC2tkC25zDufvrOa+9PfryRu/vp2X8ZnJSd7eS///BsENdsQYOQiY14j7tdrjaPPxQ4yTvbgZEg
2+ILJ/NysJ58Muzz0AiXy328GETaeoPRUL+xrS5741Sn1ZMFfzjS10a6G4jSk5k8AFkl3XtHYmrW
LvcfUfaNbAgmSvvfkkL9pQ1Bq9NAqjMNtjd0uS+v9kXTOV7joHSjAgux3AH9RwTsYKY6CndoaL3Z
fFsmvlQShqNp1Ra0BJzqTDxqbkbqHJqbU1ZepMPX77XLl3N7bywu75Oq4mXe3ttrZD23lDgzPKXE
dA5L4SUlfS29ZptbuC15jGFVUa2zVe4ufvfdd5mLNeP8+fOLi4usgUoymbx27drs7Cxb54CztQU8
hsNQ7jom5eNPz3ZfmaPLix+e+L/88rVfuF0//uWIpGUoMpLf6w8O9LhdbX2RpBQgC+4eGrM6oSQb
5Iw3UYdTE1TXwiRGutxeOY8iOa2XpElcpuXq8sfoKSUT9XW5+yeMZ5etiQE3iygUVmljb6RsW12m
ZeExXB1yu7ycqEW86gDyznUFlC8MDXN7Qwm6gY7bMZKg1cV+VkMekvfJ2/PJkNflCa3KAaDVaRjV
mQbbHbrcl1f7onGWxnxQsl0NLrcD3EcE7GGmOoreqR4+ZxrizSTBH02rtqAl4FRnevU1eW5wepS+
lTVDtvaOP6EedH/tzvXp9uuLsh/lWmW/PjU4PTSzSZf3n4WI6b30aJ2ulDjbpbnuwdk72b1CYS/9
yWy7Zp6roFpnSwzqhQsXmIW1gDhb/oZkAjG0g4ODly9ffvr0KavigLO1BTyGw5BtrXz78U9+8/vp
NF399OwP3vwwIlvc/jbtvCNDzkRemmvkowPKQkEKdPglck7yhpJbdUspoLrWRQpoOREhGerhMid3
UZ1bkT7Vtlqhz7rcvpiqV9pWSdN0mZaVx/DHlEqat3dw3cg7x/WjhhmyPdoPbaj/ZgEg0yiqMw22
O3S5L2/xi1aMN99Dup3VVrYDwC5mqqPoVWQ635aJN1UjdzQt24KWgFOdqbNVKx/NdQbml1llobCz
eIZaU7Jk2oqSvn3v2KVEmi6WONt4/NiQNJmll31rRbXOdmVl5b333mMW1oKbN29ubm6yBjI7Ozvf
fffd3NzcBx988M0337BaFThbW8BjOAzlgq1cZnwn3vnTM22VlGXiWHVuQfKfDMt/5ienJOWMRE5H
ZCGfCPZ1tblcbV39EXl7bYHqWhZDupOP+rjMic+DdEkSx1ZSioQCAV9fDxXoIW11nVh6DDVga6Jf
102xW10Y97/A6ksaAsBoENWZBtsduuyX1yTeYg/pdiW4wh0AdjFTHUWvIv6j18LKxJvWF4+mdQxo
CTjVmXrUTGiYVlKbKt88zBXlWq6+1X52If716Fj8zNXpbhJj5WyJ0K7STjovSaN3n6R3amBxq3W2
uVzuwYMHZ8+eZS5Wz+nTp2/dukWG2NjYYA04iKe9ePFiMplk6ypwtraAx3AYH9/6XfeVmbvEx658
8ubPqLMlNSf+PEdr5se8J/X3q0n+4mlLOSOR05F2aqKZx4A7UFytFVBdy2JMd2JafkUkyG8gqyXS
y0uBLvdxry8YjkrJDL278ZC2ZKGYaTWIxwAtRYOozjTY7tBlv7wm8RZ7SLcrwRXuALCLmeooehXx
Hz1ZNZkz9fGm9cWjaR0DWgJOdabOlt2NzF2ANcC12lkeClCzevn24szStwvj1tdsKfu7q08i41Lv
ELG4s3for3SrogZPkNrd3WXbzDg4OCBDsNBMhtjgDz74gLjZdDr96aefBoNB8lGybSpwtrbgtAic
wBcbCxcH6LORf/CTN3zT6/KlWrXmF29NGC7AWjjbvDSiPKaH/s4W12xBDSl3QyO3gaZFyn2JReg1
InaPAUXf1nBnHXdPo1pvlu3pAg65N1IN4zI2td78rksAGkZ1psF2h67sbuRivfke0v5YbWU7AOxi
pjqK/pCZzrdl4ov1nBq5o2nZFrQEnOpMnG0uNtsemFsgS/F4+6D02Y5SzVNstRubPTZcdL/L49Nl
na1G+nJg6rd3q30lbg2crS1evHhx7969c+fOnTp16i9/+Us2mzXcqEyAs7UFPIbD4O49Niks6PsG
qmthkiEP/yAS3UNotA2R/o4Ov/IsGQ7J73b75PSrsCWNeEjbnlBS2VBsS5+Gwj+HRsu0DvcYZZ9n
o4VxWZ1WT+rU8QtbMX8Xn66DVqZhVGcabHdoqy8vDVGfRjTh63Jz9SaDkuCBqLKnFe0AsAunOqtD
Qz9h7Vhy8225eDNJ6I6mRVvQEnCqMzhbw1t/0qPDU93XF9P0xuHt9FdSdyA+Q40ubXXqKxKzL7tf
9lyo9fjcrwanjrGf5hqd7W5Mag/EJ2lkoZBK9A7eC9Ebm6tCtLMlH9zenvw/UCgor/9hGzjgbG3B
aRE4AYOVNRQW9H0D1bU0W5L6rgnDi0O0t0pY3SuQT6hvnfD0h6TYSJfLJ+dUNOtib7BwH/f6o2pb
XTbGqU6r1wVQSHrNHgve1ad7B4lpVsfV5xPa202sXlkEWpAGUp1psL2hrb68xBwpj9OX3wcT5W50
NRs0I7/Ohw1QwQ4Au+jOsOaHhnzCFvOtZby5JHRH00oGoAXgVEc9Kv9L2u5hKfxIftCxQjY1eo29
9af7anxyjf04Nn33Pq28QTxsbi58v1MO8Fybn5mhD0CWL/OWXrPNzY3PKm/9aR+6/4eZGuSWop1t
JcDZ2gIew2EYrKyhsKDvG6gO1JSK8mCoDogHqgPigeqAeByjOjjbpgczoMMwWFlDYUHfN1AdqClw
tqBBgeqAeKA6IB7HqA7OtunBDOgwDFaWL5NwtsCZwNmCBkWo6uhNoqYc+uUAjgJzHRCPY1Rn29mm
Uqlnz54xD1oHSOdkCDYYqADMgA7jYW7bYGi1QjaxoO8bqA6IB6oD4oHqgHigOiAex6jOtrPNZrMr
Kyt1MrekW9L5xsYGGwxUAGZAh7G+t28wtFohm1jQ9w1UB8QD1QHxQHVAPFAdEI9jVGfb2RKI80yl
Ukt1YHl5GbbWLpgBnQdxsIYrt2S1cWwtAaoD4oHqgHigOiAeqA6IxzGqO4qzBQ0FZkAgHqgOiAeq
A+KB6oB4oDogHseoDs626cEMCMQD1QHxQHVAPFAdEA9UB8TjGNXB2TY9mAGBeKA6IB6oDogHqgPi
geqAeByjOjjbpgczIBAPVAfEA9UB8UB1QDxQHRCPY1R3FGebzWbr9wQp0jkbBlQGZsDWRHnK1GS2
+JQp7VlTm/sHLKhuQHVAPFAdEA9UB8QD1QHxOEZ1tp0t3vrTaGAGbEHKvBlIKfU2t1AdEA9UB8QD
1QHxQHVAPI5RnW1nm0ql6mRrFUjnZAg2GKgAzIAtiOGdQKWFBLDQ+gDVAfFAdUA8UB0QD1QHxOMY
1dl2tktLS8yD1g0yBBsMVABmwBbE4GNLy2Q2x0LrA1QHxAPVAfFAdUA8UB0Qj2NUB2fb9GAGbEEM
Pta0sND6ANUB8UB1QDxQHRAPVAfE4xjV1czZplKpsbGxMzJk4fHjx2yDfeBsbYEZsAUxmFjTwkLr
A1QHxAPVAfFAdWZkMvYyR2APsarD0QSUGqhufy3dAE8Bro2zJbb2ypUrb3FcvHjR1Nw+f/78888/
P3fu3OnTpz/88MMnT56wDRxwtrbAebcFMZhY08JC6wNUBxQyYa/LG87QRcnvcvklubZm6PrkVFer
seqxz8BROFh13JfXFpmIF9+a+lLBGbZWKsLRBAxOdWvhS1PHBoulc3j28syhmvyWtBqKsxULlocG
lRhtofbUxtlOTU0xR8vx9ttvE/s6NjZGfC+Ly2Tm5+eDweDm5ubOzs7o6OiXX37JNnDA2doCHqMF
Ue3rwtDr7jejRTf7xfzYidfHIvIyC60PUB1QqLOz1QHVAfE4WHVHdrakHbxQXalAdTVztjiaQIFT
HXW2nO3cXn803zs4PRQvn1gaWpWn4Z3t+Pg4s7NmEHObTqeVyO3t7VevXuVyOWJuia0lDZV6Hjhb
WyDba0EUH/vX91/7wQ9dqrNd/8ft86/94uc/hbMF9SYTG/Eed7tcbR5/KHCSd7YDI0G2xRdO5uVg
Pflk2OehES6X+3gxiLT1BqOhfmNbXfbGqU6rJwv+cKSvjXQ3EKUnM3kAskq6947E1Kxd7j+i7BvZ
EEyU9r8lhfpLG4JWp4FUZxpsb+hyX17ti6ZzvMZB6UYFFmK5A/qPCNjBTHUU7tDQerP5tkx8qSQM
R9OqLWgJONWZeNTcjNQ5NDenrLxIh6/fa5cv5/beWFzeJ1XFy7y9t9fIem4pcWZ4SonpHJbCS0pS
WnrNNrdwW/IYw6qiWmer3F387rvvMhdrxvnz5xcXF1kDlWQyee3atdnZWbbOAWdrC3iMFoQY17vR
s6/5Jq/4NGeb/nt07mPTa7aS3+sPDvS4XW19kaQUIAvunhEpX1idUBISclacsHn6gupamMRIl9sr
51Ekp/WSNInLtFxd/hg9pWSivi53/4Tx7LI1MeBmEYXCKm3sjZRtq8u0LDyGq0Nul5cTtYhXHUDe
ua4AEToLc3tDCbqBjtsxkqDVxX5WQx6S98nb88mQ1+UJrcoBoNVpGNWZBtsdutyXV/uicZbGfFCy
XQ0utwPcRwTsYaY6it6pHj5nGuLNJMEfTau2oCXgVGd69TV5bnB6lL6VNUO29o4/oVnm/tqd69Pt
1xfljJNrlf361OD00MwmXd5/FiKm99KjdbpS4myX5roHZ+9k9wqFvfQns+2aea6Cap0tMagXLlxg
FtYC4mz5G5IJxNAODg5evnz56dOnrIoDztYW8BgtyBfzY//9X8f+sZELFp2tXBbNna3LS/ORfHRA
WShIgQ6/RM5b3lBy60hpB1TXukgBLSciJEM9XObk1rKiwlakT7WtVuizLrcvpmqRtlXSNF2mZeUx
/DGlkubtHVw38s5x/ahhhmyP9kMbFvcdAI1GUZ1psN2hy315i1+0Yrz5HtLtrLayHQB2MVMdRa8i
0/m2TLypGrmjadkWtASc6kydrVr5aK4zML/MKguFncUz1JqSJdNWlPTte8cuJdJ0scTZxuPHhqTJ
LL3sWyuqdbYrKyvvvfces7AW3Lx5c3NzkzWQ2dnZ+e677+bm5j744INvvvmG1arA2doCHqMFidx4
w1XkjaHFQ5ztybB8KYCctpSzFjllkYV8ItjX1eZytXX1R+TtlQPVtSyGdCcf9XGZE58H6ZIkjq2k
FAkFAr6+Hiq+Q9rqOrH0GGrA1kS/rptit7ow7n+B1Zc0BIDRIKozDbY7dNkvr0m8xR7S7UpwhTsA
7GKmOopeRfxHr4WViTetLx5N6xjQEnCqM/WomdAwraQ2Vb55mCvKtVx9q/3sQvzr0bH4mavT3STG
ytkSoV2lnXRekkbvPknv1MDiVutsc7ncgwcPzp49y1ysntOnT9+6dYsMsbGxwRpwEE978eLFZDLJ
1lXgbG0Bj9GCMB9b8TXb4qlNOWuRU5Z2+qLZyYA7UFytBKiuZTGmOzEtvyLy4jeQ1RJZ5aVAl/u4
1xcMR6Vkht7deEhbslDMtBrEY4CWokFUZxpsd+iyX16TeIs9pNuV4Ap3ANjFTHUUvYr4j56smsyZ
+njT+uLRtI4BLQGnOlNny+5G5i7AGuBa7SwPBahZvXx7cWbp24Vx62u2lP3d1SeRcal3iFjc2Tv0
V7pVUYMnSO3u7rJtZhwcHJAhWGgmQ2zwBx98QNxsOp3+9NNPg8Eg+SjZNhU4W1twWgStgmZlq3G2
eWlEeZQP/Z0trtmCCil3QyO3gaZFyn2JReg1Inb/AEXf1nBnHXdPo1pvlu3pAg65N1IN4zI2td78
rksAGkZ1psF2h67sbuRivfke0v5YbWU7AOxipjqK/pCZzrdl4ov1nBq5o2nZFrQEnOpMnG0uNtse
mFsgS/F4+6D02Y5SzVNstRubPTZcdL/L49Nlna1G+nJg6rd3q30lbg2crS1evHhx7969c+fOnTp1
6i9/+Us2mzXcqEyAs7UFPEYLUrSy1oWF1georoVJhjz8g0h0D6HRNkT6Ozr8yrNkOCS/2+2T06/C
ljTiIW17QkllQ7EtfRoK/xwaLdM63GOUfZ6NFsZldVo9qVPHL2zF/F18ug5amYZRnWmw3aGtvrw0
RH0a0YSvy83VmwxKggeiyp5WtAPALpzqrA4N/YS1Y8nNt+XizSShO5oWbUFLwKnO4GwNb/1Jjw5P
dV9fTNMbh7fTX0ndgfgMNbq01amvSMy+7H7Zc6HW43O/Gpw6xn6aa3S2uzGpPRCfpJGFQirRO3gv
RG9srgrRzpZ8cHt78v9AoaC8/odt4ICztQWnRdAqGEysaWGh9QGqa2m2JPVdE4YXh2hvlbC6DyCf
UN864ekPSbGRLpdPzqlo1sXeYOE+7vVH1ba6bIxTnVavC6CQ9Jo98rurT/cOEtOsjqvPJ7S3m1i9
sgi0IA2kOtNge0NbfXmJOVIelS+/DybK3ehqNmhGfp0PG6CCHQB20Z1hzQ8N+YQt5lvLeHNJ6I6m
lQxAC8CpjnpU/pe03cNS+JH8oGOFbGr0GnvrT/fV+OQa+3Fs+u59WnmDeNjcXPh+pxzguTY/M0Mf
gCxf5i29ZpubG59V3vrTPnT/DzM1yC1FO9tKgLO1BTxGC2IwsaaFhdYHqA7UlIryYKgOiAeqA+KB
6oB4HKM6ONumBzNgC2IwsaaFhdYHqA7UFDhb0KBAdUA8UB0Qj2NUB2fb9GAGbEEMJra0TMLZgmYC
zhY0KEJVR28SNeXQLwdwFJjrgHgcozrbznZ5efnZs2fMg9YB0nkqVfXPh1sJzIAtyMPctsHKGgoJ
YKH1AaoD4oHqgHigOiAeqA6IxzGqs+1ss9nsyspKncwt6ZZ0vrGxwQYDFYAZsAVZ39s3WFlD2dw/
YKH1AaoD4oHqgHigOiAeqA6IxzGqs+1sCcR5plKppTqwvLwMW2sXzICtCTG3D3PbkyWellTW29YS
oDogHqgOiAeqA+KB6oB4HKO6ozhb0FBgBgTigeqAeKA6IB6oDogHqgPicYzq4GybHsyAQDxQHRAP
VAfEA9UB8UB1QDyOUR2cbdODGRCIB6oD4oHqgHigOiAeqA6IxzGqg7NtejADAvFAdUA8UB0QD1QH
xAPVAfE4RnVHcbbZbLZ+T5AinbNhQGVgBgRWrO/tz269vLf5giywqhoB1QHxQHVAPFAdEA9UB8Tj
GNXZdrZ460+jgRkQWEE8rfLAZOJvWVWNgOqAeKA6IB6oDogHqgPicYzqbDvbVCpVJ1urQDonQ7DB
QAVgBgRWaK8CIoVV1QioDogHqgPigeqAeKA6IB7HqM62s11aWmIetG6QIdhgoAIwAwIr4GyBk4Dq
gHigOiAeqA6IxzGqg7NtejADAivgbIGTgOqAeKA6IB6oDojHMaqrmbNNpVJjY2NnZMjC48eP2Qb7
wNnaAjMgsALOFjgJqA6IB6ozI5OxlzkCe4hVHY4moNRAdftr6QZ4CnBtnC2xtVeuXHmL4+LFi6bm
9vnz559//vm5c+dOnz794YcfPnnyhG3ggLO1Bc67wAo4W1BvMmGvyxvO0EXJ73L5Jbm2Zuj65FRX
q7Hqsc/AUThYddyX1xaZiBffmvpSwRm2VirC0QQMTnVr4UtTxwaLpXN49vLMoZr8lrQairMVC5aH
BpUYbaH21MbZTk1NMUfL8fbbbxP7OjY2Rnwvi8tk5ufng8Hg5ubmzs7O6Ojol19+yTZwwNnaAh4D
WMFs7fzYidfH9OnLatjrruZkBtUBhTo7Wx1QHRCPg1V3ZGdL2sEL1ZUKVFczZ4ujCRQ41VFny9nO
7fVH872D00Px8tdIDK3K0/DOdnx8nNlZM4i5TafTSuT29varV69yuRwxt8TWkoZKPQ+crS2Q7QEr
vthY/8ft86/94uc/1TvbxEiP213VyQyqa2kysRHvcbfL1ebxhwIneWc7MBJkW3zhZF4O1pNPhn0e
GuFyuY8Xg0hbbzAa6je21WVvnOq0erLgD0f62kh3A1F6MpMHIKuke+9ITJW93H9E2TeyIZgo7X9L
CvWXNgStTgOpzjTY3tDlvrzaF03neI2D0o0KLMRyB/QfEbCDmeoo3KGh9WbzbZn4UkkYjqZVW9AS
cKoz8ai5GalzaG5OWXmRDl+/1y5fzu29sbi8T6qKl3l7b6+R9dxS4szwlBLTOSyFlxRXXHrNNrdw
W/IYw6qiWmer3F387rvvMhdrxvnz5xcXF1kDlWQyee3atdnZWbbOAWdrC3gMYMUXG+m/R+c+1l+z
zUv+k34pSvIO9QTGkPxef3Cgx+1q64skpQBZcPeMSPnC6oSSt5CT54TaC1TXwiRGutxeOY8iOa2X
pElcpuXq8sfoKSUT9XW5+yeMZ5etiQE3i1BuHHB5I2Xb6jItC4/h6pDb5eVELeJVB5B3ritAFMzC
3N5Qgm6g43aMJGh1sZ/VkIfkffL2fDLkdXlCq3IAaHUaRnWmwXaHLvfl1b5onKUxH5RsV4PL7QD3
EQF7mKmOoneqh8+ZhngzSfBH06otaAk41ZlefU2eG5wepW9lzZCtveNPqAfdX7tzfbr9+qLsR7lW
2a9PDU4PzWzS5f1nIWJ6Lz1apyslznZprntw9k52r1DYS38y266Z5yqo1tkSg3rhwgVmYS0gzpa/
IZlADO3g4ODly5efPn3KqjjgbG0BjwGsYHcjL3LOdjXc1xcmuQk5g2knMAap8tK0JR8dUBYKUqDD
L5HTmzeU3NJnJ1Bd6yIFtJyIkAz1cJkTd4v7VqRPta1W6LMuty+mioy2VdI0XaZl5TH8MaWS5u0d
XDfyznH9qGGGbI/2QxsavxAAEBpFdabBdocu9+UtftGK8eZ7SLez2sp2ANjFTHUUvYpM59sy8aZq
5I6mZVvQEnCqM3W2auWjuc7A/DKrLBR2Fs9Qa0qWTFtR0rfvHbuUSNPFEmcbjx8bkiaz9LJvrajW
2a6srLz33nvMwlpw8+bNzc1N1kBmZ2fnu+++m5ub++CDD7755htWqwJnawt4DGBFqbOl56oi+rOW
5D9JPa98dlNObiSaLOQTwb6uNperras/Im8nQHUtiyHdyUd9XObEK0qXJHFsJaVIKBDw9fVQVR3S
VteJpcdQA7Ym+nXdFLvVhXH/C6y+pCEAjAZRnWmw3aHLfnlN4i32kG5XgivcAWAXM9VR9CriP3ot
rEy8aX3xaFrHgJaAU52pR82EhmkltanyzcNcUa7l6lvtZxfiX4+Oxc9cne4mMVbOlgjtKu2k85I0
evdJeqcGFrdaZ5vL5R48eHD27FnmYvWcPn361q1bZIiNjQ3WgIN42osXLyaTSbauAmdrC3gMYIXJ
NVsVcgbTTmAMyV88AyrbyJmNC6J3kgbYKlTXshjTnZiWXxHd8BvIqqYXlbwU6HIf9/qC4aiUzNC7
Gw9pSxaKQm0QjwFaigZRnWmw3aHLfnlN4i32kG5XgivcAWAXM9VR9CriP3qyajJn6uNN64tH0zoG
tASc6kydLbsbmbsAa4BrtbM8FKBm9fLtxZmlbxfGra/ZUvZ3V59ExqXeIWJxZ+/QX+lWRQ2eILW7
u8u2mXFwcECGYKGZDLHBH3zwAXGz6XT6008/DQaD5KNk21TgbG3BaREAHTVxtnlpRHniD/2dLa7Z
gnI3NHIbaFqk3JdYhF4jYjcGUPRtDXfWcfc0qvVm2Z4u4JB7I9UwLmNT683vugSgYVRnGmx36Mru
Ri7Wm+8h7Y/VVrYDwC5mqqPoD5npfFsmvljPqZE7mpZtQUvAqc7E2eZis+2BuQWyFI+3D0qf7SjV
PMVWu7HZY8NF97s8Pl3W2WqkLwemfnu32lfi1sDZ2uLFixf37t07d+7cqVOn/vKXv2SzWcONygQ4
W1vAYwArmLOVC6uqEVBdC5MMefgHkegeQqNtiPR3dPiVZ8lwSH632yenX4UtacRD2vaEksqGYlv6
NBT+OTRapnW4xyj7PBstjMvqtHpSp45f2Ir5u/h0HbQyDaM602C7Q1t9eWmI+jSiCV+Xm6s3GZQE
D0SVPa1oB4BdONVZHRr6CWvHkptvy8WbSUJ3NC3agpaAU53B2Rre+pMeHZ7qvr6YpjcOb6e/kroD
8RlqdGmrU1+RmH3Z/bLnQq3H5341OHWM/TTX6Gx3Y1J7ID5JIwuFVKJ38F6I3thcFaKdLfng9vbk
/4FCQXn9D9vAAWdrC06LAOiAswV1YUtS3zVheHGI9lYJ/gI/Tz6hvnXC0x+SYiNdLp+cU9Gsi73B
wn3c64+qbXXZGKc6rV4XQCHpNXuWd1ef7h0kplkdV59PaG83sXplEWhBGkh1psH2hrb68hJzpDwD
X34fTJS70dVs0Iz8Oh82QAU7AOyiO8OaHxryCVvMt5bx5pLQHU0rGYAWgFMd9aj8L2m7h6XwI/lB
xwrZ1Og19taf7qvxyTX249j03fu08gbxsLm58P1OOcBzbX5mhj4AWb7MW3rNNjc3Pqu89ad96P4f
ZmqQW4p2tpUAZ2sLeAxgBZwtaBIqyoOhOiAeqA6IB6oD4nGM6uBsmx7MgMAKOFvQJMDZggYFqgPi
geqAeByjOjjbpgczILACzhY0CXC2oEERqjp6k6gph345gKPAXAfE4xjV2Xa2y8vLz549Yx60DpDO
U6mqfz7cSmAGBFbA2QInAdUB8UB1QDxQHRCPY1Rn29lms9mVlZU6mVvSLel8Y2ODDQYqADMgsOLe
5gvF1s5uvWRVNQKqA+KB6oB4oDogHqgOiMcxqrPtbAnEeaZSqaU6sLy8DFtrF8yAwIr1vX3iaYm/
JQusqkZAdUA8UB0QD1QHxAPVAfE4RnVHcbagocAMCMQD1QHxQHVAPFAdEA9UB8TjGNXB2TY9mAGB
eKA6IB6oDogHqgPigeqAeByjOjjbpgczIBAPVAfEA9UB8UB1QDxQHRCPY1QHZ9v0YAYE4oHqgHig
OiAeqA6IB6oD4nGM6o7ibLPZbP2eIEU6Z8OAysAMCOzyMLdNCls5ElAdEA9UB8QD1QHxQHVAPI5R
nW1ni7f+NBqYAYFdqn/DLVQHxAPVAfFAdUA8UB0Qj2NUZ9vZplKpOtlaBdI5GYINBioAMyCwC5wt
aEagOiAeqA6IB6oD4nGM6mw726WlJeZB6wYZgg0GKgAzILALnC1oRqA6IB6oDogHqgPicYzq4Gyb
HsyAwC5wtqAZgeqAeKA6IB6oDojHMaqrmbNNpVJjY2NnZMjC48eP2Qb7wNnaAjMgsAucLWhGoDog
HqjOjEzGXuYI7CFWdTiagFID1e2vpRvgKcC1cbbE1l65cuUtjosXL5qa2+fPn3/++efnzp07ffr0
hx9++OTJE7aBA87WFjjvArvA2YJakQl7Xd5whi5KfpfLL8m1NUPXJ6e6Wo1Vj30GjsLBquO+vLbI
RLz41tSXCs6wtVIRjiZgcKpbC1+aOjZYLJ3Ds5dnDtXkt6TVUJytWLA8NKjEaAu1pzbOdmpqijla
jrfffpvY17GxMeJ7WVwmMz8/HwwGNzc3d3Z2RkdHv/zyS7aBA87WFvAYwC5fbKwH3/9lm8vl7hmY
WGWVtoDqgEKdna0OqA6Ix8GqO7KzJe3ghepKBaqrmbPF0QQKnOqos+Vs5/b6o/newemhePkrIoZW
5Wl4Zzs+Ps7srBnE3KbTaSVye3v71atXuVyOmFtia0lDpZ4HztYWyPaAXb6YvvQvA5/Qb34y6Omf
OMKNSFBdS5OJjXiPu12uNo8/FDjJO9uBkSDb4gsn83Kwnnwy7PPQCJfLfbwYRNp6g9FQv7GtLnvj
VKfVkwV/ONJH/0wzEKVKlgcgq6R770hMzdrl/iPKvpENwURp/1tSqL+0IWh1Gkh1psH2hi735dW+
aDrHaxyUblRgIZY7oP+IgB3MVEfhDg2tN5tvy8SXSsJwNK3agpaAU52JR83NSJ1Dc3PKyot0+Pq9
dvlybu+NxeV9UlW8zNt7e42s55YSZ4anlJjOYSm8pLji0mu2uYXbkscYVhXVOlvl7uJ3332XuVgz
zp8/v7i4yBqoJJPJa9euzc7OsnUOOFtbwGMAu3wxH3xNdbYnfTEt56FIfq8/ONDjdrX1RZJSgCy4
e0akfGF1QsleyCl0IgPVtTKJkS63V86jSE7rJWkSl2m5uvwxKqxM1NflLv2jydbEgJtFFAqrtLE3
UratLtOy8BiuDrldXk7UIl51AHnnugJEuyzM7Q0l6AY6bsdIglYX+1kNeUjeJ2/PJ0Nelyd0pJsZ
gONoGNWZBtsdutyXV/uicZbGfFCyXQ0utwPcRwTsYaY6it6pHj5nGuLNJMEfTau2oCXgVGd69TV5
bnB6lL6VNUO29o4/oR50f+3O9en264uyH+VaZb8+NTg9NLNJl/efhYjpvfRona6UONulue7B2TvZ
vUJhL/3JbLtmnqugWmdLDOqFCxeYhbWAOFv+hmQCMbSDg4OXL19++vQpq+KAs7UFPAawyxcb6T/5
XiOnRddxkuSwSgY5tXlp8pKPDigLBSnQ4ZfISc4bSm6pOQpU17pIAS0nIiRDPVzm5NayosJWpE+1
rVbosy538W8stK2SpukyLSuP4Y8plTRv7+C6kXeO60cNM2R7tB/asLjvAGg0iupMg+0OXe7LW/yi
FePN95BuZ7WV7QCwi5nqKHoVmc63ZeJN1cgdTcu2oCXgVGfqbNXKR3OdgfllVlko7CyeodaULJm2
oqRv3zt2KZGmiyXONh4/NiRNZull31pRrbNdWVl57733mIW14ObNm5ubm6yBzM7OznfffTc3N/fB
Bx988803rFYFztYW8BjALh/f+t2JPy/Qpa2o31NMdCiS/2RYvm5AznHKKY6c38hCPhHs62pzudq6
+iOrUF3rYkh38lEflznxeZAuSeLYSkqRUCDg6+uhejqkra4TS4+hBmxN9Ou6KXarC+P+F1h9SUMA
GA2iOtNgu0OX/fKaxFvsId2uBFe4A8AuZqqj6FXEf/RaWJl40/ri0bSOAS0BpzpTj5oJDdNKalPl
m4e5olzL1bfazy7Evx4di5+5Ot1NYqycLRHaVdpJ5yVp9O6T9E4NLG61zjaXyz148ODs2bPMxeo5
ffr0rVu3yBAbGxusAQfxtBcvXkwmk2xdBc7WFvAYwC6Rv71x4s9z9O/sWzF/V0A9kclI/uJ5UDnF
kfObdq6jqcyAOyBBdS2LMd2JafkVUQy/gawSpbAVRl4KdLmPe33BcFRKZujdjYe0JQvFTKtBPAZo
KRpEdabBdocu++U1ibfYQ7pdCa5wB4BdzFRH0auI/+jJqsmcqY83rS8eTesY0BJwqjN1tuxuZO4C
rAGu1c7yUICa1cu3F2eWvl0Yt75mS9nfXX0SGZd6h4jFnb1Df6VbFTV4gtTu7i7bZsbBwQEZgoVm
MsQGf/DBB8TNptPpTz/9NBgMko+SbVOBs7UFp0UAKuKLjYWLA/KzkXWPFpGxcLZ5aUR57g/9nS2u
2bYy5W5o5DbQtEi5L7EIvUbEbgmg6Nsa7qzj7mlU682yPV3AIfdGqmFcxqbWm991CUDDqM402O7Q
ld2NXKw330PaH6utbAeAXcxUR9EfMtP5tkx8sZ5TI3c0LduCloBTnYmzzcVm2wNz9Ga/eLx9UPps
R6nmKbbajc0eGy663+Xx6bLOViN9OTD127vVvhK3Bs7WFi9evLh37965c+dOnTr1l7/8JZvNGm5U
JsDZ2gIeA9gF77MFVZAMefgHkegeQqNtiPR3dPiVZ8lwSH632yenX4UtacRD2vaE5B96823p01D4
59BomdbhHqPs82y0MC6r0+pJnTq+fCcDn66DVqZhVGcabHdoqy8vDVGfRjTh63Jz9SaDkuCBqLKn
Fe0AsAunOqtDQz9h7Vhy8225eDNJ6I6mRVvQEnCqMzhbw1t/0qPDU93XF9P0xuHt9FdSdyA+Q40u
bXXqKxKzL7tf9lyo9fjcrwanjrGf5hqd7W5Mag/EJ2lkoZBK9A7eC9Ebm6tCtLMlH9zenvw/UCgo
r/9hGzjgbG3BaRGAioCzBVWxJanvmjC8OER7q4Ryab+UfEJ964SnPyTFRrpcPjmnolkXe4OF+7jX
H1Xb6rIxTnVavS6AQtJr9hTvrj7dO0hMszquPp/Q3m5i9coi0II0kOpMg+0NbfXlJeZIefq9fB9P
lLvR1WzQjPw6HzZABTsA7KI7w5ofGvIJW8y3lvHmktAdTSsZgBaAUx31qPwvabuHpfAj+UHHCtnU
6DX21p/uq/HJNfbj2PTd+7TyBvGwubnw/U45wHNtfmaGPgBZvsxbes02Nzc+q7z1p33o/h9mapBb
ina2lQBnawt4DGAXOFvQYFSUB0N1QDxQHRAPVAfE4xjVwdk2PZgBgV3gbEGDAWcLGhSoDogHqgPi
cYzq4GybHsyAwC5wtqDBgLMFDYpQ1dGbRE059MsBHAXmOiAex6jOtrNdXl5+9uwZ86B1gHSeSlX9
8+FWAjMgsAucLWhGoDogHqgOiAeqA+JxjOpsO9tsNruyslInc0u6JZ1vbGywwUAFYAYEdoGzBc0I
VAfEA9UB8UB1QDyOUZ1tZ0sgzjOVSi3VgeXlZdhau2AGBHZ5mNsmha0cCagOiAeqA+KB6oB4oDog
Hseo7ijOFjQUmAGBeKA6IB6oDogHqgPigeqAeByjOjjbpgczIBAPVAfEA9UB8UB1QDxQHRCPY1QH
Z9v0YAYE4oHqgHigOiAeqA6IB6oD4nGM6uBsmx7MgEA8UB0QD1QHxAPVAfFAdUA8jlHdUZxtNput
3xOkSOdsGFAZmAFBNazv7T/MbU9m6dOS+UIqN/cPWFAJUB0QD1QHxAPVAfFAdUA8jlGdbWeLt/40
GpgBwZEhttZgaA3FytxCdUA8UB0QD1QHxAPVAfE4RnW2nW0qlaqTrVUgnZMh2GCgAjADgiPzMLdt
sLKGYvVyIKgOiAeqA+KB6oB4oDogHseozrazXVpaYh60bpAh2GCgAjADgiNj8LGlZTKbY6F6oDog
HqgOiAeqA+KB6oB4HKM6ONumBzMgODIGH2taWKgeqA6IB6oD4oHqgHigOiAex6iuZs42lUqNjY2d
kSELjx8/ZhvsA2drC8yA4MgYTKxpYaF6oDogHqgOiAeqMyOTsZc5AnuIVR2OJqDUQHX7a+kGeApw
bZwtsbVXrlx5i+PixYum5vb58+eff/75uXPnTp8+/eGHHz558oRt4ICztQXOu+DIGEysaWGheqA6
oJAJe13ecIYuSn6Xyy/JtTVD1yenulqNVY99Bo7Cwarjvry2yES8+NbUlwrOsLVSEY4mYHCqWwtf
mjo2WCydw7OXZw7V5Lek1VCcrViwPDSoxGgLtac2znZqaoo5Wo63336b2NexsTHie1lcJjM/Px8M
Bjc3N3d2dkZHR7/88ku2gQPO1hbwGODIqPZ1Yeh195vRopv9Yn7sxOtjEXmZheqB6oBCnZ2tDqgO
iMfBqjuysyXt4IXqSgWqq5mzxdEECpzqqLPlbOf2+qP53sHpobh5QqhiaFWehne24+PjzM6aQcxt
Op1WIre3t1+9epXL5Yi5JbaWNFTqeeBsbYFsDxwZxcf+9f3XfvBDl+ps1/9x+/xrv/j5T+FsgRWZ
2Ij3uNvlavP4Q4GTvLMdGAmyLb5wMi8H68knwz4PjXC53MeLQaStNxgN9Rvb6rI3TnVaPVnwhyN9
baS7gSg9mckDkFXSvXckpmbtcv8RZd/IhmCitP8tKdRf2hC0Og2kOtNge0OX+/JqXzSd4zUOSjcq
sBDLHdB/RMAOZqqjcIeG1pvNt2XiSyVhOJpWbUFLwKnOxKPmZqTOobk5ZeVFOnz9Xrt8Obf3xuLy
PqkqXubtvb1G1nNLiTPDU0pM57AUXlKSydJrtrmF25LHGFYV1Tpb5e7id999l7lYM86fP7+4uMga
qCSTyWvXrs3OzrJ1DjhbW8BjgCNDjOvd6NnXfJNXfJqzTf89Ovex6TVbye/1Bwd63K62vv+cjQbI
grtnRMoXVieUxIacXSdwGnQ+iZEut1fOo0hO6yVpEpdpubr8MXpKyUR9Xe7+CePZZWtiwM0iCoVV
2tgbKdtWl2lZeAxXh9wuLydqEa86gLxzXQEiUBbm9oYSdAMdt2MkQauL/ayGPCTvk7fnkyGvyxNa
lQNAq9MwqjMNtjt0uS+v9kXjLI35oGS7GlxuB7iPCNijQmd76JxpiDeTBH80rdqClqC8sy0UkucG
p0fpW1kzZGvv+BOaHe6v3bk+3X59Uc4UuVbZr08NTg/NbNLl/WchYnovPVqnKyXOdmmue3D2Tnav
UNhLfzLbrpnnKqjW2RKDeuHCBWZhLSDOlr8hmUAM7eDg4OXLl58+fcqqOOBsbQFnC47MF/Nj//1f
x/6xkQsWna1cFs2drctL85p8dMD1+p9pCiYFOvwSOf95Q8ktpC8tghTQciJCMtTDZU5uLSsqbEX6
VNtqhT7rcvtiqoZoWyVN02VaVh7DH1Mqad7ewXUj7xzXjxpmyPZoP7Rhcd8B0GgU1ZkG2x263Je3
+EUrxpvvId3OaivbAWCXypyt6XxbJt5UjdzRtGwLWoLDnK1a+WiuMzC/zCoLhZ3FM9SakiXTVpT0
7XvHLiXSdLHE2cbjx4akySy97FsrqnW2Kysr7733HrOwFty8eXNzc5M1kNnZ2fnuu+/m5uY++OCD
b775htWqwNnaAs4WHJnIjTdcRd4YWjzE2Z4My5cUyOnvf4/SBXLqI6fBfCLY19XmcrV19Ufk7cDB
GNKdfNTHZU58HqRLkji2klIkFAj4+nqoaA5pq+vE0mOoAVsT/bpuit3qwrj/BVZf0hAARoOozjTY
7tBlv7wm8RZ7SLcrwRXuALBLZc6W/+i1sDLxpvXFo2kdA1qCw5xtJjRMK6lNlW8e5opyLVffaj+7
EP96dCx+5up0N4mxcrZEaFdpJ52XpNG7T9I7NbC41TrbXC734MGDs2fPMher5/Tp07du3SJDbGxs
sAYcxNNevHgxmUyydRU4W1vA2YIjw3xsxddsi6dI3tmq0FtNA8VV4EiM6U5My6+ILPgNZLVEDnkp
0OU+7vUFw1EpmaF3Nx7SliwUMy04WyAeBztb/ZfXJN5iD+l2JbjCHQB2OZKzNZkz9fGm9cWjaR0D
WoLDnC27G5m7AGuAa7WzPBSgZvXy7cWZpW8Xxq2v2VL2d1efRMal3iFicWfv0F/pVkUNniC1u7vL
tplxcHBAhmChmQyxwR988AFxs+l0+tNPPw0Gg+SjZNtU4GxtwWkRAHtoVrYaZ5uXRpRHAtHf2eKa
reMpd0Mjt4GmRcp9iUXoNSJ23Z+ib2u4s467p1GtP9RjHHJvpEnGptab33UJQMOozjTY7tCV3Y1c
rDffQ9ofq61sB4BdzFRH0R8y0/m2THyxnlMjdzQt24KWgFOdibPNxWbbA3MLZCkebx+UPttRqnmK
rXZjs8eGi+53eXy6rLPVSF8OTP32brWvxK2Bs7XFixcv7t27d+7cuVOnTv3lL3/JZrOGG5UJcLa2
gLMFR6ZoZa0LC9UD1bUwyZCHfxCJ7iE02oZIf0eHX3mWDIfkd7t9cvpV2JJGPKRtTyipbCi2pU9D
4Z9Do2Vah3uMss+z0cK4rE6rJ3Xq+IWtmL+LT9dBK9MwqjMNtju01ZeXhqhPI5rwdbm5epNBSfBA
VNnTinYA2IVTndWhoZ+wdiy5+bZcvJkkdEfToi1oCTjVGZyt4a0/6dHhqe7ri2l64/B2+iupOxCf
oUaXtjr1FYnZl90vey7UenzuV4NTx9hPc43OdjcmtQfikzSyUEglegfvheiNzVUh2tmSD25vT/4f
KBSU1/+wDRxwtrbgtAiAPQwm1rSwUD1QXUuzJanvmjC8OER7q4TV9ft8Qn3rhKc/JMVGulw+Oaei
WRd7g4X7uNcfVdvqsjFOdVq9LoBC0mv2qO6uPt07SEyzOq4+n9DebmL1yiLQgjSQ6kyD7Q1t9eUl
5kh5xL38Ppgod6Or2aAZ+XU+bIAKdgDYRXeGNT805BO2mG8t480loTuaVjIALQCnOupR+V/Sdg9L
4Ufyg44VsqnRa+ytP91X45Nr7Mex6bv3aeUN4mFzc+H7nXKA59r8zAx9ALJ8mbf0mm1ubnxWeetP
+9D9P8zUILcU7WwrAc7WFvAY4MgYTKxpYaF6oDpQUyrKg6E6IB6oDogHqgPicYzq4GybHsyA4MgY
TKxpYaF6oDpQU+BsQYMC1QHxQHVAPI5RHZxt04MZEBwZg4ktLZNwtkAEcLagQRGqOnqTqCmHfjmA
o8BcB8TjGNXZdrbLy8vPnj1jHrQOkM5Tqap/PtxKYAYER+ZhbttgZQ2FBLBQPVAdEA9UB8QD1QHx
QHVAPI5RnW1nm81mV1ZW6mRuSbek842NDTYYqADMgODIrO/tG6ysoWzuH7BQPVAdEA9UB8QD1QHx
QHVAPI5RnW1nSyDOM5VKLdWB5eVl2Fq7YAYE1UDM7cPc9mSJpyWVVraWANUB8UB1QDxQHRAPVAfE
4xjVHcXZgoYCMyAQD1QHxAPVAfFAdUA8UB0Qj2NUB2fb9GAGBOKB6oB4oDogHqgOiAeqA+JxjOrg
bAEAAAAAAAAANDdwtgAAAAAAAAAAmhs4WwAAAAAAAAAAzQ2cLQAAAAAAAACA5gbOFgAAAAAAAABA
cwNnCwAAAAAAAACguYGzBQAAAAAAAADQ3MDZAgAAAAAAAABobuBsAQAAAAAAAAA0N3C2AAAAAAAA
AACaGzhbAAAAAAAAAADNTKHw/wfciDT0y1samQAAAABJRU5ErkJggg==
"
id="image3344"
x="0"
y="0" />
</svg>

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -3314,6 +3314,84 @@
#policy_dirs = policy.d #policy_dirs = policy.d
[profiler]
#
# From osprofiler
#
#
# Enables the profiling for all services on this node. Default
# value is False
# (fully disable the profiling feature).
#
# Possible values:
#
# * True: Enables the feature
# * False: Disables the feature. The profiling cannot be
# started via this project
# operations. If the profiling is triggered by another
# project, this project part
# will be empty.
# (boolean value)
# Deprecated group/name - [profiler]/profiler_enabled
#enabled = false
#
# Enables SQL requests profiling in services. Default value is
# False (SQL
# requests won't be traced).
#
# Possible values:
#
# * True: Enables SQL requests profiling. Each SQL query will
# be part of the
# trace and can the be analyzed by how much time was spent for
# that.
# * False: Disables SQL requests profiling. The spent time is
# only shown on a
# higher level of operations. Single SQL queries cannot be
# analyzed this
# way.
# (boolean value)
#trace_sqlalchemy = false
#
# Secret key(s) to use for encrypting context data for
# performance profiling.
# This string value should have the following format:
# <key1>[,<key2>,...<keyn>],
# where each key is some random string. A user who triggers
# the profiling via
# the REST API has to set one of these keys in the headers of
# the REST API call
# to include profiling results of this node for this
# particular project.
#
# Both "enabled" flag and "hmac_keys" config options should be
# set to enable
# profiling. Also, to generate correct profiling information
# across all services
# at least one key needs to be consistent between OpenStack
# projects. This
# ensures it can be used from client side to generate the
# trace, containing
# information from all possible resources. (string value)
#hmac_keys = SECRET_KEY
#
# Connection string for a notifier backend. Default value is
# messaging:// which
# sets the notifier to oslo_messaging.
#
# Examples of possible values:
#
# * messaging://: use oslo_messaging driver for sending
# notifications.
# (string value)
#connection_string = messaging://
[pxe] [pxe]
# #

View File

@ -18,6 +18,7 @@
import keystonemiddleware.audit as audit_middleware import keystonemiddleware.audit as audit_middleware
from oslo_config import cfg from oslo_config import cfg
import oslo_middleware.cors as cors_middleware import oslo_middleware.cors as cors_middleware
import osprofiler.web as osprofiler_web
import pecan import pecan
from ironic.api import config from ironic.api import config
@ -93,6 +94,9 @@ def setup_app(pecan_config=None, extra_hooks=None):
app, dict(cfg.CONF), app, dict(cfg.CONF),
public_api_routes=pecan_config.app.acl_public_routes) public_api_routes=pecan_config.app.acl_public_routes)
if CONF.profiler.enabled:
app = osprofiler_web.WsgiMiddleware(app)
# Create a CORS wrapper, and attach ironic-specific defaults that must be # Create a CORS wrapper, and attach ironic-specific defaults that must be
# included in all CORS responses. # included in all CORS responses.
app = IronicCORS(app, CONF) app = IronicCORS(app, CONF)

View File

@ -22,6 +22,7 @@ import sys
from oslo_config import cfg from oslo_config import cfg
from oslo_reports import guru_meditation_report as gmr from oslo_reports import guru_meditation_report as gmr
from ironic.common import profiler
from ironic.common import service as ironic_service from ironic.common import service as ironic_service
from ironic.common import wsgi_service from ironic.common import wsgi_service
from ironic.objects import base from ironic.objects import base
@ -41,6 +42,8 @@ def main():
base.IronicObject.indirection_api = ( base.IronicObject.indirection_api = (
indirection.IronicObjectIndirectionAPI()) indirection.IronicObjectIndirectionAPI())
profiler.setup('ironic_api', CONF.host)
# Build and start the WSGI app # Build and start the WSGI app
launcher = ironic_service.process_launcher() launcher = ironic_service.process_launcher()
server = wsgi_service.WSGIService('ironic_api', CONF.api.enable_ssl_api) server = wsgi_service.WSGIService('ironic_api', CONF.api.enable_ssl_api)

View File

@ -26,6 +26,7 @@ from oslo_log import log
from oslo_reports import guru_meditation_report as gmr from oslo_reports import guru_meditation_report as gmr
from oslo_service import service from oslo_service import service
from ironic.common import profiler as profiler
from ironic.common import rpc_service from ironic.common import rpc_service
from ironic.common import service as ironic_service from ironic.common import service as ironic_service
from ironic import version from ironic import version
@ -78,6 +79,8 @@ def main():
issue_startup_warnings(CONF) issue_startup_warnings(CONF)
profiler.setup('ironic_conductor', CONF.host)
launcher = service.launch(CONF, mgr) launcher = service.launch(CONF, mgr)
launcher.wait() launcher.wait()

View File

@ -16,6 +16,7 @@
# under the License. # under the License.
from oslo_config import cfg from oslo_config import cfg
import osprofiler.opts as profiler_opts
from ironic.common import rpc from ironic.common import rpc
from ironic import version from ironic import version
@ -28,3 +29,4 @@ def parse_args(argv, default_config_files=None):
version=version.version_info.release_string(), version=version.version_info.release_string(),
default_config_files=default_config_files) default_config_files=default_config_files)
rpc.init(cfg.CONF) rpc.init(cfg.CONF)
profiler_opts.set_defaults(cfg.CONF)

62
ironic/common/profiler.py Normal file
View File

@ -0,0 +1,62 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log as logging
from osprofiler import initializer
from osprofiler import profiler
from ironic.common import context
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def setup(name, host='0.0.0.0'):
"""Setup OSprofiler notifier and enable profiling.
:param name: name of the service that will be profiled
:param host: hostname or host IP address that the service will be
running on. By default host will be set to 0.0.0.0, but
specifying host name / address usage is highly recommended.
:raises TypeError: in case of invalid connection string for
a notifier backend, which is set in
osprofiler.initializer.init_from_conf.
"""
if CONF.profiler.enabled:
admin_context = context.get_admin_context()
initializer.init_from_conf(conf=CONF,
context=admin_context.to_dict(),
project="ironic",
service=name,
host=host)
LOG.info("OSProfiler is enabled. Trace is generated using "
"[profiler]/hmac_keys specified in ironic.conf. "
"To disable, set [profiler]/enabled=false")
def trace_cls(name, **kwargs):
"""Wrap the OSProfiler trace_cls decorator
Wrap the OSProfiler trace_cls decorator so that it will not try to
patch the class unless OSProfiler is present and enabled in the config
:param name: The name of action. For example, wsgi, rpc, db, etc..
:param kwargs: Any other keyword args used by profiler.trace_cls
"""
def decorator(cls):
if profiler and 'profiler' in CONF and CONF.profiler.enabled:
trace_decorator = profiler.trace_cls(name, kwargs)
return trace_decorator(cls)
return cls
return decorator

View File

@ -16,6 +16,7 @@
from oslo_config import cfg from oslo_config import cfg
import oslo_messaging as messaging import oslo_messaging as messaging
from oslo_messaging.rpc import dispatcher from oslo_messaging.rpc import dispatcher
from osprofiler import profiler
from ironic.common import context as ironic_context from ironic.common import context as ironic_context
from ironic.common import exception from ironic.common import exception
@ -95,9 +96,21 @@ class RequestContextSerializer(messaging.Serializer):
return self._base.deserialize_entity(context, entity) return self._base.deserialize_entity(context, entity)
def serialize_context(self, context): def serialize_context(self, context):
return context.to_dict() _context = context.to_dict()
prof = profiler.get()
if prof:
trace_info = {
"hmac_key": prof.hmac_key,
"base_id": prof.get_base_id(),
"parent_id": prof.get_id()
}
_context.update({"trace_info": trace_info})
return _context
def deserialize_context(self, context): def deserialize_context(self, context):
trace_info = context.pop("trace_info", None)
if trace_info:
profiler.init(**trace_info)
return ironic_context.RequestContext.from_dict(context) return ironic_context.RequestContext.from_dict(context)

View File

@ -29,12 +29,15 @@ from oslo_utils import netutils
from oslo_utils import strutils from oslo_utils import strutils
from oslo_utils import timeutils from oslo_utils import timeutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
from osprofiler import sqlalchemy as osp_sqlalchemy
import sqlalchemy as sa
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy import sql from sqlalchemy import sql
from ironic.common import exception from ironic.common import exception
from ironic.common.i18n import _ from ironic.common.i18n import _
from ironic.common import profiler
from ironic.common import states from ironic.common import states
from ironic.conf import CONF from ironic.conf import CONF
from ironic.db import api from ironic.db import api
@ -53,14 +56,20 @@ def get_backend():
def _session_for_read(): def _session_for_read():
return enginefacade.reader.using(_CONTEXT) return _wrap_session(enginefacade.reader.using(_CONTEXT))
# Please add @oslo_db_api.retry_on_deadlock decorator to all methods using # Please add @oslo_db_api.retry_on_deadlock decorator to all methods using
# _session_for_write (as deadlocks happen on write), so that oslo_db is able # _session_for_write (as deadlocks happen on write), so that oslo_db is able
# to retry in case of deadlocks. # to retry in case of deadlocks.
def _session_for_write(): def _session_for_write():
return enginefacade.writer.using(_CONTEXT) return _wrap_session(enginefacade.writer.using(_CONTEXT))
def _wrap_session(session):
if CONF.profiler.enabled and CONF.profiler.trace_sqlalchemy:
session = osp_sqlalchemy.wrap_session(sa, session)
return session
def _get_node_query_with_tags(): def _get_node_query_with_tags():
@ -191,6 +200,7 @@ def _filter_active_conductors(query, interval=None):
return query return query
@profiler.trace_cls("db_api")
class Connection(api.Connection): class Connection(api.Connection):
"""SqlAlchemy connection.""" """SqlAlchemy connection."""

View File

@ -0,0 +1,43 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo_config import cfg
from osprofiler import web
from ironic.tests.unit.api import base
CONF = cfg.CONF
class TestOsprofilerWsgiMiddleware(base.BaseApiTest):
"""Provide a basic test for OSProfiler wsgi middleware.
The tests below provide minimal confirmation that the OSProfiler wsgi
middleware is called.
"""
def setUp(self):
super(TestOsprofilerWsgiMiddleware, self).setUp()
@mock.patch.object(web, 'WsgiMiddleware')
def test_enable_osp_wsgi_request(self, mock_ospmiddleware):
CONF.profiler.enabled = True
self._make_app()
mock_ospmiddleware.assert_called_once_with(mock.ANY)
@mock.patch.object(web, 'WsgiMiddleware')
def test_disable_osp_wsgi_request(self, mock_ospmiddleware):
CONF.profiler.enabled = False
self._make_app()
self.assertFalse(mock_ospmiddleware.called)

View File

@ -0,0 +1,17 @@
---
features:
- |
Adds OSProfiler support. This cross-project profiling library
provides the ability to trace various OpenStack requests through all
OpenStack services that support it. To initiate OpenStack request tracing,
`--profile <HMAC_KEY>` option needs to be added to the CLI command.
As part of the output, there will be a message with <trace_id>.
To see the HTML graphs, the following command should be used -
`$ osprofiler trace show <trace_id> --html --out result.html`. See
OSProfiler documentation: http://docs.openstack.org/developer/osprofiler/.
security:
- OSProfiler support requires passing of trace information between
various OpenStack services. This information is securely signed
by one of HMAC keys, defined in ironic.conf configuration file.
To allow cross-project tracing, user should use the key that is
common among all OpenStack services he or she wants to trace.

View File

@ -30,6 +30,7 @@ oslo.reports>=0.6.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0
oslo.service>=1.10.0 # Apache-2.0 oslo.service>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0 oslo.utils>=3.20.0 # Apache-2.0
osprofiler>=1.4.0 # Apache-2.0
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
requests>=2.14.2 # Apache-2.0 requests>=2.14.2 # Apache-2.0
rfc3986>=0.3.1 # Apache-2.0 rfc3986>=0.3.1 # Apache-2.0

View File

@ -16,4 +16,5 @@ namespace = oslo.log
namespace = oslo.service.service namespace = oslo.service.service
namespace = oslo.service.periodic_task namespace = oslo.service.periodic_task
namespace = oslo.service.sslutils namespace = oslo.service.sslutils
namespace = osprofiler
namespace = keystonemiddleware.auth_token namespace = keystonemiddleware.auth_token