From 47f849b243c02af9a61a16a6334914f4be956b3e Mon Sep 17 00:00:00 2001 From: Mohammed Boukhalfa Date: Wed, 31 Jan 2024 19:26:11 +0200 Subject: [PATCH] Move wow from dev-tools --- wow/Upgrade-image.md | 64 ++++++++ wow/cleura.md | 80 +++++++++ wow/github-workflow.md | 252 +++++++++++++++++++++++++++++ wow/jenkins_ci/README.md | 111 +++++++++++++ wow/jenkins_ci/jenkins-check-ci.sh | 37 +++++ wow/jenkins_ci/ssh.png | Bin 0 -> 20205 bytes 6 files changed, 544 insertions(+) create mode 100644 wow/Upgrade-image.md create mode 100644 wow/cleura.md create mode 100644 wow/github-workflow.md create mode 100644 wow/jenkins_ci/README.md create mode 100644 wow/jenkins_ci/jenkins-check-ci.sh create mode 100644 wow/jenkins_ci/ssh.png diff --git a/wow/Upgrade-image.md b/wow/Upgrade-image.md new file mode 100644 index 00000000..505ee843 --- /dev/null +++ b/wow/Upgrade-image.md @@ -0,0 +1,64 @@ +# Metal3 node and openstack images upgrading + +## 1. Download the vanilla image + +- **Ubuntu** + +Download the target raw version from [ubuntu.com](https://cloud-images.ubuntu.com/) +then convert it to `qcow2` + +```console +qemu-img convert -O qcow2 ubuntu-22.04-server-cloudimg-amd64.img ubuntu-22.04-server-cloudimg-amd64.qcow2 +``` + +- **Centos** + +Download the target qcow2 version directly from +[centos.org](https://cloud.centos.org/centos/9-stream/x86_64/images/) + +## 2. Upload the qcow2 to both regions in citycloud + +The region target can be specified in the openstack rc-file, download +and source the rc-file then run + +```sh +openstack image create --disk-format qcow2 --container-format bare \ + --private --file ./Centos-7-9-22.qcow2 CentOS-Stream-9-20220829 +``` + +## 3. Update the source image name in the dev-tools + +Create a PR to update the source image name `SOURCE_IMAGE_NAME` that +will be used when running the image building job, [for example]( +https://github.com/Nordix/metal3-dev-tools/pull/592/files). + +## 4. Trigger image building job + +Once the dev-tools PR get merged, the image building job will be +triggered automatically and build node images with the default +kubernetes version and the openstack images in the different regions, +but you still need to re-trigger the job manually from jenkins to build +the node images with old kubernetes versions needed. (Login to Jenkins +go to openstack_node_image_building Job and click "Build with +Parameters" after that set the kubernetes version needed). + +The main tests usually use two node images with different kubernetes +minor versions needed when testing kubernetes upgrade. check +`KUBERNETES_VERSION` and `UPGRADED_K8S_VERSION` in dev-env. + +The older CAPM3 releases might still need different kubernetes versions +for their tests! + +## 5. Update dev-env and CAPM3 + +After building all the necessary images and uploading them, we need to +update the images name and location in dev-env and CAPM3 repos. Example +PRs: +[dev-env uplift](https://github.com/metal3-io/metal3-dev-env/pull/1069/files), +[CAPM3 uplift](https://github.com/metal3-io/cluster-api-provider-metal3/pull/712/files). +Please to be noted, we might need to back port the updates to the old +releases in CAPM3. + +For PR testing, it is preferred to start with dev-env since the CAPM3 PR +depends on dev-env but both PR need to go in together since after +changing dev-env CAPM3 might be failing. diff --git a/wow/cleura.md b/wow/cleura.md new file mode 100644 index 00000000..da7abcca --- /dev/null +++ b/wow/cleura.md @@ -0,0 +1,80 @@ +# Cleura Openstack + +## Overview + +Our Openstack infrastructure is provided by Cleura. The main interface is the +web UI and can be accessed [here](https://cleura.cloud). You will need +to have an account there, you can ask the team to get one. + +## Accessing the Openstack API + +In order to access the openstack API, you need to create a user. The web page to +do so can be accessed in the menu, API -> Native Openstack API. You then need to +add the projects to which the user will be authorized. Once done, you can +download an `openstack.rc` file for each of the projects you need to access + +## Projects + +We have three projects : + +- **default**: The CI project, please do not create machines there +- **dev**: The developers project +- **dev2**: The second developers project + +For development purposes, please use either *dev* or *dev2* + +## Connectivity + +In the *dev* and *dev2* projects, we have a jumphost as a bastion host. No +floating IP should be given to the VMs directly except the jumphost. All SSH +access goes through the jumphosts. + +## Example SSH config + +In order to access the dev VMs (`10.101.10.*` or `10.201.10.*`), the SSH traffic +needs to go through the jumphost. If you want to SSH to the jumphost itself, +please use the metal3ci account with the correct SSH key. + +Replace user by your username in the following script + +```bash +Host dev_jumphost + User + IdentityFile /home//.ssh/id_rsa + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + Hostname 188.212.109.109 +Host 10.101.10.* + User ubuntu + IdentityFile /home//.ssh/id_rsa + StrictHostKeyChecking no + UserKnownHostsFile no + ProxyCommand ssh -W %h:%p dev_jumphost +Host dev2_jumphost + User + IdentityFile /home//.ssh/id_rsa + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + Hostname 188.95.226.253 +Host 10.201.10.* + User ubuntu + IdentityFile /home//.ssh/id_rsa + StrictHostKeyChecking no + UserKnownHostsFile no + ProxyCommand ssh -W %h:%p dev2_jumphost +``` + +## Create a VM + +You can create the VM through the web UI or the API as you wish, as long as it +follows those rules: + +- no floating IP +- port security and security group set (*default* allows only ssh as incoming + traffic from the jumphost or other machines in the default security group). + You can create your own security group if needed. +- sensible specs (we are sharing resources) +- network connectivity : metal3-ext-dev only , no direct connection to the + external network +- don't use passwords but SSH keys +- delete your machine when you don't need it anymore diff --git a/wow/github-workflow.md b/wow/github-workflow.md new file mode 100644 index 00000000..a717467a --- /dev/null +++ b/wow/github-workflow.md @@ -0,0 +1,252 @@ +# Github Workflow + +## Overview + +The workflow is based on the understanding that: + +- A project is forked from Open Source project to nordix +- A local copy is cloned from nordix + +We refer to the Open Source project repo as `upstream`, `upstream/main` +and to the forked repo in the Nordix organization as `origin`, +`origin/main` + +Main branch is called `main`, containing the latest stable release. + +Feature development and bug fixing are done in topic branches, branched +of `main` branch. Upon completion and code review, topic branch is +merged into `upstream` branch. + +## Branches + +### Topic branches (features and bug fixes) + +Topic branches need to be branched off `main` and named +`type/name-username`, where type is `feature` or `fix` and `username` +the Github username or the name of the person creating the branch, to +mark ownership of the branch. + +For example, a branch name for a feature called `Add support for +policies` by user xyz would be `feature/policy-support-xyz` or similar, +where a `User cannot login` bug would be `fix/user-cannot-login-xyz` or +similar. + +If applicable, branch name should also contain Github Issue ID, for +example `fix/13-userr-cannot-login-xyz`. + +## Commit Message + +Commit message should be formatted as following. + +```sh +Short (50 chars max or as subjected by open source repo practise) summary + +More detailed explainatory text, if necessary. Wrap it to about 72 +characters or so. Write your commit message in the imperative: "Fix bug" +and not "Fixed bug" or "Fixes bug". + +Signed-off-by: My Name +Co-authored-by: My Colleague +``` + +If your commit includes contributions from someone else, add this person as +co-author by adding the Co-authored-by trailer at the end of your commit. + +Note that the email address might be protected by Github, then you need to +use the address provided by Github. + +## Git workflow for a Github repo through Nordix + +### 1. Create a topic branch + +Create and checkout local branch where you will do your work. + +`git checkout -b origin/main` + +Make sure to have the latest code from the upstream repository + +```sh +git fetch upstream +git rebase upstream/main +``` + +When pushing the branch for the first time, ensure correct tracking is set up: + +`git push -u origin ` + +### 2. Keep topic branch up-to-date + +When changes have been pushed to `main` branch, ensure your topic branch is up-to-date. + +```sh +git fetch upstream +git checkout +git rebase upstream/main +``` + + +### 3. Code, test .... + + +Do your magic :) + +### 4. Commit the changes + +Changes should be grouped into logical commits, Refer to above [commit +message](#commit-message) for details. + +```sh +git add -p # only for existing files +git add # when new file added +git commit -S +``` + +### 5. Push the changes + +Rebase your changes on the upstream main to make sure +to have the latest commits in + +```sh +git fetch upstream +git rebase upstream/main +``` + +Changes should be pushed to a correct origin branch: + +`git push -u origin ` + +You may need to force push your topic-branch, however this MUST be +avoided as much as possible in this stage + +`git push -fu origin ` + +### 8. Squash your commits + +Once the pull request is approved, at this stage you should squash your commits, +making logical units, for example introducing a single feature, squashing all +the small fixes coming from the code review. + +```sh +git fetch upstream +git rebase -i upstream/main +``` + +### 9. Open an `Upstream` Pull Request + +When the local code review is done and commit gets 2 thumbs up(+2), an +upstream pull request is made from same topic-branch to the open source +project for code review. + +Before opening it, **please ensure your branch is up-to-date with +`main`** branch and your commits are properly formatted. + +```sh +git fetch upstream +git checkout +git rebase upstream/main +git push -u origin +``` + +### 10. Upstream Code review + +Upstream Code review is done based on the practises defined by the open source project. + +Nevertheless the assumption is the pull request is ready for merge to +the upstream when the reviewrs has given 1 or 2 thumbs up (+1 or +2). + +### 11. Merging the code into upstream + +Pull request author can merge the code after PR has thumbs up or practises +defined by the open source project. After a successful code review, `topic` +branch is merged to `upstream`. Merging then depends on the project and is +usually done through the web interface. Once merged, you can + +```sh +git fetch +git checkout +``` + +### 12. Delete the branch when needed + +To avoid leaving unneeded branches in the repository, delete your branch if you +don't use it anymore. + +Remove the topic branch remotely only + +```sh +git push origin : +``` + +Remove the topic branch locally only + +```bash +git branch -d +``` + +## git workflow for a Nordix github repo + +It is exactly the same process except that steps 9. 10. and 11. do not happen. +Instead the code is merged with the internal pull request. + +## How to backport + +Sometimes you may need to backport a commit (e.g. bug fix) from a main +branch into a stable release branch. This involves a couple of steps as +described below. In this example, we will use `release-0.3` as the +stable branch in to which we will backport a specific commit from the +`main` branch. + +Create and checkout to a new branch (e.g. `backport_commit_x`) based on +the stable branch (e.g. `release-0.3`) + +```bash +git checkout -b backport_commit_x origin/release-0.3 +``` + +In order to cherry-pick a specific commit(s) you want, you will need to +identify the commit hash(es). + +```bash +git log --oneline --no-merges ..main +``` + +prints out all the commits in the `main` branch which aren't in the +`release-0.3` branch in a below provided format: + +```text +34a036b73 random1 +d2ff718f9 random2 +d83cb0e4b random3 +d589bcfc2 random4 +b9a16e24e random5 +eface850b random6 +``` + +Here you need to take a copy of a SHA (e.g. `eface850b` for random6) of +the specific commit that you want to backport into the `release-0.3` +branch. + +Once you know the SHA of the commit, you can cherry-pick that commit. + +```bash +git cherry-pick -x eface850b +``` + +If you have conflicts you will need to fix them first and then run the +below commands before you push. + +```bash +git add . +git cherry-pick --continue +``` + +If you don't have conflicts or you have already fixed them, then go +ahead and push your commit. + +```bash +git push origin backport_commit_x +``` + +During the PR submission on the Github UI, make sure that you have +selected the right target branch, which in our case is `release-0.3` +branch. diff --git a/wow/jenkins_ci/README.md b/wow/jenkins_ci/README.md new file mode 100644 index 00000000..c88672b7 --- /dev/null +++ b/wow/jenkins_ci/README.md @@ -0,0 +1,111 @@ +# Jenkins + +## Access to Nordix Jenkins + +You can access to Nordix [Jenkins](https://jenkins.nordix.org/view/Metal3/) +with your Google account. + +## Daily steps to ensure successfullness of Jenkins CI + +**Note: you can run `jenkins-check-ci.sh` script to check CI job statuses** + +- jenkins-jobs-to-scan.txt lists string patterns used for checking +- running from your local repo +- running from cli by remotely accessing github, no need for local repo + + + ```bash + wget -q https://raw.githubusercontent.com/Nordix/metal3-dev-tools/master/wow/jenkins_ci/jenkins-jobs-to-scan.txt | sleep 1 | bash <(curl -Ls https://raw.githubusercontent.com/Nordix/metal3-dev-tools/master/wow/jenkins_ci/jenkins-check-ci.sh) && rm jenkins-jobs-to-scan.txt* + ``` + + +- a customized jenkins-jobs-to-scan.txt can be used by running (wget run once + to fetch `jenkins-jobs-to-scan.txt`) + + ```bash + bash <(curl -Ls https://raw.githubusercontent.com/Nordix/metal3-dev-tools/master/wow/jenkins_ci/jenkins-check-ci.sh) + ``` + +Check global status of jobs which are built on a daily basis (Jobs with prefix 'metal3_daily_'): +[Metal3 periodic jobs](https://jenkins.nordix.org/view/Metal3%20Periodic/) + +You should see successfull run indication. + +In case of job **FAILURE**: + +- first check the job's logs (```console output```) to get more info. +- check what are the PRs that were merged last time, which could potentially + cause CI failure. + +## Some of common causes of failure that you might encounter + + +- `E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)` +- `"Unable to connect to the server: dial tcp 192.168.39.150:8443: connect: no route to host` +- `"Error from server: error when creating "STDIN": etcdserver: request timed out"` +- `Failed due to timeout` - sometimes job might fail because of the timeout + which could happen due to slowleness of Cleura infrastructure. + + +## How to resolve the above failures + +Just trigger the CI manually because these causes aren't results of any pull +request but rather system instability. + +## Possible sources of notifications on CI failures + +- First place to notice the CI failure is + [Nordix Jenkins UI](https://jenkins.nordix.org/view/Metal3/) +- Metal3 [Slack channel](https://kubernetes.slack.com/messages/CHD49TLE7) + `#cluster-api-baremetal` +- Metal3 [Mailing list](https://groups.google.com/forum/#!forum/metal3-dev) + +## Workflow of Nordix Jenkins CI + +First based on a trigger-phrase from an open PR or on a daily basis, +Jenkins Job Builder (JJB) builds a Jenkins CI job, which will execute +the steps given in the corresponding pipeline (example: +[integration_tests.pipeline](https://github.com/metal3-io/project-infra/blob/main/jenkins/jobs/integration_tests.pipeline)) + +**Note:** You will find JJB files in [Nordix +Gerrit](https://gerrit.nordix.org/admin/repos/infra/cicd) and Jenkins +pipelines in +[project-infra](https://github.com/metal3-io/project-infra/blob/main/jenkins/jobs). + +When a job is triggered either by trigger-phrase or a timer, it +is executed in one of the Jenkins workers VM + (example:```metal3-static0-workers-*```), which is running on + **Default_Project_37137** of [Cleura](https://cleura.cloud/). + +In order to access the VM where the job is running: + +1. Find the name of the Jenkins slave (from + [Jenkins](https://jenkins.nordix.org/view/Metal3/)) that is executing the + job. +1. Go to [Cleura](https://cleura.cloud/) + console and get the floating IP of the corresponding Jenkins worker VM. +1. Find the IP of the VM from Jenkins job's **console_output**, which is + created for running actual integration test. See example screenshot: + + ![ssh](ssh.png) + +1. SSH into the Jenkins worker VM with its floating IP that you found in step 2 + and from there SSH into the actual tester VM with its own IP that you found + in step3. + + **Note:** to SSH the Jenkins worker VM you need an metal3ci SSH key. + If needed run `ssh-add -l` to check that the key is loaded to ssh-agent. + `ssh metal3ci@'Jenkins-worker-VM-IP' -A` and `ssh 'tester-VM-IP'` + +1. Once you are inside the tester VM you can debug it and get more info. + +## How to clean up leftover VMs from Cleura + +There is a Jenkins [job](https://jenkins.nordix.org/view/Metal3%20Periodic/job/metal3_daily_main_integration_tests_cleanup/) +that every 6 hours cleans up all the leftover VMs, which failed to be +deleted at the end of integration test. + +**Note:** If you want to trigger cleaning job manually, you can use the +`/test-clean` phrase within an open pull request under +[metal3-io/project-infra](https://github.com/metal3-io/project-infra) +repo. diff --git a/wow/jenkins_ci/jenkins-check-ci.sh b/wow/jenkins_ci/jenkins-check-ci.sh new file mode 100644 index 00000000..8de98171 --- /dev/null +++ b/wow/jenkins_ci/jenkins-check-ci.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -u +# List of jobs in 'jenkins-jobs-to-scan.txt' based on +# https://github.com/Nordix/metal3-dev-tools/blob/master/wow/jenkins_ci/README.md + +# remove empty lines +sed -i '/^\s*$/d' jenkins-jobs-to-scan.txt + +nbr_of_lines=$(wc -l < jenkins-jobs-to-scan.txt) + +count=0 +all_pass=true +tput clear +tput bold + +out=$(curl -s https://jenkins.nordix.org/view/Metal3%20Periodic/api/json?pretty=true | jq '.jobs[]|.color+" "+.name+" "+.url' | sort -u | grep -E "red|aborted"| column -t ) +if [[ -n "${out}" ]]; then + if [[ "${all_pass}" == true ]]; then + tput setaf 1 + echo "--------------------------------------" + echo "---------- FAILED CI JOBS ------------" + echo "--------------------------------------" + all_pass=false + fi + echo "${out}" +fi +if [[ "${all_pass}" == true ]]; then + if [[ -z "${out}" ]]; then + if [[ "${nbr_of_lines}" -eq "${count}" ]]; then + tput setaf 2 + echo "--------------------------------------" + echo "----- ALL REQUIRED CI JOBS PASS ------" + echo "--------------------------------------" + fi + fi +fi \ No newline at end of file diff --git a/wow/jenkins_ci/ssh.png b/wow/jenkins_ci/ssh.png new file mode 100644 index 0000000000000000000000000000000000000000..22c93f3ee4deb73f2590ed2b90ea7f51a4465a43 GIT binary patch literal 20205 zcma%@1ymbfyY4B_;_mKH+#N!3cX#*V?(Xgm#fxikDems>?(T5Y{=e^>v(9(dT{kN$ z*_k9WlRbOhd7t0=?1ah5h{8c*LxX^Tz=?|qDS&{0UIW{@kY9k0;lU)zz$b7A0dXZr z;LQ`#C=~b_%TZX(QPIZ4(M8|h7{t`t#>$x1!O-5=*xJF&#_*E#gx_Mb)mtt7Bdt<$s#3{1H2d@jO&KJ#b!$A~9? z@GIg;^*1i09tPM^wRow*fR~v0TxlYcc$+ob2;BZiY_krZas_{G#)34)(3I8>+h(w1 z>Mtf8eL(;ja%wh5}L{;u4=DvQ29w(-QWfNgnj$jP~^ zHL(r~b>KY&?uk-Pdin`GcS0MX3nQ4o3o!W8E0ERBX^}HeFxAbA=OzL5bMX{U^T7Vk ztsh@MT#Y~f-QQQ3M<&=O{fyyxq+|Oqfo{TrAjk|T`!vksUaN{WaT*`7x=eC?Y)p~J zq~j6_hi|R%L|DwJ%u?IbpW)9OHh!+r#EJJaMsdP2%TTH2JFrO}%7srbvNv|ij(fm+ zXBt{tM>h{4VmFQtuc9r;-c*q@stnIUQ}49&DWGZuL_FZ4i}k_6l8j3<3jnNR&1G=% zXNXPv2bHOf;u)oSNaISTvZT(Pf9@;v!Uk}Xh*0Sgj8s62lZhu_#Gb1APTme^f{gUU8ed7$T1E|Whu_!P(jaUoi(EKZZ?rMG zCEXex?w87T8MBxy`}V_-Fvu18_8(m{LWW^sCSo`Nfc++AVrOgtl7S^)`*9B$p|WJ< z=h}~oDn-kVqL$r!`PE#9`F?0i92>dh#-){&-CV`usm`)ITn#ueD}rer8pQJ?*Le=s zKr0JNa~-&R)KZUA)rF}SvUv%sV2xDur93O`aT~FV3Sm9A(2x0Ao2eREii8;EuQqbO ze7lJHOnGnbXn;F*(jZyB%WXDde1HG&wb&@VnId!L9ewT=nmby?#3Sad{h(Y#gk#)s znGu>cI>txeL5H~d)_yf)AY}J00q0A|uJ`J;HfhiOI$*9Fv`s9blcxtuy=~bXMSWw( z>4bGoD)BcTK!=#8KOM^oziU8fd36qKufyUq1 zLQj}fUe?rR-GmD*V<}0eSkaW3#i~Sd<%^|bZ6|XVa6rJ)_ju;U5vva!i3%(mF?fTb zy|$FEp;EFu!>;?8-Q#G~cV^Mfrps{&i?59g^p%v!a3|uSoqn>*(mXjQVYD-(6`PO7 zhU>!VlQQ>SP(}|~w{41P?wJph7L=N~$KU1+Pw}4wAXY9ZCA*6Chak)`KuZ6jAP&Te zJHmD9x4X6u$=C4>wX@TM82zfS^O@TzMeMf4JolfV);0FpIic;>%7ijKMW=iEP`&=mXc{@~Uv+ZPj^p2{tHO&c(K|1&N%~xP^7gs;&_A^#@ z#}8JKD?>I`KG7jUA)YLFoTI+)m;3ETqxwsc9b*`3my>aKi%7|uA*NHw0`~1H2h>>6 z0)qaR;%bHBNybM=`lc zJi&M7LgYOHY!2Ay!cFkBII7ADav_WX!Rm@3+eqkNG%iB34XVqvTf|wzBqm(<>8_Y| z^B?5Np#FyDN8N)FhFvgdXl)uC>lNYSjOPBsM3bR&RWU7daOXu0>gfp7pWoBXm?nn} z_W>2ls`D4`b(xzc7#+8IVQU)C5@_%N{GL(xDg${o zs;N=MUHMc*NI{*y(V|QA$~bV|jJ)MKI-lfZXBxuaEMEBJjP?DFKPDQ5G>(gL`%|mU z)qDD>$b!~~t0#Cp2uaz9I!BY`)j56&m=SI0w9m+jrE|rzKUex%(R?+eNJ^^ex&q%R zBkZv%X1c0vM)arZpH_)jLhMUA!NdLVS#@JgpSt-Ee{I;W-RpFs3!M{8H5b9f%ldB} z^0e=0b&9(=eF>mH zA0_|iDyWMH40{(d>N@i^E=;=?v@I$rGG!tqj-g&27MDjfWT?^MoKzKb4OTN&3zP@L z^})Wl-x6NxWoUYHy#`hG&d{(vPlA%PjG+f?U1|i}7(({#n6;}W9&4Za_34)g8~{vV zx4{g*=a@lmuM?@-=+?rnkR^p^;g3aK^h zh_^1n@VU(>IEEj}C0FNQc+ZeOp=Dad2ig}ymb;OWJVLZ`Wd`u|H1X2sK!einkf1x^ z`JUTEs-FDw-%pon5?p$U?spnJTNU^->HZa_xH@13@#Rn^md1}c=5YCVp8ak`;JAM< zX&2PS$hl`+=Ls3^K;U~lgeG~yNkZj4gXDA_KZ9O0;_LTslRDT;V&r?edNxY%w1<9t z9cbL}>|sY4kZORbxv~r1=-ga8gp=*SA`os?$T;5=sYlH?;ToSu;CZGSlaIC*`dK0lY<9^c00*zQ%rJ7&-sP2B}m0fE;@{w($$ zI|<8~H-fz?9Lk<_Km(iIX~Dl@74MBt_JLbYEAmGItmdwPu*tBK{nmsw*1r<8u7!S# zow$z&!;GTiRg*L!T|{;3rvAQ|09_45!bm=N&0RiN8$LH%e%H(5^4YJ z-CJf;{RnmM*p+B!{9H)~{j0hy!VG5E^~WuSo~B!ZTCUei)IaIk$fH1X&Z%7Z$M3TD zUDm9-g_YimyOC5u4Q?_GKiD}d6yf;s4qQtD^hH-Yp@ric{2+*D(6sN^g1oYp1j&O| ztcRS4lPE^>Gnn4KbbGxIZLTiOZCH5|8K|(npT_LtRL2?}*EtcrWGrc#NbqzL;V)^= zt{t?5lZ`w^)|a44ws9SAG4z1(%5Y_L zW!{qv{OwIoB2S`V9$%r|E4s4hp&S6#-8!vYN(Zw*#=_LDWZH|;J_a+5t%B}5a2iEY$^=t1CTg0BOJ$^TQ))C9NKPT9OHu3Aadaa>6CKOX*;`^{ z@sY^oe7W~E(wJO}(E<#(-9F7w8ku{6!KGqNHoEdu6>>_)sG~mfiH#@1RF%QRQRm6F zwu8$OPy4F=4+&6*3U9vNA=ikbak53Dk|N*h zvUq2)MY()JSHXZPW0LU*+3t^NQ@#I+xx>v@g77Lo|6r1aDWXR2ZPddUCbbfj^OFSR zs7nw!2;9#u;*!#jd8vX6R{}h5q&!3k)m*4bCok38zpYVvJBK0B=8Pnz#~?V%J5#_Z zLH!vQm3i0xQ)$xfqdLZ)6Jyh|>xKAnZbd8gp|;AVx03q&u>>QE#^c2&bN14FHiG8N%_npC<7L$Y)9vu=-C23N zvu$C?jlShQ;$cC#b^wV!zP(}B^09A3q|&VCxZ~j<>EUDRj8?Sma7I`5-TTa#1V+dC zp}DaI@rpR^XJb>x#oPTt9}D}5E425Gl}CNqb7hh|cbo z!$oH?ZMul4&--!vD4iS34aJV$UGu|;xIf>6YWv`J<--cAxXs*_@w@vOZ?q5{?~0FW z=PBSGJ^x0Bl<9(&25_(Q&Xx8~fAO%8v3}h16C+Hh?J0=N#_OZ8&h)72eV)Jb;USP0jm0?5tcUn zj?J1-Y!X3l=BWAW7NO}UP@=5r+2XZ!;_VeH12XFl?T!0G4UmBq&1D$gh;5Ee@1A8;6SZz{R9oi@gRT51rh1 z_U)dc zZug+}H>w~qxB&otuNB%8(Sm>s`p@$VMM~0GJdf3J{fudiFzZXkRu5%+_lyAc3!BO9 zJ;3y250lCb+&m)YGA^t8V4Ryj`|jWCQCG?!hQT29VT3w#AyaE>MuAhxa{`*g8H%F! z;=b@0S^5OZ0;>{hV48ZrZ8}Sf;$U%KX)Mcr>dQV-vrOupeJ~;jT{MjSxBklFus#PC z2&P)t%9~swb9V1M+6>a$7v`Pf!Zha8jF(^=pP%1KrHI(DGH8%wc**fqXLaqbRuZ!IOUF5+vJ zX~BX;ru9RXOb8zI73co`d(XojU}{Wyd|#l4gvtqmS(DJ*?5B53QMpdBNHe%J2jhH)HGQ%)3;g3`kw*a(Emh3yb8Qo~9<(=h^;l3L`zX4M-<)8kh>1qix5ulmRRfH&k&bu z#5w4+T_$tAPAx3X*;nOi6k5^DM=?o8pM~S%s(ww;V*i5oGrKoJwuLB%9un1z^vZxn zXhaw~YAk3L+O#$!&8zJ~l_ zHzcSoFkRY^iG(9;?H3Uy{^eE2PijsyeoD6iCV*XE5vHgwKv^q}$A>sveqB`4&%Z*3 z-YV_gvUKf^_q=mb-nj79`-32xh>fEEW-&Gn!-(kQHrvvyPCUkfEc=AKbjxejVabM)@JU_F28zDAv(( zmL{rC`s}>V5{m6XT7=|Vyj&%eY%^4juHa1oIy8yPPWdT|`f{}FfmNGw2!MEr_kNl} z59h2TQInT=;Ju_k&C;@B-45abKmup>hTVLg>AL8D8S zjK^T>_4p=~Q*sghy0>V%|mXq-Ca$v#*O z^BYN$_K$2&{+{r)qd>C1i7|j(SIlh8_>0s;Z7B7^w$bs;;l)WR%1xTuuf^{v>d3o`gz2=>qNJ>cHI$%j}S$1F<@g0xhm^KQ%tZ`ri8X9VoNy91LTsYmdtu z;dbO(`e7@5N{TJoyg$2f*bjmCI&iFY%y>TUGN`#BjHjECV|^{H%Be&IYA?vVJkl8kA`S0SoL^%$s{h#$Miw)9^+QpgF zGuSdjooE^Ex!>-pgUXKW$; z3XbSt@F`50`$gNL4fFB_xe8db#u(`!IMH9MjOCuwZxpOc&$r#oOY0YE`W-5>hjmvO zwN`OcK23zEjTr*sRSNI*?f|ASGs%JlMG#)9%|kw8Uae@Yzl2_q#T2C<7?d!USr_(I z!Xw0>J;2Jv+}di2wA&w$_3GS$t8!e=g~wIF^+X`)SdS_hM`DPsQz@_>i3_%&#}u+H zM!NAA9W&6V#%3<5_@;ytrueg?G;k~#exKtiR5tW~dHkN~*4!5X7D2SxKs~!IW44(L z5SW_+gO9pydTW>~(r_1+4bwCGH<|}x6EVPQKJ=5S*LnU(3p;*|9r}dU?h8rmKD(PX6W@~~PEH6ijUJcG1oGH@9gZ3kso`$yZbIhp^RhLG`#A=Z2p)oNWYt$g^QK`xF9!o`KB9 zY=y|0IO5sO$l*nGiM$&mBpD~)t8C<#hvH~jfZf?|?~EICF*EeNXlYT6r~xb-U3kHi z<0N|JITUeZPgH*!?frUlr??>=x9-Ik38lJ5=iB5$^+@;=W9%Ui037d}@JgSQ!1%m~<)2xXWM|`_<*YYCNwI zPp`qAjZ)oW@~z!EXUQloY{SN5q!t#cK9qA*2@KQhI7jxF%oabqDyw)jSS6~oMz1H@ zyx(A2#qaJ}9yH!jxt>e0rbjV*KTJq8S@Tl$_jZs!&b%gz5SfP>-z#7FJ~c|V$C6{Q zGw#EVK0*h%r@)ljaw{=G83g+wNye8+4;G70_^MD!ce5~za+Guv-Cx4nH%gPS)BUNp zIKEBK-iWxR*c$G`6$lZagDw4`K44+>unGzOtCk zIG=hKm-Nc0o~PV9uEP)&L0j+|dGjK!!xeJY&`1_`vl6a@wRL&EC*Dcr&YkW@C6J2v zcjkONG*kOx3l;k9fuwv_DZU^y|MaR#-iEC%8@Iq$2p~Utr6~AN!o?AVMuvKc<1=Ih z&+(73C6;}3P~EZYHJ@?C(9?H{tESqiclm1lI_O~><4*)e7xKiy{l*crCJZ_c-yFpn zzKrj-#xCq$ZE0CP=S7oJnyQd-z5K;oJwF*VeaD7DyuP#G9_)joi<76IVB=ea#YEP+cvrXaT19Z*v=4JUnZ%id$B>?{xs)hr%RC^h_U<9`7fpdmE+seC=;@ zp^Z(=7ww*}lNm8UiP=~FaC4E6_PT|4@kfm!$;OO&z>LVY=lFb_lulO~mG5X@92}Ib zcPDYZ&%8L%dt`r1w={mN^u2y?tl#1DMY<#LZVTrjwC@%3c@!(ZlHoj6d%4eQ@@2P# z1G{7IPlsrFVcrqPg|c^6?^axV>}SnyFN_7%wGjY5F0`4ltuxn4clg?Mb+Zq}2o~sD zA6CrI+Qx#YuR9IebjNbmCt?oTgT^Ajjvv;9>1%JNU)EmMJepCj&{b92g9h6kY~KnW zuCM$t!f0G$9(+2vMl_#*?>j!rT=HDR@Y--9-(}{kq)fSnDuI|ecXTzIobnb*S`V92-@Aph{qepws38yR@*bz$=C$n zy*FU&zRHesq?kTq!@0e0u-3(}CgHW=gjOWEEhVMpaAHCIVhe~dPS$HN)E95Z-QONk z)(v)Z**V){azxq(k2~0v<7OgnI=yf17gE}Sog!ue z^X6F2-JRuyol%!Z+taM3MyUJEjl7Nd+p9J?5P=qZzE5Ja_)~E-0CRN7bp6FT%uT%| z)8%%w4%+ka-v6q}s_%V2Q+lZR6M00$H$1+9ei(gliMIv4H0S{UU!Dx==#(? zg*S^hF2@JhclG#WY~pt?u*0P?Az(>EWyy&>OqOh@U9Q zauQy-YgqfdB|Noxq`B71%pqj;F>AS*pM+CF;A}zD9M9D$+)=U*sbY#cjndM_3i-_@ zZQm`t3zPwtlaAeQ;*2D1=o>l+6fWls;du%4x+U%VhX!?(71S9`M;Yyi9yZNp=!>1t z_ulKK7jDr(lWviT@@96PuP_-m$bN+>JNI}5>*k*a{{h!5M*=w7mP-!#?azi1fRTD$v(e9$9dPtEm zW}8YJwSqP*W5?<~9Iu46NQoEao1W^Z5==&H@vq0?snf0S+Wvt7#c0V;C)oKq2Q-em z{kJ`Ic#^~gA>-$l6T$MU_}U)OPhLB0CBKaJcb@0Ad{yb9P zV_zsazmS&^XR)`Gvi{U!hl>C|^w!kZDi(YOJk&v-UE|1oTywZRpK+a(YCS?&PBISL zi7kD0@PX3i(&_p$<~7qXSX#%NsootXmb_!J;KbQZ6SRij>kWFisaT(*KxugC5e*#{ zEO&*aciRVk0fcM}Ti^@t`^{FhP#g3EX0LaIZlL`tkeJgt%EEI-?M#d&J&w9+7+X-YR@u&2W)Mn{k| zbAJCPr{F{R!WtEw1&A)lJ;Cla`*@xU-5kyy0KN-Co4DN;0YVB)VGSfD^6I_a-{taSvQ0 zRJU);7!=8sh9jR)wQyaapLh-b#fXmB_u5==<&1W%g9_4q%zjai!{j`7Rp3P-kJBzz zS~qUY?7GFPx!Ucw}z4%wMla=SESpg4ijRNj*M)fDIiv6-pA z1I>77$T^_B3l8W=C&O2e7bH)c``TlYHD7;qdqzd?uFoVplS+iviQO$`5}LyU9l#Dz zzsC{thdLq47^y>R%$^+3mu2+Vthsi@H4M)rii;^v-I5*&C*=ps^IFfRgwl{hK7nvb zSuh4FS8WV20#Vxgo98>G8{v=7wlUw`t#D{-Bdt>ooxY#O4ZjZA^i*pWKb8yB-9$eW zpHHL(`P>JhboMXZ3;(Oqy-~aZLHjdn?Rduj=k(ND(%QvL3QK+1hJ=$!fJh2J>J?HF zyr-+A-NQu~uGG|R1b}7Eg6)z2!dw2}<<2*HH4}u&OrvG2udV6peEunM4~DDZ8F7+= zjcJ6RrLWKw?%P8Eu7205f#DufyBN4OduYG3z=Mf#XTBl7?Umv!cR|_{f~8G=fZBB3 zsSQQZ3ItPBbPrUXMEa@=C2<^sJE_Dh>`td(5X3LE4(f)1H>$C^B`W=FXybq&+qf)| z6sfPhn}=}idWqdjO^KIVU^xgmq(tH%On}Ur)bC{i*Hh?*A2r=QXM*;s<>9cc%Gs#g zLf5Um^weVM{8we*i6=PDhVGt&;r_%!VyYd&)(IOB=usLW-&jUOrGI%ceVU75BI(*a z&e5fa<9H(xa#ie(wz(`lGU%rV!1m;010`vjo441br^t{*wfbab#RI<`gyckR1~dsL zt@AbKd?^~$(8=`br-l8jGKR9Og`wilQyf1wLhAHBa4^+)SAE4F(;><>e(`&7#3h9n ziQiTL1dXim2L#=1XhqK8I;a%RORMwGL2Y$S1)ElVsPkz@9t~G&g zbQi_(ltN`u^a9sz)_SUZ@98~h=*Ggkn&nYK&C!HWdzsPw{`rjj+vrO3Q*6Mb{>iKS4#_a^a(D6i)xqH&4KzxCKPnHjXO zSkiim_zm{%xm2*d=>%LHG?1TL-2_Y-m^b#oPx1LeLsfVI8!9oxz87u`miJs7uU+m}chEpky}R-{YQeG)ube$_P;e3Sd7;e8 zw|W0>p=GB(Vh%{0P$Bcg(JLB#QXZJT5rVvBv)ax62-+J2uNOy|3*q~YEW7trxmGBX zBz+!j$!nI-^_yCNPT7Mv-%kKANSXt&)p6%AS6dN6(R@u#ED}W;WwoZ7Z$5ildtUc~ z#kc$X>{(gGHv-I%S}d|vzPu%G!TfwA)^ltHqWse0r?SBmnCgFFD9(&4NjE-7lswU5 zmu12fofQG-;EDD!_QHoCNK2BIvm210t`+=fT+#v{4`L6lw}i{I-8T6CjB2J2H)K7- zjrXMo{|rB{yQ>VP2^|k2afG>uKOkoru#bYVb7MNwdU|nI<8p1|LK#{h>Y~-!WRf{Tg6vqKWqU2#%}ESjDNjMZ0BIv+_I{AeLt-duAr3%gGuyva2KmmELrR&#;Lj+H9@MclgXk1!OA6(_*nSpnNyxEyUP;gOBGP? z!(vA~h5kG8erVP-k@iae`K+7D5#iDPTHDn^howo_1a*C5_-rd%!(2iA+;7wVVqNu_ z1R4uG3E5$mRyMGeJY{Od#(skjPycGo1NG)0*6O2KiMB)Y-kq7x6=pD!LZ^84L0otq zzE)0VDln)P^NDDlzLm}O2rEs$CrhtNy`C@(g^I7gmj_s9RjBgTyJ`i_0Y?ywC(tMH z2x|7p6$dstN} zH7J7Ga#`HG4BZHMSs9#tpQz`J5qO=tH-M8eS39)kdd7|6A;D(f74&c^XDORlrI)}* zBKINC;F;TbR~yhp>h4lrf}$L*jy zgl;(jNi1|OVU_nAeftH{<39rY5So$9%I&%h#arQ{} z%RT0sFZ@yj~V&z^0?eg)(dnT?;Z{W(_y0sH)oZOd_D!p^s?{k zls^B#9dkn8?6Q+-*q}M%=|#l+7_PeaUHkO0Um2lSNF*kJ?jI|LcvR3_$gn;01<^Ml zf~sk?5kzKV7GC~YIXWvNI7I2MxaGWghlAkxC#dMf6+eJAAl;qeSlv zd|D6a{sN-fACHbdeIPkjeqf6x1&P)r@B;M(h!@j+z^p@hdf4Xm1}D!H%2@hE&7n#D z@!bLS1p6frA-_`FnsrjiuO0$@GkQix(UM*N1r%>X|C>(&QDflzzimO_x{*HiFQTffSAB#aw}yVeAmm9>(m zW9@%{NUi6BH@;Bi{M+F^nvc+VPB|x zYJFNc&}7a3w0!{maR+Nbjafp)F5P8~TkOMa1$(8baN!@8z_MgT}|ARDup~_oO z2QF`0kCPxgvm>D3bJH=&{sPen^d`UiBNou_^1w<3+HI@(h-i4%fq4>qGYbzmgVkRoH5^5vuJ`-oWg1u-#XId>Cq#}lz_QVR$|TvmO=gdOe2r(CnllGoy>7VW^sbNo{NqlvI;K znVe_a6~*>LS%b(rbFlPtd_VLr^Ar>r!A~mQ-EKa=V;oci=NF|Vs42KY$;4EbQ&gzA z61TskX=EIiG>%EhWs}$bwwgKp+RKb(pbtlj+8u|Cd0oiyI;^2o-?0Q4ef9&v~lxy!=~o|=R?8l2Ly z?oeJk0n0=4Goxc;S5`G+hiA+k+($jVyYao!JE(eQ@)J3g?!99Br6@bAh1qOk=%tA> zPzFVQX`^-=PPfV-3ZBu;&1l~C>kgMY$~$l9cpG2=&OuVd&iiAutn{qEtraxHGkH!J zk*SSkta?ivJz)U6;&fT0*5HqmqYY-W?%>EV;z!sT9Q@9lVjn+5JeEOUzm!OY3(-hz zhNrm}JAdPAl43&=nQ>HzK>>GH#-3LL@RUy3lF*nM1S-K9viA62gyvw+bV#unq`{U1 zhE-}Y#$mEN0t@W|CTPqB$l=Cn(M>F6qBCxLzexAat}vlOdQwYhBcocf>KNj=ep*$AL`Z-{QxcjfrFNKrpL=3#|qFo)2X%H#mb8J3#b0h$zp6l zDaDf|oI7)QFyQ%1GZ*Qw@_mEiBRu?J)cKEK+u&y){9A$f$_&H9hrdwcj;>)SuRbyr zi%xlVrl`%1rOd=rqWf+~FjaY~*C%=UOUFS?+)!%gKFP>vD0iWz@}03$+ME7ANm2QH z(-^TOS;W#Q-HXQxO_^2r5iM5&8ul-9H9NKwX&oC;JD2d;a>~5`L3=*yE4p}n51Skd z{ZBdtL$XZ*YbtRB_O!c3e#h^CBmvN+8mv$DZKFU36Q8M5!P3BK&aFNzZ%v2842Q9p zDYbM>MQvOAz`J#_y5-3>2ZXy#v>dZCe1?Y+s8zV;808D8RFOCE+iVC)Sm@a~JP;Mg zj2n24uay4*vrx8Z=|T#5qS8qB+H;nw02C<7S6PXCNzr^k`YF+5NYfKHH-BN=n#WS5 z!C&{(=2I(00ZQ_7ed~@+1DCc)sm$YT^WEpEfXTDl%HhlNwv$ORF%DO*k=Vaz58@=B z3HJ~6D`k4Wv03;#3}l`_VcoFq{G>LHnXBC+BfqxHxtw4 z#>0lgASC`@Gz_e&lD<}|e>V1t$dbH;P52#WsB!F6Y4=7lKM&Q?LW!x%D;9SGbrv zQ^J~E$F`v2n#CAdL79bD++BX}@Q0Iu7=l@w86oYiy6mBuH=hQF47u^DV(6&mF&u;! zt0YfBUa%BXnSAgVS49~4*BeUYbOgCD5mPKDzIl+=(L}C}AmAi|kI}4{00NwY0KLn7 z-v-L=D3L*2rDZT2wz3Be zDY}u#?EG?gUR`UlALHHmZzSJL{8Li{L7W6_5@l;|h(cEvX_UO>V!IbJe(xpX{qHFm zCE5&izxke9Hy7k&J}we28N0m@9$y?^etiB_r|G4EsLa*US^MJk93RY9^PrqH_hYIM z0p$gf)PHMJv~S+>3fXBUZ_Q$c%R*s{tR(fb^9}hs<*pd?)Tu+Vf3Z_#+=z5%D&QYu zPm+ixK^ej)FN1)exI&6r?(@D5lCu1qk{5#aU1lu)bxI3ExexOOv+J8H%~27;6I@Nc zqknxpd@`Ml+skbZXePgI%>86x^6b8KBA8Lo$|X58PlT{w+oe2B-$|A2Xr^i#aO3c1 z40fzN`%RleY2(y~6ia_nVv)|Xxx+&44hfHgtW%VT<6xR3;VQ!Fn|wc70|yuh^T!z# zbRN-?3_*tzljyRi{tHIg$>MpIfHHsePV&9J%6D6=xGq>Eir*l6@49?^ar*ivaXRq? zI<`wo#31m}NeH@xV&x_amru98Vwb{B>RVQb(JTC@HP0LRMjey(a&Yq83}4p_6aNY| z@NE#=T}m*9Ozj-iwO%2&=DR)mmP6KS!5|i`(4nL7TJiSFaGt>*L~`?dP}#267F{|CLW2Yw~|KniWLR?}FeAE6gIu`XwXPpnw8OdUAD?+5Oq6~6c z3S)n{D$fY#oV6N5AFJXrl!2o1x=|_kr#_x}{W)-+0npqJ*dCmpWF_dTmbmyCmH!0_ z1lHX#lQ3*H3<+V;E8@Y0&g@l?qs8Sy#a9lbJlo0H*zB(QqAv5B@9)9x^wpPVAe=e0 z=Ie0zU2L{Puxq&t^vYH~{vx#h2pv!Icm@RroxG3^ylFyDCPA4zCpqs9L7%m?iA3@K zOJ-a=LVE@dg;d-Kxo^uIF82Q7j7xUM>k#GFRwr0L;3gYUxEgB8kv`Gdc8T4U=#L78 zzuvQzbpb@r-dW%t9X*MzJa0}ntq?@vky|{G%enO!FjpB@g~?D8?cCdMVmZpB zO>aLMT{@0y4n^oF0mr zw-rIp&YHLF@C>`I`z7Ji+owR1+>?y-rbrQz)tC7d8evH0-?(ibF?0bPQS_+IObVb3 zU3gKLYYkw<(u|rro;L{hcQ|+sIRI2}e#DN!2c$u2s&ICrucGpAgh2w2!GZ;ao5DlE z1wSMN-Dec%0&*jS=&~Z!yogAHh z%NK?nMOME!WjAUOyJz;jvfVS-lO0#!7a1F7Xdfq$tPjg05A&SCAWGNeren&MInsv2 z8O~U$m@k2NBe#6X!WLQRx1-TW!uE3e{5DT^e=e)NLJG9z&@?h+Aw^qFTP0HJjt9e4 zx8!cMQ`Rh;8peolm}FSwyHwbIQ$Y0`htgiz^G;b}dJdQBRLM2w-p*ftJQ2@<7`5JIshPrZk9>iXu_)*um@zTl7+a0=xXY!YXbtBSOyQ z<<>au#P3vwS}U3neV!}Zvroy!J5u!VW)^UL<%;I%9L_oJg+mO9Cd%z*4+Ar1)0E2j zQG1KG7Ru{V+pjJ5J0_*N`fpn#;cE!oznxAays|wu;cIAso-KiMKQ!+sSy#o1sXDy! z2L3xG0m*?X)7Lflz7Pa;c5Bat7G8;F-qA_)75Qpf%a*r?9RH^mIYe;&N2U#7b2#tM z%6^TxlfrVPB2auB-D#C-0eoHe=h(8;CuS35Mq~o+hDq;RFK~;qGbgij7*4JuJ!+rT z3~rjlWwPGYrx(}H<;u%%Midc}VP09an~QX1;=Ncij_+<$FlGJBw&>v%Tue#8o|%UO zik0kRI1-c9SG0uj+FrIR)8vOvQ?M?ucIT;GJIL}%m|9DO3!9X-iDL4f@$a@$9gLFm zsCmlv!=4Y!bj6^`CH8-WS1I%jb{L(Cf1P5zrpBm3+k1yZVKqkQl*-6Ji5;;=MzydH>|0 zW}Lalq)Lm_Yj;bL_;AmQ>G%cX@zTQ!Uef7wi*t}@8!N!yxg7$qKHz|f8}D^}Y;SN- zmNn4Ua;=RdbyjD?R~Rqra5xk=@66b6UPm=fIWfbnHGaiAeEoPh>>}<8W4KVLG*WB* z7)!$S@=~${*UTrO&o{BY?vTx6e?{B3#3Vs_fRAc-bY4;CqCTgxbw&B8a{sh4d5J=( z&V-pfj5;;zD#8Ww-?S4-z)^>| zPsDT`vF%KG0Lv9XbTAmWoq;NGv?QnveCy9$-%p4TxO&1rcRoUS4U+$ABMrj*v$z{U z4E*|^rvD`vvR~WZ5Bn3o`U(+#R59mf$;OsyxOCo%8e$)Y5wBfraTqWf)TF9CU$*W} z59_q?)u=_!9{@&2OXDSW&FQa+rv9wV7GXo0@Ipgc0t=58i6oay+*FdKg1R#{9}s2m zMOzY4((LdEcdvoh$}(P>lu|b;?Ud_CC_INz=Pgm5S(0yhiv|P)-t^D^0uaw^1{C+} zB1x6!3Gd3bZCf5I%2*`2Zc7l z#mu3Q(`AZQ`2Yhw%pP@^bVnv3EQmT}&am=}IjXYGjF;Wyq zuE7l34zaoIwNQ|v5GO?@RdhSv=Os2@$W!j%=oF&yD>9{Qq^Wd@vs9QU79&R{jW-V; z!#NW>gfPv-vq5=||2$d0u`Tz z+}wL>E@7QhNtu6eLrOwr!66_pAwMhxXkUA=9~&w6A&w*UqQyBfV2db7m_hQB3QOjN zfzK347iy5G%WNMkB4v`reEY^NRJEx z)N60I#UqdG11#u-6(oNYM${ifUrNF9iqItQ%{^wacS=j*R3?#ow!|DTcbVfD-S$>^ z@f-sSmhmY|TKOJt;FS#&@szcD_r{3avIHA_1k#G5g;OZQw6b;eM=TIuOE!jtlxM}l zyH!HBGRWWDToA=#hfKxDNWL~2g^%sy1n1I1mq3uFaNe%7RQ3pW~1mWM{`v~Nv2lzdk)4@m5ay|*kH)dekU-8Gvrjg5X zIF6D(IOg^7A8f}x#^Z}tw_9Pyuvsp=;PvqVTfsh+Tn+Qe0eSrn{pc>u?%y;v{d6ja zT&s}w`gCla{Z^O14_0vxD_s7*kJ=P}tMM+L=ivA?jq(~CE&g-)?&d$zg=4ScANWR6{+5hou<+gf)31%%vr5|ML z;F#Ah3M|_-b}HR#f$-qulwiI=yL(Jt=~Jn7=X_5hTG2ti?-;loL&e8tmY}3LE zMrThv_J@duz%mD)xkV4p^C1VPrDE?)EJ8#=@836xNL0lenAl%-=rfYe!PyySe{QmL zTf0@KRI`chHu&qWW9p?1mLDwmo9q0P{v<=a-KBl7#<;pe?Oq=gK@bGtXYhRl@{uhH zs}q_}k|fhPibjL()xg28v6YYG)Ykcro*`GN((K&`>b)_qp2RLQ&aw3x1MlXJKB3>> zXb>U)EQb~j5(tJ#r1R)ufC>Fp7go2)Yhi-HFnVE&=(t1k?Q9dirBybQLBNl?x{5j; zFu0m%^hHQ*MhO7^$SQHg#+=Rra5_hvs@puvXoQ17)M%RAMv&7ty=fplqI1;2w^m{| z6-5mMP$N3|Oah5TcuT7@Cc0ff4+jZ`HS*i5Ou8+4S2|i=$&gb0K#ZG+4Mjs^Ehc|XV>n45FJ>;bmWn)bRU@~&?d=fH!jFd*YZXwAMxMRi(IfFTj zhm3tH(Wpuw5JZh8NhcRvfa6;xm5Cw&el^8L!ll!?&j&>i1VQ*2d>?^40kl$+zh56v zNJV+zyrJ}Dom^{{hE#QfR{NOhwoZrvjbfVhQkTm(*(bBQ`zL??IsLc)D@*s7$TqSE zxJsPJt)=5b>>(&2mCO9B6hf6-YQd zc^>z2_+ane&FMCFQAFl;AzDqUfM;!`MLEy zKn?^^+ZZ?@rQiqRA9nW|{SDoz9j)STEm^~U+RG@!@$K=(-@5u;L>(Ie6n=E z&yLfg_}dY_?H81;Ox*SdBz)eOu@@$D(71SM!v!fcyUG6Aq$tJaYf`;a`lqM7sXXDZ z^NeF7$-<_Xd*Ds@;98%+f=1{BK@fx=!FQ68|B$T6aPD&ck#@hVUIaahNe2^9LrB9@ z%v+Pc3W@^5!Ig3z*Tx=8DC#19n*FFD759^Myh}t>81x2rmmqvjpGZNLq%i|~meZTq z18fwOuMh!!c!*!Sk3k75V86Z6#}2mbp{UB0c*sv6qM>Js81(}2@hM&V!)+~S7~(pA zn273O^=Ff3M{fs=r4Zp8^*xi(h|%c2`PU%fki>W}n2luFeN0aw8kXj0zj^>JqtOWW zo|$GfqT+MZREu}Z7k$Fgm#UXx0#k1v|w;^)1GkthpS$=C1Wz)FgU+v0h(hdpvIn+8V%6LI zl%(Ba(r;iiyO{Qf(a56PG4Yhp{OirD5yHN=bh;y8g41en@-NI_F-jKY;^LN*byNA%0atG6hD!Cl|rS&VfGP2PbQ>ovtQ5_JX9Y<&uws0D)R7` zbMUS3?C*<}YrcLT>pU}T_R2-lM;<;Uf?nPyqfXoXez0Fs`K`im3=fu~=;d8fH)70> z_VGLhhh(3;x}13VYUeSpSYq?INlt}eYM*`kDV2PhLr*5Owu`ZKpNW#EJWub?c^~&3 zWqEuA(ZXLGqyiA$!q{~w)v~M`KIDkb{(fpUq4%!#JGpfC*4ewf&?-DW1>ed(e;XQp zf0V+0p1r;2JbC2eTZ*$~lt|7y=rZVX`p#qguELX(*`Iy!XSAzHBmyK$2E$UBV)`YX z6hh1IQ&`wV1pRW7?5kOd{OK<-o-*rW{{ufxtIAGw$k_9tL^KM<#{44!evPeshkWG` zT1_RQt+5h1Wq9>94^~)ENL7^9-)_sK8t90frTgdfBI{PWL0|9tC%5QLwKX`p8v z@;w9XTOW(?adw?_y3a