From faac31aec7cbd7d46d1a1e2e3293b8175480b9fc Mon Sep 17 00:00:00 2001 From: Yaron Date: Wed, 31 Jul 2024 11:58:42 +0300 Subject: [PATCH 1/3] system-monitoring --- .../maintenance/alert-monitoring.md | 460 ++++++++++++------ .../maintenance/img/monitoring-webhook.png | Bin 0 -> 54091 bytes mkdocs.yml | 2 +- 3 files changed, 311 insertions(+), 151 deletions(-) create mode 100644 docs/admin/runai-setup/maintenance/img/monitoring-webhook.png diff --git a/docs/admin/runai-setup/maintenance/alert-monitoring.md b/docs/admin/runai-setup/maintenance/alert-monitoring.md index bbe9d54937..e6031fb216 100644 --- a/docs/admin/runai-setup/maintenance/alert-monitoring.md +++ b/docs/admin/runai-setup/maintenance/alert-monitoring.md @@ -1,156 +1,316 @@ ---- -title: Setting up Alert Monitoring for Run:ai Using Alertmanager in Prometheus -summary: This article describes how to set up and configure Alertmanager in Prometheus. -authors: - - Jason Novich - - Viktor Koukouliev -date: 2024-Jan-15 ---- +This article explains how to configure Run:ai to generate health alerts and to connect these alerts to alert-management systems within your organization. Alerts are generated for Run:ai clusters. -## Introduction +## Alert infrastructure -This documentation outlines the steps required to set up Alertmanager within the Prometheus Operator ecosystem. It also provides guidance on configuring Prometheus to send alerts to Alertmanager and customizing Alertmanager to trigger alerts based on specific **Run.ai** conditions. +Run:ai uses Prometheus for externalizing metrics and providing visibility to end-users. The Run:ai Cluster installation includes Prometheus or can connect to an existing Prometheus instance used in your organization. The alerts are based on the Prometheus AlertManager. Once installed, it is enabled by default. + +This document explains how to: + +* Configure alert destinations \- triggered alerts send data to specified destinations +* Understand the out-of-the-box cluster alerts, provided by Run:ai +* Add additional custom alerts ## Prerequisites -* A Kubernetes cluster with the necessary permissions and manage resources. -* `kubectl` command-line tool installed and configured to interact with the cluster. -* Basic knowledge of Kubernetes resources and manifests. -* up and running Prometheus Operator -* Up and running Run.ai environment +* A Kubernetes cluster with the necessary permissions +* Up and running Run:ai environment, including Prometheus Operator +* [kubectl](https://kubernetes.io/docs/reference/kubectl/) command-line tool installed and configured to interact with the cluster + +## Set-up + +Use the steps below to set up monitoring alerts. + +### Validating Prometheus operator installed + +1. Verify that the Prometheus Operator Deployment is running + Copy the following command and paste it in your terminal, where you have access to the Kubernetes cluster: + `kubectl get deployment kube-prometheus-stack-operator -n monitoring` + In your terminal, you can see an output indicating the deployment's status, including the number of replicas and their current state. +1. Verify that Prometheus instances are running + Copy the following command and paste it in your terminal: + `kubectl get prometheus -n runai` + You can see the Prometheus instance(s) listed along with their status. + +### Enabling Prometheus AlertManager + +In each of the steps in this section, copy the content of the code snippet to a new YAML file (e.g., `step1.yaml`). + +* Copy the following command to your terminal, to apply the YAML file to the cluster: + +kubectl apply \-f step1.yaml +Copy the following command to your terminal to create the AlertManager CustomResource, to enable AlertManager: + +``` yaml +apiVersion: monitoring.coreos.com/v1 +kind: Alertmanager +metadata: + name: runai + namespace: runai +spec: + replicas: 1 + alertmanagerConfigSelector: + matchLabels: + alertmanagerConfig: runai +``` + +* Copy the following command to your terminal to validate that the AlertManager instance has started: + `kubectl get alertmanager \-n runai` +* Copy the following command to your terminal to validate that the Prometheus operator has created a Service for AlertManager: + `kubectl get svc alertmanager-operated \-n runai` + +### Configuring Prometheus to send alerts + +1. Open the terminal on your local machine or another machine that has access to your Kubernetes cluster +1. Copy and paste the following command in your terminal to edit the Prometheus configuration for the `runai` Namespace: +``` +kubectl edit prometheus runai \-n runai +``` +This command opens the Prometheus configuration file in your default text editor (usually `vi` or `nano`). + +3. Copy and paste the following text to your terminal to change the configuration file: +``` yaml +alerting: + alertmanagers: + \- namespace: runai + name: alertmanager-operated + port: web +``` +4. Save the changes and exit the text editor. + +!!! Note + To save changes using `vi`, type `:wq` and press Enter. + The changes are applied to the Prometheus configuration in the cluster. + +## Alert destinations + +Set out below are the various alert destinations. + +### Configuring AlertManager for custom email alerts + +In each step, copy the contents of the code snippets to a new file and apply it to the cluster using `kubectl apply -f`. + +Add your smtp password as a secret: + +``` yaml +apiVersion: v1 +kind: Secret +metadata: + name: alertmanager-smtp-password + namespace: runai +stringData: + password: "your\_smtp\_password" +``` + +Replace the relevant smtp details with your own, then apply the `alertmanagerconfig` using `kubectl apply`. + +``` yaml + apiVersion: monitoring.coreos.com/v1alpha1 + kind: AlertmanagerConfig + metadata: + name: runai + namespace: runai + labels: + alertmanagerConfig: runai + spec: + route: + continue: true + groupBy: + - alertname + + groupWait: 30s + groupInterval: 5m + repeatInterval: 1h + + matchers: + - matchType: =~ + name: alertname + value: Runai.* + + receiver: email + + receivers: + - name: 'email' + emailConfigs: + - to: '' + from: '' + smarthost: 'smtp.gmail.com:587' + authUsername: '' + authPassword: + name: alertmanager-smtp-password + key: password +``` + +Save and exit the editor. The configuration is automatically reloaded. + +### Third-party alert destinations + +Prometheus AlertManager provides a structured way to connect to alert-management systems. There are built-in plugins for popular systems such as PagerDuty and OpsGenie, including a generic Webhook. + +#### Example: Integrating Run:ai with a Webhook + +1. Use [webhook.site](https://webhook.site/) to get a unique URL. +1. Use the upgrade cluster instructions to modify the values file: + Edit the values file to add the following, and replace `` with the URL from [webhook.site](http://webhook.site). + +``` yaml +codekube-prometheus-stack: + ... + alertmanager: + enabled: true + config: + global: + resolve_timeout: 5m + receivers: + - name: "null" + - name: webhook-notifications + webhook_configs: + - url: + send_resolved: true + route: + group_by: + - alertname + group_interval: 5m + group_wait: 30s + receiver: 'null' + repeat_interval: 10m + routes: + - receiver: webhook-notifications +``` +3. Verify that you are receiving alerts on the [webhook.site](https://webhook.site/), in the left pane: + +![](img/monitoring-webhook.png) + +### Built-in alerts + +A Run:ai cluster comes with several built-in alerts. Each alert notifies on a specific functionality of a Run:ai’s entity. There is also a single, inclusive alert: `Run:ai Critical Problems`, which aggregates all component-based alerts into a single cluster health test. + +Runai agent cluster info push rate low + +| Meaning | The `cluster-sync` Pod in the `runai` namespace might not be functioning properly | +| :---- | :---- | +| **Impact** | Possible impact - no info/partial info from the cluster is being synced back to the control-plane | +| **Severity** | Critical | +| **Diagnosis** | `kubectl get pod -n runai` to see if the `cluster-sync` pod is running | +| **Troubleshooting/Mitigation** | To diagnose issues with the `cluster-sync` pod, follow these steps: **Paste the following command to your terminal, to receive detailed information about the** `cluster-sync` deployment: `kubectl describe deployment cluster-sync -n runai` **Check the Logs**: Use the following command to view the logs of the `cluster-sync` deployment: `kubectl logs deployment/cluster-sync -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `cluster-sync` pod is not functioning correctly **Check Connectivity**: Ensure there is a stable network connection between the cluster and the Run:ai Control Plane. A connectivity issue may be the root cause of the problem. **Contact Support**: If the network connection is stable and you are still unable to resolve the issue, contact Run:ai support for further assistance | + +Runai agent pull rate low + +| Meaning | The `runai-agent` pod may be too loaded, is slow in processing data (possible in very big clusters), or the `runai-agent` pod itself in the `runai` namespace may not be functioning properly. | +| :---- | :---- | +| **Impact** | Possible impact \- no info/partial info from the control-plane is bein[g synced i](http://running.To)n the cluster | +| **Severity** | Critical | +| **Diagnosis** | Run: `kubectl get pod -n runai` And see if the `runai-agent` pod is running. | +| **Troubleshooting/Mitigation** | To diagnose issues with the `runai-agent` pod, follow these steps: **Describe the Deployment**: Run the following command to get detailed information about the `runai-agent` deployment: `kubectl describe deployment runai-agent -n runai` **Check the Logs**: Use the following command to view the logs of the `runai-agent` deployment: `kubectl logs deployment/runai-agent -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `runai-agent` pod is not functioning correctly. There may be a connectivity issue with the control plane. **Check Connectivity**: Ensure there is a stable network connection between the `runai-agent` and the control plane. A connectivity issue may be the root cause of the problem. **Consider Cluster Load**: If the `runai-agent` appears to be functioning properly but the cluster is very large and heavily loaded, it may take more time for the agent to process data from the control plane. **Adjust Alert Threshold**: If the cluster load is causing the alert to fire, you can adjust the threshold at which the alert triggers. The default value is 0.05. You can try changing it to a lower value (e.g., 0.045 or 0.04). To edit the value, paste the following in your terminal: `kubectl edit runaiconfig -n runai` In the editor, navigate to: spec: prometheus: agentPullPushRateMinForAlert: \ If the `agentPullPushRateMinForAlert` value does not exist, add it under `spec -> prometheus` | + +Runai container memory usage critical + +| Meaning | `Runai` container is using more than 90% of its Memory limit | +| :---- | :---- | +| **Impact** | The container might run out of memory and crash. | +| **Severity** | Critical | +| **Diagnosis** | Calculate the memory usage, this is performed by pasting the following to your terminal: `container_memory_usage_bytes{namespace=~"runai|runai-backend"}` | +| **Troubleshooting/Mitigation** | Add more memory resources to the container. If the issue persists, contact Run:ai | + +Runai container memory usage warning + +| Meaning | Runai container is using more than 80% of its memory limit | +| :---- | :---- | +| **Impact** | The container might run out of memory and crash | +| **Severity** | Warning | +| **Diagnosis** | Calculate the memory usage, this can be done by pasting the following to your terminal: `container_memory_usage_bytes{namespace=~"runai|runai-backend"}` | +| **Troubleshooting/Mitigation** | Add more memory resources to the container. If the issue persists, contact Run:ai | + +Runai container restarting + +| Meaning | `Runai` container has restarted more than twice in the last 10 min | +| :---- | :---- | +| **Impact** | The container might become unavailable and impact the Run:ai system | +| **Severity** | Warning | +| **Diagnosis** | To diagnose the issue and identify the problematic pods, paste this into your terminal: `kubectl get pods -n runai kubectl get pods -n runai-backend` One or more of the pods have a restart count \>= 2\. | +| **Troubleshooting/Mitigation** | Paste this into your terminal: `kubectl logs -n NAMESPACE POD_NAME` Replace `NAMESPACE` and `POD_NAME` with the relevant pod information from the previous step. Check the logs for any standout issues and verify that the container has sufficient resources. If you need further assistance, contact Run:ai | + +Runai CPU usage warning + +| Meaning | `runai` container is using more than 80% of its CPU limit | +| :---- | :---- | +| **Impact** | This might cause slowness in the operation of certain Run:ai features. | +| **Severity** | Warning | +| **Diagnosis** | Paste the following query to your terminal in order to calculate the CPU usage: `rate(container_cpu_usage_seconds_total{namespace=~"runai|runai-backend"}[2m])` | +| **Troubleshooting/Mitigation** | Add more CPU resources to the container. If the issue persists, please contact Run:ai. | + +Runai critical problem + +| Meaning | One of the critical Run:ai alerts is currently active | +| :---- | :---- | +| **Impact** | Impact is based on the active alert | +| **Severity** | Critical | +| **Diagnosis** | Check Run:ai alerts in Prometheus to identify any active critical alerts | + +Runai daemonSet rollout stuck / Runai DaemonSet unavailable on nodes + +| Meaning | There are currently 0 available pods for the `runai` daemonset on the relevant node | +| :---- | :---- | +| **Impact** | No fractional GPU workloads support | +| **Severity** | Critical | +| **Diagnosis** | Paste the following command to your terminal: `kubectl get daemonset -n runai-backend` In the result of this command, identify the daemonset(s) that don’t have any running pods | +| **Troubleshooting/Mitigation** | Paste the following command to your terminal, where `daemonsetX` is the problematic daemonset from the pervious step: `kubectl describe daemonsetX -n runai` on the relevant deamonset(s) from the previous step. The next step is to look for the specific error which prevents it from creating pods. Possible reasons might be: **Node Resource Constraints**: The nodes in the cluster may lack sufficient resources (CPU, memory, etc.) to accommodate new pods from the daemonset. **Node Selector or Affinity Rules**: The daemonset may have node selector or affinity rules that are not matching with any nodes currently available in the cluster, thus preventing pod creation. | + +Runai deployment insufficient replicas / Runai deployment no available replicas /RunaiDeploymentUnavailableReplicas + +| Meaning | `Runai` deployment has one or more unavailable pods | +| :---- | :---- | +| **Impact** | When this happens, there may be scale issues. Additionally, new versions cannot be deployed, potentially resulting in missing features. | +| **Severity** | Critical | +| **Diagnosis** | Paste the following commands to your terminal, in order to get the status of the deployments in the `runai` and `runai-backend` namespaces: `kubectl get deployment -n runai kubectl get deployment -n runai-backend` Identify any deployments that have missing pods. Look for discrepancies in the `DESIRED` and `AVAILABLE` columns. If the number of `AVAILABLE` pods is less than the `DESIRED` pods, it indicates that there are missing pods. | +| **Troubleshooting/Mitigation** | Paste the following commands to your terminal, to receive detailed information about the problematic deployment: `kubectl describe deployment -n runai kubectl describe deployment -n runai-backend` Paste the following commands to your terminal, to check the replicaset details associated with the deployment: `kubectl describe replicaset -n runai kubectl describe replicaset -n runai-backend` Paste the following commands to your terminal to retrieve the logs for the deployment to identify any errors or issues: `kubectl logs deployment/ -n runai kubectl logs deployment/ -n runai-backend` From the logs and the detailed information provided by the `describe` commands, analyze the reasons why the deployment is unable to create pods. Look for common issues such as: Resource constraints (CPU, memory) Misconfigured deployment settings or replicasets Node selector or affinity rules preventing pod scheduling If the issue persists, contact Run:ai. | + +Runai project controller reconcile failure + +| Meaning | The `project-controller` in `runai` namespace had errors while reconciling projects | +| :---- | :---- | +| **Impact** | Some projects might not be in the “Ready” state. This means that they are not fully operational and may not have all the necessary components running or configured correctly. | +| **Severity** | Critical | +| **Diagnosis** | Retrieve the logs for the `project-controller` deployment by pasting the following command in your terminal: `kubectl logs deployment/project-controller -n runai` Carefully examine the logs for any errors or warning messages. These logs help you understand what might be going wrong with the project controller. | +| **Troubleshooting/Mitigation** | Once errors in the log have been identified, follow these steps to mitigate the issue: The error messages in the logs should provide detailed information about the problem. Read through them to understand the nature of the issue. If the logs indicate which project failed to reconcile, you can further investigate by checking the status of that specific project. Run the following command, replacing `` with the name of the problematic project: `kubectl get project -o yaml` Review the status section in the YAML output. This section describes the current state of the project and provide insights into what might be causing the failure. If the issue persists, contact Run:ai. | + +Runai StatefulSet insufficient replicas / Runai StatefulSet no available replicas + +| Meaning | `Runai` statefulset has no available pods | +| :---- | :---- | +| **Impact** | Absence of Metrics Database Unavailability | +| **Severity** | Critical | +| **Diagnosis** | To diagnose the issue, follow these steps: Check the status of the stateful sets in the `runai-backend` namespace by running the following command: `kubectl get statefulset -n runai-backend` Identify any stateful sets that have no running pods. These are the ones that might be causing the problem. | +| **Troubleshooting/Mitigation** | Once you've identified the problematic stateful sets, follow these steps to mitigate the issue: Describe the stateful set to get detailed information on why it cannot create pods. Replace `X` with the name of the stateful set: `kubectl describe statefulset X -n runai-backend` Review the description output to understand the root cause of the issue. Look for events or error messages that explain why the pods are not being created. If you're unable to resolve the issue based on the information gathered, contact Run:ai support for further assistance. | + +### Adding a custom alert + +You can add additional alerts from Run:ai. Alerts are triggered by using the Prometheus query language with any Run:ai metric. + +To create an alert, follow these steps using Prometheus query language with Run:ai Metrics: + +* **Modify Values File:** Use the upgrade cluster instructions to modify the values file. +* **Add Alert Structure:** Incorporate alerts according to the structure outlined below. Replace placeholders ``, ``, ``, ``, and `` with appropriate values for your alert, as described below. + +``` yaml +kube-prometheus-stack: + additionalPrometheusRulesMap: + custom-runai: + groups: + - name: custom-runai-rules + rules: + - alert: + annotations: + summary: + expr: + for: + labels: + severity: +``` +* ``: Choose a descriptive name for your alert, such as `HighCPUUsage` or `LowMemory`. +* ``: Provide a brief summary of what the alert signifies, for example, `High CPU usage detected` or `Memory usage below threshold`. +* ``: Construct a Prometheus query (PROMQL) that defines the conditions under which the alert should trigger. This query should evaluate to a boolean value (`1` for alert, `0` for no alert). +* ``: Optionally, specify a duration in seconds (`s`), minutes (`m`), or hours (`h`) that the alert condition should persist before triggering an alert. If not specified, the alert triggers as soon as the condition is met. +* ``: Assign a severity level to the alert, indicating its importance. Choose between `critical` for severe issues requiring immediate attention, or `warning` for less critical issues that still need monitoring. + +You can find an example in the [Prometheus documentation](https://prometheus.io/docs/prometheus/latest/querying/examples/). -## Validate Prometheus Operator Installed - -1. Verify that the Prometheus Operator deployment is running: - - `kubectl get deployment prometheus-operator -n runai` - - You should see output indicating the deployment's status, including the number of replicas and their current state. - -2. Check if Prometheus instances are running: - - `kubectl get prometheus -n runai` - - You should see the Prometheus instance(s) listed along with their status. - -## Enabling Alertmanager - -1. Create an `AlertmanagerConfig` file that triggers alerts on Run.ai events: - - cat <mX+j2+Q633L7aSK3kMG36 z?CZnK-|`_jWZEILNEvHP$vhXR%sg*PZxqkdl(2rs@oR@QFCX`EAK?7zt#t<#A=SvM zaY1Dad=1`qGH?Gqx5JrquWyGl#bd_CDTiWqM~jbNZ;rk$-sYOT^x2CZzSfQU}V;wf}{KYTp4E5Wvtx7~#z4 zy!+Q5)g1co^#6y=-zy-zz3bs?J_n1H3lp#Nh6NOtf3U3LiDDec0eN8*WRZrrgjB$A zT#^j)R@Gvq#C&+D*$-cx7cX9%ZB3WG_IS8^U*o?hFMb=w`V(3wN7(9VnKIJxv$>W{)))q zv9i1Q4*9Op__67B$-bM#l3+paKz|}5F9F3*W^2X7jG+5l zwMG|>-x$n>LA!f<#SIPmJf=;br0KwQc4N88U%$RsXb)~rIc)Z{6JmB5Mb@3uM zxsbI`+(im^?E!;RS*pIBoSaZBsj;yHrl+NCv!;Ii*d)B@>FVS*+*8j~vMor7`p9EjB-!+$Sd{K1HbZIQAI4ew_-ll`n|2 zWKtv^NY?Gj0GVudgkn0dBoMy-qM5og^<__zR@ga-L~7ob+Q{>lhRCQ6wHU0xBIvq! zeh-J3j`iIy?@Ub!S`nADdZ!g9p=*|Lgu~S4#Ao^1fa{Z@O-B0CL9zEIkoc1o-;H>E za__~}`qM5_|Ff%~p5w)mV?I84P4v_*t>?nj!pVtkTzmT8P%atKV0y;#Z~zayI5` ztWQ=R?^o~(8l9RCqiAg%{1L}PT;B$2ZFto#4<#o79PUKmR<|{|g|@(!yT8%W)5j&A z6OT$#ClNorrZiM1SMCqr{hlsMtz^IPx^X-b8t~i7)7XGu+z%PFrCf+EExjxKrWJf6 zC}7=3nD^@OVCCT;1v)b{U$e3KC&yL4CE#>a#OCoK@IBnRr24OqI8G=rn=vyyn!(R7 zXhS4O9*3BQm2&K(!K7|jWmN{j%nbaotXHlI+@e?kuA}>jDeG~zJEQiw>`jn*QI5 zPT$@X++Q@dR|-cti!A%5zPefse}e7z^T+$wt=|R$+n;ppPaokFAA5M<>B4gHei%^swP!^AjO4tUy(*Cpy_NIDNot`oV=tZ z%8KAHZBtb0?ytO9;LV)%=3TW_w+-t2Xiv>*d=N3is}F{_VZ4fQR7`tw-&|)k)vR|& z3+lK35?EZBXt?suPTLnPPH^gW%jq2`u+^Qud86z7@Z%{Z<*-5f&7139-k{GX(tkTJ zJ@zUaUm(|6nFi&m={Q3_dhg8+CI;WJRMr%WyM0}9ZI^dxIS_`P{?4?>Xk0eV2WqRi z!vz{$etp%@DKEbN_;_arztGV6_;B_meZOpcQrZSHCs2n5$*=P=rViw&bKM2YIBTz| zksTTuI$Qq!-LExKrR@8SoS+?y4D_3*YG>|SyW&0(k;Y}dbnsfOzXlG(MlEk}$W`D; z!?X~HLKxZ^%VH?Cb;BU}ouJ;aN{h|uD@-^oTmT?6m@c>)HJT$b?DVZQBLlX5cC%;am=RXh?AjaCm~$<*$G1&KzjTv$ z5YVMKz-JMB?_JO4oEdT~v2vYY+pv>?D-mH&y}ywd41Ty9e>ClU{sj27+*LUVl*}eg zXK}kYx7jcK;4WBTBit=pI!rdWPKOqj{Fk~NJyp-`{^s)a*vP=kpgSy(wcCos(GQmP zyWhNI9Y_)+_s;L~Z*5=un(UFxLW)C#cH{ZT3kSQ0JM1ui;Beiz6j!-^<#fB6n!m%# zF+yc{I2=tuj*gRLk~opCpce>RXROdE>IvbhBGt|7R$0HO`b>8bAuo74tOyUERx9 zK+aCaKDJQjn)dv4$@ct$%RtS$BlDR#WT6syZ0gUYmUoO!a)&^F8rToVp z4k;#b4$U-+hm%bBAg1*9-LK`F*-lkRf#uV2Y2Kvm|D`rP%wwPaFxMKaY z^z_}_cp{>c^lw3LC?iB+_6x-_M(EYbfqcYtPvk-%mAN6|vS8HAw-?7b>YyRV?W9hr z%>o}*!$~&nq;HLw{b*nL!e-rcc2U9qH5=X2zCdt}Nu!I7uA)vzV!(jr%R!7Mto=j6 zit!ctv5N2kSok-?8ae%M=6NAq%*Lufbx~6E`!H&2n>b6i%>lrB)cZ^}MoM-7C+9#w z8SYkBgZ5JW;riwQ$Gts{;x}0WziHAL?J$Q+D@ZA>v@uBw1*1a^ajJp25j%%wuKJL|PZ7sy`{v7K|7V_jayUWOb^`;x zhJOQgiZjn#A)hYBdNANp=hK;+`TmD*IB?#TKbjP&wbGjurFDx^g1(zw2AV8wbEKO~ zq$r#04u?gz-?p@?aeojd zx3Sv$XV13CQkRmL44yl<=lgKhSq%>opMr)Qu(VKlMp9zn{sv9Rs-48ULuG0mWAL3s z`>Dhb{`}KRGS0O^h}*W;SZ?!4O=6&W-Qw2AV9li-AABmjG@uo8Am97dP+W3wi~nWS z9o!y$ud0P&cuV^6J)5>f0fA5v_8Uqb`|FU>vyYG0AH8P<3i2fV8y-fv<)K7&IHIu- z2NFv+9>T}6FZn44OO2@6-bvMqY2c^JVT+B4@y>a+x`B8+W_n#?9HsgCNg=g31vfij(U z> zQV|ypvI8$##skRlNe9ElB2*W!wyaKA!dA`u&>N@YwU{ACt5zT)mtpbaj9GNy4tP}{MNrOgN`l{M@Io$ zOV?_MkaLdU6OJboEl<8b6?#U@{go)RATDG|HpJp)GIP^p#%{jxt4U zm?e75c$}rf@UDjF8^b5C*Em=T({Sb_+!Tm32x~~c(x}e%`TNDMXa54b5c{qVDq1`i z3+WX+PXl|YZ}t_?TuNTdTfg7}a3ym+m)?x{K}8RsN+6=vJ(Bf-QE=E1Rzyi({;U(< zsH^UK&m0p;;QD4`gGQAm2@t$=!4pS$oxx+q{6*^{(sNa%h5KYe`qDlB?C4_2b&eiQ zk$WJvg6<68${2wcO1e;EZ;u7_*D+#c?JBK=`elEssK_kY*pBy^tuSKY{qgsQrXdqD zWoI=&^m8(|$vG9}$rle+lkHDZn%}jsdNt8a_AP&=1p$@3LRo|kw5p(r2(YLqQz||= zJ@r#1a{kn2uS^2UvEe57jnv&|Is6p`eh13T(6Vn3@Ngi7>|2s~*5BcYL1)$iwj)$| zVEBG#GJaYL1vPMPB=>#z+di!Rh#pz?eiCpDeeg-@$H@~iwh+{wY#ZZgLnk)MSjH}xzXv#bA;@_5#t zIwG13lwGhQvJxOqG}zZ6sxl4?7=SBhMT!uzvl=&ig3edB86moc4*q=$0zYC|L;l#V zJz0SNQU079j>of~I2fVOZQ|0b;9iVFgg=(&UssX^mPIHnVn3|4CV_|*Sv8(we6DF1 zVKs*NFaLN?Q|ZZ@a5W~uwYk6G33Ab@gZe?9l7a$BWdZeaR}c)d7N2C5RCX@&X~%1P zHC)k~;D@bX$D)sp{sxA;>LmtrRA0c~=9RrT)YMq#0b3@_#$KL}_m|~?ufv!R*!|eT zTiiYyD->nK{z{UxJpC8D%YTauykBW+^&_&u*vG7>Mvey_lB9DFIy;9ZtB`iFdw%*R zYLO?jhm$4Z+J^IHJE=a+F8{saZMaE_WNAd(JXhkkmxI^jJF}JG`%LWXe`)zH%RDLM z36DDKeE6WOjFR*`j?cKh^iYI4>3byvDNETx#PP;&IgR+I?{;2Hc8rBqd0hQv+A%Y) zLYozO$y)F$zqt4$k~cuM?RxZal4b|m2+|Fy;8DYhos!ojJw@$cg+N=LYN33@1;u)} za~SLZK#}U%zwMpIFNEeoNE_VN-ISPO9B4@wgB?CoZon22{R!5gl4^L>O_iJod$#aF z+j-{c+n#N{mk=Nggzaf9D@~v1b8FJiz3GO09z!H)BzzyN`xDqvsV}vhHCgpDWXa7I z+V%7osp2U4h*1nuq^PxBUt@2FeS~Ff)N~op0T!o@9vz`gMXsp=AvX)H$Aj~`8$!8R zja7-%8HC4X56y~$2^qsS&`fd@Q=R}Q#6#RvQup?9^ebNjK$^Hnw}{%mpET6`dMV&% zNG@RvrXQEf*@!*gYZ=7luXpV@_!f^hb8mPpLqUt8)dm4H(j8Us8>3<1>Dx&{g9BU= zh9Y@6l-tjFWlGg|?>^B6c^=v9347Oj{PLc2dZc(x?jV>|#}}#LPLgW$Gc*@c4B?!% zgJMwezb#r;n~k8i=H1Q>{F}s0&WbfAYY`WHjz0^Tzn1rb#9F;4N3O4Ozc@Y{|7+D< zlr34?+bc(eP^L)_VQNa0I*v%;!*nkFX0U#L+y3ZZ317Vm(E!cBhK4XJa!*7YzDsK0 zh>{A_D-Mx>B<0|7jE`3w(_(I8|8}l3c(Gp8ES4D!dW#g}r3Qdr*`)oCy+9^CSO#^r z7dCT!*mqFIyz5d!#AhH^@=L80BRy3pL0IFq)Js<7ut-`Mw!DH=fmI7-Rx(RPyZiVj z*>G~O8kQ^~aZSDrTukNqbIQ5FexOJG2^_iRn`UD8Dr~+opHd0Y__J1Xjo0Qr;jfhs*yn%`$-aZuo+MG-=*Jv-9 zv$)?i$WAY6!RDL;4?|8iQ$J4Ab6s&?$Y$S-x(1!r;)<014#P*srN;K@>>*=7^vn9l zF2u@2?&GgiV>>(NWjizt#Awx8<1Vqn3W}7p`>apFgWKuj&-WI_imELRIZRl>S%7uW z&!(8sqEGzg740|W?I~8dbCUHTre6~kFd}AnjQ*n05vx&u@D}6Lm-j)Nnht`O zpp!z?5^Ln-rX`K0*Fu_i<^>6yg9?nDP`G{j{ekPwp8!aty%F82B(ZyuC2RKw zXPpj0VirYx<|xquHrg6{K~;oh2Qy8NtE(#}i;swQl}hF(H*R)rb{RUtoUnjvrmi9l zX38Nl@FwbtHG>&vG@5h+@ z)>H|_CoH%Pm%hRzQvDFJ&_3E3BSlT}pp=)Pl06b;hUdH{F9OaW|S3(nNTvp;qeP;Ei!=bYBT^E~FLX>jB9h-D@Z2ltfm}}{oP+h}Z=KD1nc73z= zx>(GC_vdrj)FGgJ!2PIfvqF%L-ZF|sK{3L^NvUu4xeLy?|U1T!!DVqLf2$d1AG zwMPnWio{K3_lpKE^k}(R9btxE&BHq|D3Bb!{QRe4#W?IXi|owUy^6-|UG?$~H63r9!};){V8sqIZ92H%7qZ4Ur6ZO}pz`S=7O;2G za}w#ZBsyt#xk7z3+s^)cmrk)PI6qLCW_{yf`<7sxaF#+3Eq^;&*xh`$l@nipARUZ| zcy$3|2qbqPH(MeY%+gS)WFmyI-aKFrV92uylt?q%DGQkrIvHC!GFW*qo?Ej&8vxMR zx7XGdya78w7QSd%^yWDOf9jCZR4Pn3f5gD0z%J#eD-7Wd$E%vn%Dl~BgON#Z%VB6ZcZ2uS@q zSbShhQfs~1i^K z3!oI=vml(6^X4~R>|GVo)P0{GPIw=6RTLOoq0Z{B=sM!MI)zEo;4BNn+VkvP&Uo&% z9#>gf!Nz0ydPCP=hro*of*vx{;P5114?cb^_GYy7ovg89LY#Bu_v1d=bkZj2!#wN~ z)&|%F2RJlT*SY`Gb`ImFWfVAcU&V%_3k8OzQ;E*!-~q^?3mL4;jD0d^N-d;Vg4~x& zER7=*X@t&^%lUGJ7pvahv5 zoSX@uL1vaBrTh4`vUT2h4t>dGKi(NJ=);^}WUW4Z2=sJB!6=Wt2Rh70w z70CJcJ?gThHszu)s=yx8w>0z-+|8@>=q}FUdjvFv0(?7pIn9BWD$Ohp|-jfNh zVp_6S>=e3qcv=@#~!d2b=MsH7Mkq?uyN&Mm&qSP7`r)b-?j4KsWU3Bjb86 z>XWhWz@(3pWd@{0>vupyD;5-`yC;#l6mxK1O^<+4?KraUtWrCG{hR!H{>Ae#WuwkX0AciC zyJFsi425~2jnfl<6K+>ELKA8*6XM)Pmv zd>V3-br%c!lgQZUV-Ml_-1G|i14Ou1op8bk&w=cHfawiT^>afM(dxuJevj6sqYbf_ z%3wqu@mdBw9>$h!%F7emc(jV-?ny%dG+0Jk(sOQl(!6AI&rgDo)vaIeR^E8XeM@>K ztaxS%=|2B#o~5@ObX$qo8=;r2J(D%U&iQjs=`&Az;%gksAJqd1C1~g%H@mUadGqFN zIVE&nNW(&Q=FCysOXtnZnUB<>;CfG$|M`n4@%LxhoH$l1XX6aFCBUK`P|&=~l!Vxr zQ0fx1*B!eNK3bOj)MiH;m4O<0Vf|>mJ6mTi0EB5%C_n<@6E&H5TTfDe#hFW1XqOSL z-4qS$UG@(_e?&4q*2K~9%N3O>=Y^-Go<(DZ^;{j4aoW<1eKBFI1F1LgMdUgkFcHPG zEbdI%+4scc7X3gTXi(r+&!uJ6seEn^YOHAGjLgcCETbY0Jeeja6NKQ3$&y}}n;)*> z-hBuuEn6(7IvC`m_^aH>Iotz^(&1ov!J^yn6yJymjF|^*!m6^o3k%t73cv-tA3`Zb3!XAJd(S6lHFd5z< z_nwJLSDGTe2`BdeWSvBQ*`pv)6wl4B%Ok6)E1z2bJn-l8z8Usvzi8RGY*gA)x#%_5 zp{GeA--|$hvF!vHZ@&Wt68`43uuGp?o>?C;$?&Q-B^65=xR$YC5t)O_KNBW#`-MO{ zVYkVlPTT@c@#ZEQNkLF6<_RXSlMbkikyvIEzM;L<6&mj>W~T$VT-6gTES^k4>mxy* zw|iOwxAk@RbX)b~>8h`)JGwD`$CGVaeTr zhCD@5Y!;ES$ad_*N#W}(?fO!;_USM~jB+}UJJF8+Rhub`^-W>$q?*3@dwJ@sx|vAf zR0aNkF_JPi@+U%KUWCFr9u4qD2eQqYxe_IxLZwoI?hjI3l|DLQiVr34EMFdoqj9h^ zRVTzY=&n7RYagUq&r2|$s+VrBaszCW76@&<70Q2FzvJFt!no^jG3n}GN2voMR+|pj zsl&q@d|CN&?m4>2L41J-7IZ~SQFSnX!rony{u#TP!ula}uf9w-+djwr@k{EH`txka zJ%|imS43oZ z9QScd3iz+pD#$C=Ug*WQ77v?`Ij{UcE0gO=qX91Qn6NR(8iJ`RTdYnN!Tz={*7EFt!b?+H*hFR+u5~)du^E^ZXA2w1_oS4 zZsn&R1zk#boNd?qSOhK`5qAFeLKXV=nI=Aiow_a8!tS#wd|u{JYAP(uq2~A=R8^?;GaCG0A&tv4E!QlCAyDKOhMVlru?E7-CGuJ=UF(GmgTK zx)^*ZQ1Q#XBlNn*>o`VO#!3Lo{O54o^JJ-u;fAxY?K7rhF8cq-2izE9EXG4P6@+!? zaHtA*K#c-S09~gtkc6tc-c`5S4BuJRt{+3|zUOJm2>Q@m0F+Z8 zVmN;a#R4$9aVd~8X0H~>TN>_sPmS%*l#`z+mFz3Wn)l|oL4Na{_&+Zvq_9rH?5V>J zG$6d}#pp}iE-S`E?}a-~GcN!B?mD1tTRA|n5)x!C00XoI^`HBo+^!CfkPE95hX0rn z_7WHnP(IjxvIF zdy73#6O19(0dELN+mUxi8F%1M_I+{G0rwe<{|%%lhLPN-ZB!B4r(l$n{$EbYFzTUgsV!ZX|M54_IgA_sO}!gdZ5+zU4D^dX|1E|8$L5O| z2y}n6&M1oecC_f+izGSjtDNvJYj*>@SWh&xP(x#5agfnBz*6;@D^Hs)$0x@i`lU9^ z&!gagbZVzb^9fQ}Ff!jd^*L+Zk|xvcAY8abI5l;4Z+Evy>!Z}c^Z>^)Bp;j z{2fjrBG-P&$=T@p3d3fY7DtR;yBMFq8t9w8)O{4pb6RAQGhe1@{8%R`3Q4tpeSm~IJi7Szr9JO8 z+5x5lpkLkVZAVb?2cK|pQpx1d;akN*jJ-)=c}A5@+*-z9)80WHaT&5?u?p~_r%jPf zJmlg9=;IM?PHEU;th_Kx*o?j;+?(g})Hd6`TP3BP2`_=i?EA~`f@1#02v@bsFX8?s z4I17NrtY!mfx`rqRt&% z2@Rr#!thx_Jo+e)C@Q6Kg-6%n4+6#A>SR!5xp|lId`a(U6z2SEI-^iH&+(^~iTk`Q zMx9%>M<|__^{$BpHY;vjUF3{HuiKo}XJ%#` zKcEnLmp>g@eAVh=4h@SnS;t??t5ObswG5+n2QP=9dkd zkjzdZ?>;~lM#s^K>5l(nE?ia=xIX-;LzP-=3HlI=qZG*6*w6!IQF=|dd_Ic*qM0ko zM9E{S?6gjJEaAPIw!EZItBivan3kDIApXi{|HFiqnmGRN^?X6QF^FkZ>5r^9`@&Rg zVSJntuCv!VI-d=};kZ*=kYT`XeQmAorM30ZU3|RLncvRsy0g0FFD3wVyU4&Iu>K!u z0$0z(B&UNiyh}!BeYw^DJV1?gN%y|Ieye+1AZ?+8K-%e>^JlB9TtV9rZA^0%a^G^% zW*cjtOuq5sPqtH$!8dcq+=`z$Rc^{s|CO`g3sSxLGwvIGgVBsZrA2g^qdiv1ah%4J z4rw(7zVPGm~O^!6tv|1T7aNSp$%xETLatKX0wn3m0`>5J=1+Y{VQ`uk5@ zwMj|-O{f>eD&|e80p48IuNv#Xl4kBHEl!C0ZYskHG}Di42m)>FQ^WxLq4* zqPwWMI4h&aBHlAMbz%zenyp?m^wkh;VU=*L(?dW28T{*U?EBKjnXyB*)(GK)08Vlp zY%l?_(`>~cS3&*ph8xw&)$zv6Cm>lIkr`7vptr)PE=`ZgfZ2js@`1wxZL3tXP@Len zwq5Xz?hq@I=Cfx0D9>27hQ`F?%(cIuKY*dS36 zui|m0P6os;Fmw_H3A?X@XXrhwJj;j=naEprN^ zCiPel_OxK?-2UU{%+n%=4B`26gmpr=ERb>TZ0Y@tfTUw6GX`r^eE_epVWf37MNL8#mreLApuu0~y|pARGr0PcVo zcbIgd>-+iRL|;hz`R=iuP8s)~8f^!oNPe}@CEWy3hdo*%{%c`izzrX#d$gGG6 za4~!vvW*#yFQ0t;do&TS$YC=}Ocl*-xax$%utdAeE$gacl|y!&VTI`@{zI!YwlT*?L%VZ;zkF z{~)apdu1IqJs~)T8ofg}gqqgJ1I6j%GV&zK%2>elNxTQ#Pcj;why+ED$b4UgNnOeE z1Z_t**r%#vq}X)TO;e_X@MZE^EOQ&ml3YD?!VyL%_5CEVXvsY=yxH$PE4?+!u=w?h zIv63$gruk?)2p;-mkRYSm5=S{R?bC>=VzO8nwJtL770y1run|=xi4x5j>SxNjHqiU zp5-LR7QnPZ6ul5G-zbVWOaf?ja}S5IEXiT@^_+9kSw|T1zd}RvQqFVYli3WhhYDlZ zE2rTt64F|?AAaAPrd|%bG!xQ2T=Rq!YoztP-{t=qD^JSy$&wwPS-dZHU6~^}9@bT$ zz?HMff)o%gU||=^UB*N2sy-HQh%DnB!^P1j!Q$`?a%0;-b2{uq=hMw47swZJ&A-3| z@RhlL(5#8P_z}-d3nmcW&elb5u<8s?kLbXl4ao%x4I~dtGh29(EC>wBj7-bb*s#BM z#!<4<#bg=&QLR*qvCoi$PJYw3Y)`qrGb}*NH5|ev6+v&j15B_-Uhgl|&14|oDI>NM zEU{`ixOx&Rf(PJIOu24WoNL<-56N&?Mpc}8&Fc-KY9V@esS3MjC&4((yy8hND8J8e zACjrbV|7d2GRc1oM)5lW9BU~YYjUQ_Ic~{M{4`#6seuqiQ5d1DBdXe4%`YAo!#HNG zP4&EE@*{K{xCq?e%6Ds!C&t6(h~5UBL`^u5Pr%5wDOtLYp`p?K?r4zS2_UnHmkc_c zD1r3ah$Gj>hCQGK^I~8J2j)E=4>XV4XA{odg+`bcTpFWs<%$Ho~-`C^HPOy*nrT03HyM{J5&A%CUp^4F? z&ijd*a8?aldGgptX$z~4sBX;1PiAMK@nLzb#e_fXhXs-w$Uws5s^Y1P_tCN6D^DV_}?!q%Xyf?ta+T0d%co+*XCA(MQ&pS5i>&xK7?Q zat}oW=K@9gh&G?Nt$?SStvOC)H6dML%^T+dyngvI&Yy&|Z~p|10q8&T(dC@}bXpPw z+RFJ6(g@h<_fzvZ>-rO7|CXtmc4U%O%Sw(tiAV=H`+$8q6d5)J3$T52Uh#Px50*-F>c`51?FINo8ef+3&+_r8TYw(OA^wIh{Cqx?4kSu(`CsqGmO{L zbEvSE#32n)Q{NxxAxVe^h2w z;C?V);}->@-G5V8QH&Mx23-O3@MKy7!oC{})A1EpeNlLW-Lth+7-(kh18Osh6 z1syapOZGScqFaMT3wY>4+CF4e1jmv8P9ozAmlrt0Uy$z+CDj~{v!$JetA5x?4tJ{b z>R8Em3zT@WC3V>7ufu>9$+C%wWH+gaKRkGeSvN_5L!pG=4iYHSxwIZZSo_tb(G>iS z*2N$Y@)qpkK5Rm*>a=M#6k%zP^bO^T?504@OR+ zv#QF3N^MJz2yl-^b#yDN&+fh;2UIRp*DExKA6v#=`CTC>JE`b8>QQW<2F<(encaD- zS(@E+mDBfEF~60Kv5!y z3@uusz;#Y(7mT7;5XXm?Pw_^^rzO*#*TNC;Iaz?mq$ZNJD=?GdKu%ORUlc{O>~!c1 z!xmROi>@JmMv6br%n3k)^oZREaNsDF;~O`Z)Q=6Hqdu$7=v&O+<;@4k0~ayraxq29 zoldV&6v;DVXBu3{T@v>Ot~9eX-`g4_dp+NidVHE!K()ipgqlF*j0YgOR6j{|Fx|(= zXTs6B~!{p7V+3}r13R+pgYO^5;3EjRk?}30? zGCqw_tm6m$b#Rmarv6I3VDRioa7d#Kzdq#`*F&2Fxw>x&?8du_q*Ox$j4OnBefgy_ z_R15J?1#q|pd8DX(|OV&jLX>eD= zY6ZTt5NCC&2DPp;8zjb@+n7%*Uzrso3jHPu2qF^*Ove6Xz4V%3j9p^Rke)GbV?^EO zzz8z<6lpviBb97$sY>x|hxIL>q>_uzWdN_jIU2)y)wnP5myA6rXO8koQroP$SY(9LgoH7di;saC_MdHA_>)M|$^0=9l2 zjzb)pjhrC1d^=6o(D4>%l;-F!;{GHTjpdKvVO?uYhTMm6qm~dlo<9q!tQ!iNYK3t> zoKr=ip1iC!k?*R;aSQ5e2~aYPa3!Zgq*Did;C$Um+*Cecxca^srLYTMcv@wGOH@Ka zp*Y)XV0}X&NHf==K!L)!v#l`ReL+oeWUMRNYJ&eN!YAA;96h496^q5vW+}qigu+MN zq+tNd=!E)y%4NDLnW(u#T0Iq7*}d2`<`8{RL4VU29WsGG2c*0-v>iCV@+jpvV@T05 z#D!|$q?EyC3l{%|(m-rqsjK$kZifsG)&e$h1TlozQ$<@BMMpW*wN^*1Udc(&%OTcw z^L_kwiU}Hwsm0aLjH?V67W4h$Zt#1;@CMxc_CtI3SJHXupWf6mC zQxpO!HX-h*YCr9C>>TjJAzOkP2+-g&ySlP{_A%RaJ`xoc9+sC9gu(qgFLSkDFF2_M z7EQXFc%=`*gmcxkh3ZSuJclqoB4zBSH+U_G1NQxKc%`^tW%!{V+3U!GIrN}=XAqH<( zG!cXKF5uyzI>~HDtqU`FL&`VnFEWZTu55_t7~+1_ zEFIY4nf6Zk++eKUUow;QdoxOII+Yx%ss7wQkD?&i_6ew;{k5`fW8Qyhq zgbU_>04jtUh5B)0?vMTlsH2(-|C7ii$o#)*uKm(=`G;cke?mVL{_KzUH1PMZ1q#w- zXj`sDLAqXVv0`Fk-`w=6t*Fh`&?Il zv96M?{PNj94mJN_?9csT;)fRg4m?zXi9*|pD z!`H80k$Js&#oBqj{l8PKO|FRa*$Tzp9p*m7F-kAP8$dGOF;RcNd_$7saI51{5aPgs zpj}Zxt$-||^8UiadW)HP(MP9#W&ghi4`u40A+mVqbu;~(Z4sr+*~Wt&l+<^77eGO8 zgIfQg_dRHvLP1=8d0&I49KP2^P$BgD-3=QW zR-8>4w*+;JOg0R3sFwr|y&yw46wS_cQ>b9l;mG?ua?_~~nfgw(p^bLm;{v@o)9GP9FW%&o zl$40LyX3l|^9ZTphX3W~u+AqW^TP`IF|YWcU5afoX9szJA?&>s^nc zvGX>3YdW54JZGdVJE8Vllfh~E6YwTIq4LKM)9>DU8TR64TZuztis##-uveiPMueihlM4cA(^>j{>dEaqyj``rI1_lPFp0zfuPZM`O7#ZaG4!baXfr7M`WQsrBslDJv^W_S_m%`DWgV$Sbe< zu3FW0*lwYaRSH`HTb@|vYpRZYlk zwfeR>lRxy^g4a{QzNq_4lx*-Gzx@MBeEiTb$SLl?kve!&Syq*CO39;qnL<{-*W_GP z|9yCFPl6t~Zt2=~UGiedc8AndYH#XGqG|B`xhe+f&)u1F>u>e9hfN#ALd*mH_cufy zcUSyE3_%qnun!kitry1LRp&?TyhoL0F$wPz7hfQ(uFFZPq`o#uuX>g>pq zrRVrmj=O7u?)?_NdzTN5%bH-~5GLigd{^O_ogN_IZR3>mzew{xYE~NZztoH?0|D4I zk*)sk()S`M&9#3{JceNtKqfxPY7`-Y+kf0ms=eq(ZQb-V-5R&&&H#%2RuR-}>GonA z31IoI1g=WM=02EMuCxA+(*!zkUu|3Uk36aDTKXnLOV&U3W~(&jy>jC<^Tglq2XDlS zOgFfgHEG|RAAN)=@9>TgcRyB2a%ot#Y(F&-X%TJ)l@A+CI>(ykCD`-d%vl7_j@)Md zFBib9@a03k==<8U{be(n-M!xf#ie*axAi5L77cvYe;aNh00XNtmSa2Aw#2M}cad$e zyUfj*j+m??+5N?0kn1RoQHx7n1Az`Xs>l_^)?Pj+zL}V`c(t*|vXbhg)IX zE+lXpy3{a;+JA9jK1LH-nAU>b>BKyWhWgQw#MG}0`{EgSd0Wp?hGJY`G$i!mMS-Nf zEALhUUvNQ2U3<%dgBNPO%N6gZzG!7;3EB;zg1C19s_fRFsR$l{de0}>J5aW=NQ>LP zwIZDFskIsQ;#N;eBK`15tE!hltgDv%!nPQY({Uj9Ad(Ve-Y?cCe;r-u)aasmp+jcZ zRWsh@)bwsJg)N2z9q%e)-i?IZ#D2_l0MNo^n`?c{SbLkdcl>ZI3Svziep;L$VVNJaG(bTUDlP#19R!6t(TLDk$H1E`o1 z+TZrZMAXUpkY1tK-IQtwFpgrEP61mO1Oso+l=NjFy|jU@{=0|5}WOmpq-Ji}4%YEHa+D)}5_u7?&{+jH=D3S`z#j&+L?sQVx_4uLwMn z?2UQpG4`_={|gZd4=kRHC_#m_(P4_cm!hI#S)EmG(;4ivBdi%;`08T2P&I12{co7! zga}HadoRzK#Az+%`6rHyg0+{muSkg+z1EfvJeBlH6Mu(=;5*yb$!B>7zR{%Z+s{#92MzO!oh7MSr*VN&u3LEw6q*Bvx#hPt9L|_o2tHnTErFSmp zHYMGrjoxHtnF6|gxfvmx6qS1*h-nw7u-1;mD%x!Z6jP&a-?vb8;@(Z23_#>jw__qm zoCPbI!-qJ29O|P6^6U(e%_N*rrl9mN(@+K)fkh$We1#Y+v=xU*z9M8lEzle%EbQ1X z<>)NFJDc!NkFvTp9j}eI7aO|!jA|r#Vo}OeL*ILVx&r(D=D(zPeI<{PTMiSs@MQwR zQKM)P0ucwPZz6=gakI z*g{1UeVh;!T>X-M9>@YAR!rFicpe4#>6kqsV7%=ExLz28vSEy2Rv|TY_|uE7ckfSC z*VChnCx-ndC;~6l%DT0d3&;=Ik@Aqvuu+XQ&LR7E_TfGLta`1}?C^Gq4)V zsIG`&rTf-waXIXd{7^-b1mjRFFVz_j`}#p)KtQC3{944=>5jT$r2JHiy*m^Yi_uHK z;auKcXJ2q1D)VBT@!|!DGi7617A#W&I6sv<_d)6I8q~m+z}zj~0>22$;R7wTRI@q|CM9fDKMy=0ycSMB6_)8PEYl6yocKpJm-JxQxa`S z$dJwF^h5+?9J>HdJ-Wixt=Wv@YTLu9LdPnnN26A8r3xYH6^osa@$2(lJm92g=xCmX zaECv`T%y?#EC&a7FmHKQo5jOY6C`xPf3H@eG`56ZF&6F)F24;Rsu3B11$F2Rt2Gnz zgq8_3sRaLZ_9}`pg}{ItXz2~4lz{G|H2)NeC3=54C33t-_@^NJZC=9m&67d{k@<_p zGDi{lPm+JW`$E=s3@qGVOIVQM zvs-E9qzxgDmeoRGZQaY@Fs8&p*|lB^kwP%+$wl`v=tJ~3QB|9@!@-b4eyB|D65+)o z=2=?O^`m5B67>=3-Xz3|1|b0!O;#I~N8h4E4Tnr*C_%L#iNmnQKcr}c@xExNoWDhO znQ{ZwzHtMaQ5~H|8D@6?vvK!U03av=!q4rr$aWe*VhXu19#0gC^(;s<)n^i$1kMKi z(yh@9Q-t9`hnVGm)=<1Jp%Sxa@jB9FuW$=6B;r02tfA5|ZRK!S2Jv%|Foz^fs=a77 zxHq6*1zELO|#sm>5`=OD?%zeR4PgI?~YKEV|r= zZ?V^~UNKQhO03&K5|S%8v;kmfLnk0e2zmN@kS(7;zPSFm@*X45FC49+ftzhA72_Gfv~{AnSkB{#xMGGD>aT$)E8+Hvp|s@5OC zpT2t#8ddSofII=L&&TAfkW{xtQR&P=>03XN2hle zZ;`Pq4s|gfNMnx!+K@wxTjt@X*#G3Y=60$k(JL7Qd2YYb`O`c7y<`x=HQxHLsNRg4DKdh(eGZ5m2rbyVA`^^@4 z!dREr#R;-IE5s0%b|gUZ`6(HB48eJu#SyX8OUJqScKfd2e+&R)GtO`qRE{s9tf-Q| z$_o1G>%3OjD<*$YOnqD+BR7mjmaPJmW>F&skdfka~p4@PBu@|P(I7EVjR z4k4*ge+pV1#;F#azz}*nR_&5n?c=OwJYB_N$wR9^s}Rjag;^L9tw*Kb@c~#5=oqLN zC{0Sz~oyRV6UZ)Vx(mE zgF;yOulh04Mpzt{rT9ePn@((r74Qc?Kv-^@75l@n;Z=9|ZJkC>#q|nHShi?%>HCX$ zup8*7aB{q2MC$W$k_TCP*ja7pH)mt-kRNNcm?v@<-F>VPnr*ZdUly-71%->NHK8w!?@5i8 z!3aM75QborMh9QJl{Z5&kzAKwaF#fpro=3Tmh5)Z`5->bS0tiu66Pnz^{0@qi|mF` zlZ)G!?4r+$g=Y}}lje;xW%EyDW>cX0{qiycHdY_I_od&6tfnE>At9Gb^_n#x6lTXs zDA?67AlpY-#!3d?VGJ6#afdXjU*2fLxe3;DUQ}lC>^%-EDNa|E#bw1(AAG+Yo-xUn zUSP0)1!5svkNfkP_mh+30_j)@ue?JW7oNvFo_`M2V zi8+6F*%garDYnj14o2LlwfJ34zrR7jHLP733{k4wN9u);gy@6@Eq(5GB|(eGE*{Nd zK(H9BN4QcjY3!(N{I35<%rFM1m0& zAU8Mhj)TEw(6XhGc_JSOKw+R369%AC45u3^BQ_Kr2HA#!Tsm|`sy+s7X=L6?mi9O& z()Y8IB~jlV4y$`YR3P~CS}dhz$pDs5h=dhHyx`_$PT`?b?_;4?foBjA*W!t+$0nqk zB8Ks_NN^0QAIw3hR4m5J*_EN@;Wtn4m+lX_`%|{Hl&1cy#t3IGoCs`{n+-Mq~7!`p&^RSL&7onYFaN zM9WuR_4M&{s)lU24MjTN$uuLw!qakRE@{wtf|*d6VHH*1Pq6>k%8TS3b{y|Ul4-Yn z>*(r6Uhbx$3p<&rQ@WuHyAI)Qjsn2iRY_C2!~U z?{tC@&GbDR4~?wwhBbJ$9&>lT2V#C^bic22Hq1i^c=P*??fJRr}|Lb3^aGj6y-1u{B^OoO`2SA z=FW|DxGcVDfVnJoNY@ub`i9#Run-(Ig(v*!BSq!AqhaU?rfrnx>Np|CU(!J(Tc6QE39hn53K^lf>L6h`#kE8HVU0Ay9ZL!+oMFll z<^GrvZ%g!$ba+MCkrGR~FE@q|BFcrF=_nsL>W8T1h7Bd1v=57N_>th2zj>I4uP<*u z5IV^N+CtO^3S1iX+YEE|=YDUi4wxnp{bbR$yb5tqa;^$P=8{>4 z@zSLsQ4V5SQ-{U$cS}j|-KQjY5JC6)AnZ6Xtpr?-o=f%8=iUfPZc@->;C)IIUCAI8 z5~MKK4imyKt2$t1HMOa@OODzMkh$FgrGLakD2^}6bImJr!pyRa zGlMmmP5Aot9TC;C=bTK`ZWwu$p@L@=NX8Lg^_3T!~zG)N0aC#tG1oHlzH7!hqYG6SU-PQigO-^r+Q)EjEtQ?=0*cj zrGqCFoZkpKbYwRnj*Hou{)_TioUz~Gphvkp)N=ULB`lm)V;2CW^ULzOYLW1V+5!fv zf{%@2S5coNaQNVp%m0NTg}uK+km! zdgi*~hJ$(s*EE_V^*P*A#&`-gRV1kJ(rAs%CS83HPc4N{Ud`PmkM%J4Ra1or{OW7s z=~?jJiR6F0p%v*@)ptL;L}t^ro~9FTJHs^8+b(+}?W-aXP3pS)MBObm#p@VnSR<8J{<@*p73E&B@I#%@-JHjDeL{1I)l zw#&7`_Vlj%_h;x35t#YSq#UJI0$d^$~1DcvzS5&PR@!uUFj7>50-*X~z0D>E4V*2}; zx@{I(lT8AAHa5rhIlRB!qzkltsNk%?rAMcI2=>dO%fnI|bhcfbIljpyMyDj{*A11__=lGxxM$xeey{Lc3r@j@B?xr@~rw z)E9z7&iF|`0tczCzN5Vlv50)=(2EO_FjVlH^zP>*PpaQul7+*$(93^*>%!x9`uk0K z+#lxXS}&KC(~-LW`!Qt8hvEE>=mRKCmWg3u4&$A)A4&eIXs+*=T~I{QW)1QAXO>4{ zbZjgmofJ%k%y(`^Gjaz|o5*BW>Y5I1Y&~ynO!ssMss1R48## zTidTHhVLe>Yhh|n@w_^M_9E8^MvbEX@qCmZ%0121QPnF%qQSn2FBoEcg)wSKgCSUW zFO1*$7^}(}1m_p##cU>SJqV*iO zv(6vqDM)gQ;dwi@bd#uK+5D88W8J+fIZ@2EqZVPvkVT9DJqpC@T9*5h`e_e?WEp=od6rq%HZkt zNNOENXRoDB!)M!lS8uFnGGprGaf}k`Iirz8v6>0Js^tN~7#>cvU%aXp)6k6duJz=W}J&!T4=HWy~6YkY$rvt2L6Y11y+z z6dOdN=7&{4hA^Fg+p+j9h?mqriU7#M=dh%Z+7XfKdEO4&^&xRkPicJnRKn^ECKm2G zncy)Rs?@HvI#I#>W*Q@Q9kbo(^=t@;J5PIItR~}eJy38XJ^pZ?!vXlvQF9BjI!yz~ zWZJ|0$OPd^VoJ|FP|gvCnqKQ`^uJmytDsIccw`mZcy(vJ3|dwBdU%l#OyLzZujbQjMswh zKx$gDy9>|*Q@^>{*DYaPdz>{aB(%pq0L;Ou0Y+LErirEvZ%uZ~#ot!zUXy&a2G7os z`=mY37hSr;X~TK|#hLqj#ai=Ahez@#ZB=`&8jdk&A%QK$^`H1T;3pYump1kiITjHs zi9{A$Y?dAxYB!O_Myr56T-eii8s{xaN~X6$klKHx`-=vd_8{^8n8NG%c53pnqjW?H zm)kN07M|d-*(*AA&7T;JPW?80{6o$RS_LlJ=65oZwEm@vO{6QqepFoP*KC zRc9D2iXwa5Z`rISQH>B=%>LJN3-LuVvHubUe@R$#l_ZkxNx9&U3)8I?cdA1YYxv$@ zZrq7l0O`BOc;hzgs=dv^LyiupJI;?h*Q zb-TjT?OB;&r`?X2)xmk&g-RTZDspu<>JbXryWR|Cr1wSJ1%C(1G%W3T-V5q{9m3R- zmrRRDH&%8m$rx{+jolxo_#oIL6~){odWFgg=EYwu4=a3^(CkqH0cR!#3BV`R>fW#U z*xX`oY^e@!4&6&w4`cx{jXC`F_r~a=(@QG%Ws<11a;=qStC}K!okRgX*7WmFa?vdZ zV*xVGNE~cNm0n}JPurU9t~KaPv{|D`^fR5I*VLZ{*})KhMfw{WoN67-lp>REV!nDg z5SQ?kJg&AlV1%0|^|s$mOLIGj7@`(=y<@P=Uf1eKl>+5kQ#Ub(m1}Kxtb^Bpa!qR| zoQ5@JKRz%0WrQo&xmqtGB9VC#Fv;%$*tI%5;zhyVT3rqc*6MHj_}u(tmSESJLRqPP zt>n=P$0b`t8`dsVco!5xPTS2|7GFt(&^Yz&qQ*R5Cu}g+YG(HxP|(2xYLu(@>qJ77 zK%k=X`VA8Fik-#k<#W9JUEZm@lELD}f+Aq??b9VSNkj-K(zFj&a0s%Qzi1`|6x{GI z#t=-PaIskZtZb+jDZk-XI{%Wwhn9Hf8LR-&*th=Sc&U2coa=1_M$;xx72PT`T1>8p z3Mzf9?ISc!9TOVktB`$0(U}sJ{K&|UvI5<%PN{2Dww>0S2_B~iP@z~oDg}lJkmY5! znLpITMiz@O4T3Sq<~55W;B@_dVereZnpqgJv9(Z4$NPvvwkL(D*oF1{Z__GSJeAz7 zDSMY|$!7jXD*NNQt%cNJ3TSY=Jz?~^y}XE52f)c86B^rkNRKVqnq1uh;gf2FKNc&X zy9s?ufLAm9iXKZY9(`=i2SEVzYK!WAb240e2jZig_m&lHyKB zb2s9$u8^D8iHm*)a38-pQO;52>eM=x#Qo!rDFV~qw-*cIbuw5_H$`(M8YfwUC z)rHjW0RC=_@whYx;$8XD$>XlG`rpJ8LfxmvA5cc9We^dt8D{M|eL_9yk74kuH}TB- zW*bs4ozIsGtQ0hsUbccm5jO#WR%+}X49dilF^xW9o*f9km|wOLr=!Ls@Obo{7V8ed z$~B}y*~LY-R1?;#NwbWEA~s^QdffaqXR5wHx_PM$hsK6O@&P7RNaX`O+7dh62;`VE z$O`z7wPCfA(&d8D$QJ{@GaO9(06ycviJ*)29pp$~Qq2$*^3`K=`o^&Qv;Xx1Q2dFS zCt*xPCc(vof4)mvYP6cwGmfWvc) zs0v9Ma*6J|J&F(KUH}=l-Ws~5PSCi(-bNWI{B@uc&fXH0eF@)`P6B0h(uT}n^@o9$ zap7Y?E8T_s?=O&7)07Ls=jF{mLH8d9Npe?-_#Df%po}ed+384BzzOU)R6$^5C{{iG zJo@`R;e8E7;81}6QtL*fyOBIBV!IGQ$C^Z^&y9M^*5nAktM#!=t*C^WD@K>=I(8P@ zmnw`5mxMb2AR$RWSu|`IRtG-b?Z)LeAE|2$_QK-p6vsnAbnLX4+Reuk9tGk0d((|Z z)1_CHruxR-q93`RBC`0@M?bq~TF3k|w02@+)%`up5Tgd;JMH5)ga6 z>XssmBb#C(VH|Z1I05U>=aPzWThSjse#kQZ8k^QfCY-PxZmku+*Jx#zGG~AMUZdY7 zCgZHT7>(vGQ3=MLXF8)vJ`_8uj#kdk2%FtLmkx%uLY!h=;RHa;6?Sn z>eN#CTL)V*pJfGvArarBzRrSaUkHB@h{sHM^qR6%RwX51jS!)md^3;6kH=NM?fhP7 zXwc}vY#OdZGrowyG0bFU#_PR~W{Lo*z_aHw&o}`f;{Zlnaz{xxKZ!Px-ljf5@Ou7bvwe55ycAQG!(Y%;go)9xGX zf}6HO{UakHuOne$CqIPoRl!}7={?psQ(dGt5Xn_L<7t<-PQOhy>bpKi2{xit4;0U% zTX7x@B_hqJpO{K#pY@PmgtF5q*U=B703rL~Dtxs=0se*M`ApGx*?Ev4_X*AL{5Nj& z0Xfn7(~XD;6~d265B~raXX1jAMfq(BcVDeIrW$qAqRdEve_iVwDa4Gj-2jVFMcanNd8zL9!28(SOewWtnh+|FT@ds>cUEUGej|5rW_%+%mn zpp&qz@S%jTt;cA4M_{-{3rSbhDeFaOBYDqd=YQl5Ff5QgSQ4CD0sO##?^X~vs0@YB@q$5nz9OMgI(vVwJWCqzaQl+mijsa;R;Fucz%JO| z9_V)=poIGUb{;LYaB}eFzE`{|oI=A3%H6HS(PJM@@w%vsT#<~deHgKGugv1?;WJDd z$~=(vs8oaA{wdoW!+6m_ZGTnr9uo&A5POTZmlS&M!$+eyg6$Ui?K+cBu3ojg;%_&h zA1#(2PA>iSC}mp+*ey03I6Gny+zs05&$F^-D;B~WeLU!*TzlK-GSxtQK4Bb*diK^mKEVf!t7fEq z|E3UNK1YKf3Nq?wJQz@#{zJ{;Ja%|5TK|5sf*;SX+oreDv^#9`=FgAYcv~Y7uRHdr zO#1WK03f?Sh;On$<1u6oAO(>$-7Rr z_hT~8n~XR2k%DS4&|OYQRcOeAN!3yE1*Eu*tQmP&B%)RRTqtPlc$XG6Q}h4!H83tuvSr~z+oCh zWbd^xA@_DPTT40u|4l#Yf5#0WX!Y>({>$<40duis!B6^MA7G*Yqr4yOV(`H~qdef+ zXMfo2&vHQ=pzk1S50f1%v zApg1kyFZ`yIRK5-f3ANI!e;1yu7BWGQ&`Qvyj=ge{yl)sI8;F;|M%bl9L+MMYBkCv z@D}X!TNX>NYH-{Jxq=l@*)9mrb19nk(CevG43?io)j?*rIK=vS-A zXGJ$=1SF66e|=Me<|dpHuH}Qf2h*4?9k*}EG$@}*M_ZoYfdH+p;Gp2bvdgwcr`73< zOglVYdWg@tU)#iL8d-eNyOgu?hpR9ju zSJv6*R%4m@wPCPux`$`2b2(f+r0wYIQZvhxs)g-Hkp&OZRBnDJA84cqWrXU5g#p3P z!%e&GVvB3(((8M7GBkvWpA8OvZb<)L$oX2BmmR^Q3CF%@7IOcS z&yY;f-bx>XzEz-o-&G2uxV$8}%f~eU)9Hla{UCKsQHAVU^&v8T=QH+hRrUs>(ONp$ z^kw%SY}sS_=ndOMg0kYINr5g#yEF%KckEFrW0V9TuhD|r>DL2`W24cUuj-9gu8NT2 zjM*uCf>`qSWFGR$=51nQ>|E>YZoXsq3lFu<**Z>NgfO+9Yt*3(=ZiaQ40P)rB0Ntr z4QdQ_V3|_6>OuT%wvMN-k&%(tcMJC;6En&3pqPPei)R}4xjUrm_gC}aj1ueAm;DHu zf4x*B?6N$qP+caZSz{(qR37mryrV>31US^sUR)!JX^H%b<@7+8pIYt2_4Kc7oWY+{O%PUR3Dkave7oaW3zk`7J2 zmtfFGDK9q&Wxe^I60s_wtf9o%76tIU3f2tAVpvKlDw6j!qlT3jiCZHOZD*Ir zM|T;|i5W$n?_)BDCe7Lo!-&b6J&I6bf=!U)z4s_;pG^xg_;hI(B9DsBI-9RTJkRdP zLoEc}7hO}mophJ%o83SHzuVK>JI)e#@234m2aU6Aa~g&Cy+wTfZn((C7yx6zP}GW* z%Fi_0T|fAgbB-jrlpZLg#qxOtgK#<@b%I=!DcA*pZ{sW9ZKK;3TR_?S>*2BV0dlyunk5 z{omExSeA0#l9#?4&Ang?dCBaoWI5qSZPB;=*eezzwbYEtO6glRecKX(s`7Z^D*i9> zRa}K$iI^PVCLf0|#KSe|M#75L2xS#(0h$dhH!>`^y7aDAn|dvQ(n%v{ht}=w_sMlP z-ywxet7rAI(gz(Y^*9e3M;TU%%|9MC9|QhOQx7M16GKXp=#oIg=L8YCf6Q5QL_{8F z=4cs?D_=h`FQ9*a$TFHQW5E9lx^~-dZH~xaay#hQNcEV=a4?3GZkjEA8WGK(*%_dK z%ip>tzkVv0PhJRK*;wQydC;$0_t6*06RTHTyglroT~0;zsrwnZ!l6e~ewVh~`kkQj zgyiBxq=n((_sQ+csvx~a+1~wv^uFF+l>5seahdIGzTwLSOx@KohtcCs+nQ!QL@ZHy zq)3smPyhy`AGz+qie<0zH9$$4;_~tu$h6E0myJ4-UbkUh@+ntXXkTt)e z(;ZO8gglZ}=N4Ldns=0ayv{u>Si_FFgO#)2e_=dGffdM?*UYA}(g-7)seJ?tE~i(| zdmBsdb;ug#8R6^tPOg4~p)9M+2NaJm5j8;74%g_UC&SZ+_IZtE7-b_bE2p&9aV!2$ zzcJp1>F@lpY8j_Anzk~n8Rb&WZCbpVbMRbV+fc)eO^UPM@849MEEbQ}oO(5y?giAC zU^Oi=Qc{Q_3Gb}@uqs|&6OQa2|K>_kSK0LZjjn{VbZ+j@G3@8G-GGUYMI(;X<*oZf zjLijAQPk}m4eq->b6ON&WUkg;QmvW{KZzb2#C<-{JEDx0L(?L{H+;W|>$CeysxA?N zJg^qtWMEQ<&1FaGdUgD&9DaS;RfV!z+34bqTKFg_?dTiJ|KYve6MY(e$95lT<9GQ| zq^)=edJvrovFRm!>m1ALlHK1$^^5-I{_o9Jq|GliY_DPSrF~XKQA6d-0499ry+p{k z9BK|YD(LW!qn5jCR_kHL!zHX?|MFE6LSZS^A$^r~Z=9^`S7MVQ{2_VS?p$><>I#d# zjbxQOH!X0WlaMvEHIE0kB}bhk*#}4T@G7Y zop07!%D(-F@GtuXcWSkjpNhuE`>W(LOV0zmUrvqt#W*n;qlf%2zrQoD>n4j`29Adr z5pt9$AoIFTVdf8sZ|!5xmz*PQT^{bS#^P8HNj_A741!hXhDvR8?{IHHxT3TXcvI(c z;rCguEU~D#^A(8GaSl#y-)E*nlMyTuaS9sT#%`6zq@#pEDNxhD6YqGda~hWdjo9d2 zE5>}JDdPAH6h94q5%1Z#X>ujJM}2H)8QLkCYr5)0Hp1U6VZoe-@Wk*s*V zp0KPsZs&J9i}p&!cKc(?iMVTVTDzN(f5q1}@0Ng-HZ-$ygGiU1%PW}KD1F;mnwgV) zKdt?=TOe9;*QnB%+q}+pD42qn&}ln>Nb(J_%TwRKG+rV%rvrhfbfvn$S=B!GKY8)ro378O|eb^G(FZMF9a^MxO?Z2XAHA;PGJi zU?dJA0c3GG$sv!EuUDfBVYavZYAfsL)a_kc0Ojb4D!+aTk(o>R*Qqz#!kYNg8?O-jrEHXP8QFrL3neu9mX;d zt!J@4aSsd1xtzS1H@(8Pn~#Rz?$c|lhR5;(gkazbSBIOOIre;~OD6?`-z1Y~rl<40 zXJv}O5PAXxy37zLsxNR)kQJRmM>mKlHCv-rcVF*!vJ<~5d2-`NTshp2@%xGV8A+PnM2Om35nu*Ae;K zOlmw6KP_^XX9=pa%fp!lR5Ig>D?j(D4sT7p8j`)bzh&*&=Ynyy_EwF^fKm1;0T!hO zZ(2N_?;FR$(@m_zyYCCC-*zezp-{lG@(nwk;l{ld2t7$*N!z$ z$L!0;_m6XSTxv}8nrkE8b$K77b(yhkx$KtW@!`(%&aQuM^>b=@oN~JIvbT5DzP8;G4;to-*(bX2@MY~Ed8woYgEc*nDNnJ^0f%s$GZu>DU(~l$p@MhTSqQg zbB@Zjy0&V^(O53Ryu`b<<)d6v*PX>0#mjMk=iHp#QXXw}W37_5?VIiVH%DjZpBA#> zO;0LpEtkg}iGELrOFDU`1OJvAtEobqs+7gH}29Dfb!pEaAWhWl;E+0=(Hfw%f z>>9KjsanRQZ)HbZfQn>^Q<)kY1@95U&E?(Eh}V^w6!2@7v)60|f#PTKkY6mKN4jxuYOn5(rC$DappT7)9a3n7QdR7Q zqe%25itp1XNLuJ5-8M5hx_dota3IvUI;7)a#=bTmhahHf3BcJ@ly+Zi(Dd{ewAn16 zS2)5*gqK$qU^oLU5=}*%Ry|dJOB8RdO6wNlPSd#7JtywW<9;j4lm6!V!|rZ%A1M3z zH{EJomP-Cs!Lz3NYt;)=kg#J)>t+Ec*g)G1FvpT`MDQ4yL7{59&xdX~)dT49eQgigqMz_3vHB3@2fv9PV%Wu zO!;DG_+M|gkEK3$sYV5^=O?WY52MylyD^Qerun+>*L{P*WxPvvx0y;ZtPyqhp4m~IUVl~KTYBN?s|;C|xnlU=;}q{~eOmEc6IW_40s9;Z2MsOJ(EDH7x$M?Qlbi1=%YF{T8qo~V z*!MB0Y>6k>8#fPp>(@^zm~$<*ARR-&`sCL>ffKeZ<65CbGKSd7}F?=18k@RJ&o^}wNSoSeH%jRSQ z76s|PsACn+_6C?aS%$?kcA1H=o(6;=>LvcmH+J3|Cqm@0yUBzY>*$q@)u>)`s@-|^ zW>L-6!y}iksZKTOOr$@?3)Ozi{yzVbKe-f_Fjm}rvX<#LUj(r935PI7zd|l3m)SA+kuApuphLq#(M5 zj;@M@vlk}=gC7q zHsrF>qY@V33D`-I6}I$UcTO_lofd7US1o6`+AjCzDchSG@m4G{A4gl_nHeZP$$P2% zLScVmWRIUApW6)9^0oG`Dm%tbnBOIqA60q{o34Fd88Rxiyp@-({X(HlB2T~OM{#nZ zoNcV4_~rbs3+cS-V<18M8jsFKSXdH+VL$ifBg%ehtml^3B;4L{f1KzOfsf0vtITMq zs#k`OmR2b&m~2xxaR#Dj1wlLn(eUpxRfS*TitdWwia7YY1 zY203Zli}4q9@Csou?bj@uf$2+X*5^;MLd^w`u^^lBvi}*C z^Vg4hc4wJZJ+=@7f|jqYu?t*n4DyamB0tsj#U<3+SGoU0lG|W}Dw-Ho(Uuc%bB3B% ztuOJy_zV6pM?9HQ-db7d{qytuoGYx=+&z^>%OU|UB|#UD2W+qK?^fg_EEi}7te)(6 zh<2*3@`1&EriRJSvYBfslVk8h*^DWn)$i#^cV)@!n>U0L-VdW`O&-@7-(-fPlvri> z87%upX)P3#PXwZ1OQUbC9!@WaEdMw_Ki6+)sys=` z1JmzSt9JEH-L5JXUL{;vqg3FfQIwms*Ds;jc8-I#$(yB1>5JjrlvGz$1ENVd`=bgQ z6&E^g4cc*1XJreLT@HJHfB)~?rH{B&-urcmmKEmy^^^sl8*17`W%H9opJ0oOhjQlj z1`BJkFz1>|R2C2f(h6He->xT&*%*~H#%lu>g)dJq2B{^7&o0wPX%mVIelS*WS{$`# zyESi)&pEk17d@B!Fx1=kw>n#cm9FIZD*aIc_NTR19ef=N`P84)Ap4@c6^W+$sO+|% zrON`T98V)@gZu~6Bk?9z`uvtQw~iS31e*dp-1rBC-&6+NkHRx!O6=mcgKGD!Eh&u$ zXpEqiep3S?}cBKPGNKr5|aj6K?<0MowP`U|aE2gO|jkU!PclL1s%V>o9L!vMrkMm2- z9JY#dRiW9LGw3x=^64a^d&b6?UM|6qGZlk?QS-Otw?eIjsMDx%iCueMA5Obu^g19@(y2* zSl%zbIGgWo@x^O6sZocj!}6xkpe`mI-M>hHaiD1BCH{Ty!KzaGH6Q(?h4HK1N{Lrp zY>ACF|L@{f*}ImFdlj>)q>MRibEL02*NFd)v+@D@J~;65cFDe^ZGkgw@p4s>1Ud4lhSchEMKfK?v zUs+>`us^40e^;D|dOZA&nJ>PT{|j?&oMgsvz1*_T26;q5X|PeHVSC)_E++W1VT+}; zhF%O^Gov%7X8n8(8I|9ys8pHaQzG$WJqyz!8C5g|soO7=d`tQy=v~9-;VX=}fgSk^ z%(9P1n&#S%qf0wKIEFbi%j_nfSqys0vY19>KMgTrMXEwkqFy|%O1-i9A6=*y;JOloZFZeI1S?eft3oAmW%&p-2P5&2N-65BB z-Lh8WUO(N;Z)oRo*yrv|YDg?n@3}Hc@!}zS=SHFm7)jO^3SK!)**r>oYxj#q1?GaX zofst5UE;evXUE^4HRp~8Fa%O6vv54j{>r@=n7NTO0ozgq6e$Vfdy42vrJ2>JEP~*d zdTPrmYt`ued#xvoigGHS=WL9@()q2%QmoawW(nDuxL0nMF2}n+0lZ+_J0*NQe{A_z zQ=(HH6r#ss59DM9aIgAvq=LU;t+i1Z_RSFJr?pPI`?lP^xh9Hx1{05__AT+#Z}^oH zEr}@m;tP*ztSz#;mJ6+SM^3kxof`R2)gNV8mx=1kYD~-&OgNM%v|w^H z1Et*AR%wof?VM|EZMbcp%cIJR&p1*APxy%OE9Kerw*t_5ojQ8;kEPdtX3$-a5aI54@gc$bg++$8u3uc6xA)*%ft( zb*~d6)>)EiU|;>1>8i82A9|Z(B=}o}UX=ZT!#mZFnD8qnaifQkoUYfnBbT9Z8Pz&k z@7r08JEyEFT~z%|ROJGGh?~Y1^|PvKV{O*$=ty5vZRPEAr_R)})&I2j)o*PEO}oXR zSaF9IZHt%UTHLK@aCa~6h2ri`v7*7<-K9vd;1nnlv;-$#`o7;e|HC;~^ILN5ZuXg- z-Dl>WnR^$5zfet1DoK9ULks9G^l3TT$hVe4hrbOm!xa_#m1Z7jUMDP;QJ%DPHls8_ zI__6}P#f=worJvcJr){w)8YG|Qs>H=L^*Cm&g}ys8o1@dwRhM1mX<}(_WYER|Hj*0kFX4{$Y+(LTTs&U3Zun6V!A%9BaJzQ9%>5i7&K@&Y%bSQ6}Ve?myfO-ID( zK_h@yXvx4QZh!0SfW4uwN0VS~#9@&Gw8Akt#c37q*Qgqzps1~AY}y==lPbG0;K0^o zH3+skWu4s!oc%(i-tDv<*P^gMprPwh(0bmB1u7vV+mS#!i3mbdt_ch@($$P!b?^DQJ~v4##55#$^soxZ{~g{OiqTey{x*r zR*6EYuMizFvwND{R>e%xTK6t7;YmC~0@PX1L;$wS2|oLVJ`GxBuiOuznqPEze>@h# z=^Asbng87V*`yW{pVsr&J5r9;LVL{f?;ap?`_7(il*b~GiErkwOb;AOHtwrK9e4Tul+ZKw>@V2C%#m8w;~#;26(|#|7@9rg4Nw3Rca;b?;i=o7=n>Aj4V`2~3B;(dM{DVu)w3$g&j-Tu5aPyY<9>9lTBl zw=Li_N2f$-cF8X=Vki;eR^(!k)Es5^xaBWOku?H%qk>nY@B+vrxv7{SI^Rvd_10g@ zjV0s|rI1cB+qbEE0`y{tbYZ<^1VBY*47mtZc6!3?_6YzqGtdIRwV@rQHaso^DO6A# zk^X!gBSv5r@NS}!$k!BE2%GABFsy%Lj{8?WaOV2a)3b$3|5y)9)~^i;xQTMZgpa$5 z5d)Y7%&UcFOkQIJeEd?I|4<~fd;neC1VV7!eG;HWp$Kw8$lV0NYRs!=Dcqupi11$I z7^;orCR~IV2|=02ZvkA#(^c?BAMw9ibN5@m#ea>!g%RU33vk+egbH%{XwKeuJQno0 zKO)(RrFYzP?Ame}t&wsiwL!;?VLX<54i2ii~ZMnS;fJT7;8W z&Sf?N2m6y=Itg=BHd4(tI&tFYaiGeSl_wm@W(KvlJZlBvBdgoTGZ7exi zF)L=fh+rps_njsp?xUv7OJ$Z7CvUn_yyT>Xju~?o?@ljY3vR7c!Bl%-^lZ7?=fqd@ z{zjWR2E1FIo#W6@H`f%ZmK>d*(G8D~AQw(PZ%64GE_vu~wI^!8Y~D$BC)ZI@$Q*~K zB1-^l8t0?OEj#|=(Dq>FSVne7^rx9e)TAo=hXvh89Xxt8?$)z`@m{FZDnZi8(e*;ULxoz+)$?_s zOGYw9yh9V!y2!(Qlxyd$Qf`#XM!*=Kg(LBaN4}4Qn4@iq55r`-lv3;NCiv&V_UEJy zXoisa&?<;IkDyS3lb2nsYv_7AUg5%B&Th-}qpv+n_dCba;hk?a;}<)ZwhWNGXb^eI znToKDVU|z028R{HHXA#e=v(Y`n#6E+IQ#>abcn{h@lz!>wtV8eMNB8K8foObXg&XK zPapc=e6f41I{SVTcpTUj(5!11;LEIXBSb5y%Ljx)aH#hN< z*56`nz!&9y*}7lGDH|Jql-knSSw96C8oQ}p&b^8_PU;OpmQJ;1eV6C|Q|A|bDC))% z5z7m2yfsj`#a1E8?)fPkK)yPDf6e-I8Ackn~3avlJC3>n#Kw_2G z?9!nWWH9U+sHm?)(iUzbhB(6X^npX|dTbUr?)yt+dp-MCvJg{*ptK7eUm= zGWlpXO=@s`=L_0~?azh>X;TA#9r9uN5meHa=H{JxCSFuYJBNq=jlHw1EQj8faXfDQ zRHWn+X#;1wOD)dFm`b2ZA|A&HUrrLq+L|GG-kVOF}Jp<+C38KC*EF{1y)ndkn@h{(8K#G5Vm(V2(DF@q4 zN*@wC&}w zt>h>tMlj@`gu0P=k0{(3&OhK?UP9 zpa+YKtKS8rwyQe7{8cni0|@B945)m!;u7pI5&bem3Vfwdy4UZz)+h<`VXJl+fH*ly zWP^FETgC$qQY;o`WsNl=7ky~dE&VcVOQxsd2H92e=4!0>rfL};Xp28Z>7983~&t@kq%?!M`PH&gA za(I}iSgYBDU`k!9n_EkX(bj=?s~(SATN;C5;U3XU{@@z}K5UN~igcm6@+Ac-U)O1+ zmjkdot}Y6zk6^l)u48@Z_$d&V9idNKfrBrW|MXN9s zLE0u*fy(LDu=*&h?Ytm$y&dP*RIAmAsC3tlhxu6Sh+r21PgJt)K8oHy%+Wp?Zok%3K82~bo z7;9;LoDTdVvBluM*pYzWFLA!Mm#ntFjTxZ@{p2XT2h5{#WGByk?xQ_qfA0Irxvah( zmoL=Af8JdwnyVJHvYX_*w`;d>++M={P9b@s5;aS*{x2j^e&wnmdca!aG}Mpba(i9= z85AILYm=H3a_!$)qt8XM7wd4l7yZrp?9ZD?6PeukN=NX)zT|e)z(`rk+4ElR)KPyT z-n`&Olg!>0JcsA@iy1?}osUbteFLdmz z_=ZmC#WnYR@yt(19w^V4$>=8ykZ0am)E=j!=PO22TWPH6KrhYzrXH}CDobkUyp^{F zzp42;qY^vJMDhL{_H0lExZh2th&er8DNF1!jv??ZQnofcikD(3BG)5>}vOSR6g?=6`DnPn*wZlFF^{NTI z{9uM>f{U@{ahgsQ*D;+P9KWQwRgL>7-au@FP%48IZzP1Gsq6&L12D3tgH6LPfr-5O z!138p6D)XfUTSgFv^b}pn?wEswNEScYNqt$fK#wcz;0DOmov~0m6ve#TeI%mxje*+HA6C+Kr37`vd9lyYw7+g^VH~*IjyD z3n&#lo4Z^`yonJs9!+<^KuslMZfL@QH+_v9;_e;2e zfX`Xur%V~{c5CU@K>q4zOZwebo3V@pvS=bHY%ddU?!^;(O>VsHd_i`MC2GMpKWUf^ zUTAIZZzn(IQ|05u#xE|JUJRpN>)z#nX2{nHn+9Q%@%sgh-9$?wpUVLAbJ)%s&xaZO zY`SAR15Mms7Meivh$OI)0^xuinNM>cbHMKsV+%n|Pjfc)kPfwm8_2;>wRBOA{C!ptHls9xd^Qd~8 zCO@qL;nN`wpQSt^8y`K1k$vS5HaiIl-~qqmpe0`pyGEcYaCV%N-av*oFc5!3Pdic% z)+8~-x7||auMIrE68`J)RHWI_umbp9Mh3tAjX60`3*r|(PAwz>n9MbFQ47tDWi3gB z0#;Z)HnurmH&7tx-4NKno{d6R&P$DHxVcg3@j0A$S+%yZp`>3wZI-U6$qLTzQ7yYS z1AfYA*uN`vl*7CY!REd-cS|PcPG`79r2WwLd0SH7v8$;X=U726<fS zsGMT&34&;d9yFgVdLAbRq@u($al9lyd}3!Nv>=D zS_qa_BU_hDyamOxpkrjr2hKtq{(9iGmz4u6qowrja(VfY z_{9|oPdV{jv}j&*+0R!(9aV&>z;zltwn{fssZ0V~qmN{tKbSqlFzGL*G-KV$+69t) z-1b{Mk<|CK|HM1pFf3gepn2%l{WJx6Tj9CgkED(?-;rlzxCGQ>9;NOw#~-F2+WOiP z7*fF#NFrv9?tIpkoRCZy>A9$7>MoaUE1b_EOg2A4zXi_=bUsM>Kq<^gTskwOPU#fj zpw}YveXr1Kw~k-uqhQ05aR%k>qH)D!a`$;6wm;5Gbpm=0N@QuEH7mkez^Nh&bCsr> zbP4W4R@Rrp;Bp;4E-J?sm8P&cQ}NpBDyl$3^{Tw79#|onPE!$ek55tYQVI=%UF@Z( z&&tP>Dz}}#kZUJgy8OOEmX=aQ^*~?D_Y3s-$rNLyAi4`vgMZNTddG5cfjr_w8{Pwh+rcL2N&?685iYts3D1zzI*_H&6jVf&Aj zZ|)Y)HWF#{Qi#d*W{Cs`s<<=@%^n5C1q2lDR~P&i8g6EWk1OreboK(B3wkVIk6w)) zUbO{l?AUmde@;lRjgd}pxJk5s=!}_$<6c8@e>=CIKj|Lc8h@thW`WL(H4X|h^HRH( z+PVEX#Y}N*6Cx90mF#XQut_KE7x`pRHNF_(4n($;U>!N#u`RyWm0 zY$wBMGF z-54yy|DuhtFQf$L-uFMfLBL-=Kv!*i(3i`6g^|!J3vU$H808!&8-xtyhxZoIR%et% zr01A}H=+a5uF=5ZO#iqSQXMm?DHw_W@BIZO{GSwTgQZ&Aza|`{RTejDT ztvBZs7nj9cuPo8l3}H;>!pATfa{5zTjD!~$Cm0A9Su6wZSI;)*^%~#25o^HYv)FAZ zY(l!B_NOzuOKbnrw{ixZanmJb)}>)=G0?@gHFF7*qI-Y)l($T_0CI5vle z=olEmH+pwtFwb>=E^*kGQb5a9ffb&|ocGb$WlLT(WIa{Tx5>IoguPvyF7f8#D&yk8 z4rI0Xyv0bEdyN_D!H;Kp}1_A3Ji8(T`kUl;(;>*=tD zPs+!g%1bEk)Bx=hE5OK(xdTUfrwivM60WYx=&}=De_lyhrwE>n?wNf3t3d!>`!GpET9A2OQ zUqxp|ro=(ZBBuZu>jVS@ybfd7UiUFBI55tTZBDn|8w(d*kFUn84r^)ntYoqcN87~^ zA3h*l=$FoaYv0%UW%a{DK{N09$ZsDZblo}j{^`3)7`9xaNzidU4H6o49lM)_BfJa! z&)A@uV+om33V4QS*Jx|cE$MbV4Er}F+pIJ~UJT1}VUjK?96`tD$nI_7{nOnnu*^IW z3>78>a+4B6M|07;_AGnvcSu`S{4$0ADqrsre^d9tP*-?ist7<*`pr%_lzn-mNSE*ewK66F{#v=a*%9qBswsooKoHwOIn-&$pd*c!r zd?t9@WzW=XuT#9J`1C*HSw;>cHZ=208KzpPjl zAVrbD+LIW$IocTSM>pRM9b%faItwUBzK2#j9n6j|(c?5@(Ss4B?8eei);mxbj4tl=m^+sPJeqLondSiTqV@)1mDe&e537XkJbx0rj#Ti`K!+4~>!5#NL z6A3shf(k)OIT!Ff5(7Wk$hBP=;X?VI{X(iTn{O9>e38lo z6>?YqQp`Y>72`#S(&BX)rh_jH{D8C5AIs!`$3Gkq34x9~F*5K;P$EPvwkC0zz$L#9 zkBY1hlEov-_VU3SxG-4t!>7{@51X_{a#6#(xxgFj%1?*F!zNz{zFWH!SP8+q?ZQvd z;nW-qxBz}Lip?G|PJ8|5DgI6PpM?LZ#J^4V@09p=4*z>`{ChS3vnBpnYyZs4e+K+N zkK><<^v?u^NjX{ zunI3V1f&Hj>9QzGnDCI_{Yf`+X7i`wD&kz~a+yq;`dLoS1o*^7s0(G1$24yLz(>u(9XfLu>ldIJY*GRHcGTKv7qSQm|ck0B^8p5i|&8S z;TRkmF2kHV-RD;2RhrQ{ICb>>PB1*KvJ$Iwul=#-2WC;&hD=POdGP@_Bhw&!mSRHON)p=?`&(A-wOn}+>ORzV?MIBUN1JJl23jjg?6ILP1q}WgUf_?SZ2rX z{;VuYcXkz0GEGkPf5nJ&ZqtWz`SB|}_mS{KgNzT7K(1-zV?0Nz0vDG{ntWdBAK+O< z@fB`z)3IUqK8=mdrv0H9!NcIZwWk$$)E$+^hWymy?o|uZw=^WP&vM*wwmo7QWtEW} zeVZ;XBt3MDx;OZ2?yf{jcY0lB$+SM}KSmMo{R#o16H$oMNs?Y(d})q0s%V8d#r!VY z6$<@HBd5?tX zjRY0qSZ4C2!qiH6T`7iVsBXyn#qH!IP%z$Fe&D^&UH#gg? zn}_218fEPUt6Jb-DiF}x8lrK0U@`dpwJ`bI%)?(?vQwQrOJ73qJp87)h$o>1>;Ww<)o2$tXjG5RW&7*z`s>d^6aBSXw3z5;vVl=yZf156D-kQ7kIzf!jDjkYtA>UK`|S8oQIB7-UEkrCid`wj z^2x~<4Flv#W zE;gLVL>zY)nm9Al+MJs|XT#B2)xECje>#PUf`ytJHC(#>B-k%Bx1Ueezl>4Akov60 z6h$G-=WP1YHJR@Gxt)AaI*fL~F=S1?MPQv2okZXzQ)p0_wN1Py-%C;muMfP{fLMH&NXkaz;ef znkl&??|g(;+`vhxq#fLt>XT_ZTm&5D5e0;L{m+OhXL7rY+VLyU1I)ZJ4Gj#-Pes1! zaSXhP?UsZSQLcD-N)%OWm!L6L23T#AtQDrFSvh1^Zu-ULQr1A9c3Gz?N&?SAktsil zkhw#0y|zX7&b|EkY_#xsmfGvet8}R-G9wc+a;U;l?q-h~I(+SsmwHN?uxHg05iWE* zwFg)W3!=1kCQz8F@fq(FGDF6+x+Suj^XqN#$T#;6P%091Q1@L0 z(bWcsz9$FK);X4g4IJH>ScXT4)3Yb*qxqlRRXVNt5wor$EXqhMJKC zRt#q1%JoOCZ>y|_19_Irwj0eE3d2R;sWB~T%EU{k!#5;fXGa0`u|k&fDZ=5Xd<^+w znu1Z`69~ghZR2E^AU}0CsFReEmrm)zce}D)Y^iTKRJOCb5b@g{P=`aLdBzVXFX3yH zG}Cia1wihh*jsm5b+H&=7QJs_8lX%_ZouQ$)}=;8aoG_G*BDHQh*?oha8q}&v4QMf zVe6OA+yZO8{pHV}*7AVs+ezcbaB?N9y&S!s28@m*cr74Z-1Y{$;nEDy)6p`+D;8Rf!Wsiw`HW;1s?ieev{Hmt!gO9 zDAV(+5i2V8hMq{mOWXQaW+TIz*?!T>lvP6D1XcdfS)7ADJillyjm>X2i&~%9=;2xX zxQ7VX$KQXid`R0wi`Hr;GxID0?TWVUnI{mBu2reBWMmac-X1WNM9r69&8a337diHv z!JJD0XGuu-KTo2y@?+1NcH3$w5(p{6CUBxf9_@6|&kY;#Q0axxiHmF)&!;aTBZb5bB}JO46PuX0e@xMgQYv+~q;zQ)%- zz%TYxTet{UuowZA`I^x3s%~rsZeT_t6_ScIy?riZS>t%Pr@MS`?JIqbn;6c9?&oju zi<;$Z%{KfOvKYte9cmjde+{m_qM->-l4g3aw)in5OM{gh(ox$eef{p<$!2%^+2egY zA@>K3{i%C6CBY0a@Js&$1criU@y=WJxS+5O$q5M5WaT8Qi;JtJ<6=|1=8jXq(nNZf z?^ul+u}EImj0y`<;@L??yGi)YILNZum`^XR%VQ_8;G8 z3m^h#C*meG6{Qg8-0@9DzTfEw$od!uT!4=sJwMj#yDwyjO$d1nigV&*bEnn?D}zOS|)0PI{&yW<&W z&G6fstZ%}sfr$qEtxLp9TU|;HNA$^Q?bcW!`iQ6X=p2jTVoNA|SMs+)BX1x(8Yk!TU2o+CSOZfJ zpo0@G%+bZXh_H6O2t~Nc%qA)r{Q2v02coH2;VYL$aPXt@6HlUv$}E6O{i_r+Y;$=z zbVgx4WRW9djMu`T;!GR$CN4KC=(g$p3s2=Q9sckV z-!B3kSDU0TFhFesl2hS1-noOL@zJxwt-QF|K<*|XGBV*bV<*fb%A>K-I>d?!88=K9 ztpYz{AoyW(lk>av6O);seez`_0GC408wy)O9x z5t`e=c&cZ$V-%~k-up_=O2+@DWK*jheR_?ZYTLx5LTdLCu~Htq&`k-isEh6>Z>LfT zRF65EksAn$@(2|?;e+)~_OgU;XSoS} z@B-%Y?La>%Ol2apsmson=I(V}>#1Msw3m>5Ru|{66W3}9*xcsZsJbfdsYW`U9ssED z3Bfc=+L!g~IB>~0-=Mqm{oMMpd)m^10%(Mn70I}DP{=6Ci=|IhPnYC^l)NsE-~X~2 z+!}{3R#7+W>s5)72di($`7Hx32pbe&j&3QtsfXitT?G+ZfPfFPU9Ig(*dE1$VHMq_ zAWcW^b2_@ckr~BshSgn5D`U$ngIIJl6{d&kZ`i~@hOVT095{7r41pz_foY7KqfWXY z#0sF(b8Khi6UD>)<0e@RUUsJ}u>Hrv1Vv>dDQ`H3%=L>5vE|`gzs;q=haL zlXh8ECn^e~CNcbFwbU_WQ}09#jA}h0DKgQCWY_{5wMce)SPIc9XQ;&xyYE^$5$M}G zl#>?`Q7C4V`g_UajbP&z?Z6}(aY>qAFJy$=)O-n^IUpj)r7$nXXB8km3kBmG3%2`} z&u52(_mpf8jZ?2>Q{vkMda2_}NVM`t(BJRrkOtgOyn2(S;`FB%6o(o_EL!DIDs_u4 zp>`t@l@>{SOinZCtZ9R?pEB%i*bALSLG= zBi9T-%jT|(h+3j_-U9Jj!j^Iq&Y&WOLM5vY=T8lx=Qy0o(d>g`^UE)|X#R+w?aj>* zcMYJa@O!(6t9FdO?e!{LrJ?i` z>R#8M>|cuCO_-$aU5|_yy&JsWhph#j5#!TRUffMl>uh}3dVc)z6I+q0)2--6=l3wn zaZuhw@>}J4;edGbma+?PUSYsmQ7>QTeU!dqP@nUw055WaWUN)W_j<3gnbk1S7blE*Sn08t_h{QnI4r$?$WqhK9Cb4r!`DzXwAfT`F$)w z^>g1>_*0H7CiX*mdd+SqWL2KX_+8qIUFW873Y({O1X6TLivVK-PBR+fC65B8U*QGQ zNjJVp&}=f4CNi+}QwKL8VcqBUM&z!NFWoON6$HP&Er;C(2tLV!^R3Is@G+3`YODsO zx0_@;ZmSbg$9m^2kO2Nl;x*R0FWr$ueOr2fij5u-61nv6rWKg6X-&BlPlT9OTHnO% z%DWe0-F5X0p*h{48M~|p=~Oh9A2|7;4EVp1EpDhKocZ+e_qXjlo?baq2k_e!bv9NW z!`U=i1g90tG*8!8U?oicrNU1@k=4Ty-4q~mA%n$$@&t8|?O<`^FO;NyZE(z|5dQNN zj~$ngh%_#Gz3S{={D%g{!tDzzO#y=Lc?8xdeBY|X!$_oc*Neh31ftQ zcy6;ECw0T~*ar=R1Q*bC`1t&wwo;lhZ*6Dp^Z0G$8(P6o2Nd467<3EDXH8nbO7NSi z&Y(P7o04z&+c1r4dj&Lpyor)zS6i@k;TJRf=I9XJyLNg&R^;AZW7Tr~+_(a-J6Wl( zv|+L0c=4+v{Pk+iOza=>747Finq(hbv;o~(bbu!6C3SuPKNhmY;~689BA_5J0<I$^y#EF%G9?oLi%Qk?k|G4(GxYEH z!Jl7m@y#;gM;7YID5}h=Jiq_X;0IwryOMUK!*x>}8>E6Qb$d}{2+~_$|F+$~x}$wQ zO}w9@0(ZV9b><>PfKSeu2w^1B!_l#tPe9;(fVr|Kn8>%aI*tkR?_4k=;DZSY3hL!# zWqqxy<8=aNh-s@<=_4^m#Y0_S?ZAu1RcW8lia&lPyX3aJmGVak3Z?$4s zdgLk}CxD~1muD_?;#W#OTcK^E)qaBhAT4y5nU}}56AxBWR_-4hM8?9wc{!8Dw$xmi zpr40VhJyUwfI%12;ebaVT#P|j>~hcucO`P9PnOZd++0$lqWXTSI=eXS85iNx{gROO S(VG|WkDQdUWVN{Q*Z%=q*KN%J literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index 1cea279e31..24fd4f26a2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -186,7 +186,7 @@ nav: - 'Email and System Notifications': 'admin/runai-setup/notifications/notifications.md' - 'Maintenance' : - 'Node Downtime' : 'admin/runai-setup/maintenance/node-downtime.md' - - 'Monitoring Cluster Health' : 'admin/runai-setup/maintenance/alert-monitoring.md' + - 'System Monitoring' : 'admin/runai-setup/maintenance/alert-monitoring.md' - 'Audit Log' : 'admin/runai-setup/maintenance/audit-log.md' - 'Researcher Setup' : - 'Introduction' : 'admin/researcher-setup/researcher-setup-intro.md' From a941ee5c0b29ade9d824f3c73b805e9f2ccdb4c2 Mon Sep 17 00:00:00 2001 From: Yaron Date: Wed, 31 Jul 2024 12:04:42 +0300 Subject: [PATCH 2/3] system-monitoring --- mkdocs.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 24fd4f26a2..787805413d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -219,23 +219,6 @@ nav: - 'Cluster Health' : 'admin/troubleshooting/cluster-health-check.md' - 'Troubleshooting' : 'admin/troubleshooting/troubleshooting.md' - 'Diagnostics' : 'admin/troubleshooting/diagnostics.md' - - 'Alert Manager Alerts' : - - 'admin/troubleshooting/alertmanager/README.md' - - 'Runai Agent Cluster Info Push Rate Low' : 'admin/troubleshooting/alertmanager/RunaiAgentClusterInfoPushRateLow.md' - - 'Runai Agent Pull Rate Low' : 'admin/troubleshooting/alertmanager/RunaiAgentPullRateLow.md' - - 'Runai Container Memory Usage Critical' : 'admin/troubleshooting/alertmanager/RunaiContainerMemoryUsageCritical.md' - - 'Runai Container Memory Usage Warning' : 'admin/troubleshooting/alertmanager/RunaiContainerMemoryUsageWarning.md' - - 'Runai Container Restarting' : 'admin/troubleshooting/alertmanager/RunaiContainerRestarting.md' - - 'Runai Cpu Usage Warning' : 'admin/troubleshooting/alertmanager/RunaiCpuUsageWarning.md' - - 'Runai Critical Problem' : 'admin/troubleshooting/alertmanager/RunaiCriticalProblem.md' - - 'Runai DaemonSet Rollout Stuck' : 'admin/troubleshooting/alertmanager/RunaiDaemonSetRolloutStuck.md' - - 'Runai DaemonSet Unavailable On Nodes' : 'admin/troubleshooting/alertmanager/RunaiDaemonSetUnavailableOnNodes.md' - - 'Runai Deployment Insufficient Replicas' : 'admin/troubleshooting/alertmanager/RunaiDeploymentInsufficientReplicas.md' - - 'Runai Deployment NoAvailable Replicas' : 'admin/troubleshooting/alertmanager/RunaiDeploymentNoAvailableReplicas.md' - - 'Runai Deployment Unavailable Replicas' : 'admin/troubleshooting/alertmanager/RunaiDeploymentUnavailableReplicas.md' - - 'Runai Project Controller Reconcile Failure' : 'admin/troubleshooting/alertmanager/RunaiProjectControllerReconcileFailure.md' - - 'Runai StatefulSet Insufficient Replicas' : 'admin/troubleshooting/alertmanager/RunaiStatefulSetInsufficientReplicas.md' - - 'Runai StatefulSet No Available Replicas' : 'admin/troubleshooting/alertmanager/RunaiStatefulSetNoAvailableReplicas.md' - 'Best Practices' : - 'From Docker to Run:ai ' : 'admin/researcher-setup/docker-to-runai.md' - 'Researcher' : From 55ee3a4109e4df29dc53863f175032c852e2b505 Mon Sep 17 00:00:00 2001 From: Yaron Date: Thu, 1 Aug 2024 10:03:52 +0300 Subject: [PATCH 3/3] special-characters --- .../maintenance/alert-monitoring.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/admin/runai-setup/maintenance/alert-monitoring.md b/docs/admin/runai-setup/maintenance/alert-monitoring.md index e6031fb216..4616c259eb 100644 --- a/docs/admin/runai-setup/maintenance/alert-monitoring.md +++ b/docs/admin/runai-setup/maintenance/alert-monitoring.md @@ -6,7 +6,7 @@ Run:ai uses Prometheus for externalizing metrics and providing visibility to end This document explains how to: -* Configure alert destinations \- triggered alerts send data to specified destinations +* Configure alert destinations - triggered alerts send data to specified destinations * Understand the out-of-the-box cluster alerts, provided by Run:ai * Add additional custom alerts @@ -37,7 +37,7 @@ In each of the steps in this section, copy the content of the code snippet to a * Copy the following command to your terminal, to apply the YAML file to the cluster: -kubectl apply \-f step1.yaml +kubectl apply -f step1.yaml Copy the following command to your terminal to create the AlertManager CustomResource, to enable AlertManager: ``` yaml @@ -54,16 +54,16 @@ spec: ``` * Copy the following command to your terminal to validate that the AlertManager instance has started: - `kubectl get alertmanager \-n runai` + `kubectl get alertmanager -n runai` * Copy the following command to your terminal to validate that the Prometheus operator has created a Service for AlertManager: - `kubectl get svc alertmanager-operated \-n runai` + `kubectl get svc alertmanager-operated -n runai` ### Configuring Prometheus to send alerts 1. Open the terminal on your local machine or another machine that has access to your Kubernetes cluster 1. Copy and paste the following command in your terminal to edit the Prometheus configuration for the `runai` Namespace: ``` -kubectl edit prometheus runai \-n runai +kubectl edit prometheus runai -n runai ``` This command opens the Prometheus configuration file in your default text editor (usually `vi` or `nano`). @@ -71,7 +71,7 @@ This command opens the Prometheus configuration file in your default text editor ``` yaml alerting: alertmanagers: - \- namespace: runai + - namespace: runai name: alertmanager-operated port: web ``` @@ -98,7 +98,7 @@ metadata: name: alertmanager-smtp-password namespace: runai stringData: - password: "your\_smtp\_password" + password: "your_smtp_password" ``` Replace the relevant smtp details with your own, then apply the `alertmanagerconfig` using `kubectl apply`. @@ -191,16 +191,16 @@ Runai agent cluster info push rate low | **Impact** | Possible impact - no info/partial info from the cluster is being synced back to the control-plane | | **Severity** | Critical | | **Diagnosis** | `kubectl get pod -n runai` to see if the `cluster-sync` pod is running | -| **Troubleshooting/Mitigation** | To diagnose issues with the `cluster-sync` pod, follow these steps: **Paste the following command to your terminal, to receive detailed information about the** `cluster-sync` deployment: `kubectl describe deployment cluster-sync -n runai` **Check the Logs**: Use the following command to view the logs of the `cluster-sync` deployment: `kubectl logs deployment/cluster-sync -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `cluster-sync` pod is not functioning correctly **Check Connectivity**: Ensure there is a stable network connection between the cluster and the Run:ai Control Plane. A connectivity issue may be the root cause of the problem. **Contact Support**: If the network connection is stable and you are still unable to resolve the issue, contact Run:ai support for further assistance | +| **Troubleshooting/Mitigation** | To diagnose issues with the `cluster-sync` pod, follow these steps: **Paste the following command to your terminal, to receive detailed information about the** `cluster-sync` deployment:`kubectl describe deployment cluster-sync -n runai` **Check the Logs**: Use the following command to view the logs of the `cluster-sync` deployment:`kubectl logs deployment/cluster-sync -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `cluster-sync` pod is not functioning correctly **Check Connectivity**: Ensure there is a stable network connection between the cluster and the Run:ai Control Plane. A connectivity issue may be the root cause of the problem. **Contact Support**: If the network connection is stable and you are still unable to resolve the issue, contact Run:ai support for further assistance | Runai agent pull rate low | Meaning | The `runai-agent` pod may be too loaded, is slow in processing data (possible in very big clusters), or the `runai-agent` pod itself in the `runai` namespace may not be functioning properly. | | :---- | :---- | -| **Impact** | Possible impact \- no info/partial info from the control-plane is bein[g synced i](http://running.To)n the cluster | +| **Impact** | Possible impact - no info/partial info from the control-plane is bein[g synced i](http://running.To)n the cluster | | **Severity** | Critical | | **Diagnosis** | Run: `kubectl get pod -n runai` And see if the `runai-agent` pod is running. | -| **Troubleshooting/Mitigation** | To diagnose issues with the `runai-agent` pod, follow these steps: **Describe the Deployment**: Run the following command to get detailed information about the `runai-agent` deployment: `kubectl describe deployment runai-agent -n runai` **Check the Logs**: Use the following command to view the logs of the `runai-agent` deployment: `kubectl logs deployment/runai-agent -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `runai-agent` pod is not functioning correctly. There may be a connectivity issue with the control plane. **Check Connectivity**: Ensure there is a stable network connection between the `runai-agent` and the control plane. A connectivity issue may be the root cause of the problem. **Consider Cluster Load**: If the `runai-agent` appears to be functioning properly but the cluster is very large and heavily loaded, it may take more time for the agent to process data from the control plane. **Adjust Alert Threshold**: If the cluster load is causing the alert to fire, you can adjust the threshold at which the alert triggers. The default value is 0.05. You can try changing it to a lower value (e.g., 0.045 or 0.04). To edit the value, paste the following in your terminal: `kubectl edit runaiconfig -n runai` In the editor, navigate to: spec: prometheus: agentPullPushRateMinForAlert: \ If the `agentPullPushRateMinForAlert` value does not exist, add it under `spec -> prometheus` | +| **Troubleshooting/Mitigation** | To diagnose issues with the `runai-agent` pod, follow these steps: **Describe the Deployment**: Run the following command to get detailed information about the `runai-agent` deployment:`kubectl describe deployment runai-agent -n runai` **Check the Logs**: Use the following command to view the logs of the `runai-agent` deployment:`kubectl logs deployment/runai-agent -n runai` **Analyze the Logs and Pod Details**: From the information provided by the logs and the deployment details, attempt to identify the reason why the `runai-agent` pod is not functioning correctly. There may be a connectivity issue with the control plane. **Check Connectivity**: Ensure there is a stable network connection between the `runai-agent` and the control plane. A connectivity issue may be the root cause of the problem. **Consider Cluster Load**: If the `runai-agent` appears to be functioning properly but the cluster is very large and heavily loaded, it may take more time for the agent to process data from the control plane. **Adjust Alert Threshold**: If the cluster load is causing the alert to fire, you can adjust the threshold at which the alert triggers. The default value is 0.05. You can try changing it to a lower value (e.g., 0.045 or 0.04).To edit the value, paste the following in your terminal:`kubectl edit runaiconfig -n runai`In the editor, navigate to:spec: prometheus: agentPullPushRateMinForAlert: If the `agentPullPushRateMinForAlert` value does not exist, add it under `spec -> prometheus` | Runai container memory usage critical @@ -226,8 +226,8 @@ Runai container restarting | :---- | :---- | | **Impact** | The container might become unavailable and impact the Run:ai system | | **Severity** | Warning | -| **Diagnosis** | To diagnose the issue and identify the problematic pods, paste this into your terminal: `kubectl get pods -n runai kubectl get pods -n runai-backend` One or more of the pods have a restart count \>= 2\. | -| **Troubleshooting/Mitigation** | Paste this into your terminal: `kubectl logs -n NAMESPACE POD_NAME` Replace `NAMESPACE` and `POD_NAME` with the relevant pod information from the previous step. Check the logs for any standout issues and verify that the container has sufficient resources. If you need further assistance, contact Run:ai | +| **Diagnosis** | To diagnose the issue and identify the problematic pods, paste this into your terminal: `kubectl get pods -n runai kubectl get pods -n runai-backend`One or more of the pods have a restart count >= 2. | +| **Troubleshooting/Mitigation** | Paste this into your terminal:`kubectl logs -n NAMESPACE POD_NAME`Replace `NAMESPACE` and `POD_NAME` with the relevant pod information from the previous step. Check the logs for any standout issues and verify that the container has sufficient resources. If you need further assistance, contact Run:ai | Runai CPU usage warning @@ -253,7 +253,7 @@ Runai daemonSet rollout stuck / Runai DaemonSet unavailable on nodes | **Impact** | No fractional GPU workloads support | | **Severity** | Critical | | **Diagnosis** | Paste the following command to your terminal: `kubectl get daemonset -n runai-backend` In the result of this command, identify the daemonset(s) that don’t have any running pods | -| **Troubleshooting/Mitigation** | Paste the following command to your terminal, where `daemonsetX` is the problematic daemonset from the pervious step: `kubectl describe daemonsetX -n runai` on the relevant deamonset(s) from the previous step. The next step is to look for the specific error which prevents it from creating pods. Possible reasons might be: **Node Resource Constraints**: The nodes in the cluster may lack sufficient resources (CPU, memory, etc.) to accommodate new pods from the daemonset. **Node Selector or Affinity Rules**: The daemonset may have node selector or affinity rules that are not matching with any nodes currently available in the cluster, thus preventing pod creation. | +| **Troubleshooting/Mitigation** | Paste the following command to your terminal, where `daemonsetX` is the problematic daemonset from the pervious step: `kubectl describe daemonsetX -n runai` on the relevant deamonset(s) from the previous step. The next step is to look for the specific error which prevents it from creating pods. Possible reasons might be:**Node Resource Constraints**: The nodes in the cluster may lack sufficient resources (CPU, memory, etc.) to accommodate new pods from the daemonset. **Node Selector or Affinity Rules**: The daemonset may have node selector or affinity rules that are not matching with any nodes currently available in the cluster, thus preventing pod creation. | Runai deployment insufficient replicas / Runai deployment no available replicas /RunaiDeploymentUnavailableReplicas @@ -261,8 +261,8 @@ Runai deployment insufficient replicas / Runai deployment no available replicas | :---- | :---- | | **Impact** | When this happens, there may be scale issues. Additionally, new versions cannot be deployed, potentially resulting in missing features. | | **Severity** | Critical | -| **Diagnosis** | Paste the following commands to your terminal, in order to get the status of the deployments in the `runai` and `runai-backend` namespaces: `kubectl get deployment -n runai kubectl get deployment -n runai-backend` Identify any deployments that have missing pods. Look for discrepancies in the `DESIRED` and `AVAILABLE` columns. If the number of `AVAILABLE` pods is less than the `DESIRED` pods, it indicates that there are missing pods. | -| **Troubleshooting/Mitigation** | Paste the following commands to your terminal, to receive detailed information about the problematic deployment: `kubectl describe deployment -n runai kubectl describe deployment -n runai-backend` Paste the following commands to your terminal, to check the replicaset details associated with the deployment: `kubectl describe replicaset -n runai kubectl describe replicaset -n runai-backend` Paste the following commands to your terminal to retrieve the logs for the deployment to identify any errors or issues: `kubectl logs deployment/ -n runai kubectl logs deployment/ -n runai-backend` From the logs and the detailed information provided by the `describe` commands, analyze the reasons why the deployment is unable to create pods. Look for common issues such as: Resource constraints (CPU, memory) Misconfigured deployment settings or replicasets Node selector or affinity rules preventing pod scheduling If the issue persists, contact Run:ai. | +| **Diagnosis** | Paste the following commands to your terminal, in order to get the status of the deployments in the `runai` and `runai-backend` namespaces:`kubectl get deployment -n runai kubectl get deployment -n runai-backend`Identify any deployments that have missing pods. Look for discrepancies in the `DESIRED` and `AVAILABLE` columns. If the number of `AVAILABLE` pods is less than the `DESIRED` pods, it indicates that there are missing pods. | +| **Troubleshooting/Mitigation** | Paste the following commands to your terminal, to receive detailed information about the problematic deployment:`kubectl describe deployment -n runai kubectl describe deployment -n runai-backend` Paste the following commands to your terminal, to check the replicaset details associated with the deployment:`kubectl describe replicaset -n runai kubectl describe replicaset -n runai-backend` Paste the following commands to your terminal to retrieve the logs for the deployment to identify any errors or issues:`kubectl logs deployment/ -n runai kubectl logs deployment/ -n runai-backend` From the logs and the detailed information provided by the `describe` commands, analyze the reasons why the deployment is unable to create pods. Look for common issues such as: Resource constraints (CPU, memory) Misconfigured deployment settings or replicasets Node selector or affinity rules preventing pod schedulingIf the issue persists, contact Run:ai. | Runai project controller reconcile failure @@ -270,17 +270,17 @@ Runai project controller reconcile failure | :---- | :---- | | **Impact** | Some projects might not be in the “Ready” state. This means that they are not fully operational and may not have all the necessary components running or configured correctly. | | **Severity** | Critical | -| **Diagnosis** | Retrieve the logs for the `project-controller` deployment by pasting the following command in your terminal: `kubectl logs deployment/project-controller -n runai` Carefully examine the logs for any errors or warning messages. These logs help you understand what might be going wrong with the project controller. | -| **Troubleshooting/Mitigation** | Once errors in the log have been identified, follow these steps to mitigate the issue: The error messages in the logs should provide detailed information about the problem. Read through them to understand the nature of the issue. If the logs indicate which project failed to reconcile, you can further investigate by checking the status of that specific project. Run the following command, replacing `` with the name of the problematic project: `kubectl get project -o yaml` Review the status section in the YAML output. This section describes the current state of the project and provide insights into what might be causing the failure. If the issue persists, contact Run:ai. | +| **Diagnosis** | Retrieve the logs for the `project-controller` deployment by pasting the following command in your terminal:`kubectl logs deployment/project-controller -n runai` Carefully examine the logs for any errors or warning messages. These logs help you understand what might be going wrong with the project controller. | +| **Troubleshooting/Mitigation** | Once errors in the log have been identified, follow these steps to mitigate the issue: The error messages in the logs should provide detailed information about the problem. Read through them to understand the nature of the issue. If the logs indicate which project failed to reconcile, you can further investigate by checking the status of that specific project. Run the following command, replacing `` with the name of the problematic project:`kubectl get project -o yaml` Review the status section in the YAML output. This section describes the current state of the project and provide insights into what might be causing the failure.If the issue persists, contact Run:ai. | Runai StatefulSet insufficient replicas / Runai StatefulSet no available replicas | Meaning | `Runai` statefulset has no available pods | | :---- | :---- | -| **Impact** | Absence of Metrics Database Unavailability | +| **Impact** | Absence of Metrics Database Unavailability | | **Severity** | Critical | -| **Diagnosis** | To diagnose the issue, follow these steps: Check the status of the stateful sets in the `runai-backend` namespace by running the following command: `kubectl get statefulset -n runai-backend` Identify any stateful sets that have no running pods. These are the ones that might be causing the problem. | -| **Troubleshooting/Mitigation** | Once you've identified the problematic stateful sets, follow these steps to mitigate the issue: Describe the stateful set to get detailed information on why it cannot create pods. Replace `X` with the name of the stateful set: `kubectl describe statefulset X -n runai-backend` Review the description output to understand the root cause of the issue. Look for events or error messages that explain why the pods are not being created. If you're unable to resolve the issue based on the information gathered, contact Run:ai support for further assistance. | +| **Diagnosis** | To diagnose the issue, follow these steps: Check the status of the stateful sets in the `runai-backend` namespace by running the following command:`kubectl get statefulset -n runai-backend` Identify any stateful sets that have no running pods. These are the ones that might be causing the problem. | +| **Troubleshooting/Mitigation** | Once you've identified the problematic stateful sets, follow these steps to mitigate the issue: Describe the stateful set to get detailed information on why it cannot create pods. Replace `X` with the name of the stateful set:`kubectl describe statefulset X -n runai-backend` Review the description output to understand the root cause of the issue. Look for events or error messages that explain why the pods are not being created. If you're unable to resolve the issue based on the information gathered, contact Run:ai support for further assistance. | ### Adding a custom alert