From 566f650505b87ded386cc5a468a7ec209767e54a Mon Sep 17 00:00:00 2001 From: zhanghelong Date: Fri, 22 Aug 2025 15:04:04 +0800 Subject: [PATCH] doc: Add documentation for enabling Kubelet proxy in Module Controller V2 --- .../virtual-kubelet-proxy.md | 29 +++ .../enable-virtual-kubelet-proxy.md | 193 ++++++++++++++++++ .../module-controller-deployment.md | 9 +- .../virtual-kubelet-proxy.md | 27 +++ .../enable-virtual-kubelet-proxy.md | 185 +++++++++++++++++ .../module-controller-deployment.md | 7 + .../kubelet_proxy_sequence_diagram.png | Bin 0 -> 28541 bytes 7 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 content/en/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md create mode 100644 content/en/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md create mode 100644 content/zh-cn/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md create mode 100644 content/zh-cn/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md create mode 100644 static/img/module-controller-v2/kubelet_proxy_sequence_diagram.png diff --git a/content/en/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md b/content/en/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md new file mode 100644 index 00000000..d651b5e9 --- /dev/null +++ b/content/en/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md @@ -0,0 +1,29 @@ +--- +title: 6.6.4 Kubelet Proxy +date: 2025-08-22T13:00:03+08:00 +description: Koupleless Module Controller V2 Kubelet Proxy +weight: 930 +--- + +## Kubelet Proxy + +The Kubelet Proxy is an enhanced feature of Module Controller V2 on the K8s side. +It allows users to interact directly with Module Controller V2 using the ``kubectl`` tool, +providing an operational experience similar to the native K8s Kubelet. + +
+ +

Logs command schematic

+
+ +## Iteration Plan + +The adaptation will be carried out in two phases: + +- [x] Use the proxy solution to provide logs capability for modules deployed in the Pod base -> **Completed** +- [ ] Ensure semantic consistency and implement logs capability through tunnel or arklet for smooth transition -> * + *Planned** + +## Notes + +Currently, only the logs capability is implemented, and the base must be deployed in the K8s cluster. diff --git a/content/en/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md b/content/en/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md new file mode 100644 index 00000000..e07c3891 --- /dev/null +++ b/content/en/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md @@ -0,0 +1,193 @@ +--- +title: 5.7 Enable Kubelet Proxy +date: 2025-08-22T13:00:03+08:00 +description: How to enable Koupleless Module Controller V2 Kubelet Proxy +weight: 1100 +--- + +## Kubelet Proxy + +Kubelet Proxy is an enhanced feature of Module Controller V2 on the K8s side. +It allows users to interact directly with Module Controller V2 using the ``kubectl`` tool, +providing an operational experience similar to the native K8s Kubelet. + +For design details, please refer to +the [documentation](/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy). + +## Enable Kubelet Proxy + +0. Deploy cert-manager to manage certificate generation and rotation + cert-manager is a Kubernetes plugin for automating the management and rotation of TLS certificates. It helps generate + and manage TLS certificates used for the Kubelet Proxy. + Please refer to the [cert-manager documentation](https://cert-manager.io/docs/installation/) for installation + instructions. + Here is a simple installation example (v1.18.2): + +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml +``` + +After successful deployment, deploy the corresponding Issuer and Certificate: + +- To create Issuer + +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: virtual-kubelet-issuer +spec: + selfSigned: {} +``` + +- To create Cert + +```yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: virtual-kubelet-cert +spec: + secretName: virtual-kubelet-tls # secretName: virtual-kubelet-tls # The name of the Secret where the certificate is stored, which will be used later in the ModuleController + duration: 2160h # 90 days + renewBefore: 360h # renew 15 days before expiration + issuerRef: + name: virtual-kubelet-issuer # Reference to the above Issuer + kind: ClusterIssuer + commonName: koupleless-virtual-kubelet # Common Name + usages: + - server auth + - digital signature + - key encipherment +``` + +After creation, you can use the following command to check whether the certificate secret was generated successfully: + +If the output is similar to the following, the certificate has been generated successfully: + +```bash +kubectl get secret virtual-kubelet-tls +``` + +If the output is similar to the following, the certificate has been generated successfully: + +``` +NAME TYPE DATA AGE +virtual-kubelet-tls kubernetes.io/tls 3 1m +``` + +1. Add `pods/log` permission to the Role + +```yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: virtual-kubelet-role +rules: + - apiGroups: [""] # "" indicates the core API group + resources: ["pods" , "pods/status", "pods/spec","nodes", "nodes/status", "events", "pods/log"] + verbs: ["get", "watch", "list", "update", "patch", "create", "delete"] + - apiGroups: [ "apps" ] + resources: [ "deployments", "deployments/status", "deployments/spec", "daemonSets", "daemonSets/status", "daemonSets/spec" ] + verbs: [ "get", "watch", "list" ] + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets", "services"] + verbs: ["get", "watch", "list"] + - apiGroups: ["coordination.k8s.io"] # "" indicates the core API group + resources: ["leases"] + verbs: ["get", "watch", "list", "update", "patch", "create", "delete"] +``` + +2. Create a Service for the ModuleController deployment + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: module-controller + namespace: default + labels: + app: module-controller + virtual-kubelet.koupleless.io/kubelet-proxy-service: "true" # Necessary, indicates that this Service is used for Kubelet Proxy +spec: + selector: + app: module-controller + ports: + - name: httptunnel # If HTTP tunneling is not enabled, please remove this port + port: 7777 + targetPort: 7777 + - name: kubelet-proxy # Kubelet Proxy port + port: 10250 + type: ClusterIP +``` + +3. Modify the ENV configuration of ModuleController + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: module-controller +spec: + replicas: 1 + selector: + matchLabels: + app: module-controller + template: + metadata: + labels: + app: module-controller + spec: + serviceAccountName: virtual-kubelet + volumes: + - name: tls-certs + secret: + secretName: virtual-kubelet-tls # Necessary, mount the TLS certificate generated by cert-manager + containers: + - name: module-controller + image: serverless-registry.cn-shanghai.cr.aliyuncs.com/opensource/release/module-controller-v2: # Please replace with the actual version number, e.g., v2.1.4 + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: "1000m" + memory: "400Mi" + ports: + - name: httptunnel # If HTTP tunneling is not enabled, please remove this port + containerPort: 7777 + - name: kubelet-proxy # Kubelet Proxy port + containerPort: 10250 + env: + - name: ENABLE_HTTP_TUNNEL + value: "true" + - name: NAMESPACE # Necessary, the namespace where ModuleController is deployed + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: KUBELET_PROXY_ENABLED # Necessary, enable Kubelet Proxy + value: "true" + volumeMounts: # Necessary, mount the TLS certificate generated by cert-manager + - name: tls-certs + mountPath: /etc/virtual-kubelet/tls + readOnly: true +``` + +## Verify Kubelet Proxy + +Assume that a module named `biz1-web-single-host` has been deployed and the Module Controller has enabled the Kubelet +Proxy. + +``` +NAME READY STATUS RESTARTS AGE +base-76d79d8599-f64jt 1/1 Running 0 13d +biz1-web-single-host-786dfc476f-qsp7q 1/1 Running 0 7m40s +module-controller-59f7bb765-8w84l 1/1 Running 0 13d +``` + +At this point, you can directly access the module's logs using the kubectl command: + +```bash +kubectl logs --tail=50 biz1-web-single-host-786dfc476f-qsp7q +``` + +It is expected to see normal log output. If an error occurs, it may indicate that the Kubelet Proxy is not properly +configured or not enabled. diff --git a/content/en/docs/tutorials/module-operation-v2/module-controller-deployment.md b/content/en/docs/tutorials/module-operation-v2/module-controller-deployment.md index 887ceab0..18a5e8d0 100644 --- a/content/en/docs/tutorials/module-operation-v2/module-controller-deployment.md +++ b/content/en/docs/tutorials/module-operation-v2/module-controller-deployment.md @@ -73,6 +73,13 @@ Below are some configurable environment variables and their explanations: - **CLIENT_ID** - Meaning: Optional, Module Controller instance ID. need to be unique in one env, will generate a random UUID in default. +- **KUBELET_PROXY_ENABLED** + - Meaning: Flag to enable Kubelet proxy. If `true`, the Kubelet proxy will be enabled. For prerequisites to enable, + please refer to documentation [here](/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy/). + +- **KUBELET_PROXY_PORT** + - Meaning: Port for Kubelet proxy. Default is 10250. + ### Documentation Reference -For detailed structure and implementation, refer to the [documentation](/docs/contribution-guidelines/module-controller-v2/architecture/). \ No newline at end of file +For detailed structure and implementation, refer to the [documentation](/docs/contribution-guidelines/module-controller-v2/architecture/). diff --git a/content/zh-cn/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md b/content/zh-cn/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md new file mode 100644 index 00000000..0ad84b33 --- /dev/null +++ b/content/zh-cn/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy.md @@ -0,0 +1,27 @@ +--- +title: 6.6.4 Kubelet 代理 +date: 2025-08-22T13:00:03+08:00 +description: Koupleless Module Controller V2 Kubelet 代理 +weight: 930 +--- + +## Kubelet 代理 + +Kubelet 代理是 Module Controller V2 在 K8s 侧的增强功能,它允许用户通过 ``kubectl`` 工具直接与 Module Controller V2 +交互,提供类似于 K8s 原生 Kubelet 的操作体验。 + +
+ +

logs 命令示意图

+
+ +## 迭代计划 + +适配分两阶段进行: + +- [x] 使用 proxy 代理方案,为部署在 Pod 基座中的模块提供 logs 能力 -> **已完成** +- [ ] 在保证语义的前提下,通过 tunnel 或 arklet 实现 logs 能力,完成平滑切换 -> **规划中** + +## 注意事项 + +当前仅实现了 logs 能力,且基座必须部署在 K8s 集群中。 diff --git a/content/zh-cn/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md b/content/zh-cn/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md new file mode 100644 index 00000000..fa2786e0 --- /dev/null +++ b/content/zh-cn/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy.md @@ -0,0 +1,185 @@ +--- +title: 5.7 启用 Kubelet 代理 +date: 2025-08-22T13:00:03+08:00 +description: Koupleless Module Controller V2 Kubelet 代理的启用方式 +weight: 1100 +--- + +## Kubelet 代理 + +Kubelet 代理是 Module Controller V2 在 K8s 侧的增强功能,它允许用户通过 ``kubectl`` 工具直接与 Module Controller V2 交互, +提供类似于 K8s 原生 Kubelet 的操作体验。 + +设计请参考[文档](/docs/contribution-guidelines/module-controller-v2/virtual-kubelet-proxy) + +## 启用 Kubelet 代理 + +0. 部署 cert-manager 管理证书的生成与轮换 + cert-manager 是一个 Kubernetes 插件,用于自动化管理和轮换 TLS 证书。它可以帮助我们生成和管理用于 Kubelet 代理的 TLS 证书。 + 请参考 [cert-manager 文档](https://cert-manager.io/docs/installation/) 进行安装。 + 这里给出一个简单的安装示例(v1.18.2): + +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml +``` + +部署成功后,我们部署相应的 Issuer 以及 Certificate: + +- 创建 Issuer + +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: virtual-kubelet-issuer +spec: + selfSigned: {} +``` + +- 创建 Cert + +```yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: virtual-kubelet-cert +spec: + secretName: virtual-kubelet-tls # 证书存储的 Secret 名称,后续我们将会在 ModuleController 中使用 + duration: 2160h # 90天 + renewBefore: 360h # 15天前续期 + issuerRef: + name: virtual-kubelet-issuer # 上一步创建的 Issuer + kind: ClusterIssuer + commonName: koupleless-virtual-kubelet # 公共名称 + usages: + - server auth + - digital signature + - key encipherment +``` + +创建完毕后,可以通过以下命令查看证书密钥是否生成成功: + +```bash +kubectl get secret virtual-kubelet-tls +``` + +如果输出类似以下内容,说明证书生成成功: + +``` +NAME TYPE DATA AGE +virtual-kubelet-tls kubernetes.io/tls 3 1m +``` + +1. 为 Role 增加 `pods/log` 权限 + +```yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: virtual-kubelet-role +rules: + - apiGroups: [""] # "" indicates the core API group + resources: ["pods" , "pods/status", "pods/spec","nodes", "nodes/status", "events", "pods/log"] + verbs: ["get", "watch", "list", "update", "patch", "create", "delete"] + - apiGroups: [ "apps" ] + resources: [ "deployments", "deployments/status", "deployments/spec", "daemonSets", "daemonSets/status", "daemonSets/spec" ] + verbs: [ "get", "watch", "list" ] + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets", "services"] + verbs: ["get", "watch", "list"] + - apiGroups: ["coordination.k8s.io"] # "" indicates the core API group + resources: ["leases"] + verbs: ["get", "watch", "list", "update", "patch", "create", "delete"] +``` + +2. 为 ModuleController 部署创建 Service + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: module-controller + namespace: default + labels: + app: module-controller + virtual-kubelet.koupleless.io/kubelet-proxy-service: "true" # 必须,用于标识这是 Kubelet 的代理 Service +spec: + selector: + app: module-controller + ports: + - name: httptunnel # 运维 HTTP 管道端口,如果启用了 MQTT 管道,请将此端口删除 + port: 7777 + targetPort: 7777 + - name: kubelet-proxy # Kubelet 代理端口,与 ModuleController ENV 中的 KUBELET_PROXY_PORT 保持一致 + port: 10250 + type: ClusterIP +``` + +3. 修改 ModuleController 的 ENV 配置 + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: module-controller +spec: + replicas: 1 + selector: + matchLabels: + app: module-controller + template: + metadata: + labels: + app: module-controller + spec: + serviceAccountName: virtual-kubelet + volumes: + - name: tls-certs + secret: + secretName: virtual-kubelet-tls # 必须,挂载前面创建的 TLS 证书 + containers: + - name: module-controller + image: serverless-registry.cn-shanghai.cr.aliyuncs.com/opensource/release/module-controller-v2:<版本号> + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: "1000m" + memory: "400Mi" + ports: + - name: httptunnel # 如果未启用 HTTP 管道,请将此端口删除 + containerPort: 7777 + - name: kubelet-proxy # Kubelet 代理端口 + containerPort: 10250 + env: + - name: ENABLE_HTTP_TUNNEL + value: "true" + - name: NAMESPACE # 必须,用于标识 ModuleController Pod 所在的命名空间 + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: KUBELET_PROXY_ENABLED # 必须,启用 Kubelet 代理 + value: "true" + volumeMounts: # 必须,挂载 TLS 证书 + - name: tls-certs + mountPath: /etc/virtual-kubelet/tls + readOnly: true +``` + +## 验证 Kubelet 代理 + +假设目前已部署了名为 `biz1-web-single-host` 的模块,并且 Module Controller 启用了 Kubelet 代理。 + +``` +NAME READY STATUS RESTARTS AGE +base-76d79d8599-f64jt 1/1 Running 0 13d +biz1-web-single-host-786dfc476f-qsp7q 1/1 Running 0 7m40s +module-controller-59f7bb765-8w84l 1/1 Running 0 13d +``` + +此时,通过 kubectl 命令可以直接访问模块的日志: + +```bash +kubectl logs --tail=50 biz1-web-single-host-786dfc476f-qsp7q +``` + +期望会有正常的日志输出,如果报错,则可能是 Kubelet 代理未正确配置或未启用。 diff --git a/content/zh-cn/docs/tutorials/module-operation-v2/module-controller-deployment.md b/content/zh-cn/docs/tutorials/module-operation-v2/module-controller-deployment.md index 1a030e3f..9cb3d875 100644 --- a/content/zh-cn/docs/tutorials/module-operation-v2/module-controller-deployment.md +++ b/content/zh-cn/docs/tutorials/module-operation-v2/module-controller-deployment.md @@ -73,6 +73,13 @@ weight: 800 - **CLIENT_ID** - 含义: 可选配置,Module Controller 实例ID,需保证同环境中全局唯一,默认情况下会生成随机UUID +- **KUBELET_PROXY_ENABLED** +- 含义: Kubelet 代理启用标志,若为 `true`,将启用 kubelet + 代理。启用方式,请参考[文档](/docs/tutorials/module-operation-v2/enable-virtual-kubelet-proxy/)。 + +- **KUBELET_PROXY_PORT** +- 含义: Kubelet 代理端口,当 KUBELET_PROXY_ENABLED 设置为 `true` 时生效,默认值为 10250。 + ### 文档参考 具体的结构和实现介绍请参考[文档](/docs/contribution-guidelines/module-controller-v2/architecture/) diff --git a/static/img/module-controller-v2/kubelet_proxy_sequence_diagram.png b/static/img/module-controller-v2/kubelet_proxy_sequence_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..b995ce1734e89269fcb30a4fca8a3821ac1fda29 GIT binary patch literal 28541 zcmeFZcU)6jw=Rsh1-FQ7ML|G8MFmBQ66p{d!9o=f=?F^iy(Y2|5Tu9*NR1FW0@9_U zh;$+)v=Dj?gdmUv5|Vr?SYF?A&i(Fpf4}dPd+z-+Yptv`*Bo<=@r-9YV}@y}tFRy7 zJ;21o#D3@Yt@}(&f0!^a?cKYd88~t@2ExI_varCR5J3#X4xZS6lpBhg7oh zh;9Da+`qYs?>X~c)e=azPu;w8vaB+%N?*9JZF)34+@iRqr<90O+}Mzxz;}(g;oXp9 z@^GI3!Yfi5J~2_!%2H{95-=f){I)t<%fE+-Y50Tj$UY{f_g6CxGci52{)36>6fbZ% z)6*jZ{r_tULd~kD*rTEg8}~v!K|I zD&C9*Q*(tBqKDg4RQbO1nKluGeUw|6+uq{HyRR!k@aWblUK}*v*WKjfI9l92-DOgg zo994}{*~lMI`XmVGL9f%<++{P>m=oT)yGVXyMAu$<62u04V7$qxw(CKP4nOpgtfau zMsHkoRpVW8(7Bq?zKfjdBa)-wis4Aa?ki~^w5S`~`=I#uEg^>lfSZ?Y&DcR_md`W3 z8oeuP*?aXiHa3NacdVb(D3RSM^U!%|QlAykt^#(?+E7HfJ?KlPI5;mxm?!)<5oJId)lVV9se|YVzxVnUs0NfWhHNtN|3a zm)>gDP0UgeQDh73=29Ya>Uz2Ey~xwSLUFeFVTH$&9rPr(VqTco<)9jAqRzLN84509 zF}MN0e)HSnC)S>rd=D_Wm+GB-u&jl>oVN8G(kjSnoajeY2ESQ6OQnP=KZ?%G^DJD= z&`7Yilnlxt8YbVB@d4#`ToCQCFZpP4^~nfwyOb6k(T$B#1{T%+ed9YvF0Mmp@-}CA z*- zl?3i>pI+fSQssTia5<48TQ=?B6b|0ROT4{WlgNqQ#C>lwe+(ITv5RaS&le`PhC^o z>iqDJm1tUPYTD}a@r2H>ahOz#W@U8Lj#`#3OM0nL@>s;B2M*x+oB_fPf(lc~=xu{P zin{fEv=Bs@ndDBeuQv#bwad;8y?H&pwML3Yk%>i0l!AlLe_R=-eY4JzRzx+gRFGvr zQm+(*e|#Wd=VP%c*r^svO#)ZPpbBDBLkH2D8x4BGcQSl|OUWw=6mio6R=8>iy=h~c z914UAh6^aJc1Fu;8v5zdTMpE21vwHg2K}j4aPYlHR=OXcPrF_3BrF zUNX+?kZQ*+o=dXwLHQ4OkO${(dz*mdoQ2a&y`3zh+>3o|zxEm4L^R6WLd+bFEb6MK z>Kbr6EArTe%PvibOX&^cw6!;q!7_S6PyV{-m#^0~bdtiU+^9-kS;L>%_B@~SMDP2; zRN8V#7{5?|8)VzzUn$p@ZYJS-bp5)ZB;n%RGqcLRS}!e(i29e8#NuQWSYHhClr17Q(qRhQfQVun>sJL>$rOty%}@n1dEdj z*6PU^6{%I@Hhx6vkNVi`7gUiS+ALa5crV^YUhs{Z)~E~6s1Op&k~gw{&$ra02aewP zh>$cO>fPS8bQ=Bidy&woEED>DRfHDN=H>O^sAGi5AzMk`gJ(v>t0>Mr;*)v2mxTV1 zj7xLO95$m^=8&fPfN0$lcd(9grVIMAdf;F_Pj-jRec2=GDu@^CEoE#~#c_?@^(AYP z1S0FtsU+Sn5|H9{zhan=25;RUz#HDjO6^#z)lbFJw^|!30`iknb#Q#}?M029qI~ek zb`nqDt!Z2uv(p)5dUTe~^9wF<_F`%#*cKA^jFiOa&Fv&#ooQ>kl_o7LB! z4TF=*GjmyC>(;PNPn^mN(1b{RF3&;j(@QDXbk%8Ui-Hpk2fvV7Sp6 zwX^rM9^|*X{9nxSpN#af036&%sG|2U5c7JenP`vt#K@gX$V(~0YlMFSxeX)=Z2*AQ z@SO&{Nby0(hB8jC-=J;^bLiD8Yeh+cUIQT+y>|!;k!3F?FP)+PU77Fc+0mn(0=AdX z2rMoK)`$3B{N3b0uZ~K_b=*;9%aeH83bMt`prRD~v`l-xnD@kuz~UI@P+iHjq8Q-9 z`3x;Hk39+0YfJ}Dm_1?{XFn1-t=aU~8)nvrZvwr7ZXsljO8k-Cw1>-b5_76o_|U$C zfft;g2J?7J-v))>+;h|H|IELwq!o8ehCLNb{xMI?>ZhcZYYu!!jPS%ky|n5j{4*Sj zclru^^d`t2Dl2Jnu*4a^`FoU9@42N=ezCNga`H7ry-m}46;pI$-;3HI6i2_?kOzN; zEO);Mmyk&H@oc0SR8-C0AHp5^N-YxpZbfsfx;e%Jt0#9c??oAT`X^DIih=GyJsVe0t6!>FvH3czJ9DHVj^xcgrMeWXb;OC9 zsdhP#hLlfsw>sgARfbO92Rjg-orD<-bQ-a;Tj{JXL6uc!5}eU{IK}U65rm5m051ubWAw^mJr=`yGJ4NNsRC%P05oxE(2ZNh{fmEJ&y&!lCtHE__FpE-r$paTypqvIl)*a3)EDHzu1++c z`AjOoQm9JbF2e#-<98Ls=Yw0ua3Z?}az8>|9goF(R*=`~7akSw|8x6WG577NF^5N+ z^{)+c+j?z{}#10?UhIs@VlRKJtD==etL&+B<3?l(eZboV|SN zJEXmv1Vw{XNs*Rl?^HXP>rO`>E5PN*k8L)(QkFu~(iGD?Uh<_BuQUg$(JqXC+Ek3c z8KeSjw%vM!%ziC{%12LX~(F6?o^|M#5lgk}mS*jpkBe0(I^@ks*B^FRVe8-HGV)b1uo@khxd5 z+MY9-RlYQ0XJO=+=e@txJaw!{KK^mgvN9g~tv)Jpgzc&pF3gzAyYFVIL-lPJ!J*;d z^oN1iNKw5>rsLky){l#t?}{2VarV!-$Agt-G$K?DRgTf$KC$iGHUcm4L|zW6{cFTX zmi~D(z1NyPFgas&XW8OQ+rr27D(zKW^o9jzukiLYV`ym3Xw__6#FwC6YaOS2Aoi-S zO6%5JSLJ<+jWZSUS>+wubI$-{dbXfwfsI1v!i)G(bgimn1F zKKU{RGvVYJVXf2iq;o$A1#7n+z!VEh`2|{od`->mSCyb|JL<8%eK{Qwqbw1#CU*l$ z*Xv#j6eU{gh> ztEzs((^lptlnP=c`&OyB6pDWdjNj{_-D~~cSrXlF8+7r8a`BtmDsjCNp;v^?{+X_J z!9%3<^DsEOqY6AW+1A|aby;D_=L4_2zAnA3b`{_0(V5`n^M3aBWV?9!N^l3v4&(ut z8=HE`V3LW?it&yIKKUA}>=|++KR!P?R{WvETBo~Z<4K6P4)Q4p%&{=Y+VaM{aCKzU z*qwu8%#zc1^bVaiHF+Mnr`Ot2r~uyic$g1@Ak(^TmsqtDr+afpn|B(tw;@TX$TQkR z_5&Dmi&{CETT4+_!5lZtYLFv-aPZN&tD5sAJ5MiVL%;oed%{lC!ttVlr^&KUhR9*A z+!y=e)fYL!AhB*Ev;ZH=9YrigESk$$YKmcjz@UURgwr+BY$cMx`65E6qU)o~7Am`WwI_qwXNz zv*5dP2As%jam4`PTY^lkfWN3ooA`Djh1O3C%ie6TE#B<;{v-Ttt zo8+#~2xSgwIx5rj>0lk-S>BfPr>7+V7bgMuYfu-Sgqz`d8cfJbF$o%nbD+u^aA zfQ2k^Xtmg6O{${8@}-179&|Wa{|L?oRVo60b;z3*IQu|XQ8N#0xY!T39tIKdTqdR} z?NyVmiazzUCZ+So>}2#Br1~`qJFK4kIEtz;BJOoQy9)>g^O1^oD5Lbv1^U)944YNw zH_;)=B;BeX1Kr_-`&0QQjFeEKZ(r_-f6M?0)^T6JcS%bm>Y}Otauv=Ib{b|r;s5TC zV`-5Nn7XqtL5uQI7uEcA`v(^&N;R2^6bxtYqJ5mJd=q=ju@$`r@_Ow!HO)29Rr$N^ zGI}o(ICJaNAPDUWcIk&EMGk&=ienDjYZ2xj<9v_@m!5MFPl2^JtIX5>#UwR@$1%Sr+K%W%>~X%I{JmE;zaM=8he5zBxNLTFIeEC~^P&x!b%f z`_C5-pFNuO`_pVzI%|$Gu-rij}g(yU{qKV$hX`KC(D_c|dWzKM057C4l{{I%@7$4;!=Jtk`-2S&>3%>$Z zx#PmPyldlr^IVadU$;_r2CTUvzud!LqyIWhr*L##hDV_%f52ub|9s$bGHzxchBjn2oJxEulB z4-Z}4TNc7;ZlI6ZYNp7+VrY!SdESzz3?ei^xIx%r zMjwuRc+HsS2{@2P`#U;bus#%iPR&0b-H9)jL;I;YbSfRK^1Ep4jqe@GPZRP~2IWgv zG-{yUp~_c!bn6T5a7M~xlP`+=_7s)-nXm7|4T+u7y;)KB7sjsUGwX6Y<(p}r%bHeB z_8#2iKAqmsj^`LCdG^n5sB#~IxJ$oK`%z`-mFI2HUGCh<{!1fu z)_wVfgsM1}+7f&_9ALe#1-Qgh|FBdI+Xeb5f*0t@n&+Y+oTfzqjv(7BT?=XNDz9v@ z)P*UW=XJ5r;Z6+nGK{$JeI>XlSWM+aL(1s+3p>`Y{S9w64&MUt?jW+M=2TYfIyd9? z9x*)LRV}}!eE_;)=&5J5X3S>nISO8J9eDVzqwSMg_M{;V%1+V&Vd1u;lbyAlu=KOM zE;(6P-MesP6!PLtrtO@dvDYQ{srMDBIUj!Svw> z;kF_0&)rkE9Wf34R&ST)iHDnF2Ab^w?yB9Tkis9W&vo1&Yzh1@HFZ)3&XiEYUREG)T z-ew_j>?wtS1Fj_3!IA_G7>YsrZE$;))lY zh^7nU2S955MISKRO|b-yIbpT$Z)&~>ljO!pI$@~26K(QW)%wdtoCJ2(`v1ixR=7~l z+FIZW^aDrMr##yd|8TI(oV&?p^Wu<19ocln6TIGCSLM(UvS%`5JqGlr@)Gl0_#fwY zgKS8QIG(m#TSokPlS0Q-RZ-1}b>euI54r9~yKiXKT>CZsi!fsWhRc;G<_D|X{QZpg zW=ZRExKd`SsFCBIr#_PDxeuaCe$C$FSql$~Zj~jbs7!v#PUw%Jbybt1#>AOr(tI<2 z+46Rk<3xKy+3HGqvNBVvrDer`K&=0F^REAdV|pwVHnONKG^1XQd%uGn5iQo_%=#Ug zd7@9oVQJ-nKNF}w%p$R`=kCDAd4_M@TA5nSBX>CP^Fu(>*%H5DC6UX|Ay)hWg*BdV z8UKdUye`^6lCij!9-geuAP`dco{;=Kl*jQ_hmj9XimyU1y?`ve>PD*ZJ%gXWuBN~? zl+nQT%OY=>7eaW(&^AgkRY-8GS7eev5(se8Z}s0r>Ecqe$QOE_FYB4U`Ds@GkGb^^ zXf3p0mP5eNG(*HfM^pdUbzk#@&-vsF0=YBUx#AP0@TQ+cN3~CWc^RF#=3*CU;+8ax z-9wqSpYbQ*2izD$i4Sd(P^nOAox7jS~V?iPcM zZqK4GD9`j-ukQ80aWsoQhZr?t`#@`sFLvDs041gS*Z7X|Cq_X=s=RaVucH+6R6t8vj)!X=|H+igUssoOu zF^-o5$D2;?qowC4J@90fz>iUsZQSs}QoX`aHRherQ%|>Risnrl$cvEz0bY3SK%m+&Z|?AHE+(@t!zxSArDnR_M!%cWX#Ly}3o@1b z(AXMq`X1Hs0Dtx*&?-IGi0P@@lL?iCDuGel>RfVt+Kfhdzn$S!jscz3NcKfk4zg+D8sBhHlAkhj~RnF4g#MF7_g_J&t=rJ;=cbcp2Mc%pz<%K*&G> z5ZsmiqUIs+N|FBT%{j2?g&H`x22E{~j$I&j4@oe5fL4Ot2*)21x|2?@R(S@xuQeT> zV`l0)PFY`t(*h?pL?>t=6BJ5=TNR}lOhB$%1^9S9{xxYE`)Fk8hV2>n)@&Culj_nH zWMJVK^P}fLDy7FrrB1X1FnN3-ZDVxg(;V0So1kz+(Qv82{%gP~+I{X68B&de?-5*T^Ii0 zSaPvHIS{8 ziEE!m}q}+#s)Wb-deSSl;%ChwnSC7m#ibznK2d=LW1ktO&i| zF11qIC9R`p-=F=e{`c}=*PGB(3(jdJUP79M|Xr+_i6q8$Q-FbDz95cyrv_Pkye9`geP6!f7i9Ou+Q_@0; z)*Xq(_!a1JReuuOklTdq5qN-D0b1SfUgiY4cSVcOGVJ54C1kVU*L@)ZwVzkxC@+;$ z4U*1X#GDodpB+3=w24|cc8?$blw{RtsEFGsW>DjwE-#a@p zxm}xpyH*&Pw2g~$?=xKptQD}~>NfPVvc#Ud4@6ozcH2>4Jt{n?zw!|X3+0C(&RY?2 zXMh6oV)J=k(LAMj03GDze$S+$A8%Gd4oCLYLh}6YrnXWnjYqn!@C zA+hQbujpI3&pE$8=sZ0I)qaXMQX#o5XCU#6Wci^s|2l&D?fX7Y&Zjvd404YkoR z6U`Sa=?NqCQ(UeXqsBJb=FKZyw>V%k{k@A<@YY0+jj{>I1Z~C{bNP-1Hn7)vx^A<_ z_$jL%yb3@IIy&Fe>++n^O)$DjE6cW9>T&0|zOtwL|#V&*=C@ZDqy~;TDfqQa8a)0(hL{}{6lBxjlp}n{-Lb~eZk@0 zrq}lB>qRagB0%@03;nGejN?e)oEpx=YYht92TS48C;G`A;?G6Kv&1rvdiv zLjL#lQ2iP^e#1q6**6Tr;RthU7e&kfQ21*%ub9tYyM&(6ARB?6y4Zc1SMfccmpbCg zZ%Fr_(DZ)}EBLQ6g&Q>nDm`FzeuVjp zytDwO6TRx(Yy*Ej>+{P10plSP--X7_9D2JrHMqpuz4C7LNhZt3dzXIa2!G^jH|a0r z9K;&}NP-gziqy|u(aHc@$l-jQk#&+9@SZilr@_>*DkQZDzdZ%3qfd?GS!dcLWg9=L z1;7+Q4{9ZS&j~(%rCU0p!Ss)qWF>9-R+kr^ww@D$v`xyk(Hs9kCI0iZbPrMwrqPqs z6-{fYf}&T|VACovB7F8mZotzQ?Lev>u$ULkU=ojfXA+KQH-x0y&IsggTs_Fd9T%N> zNBAzcu-@74R=BJR^C2zifY#?Qz{#i#ea6Y3p#M0vc)8i2dLPp~YG%RupUy-p5xtFj zL(9v8JAq`_>HJX?_VPbW+Xa1BrM|kGcujK*}ekaKy!87i*c;+OkZj zJ~R|xL3VWF#ktd5md<`vO)5xnn}o!NLr^Yl96jlW{Kd2Qcp|Z8vE^(g{Q98$Lp?3y zf_k}1p@6S4_C7oPCx0DvX8HBS9 z9ojBTe_qR~Z3*Gifaf11#D?KX@SzF_pr*;4vtDNxzFQN z9=u~PpLjMBqRhe<2PFMc7qaBP*4>T0%<^$P3^Ua$jA_60Y#`L}{alH>sD_wN|%4cNUS?zLcjV2^giD!}DDjBY=h7p#^oW zIhS0OXzzoq2v3P!c=-Sd3Q10qbqTV5eXD;bxJL0(j~2itT$(7&B!2~%miTDicL_fp zY=y=l;TXEpRb??c<{o+@*fG&wUJ&kCfX>R$k_^I+0vzkg_U%rD7QN3+d&3RUOKUsm zw6b|90y1Z~8s9bHH`Egi2}-at$#5db+d7F=IN1_Evx5VM+@n&TSLO_#>s@5Y;|Ksg z|Lxq5zCYH2z3sS0tAGS=jgdgMVRy99nXSuxFTdYxkc1yO%yUCu&C2N3bfj?1%(U6o0rXUl-Uvt;_4 zR4>jk^K7(}5d9@8!k*Hc%99y0pBH95p#B+V@6G}?Iv)w~)2<2tUZmx;?Frt z$R$aBG)s7u6g264-))jf{)c36vS{qd;T8K z8(4DQDPD>_eGz?%EmuPgnA3}*y8@auJ88L_Cqoj&;%DzkEk`LPgFWbu#G0T;p^tgS zm&2~AuC>Wuyc9Qzd%0I28iHxAtlzok1umU1Bb%t# zq-a-|lH;&on|YpcrDu;d0#@5&j0?wy3YL_Pnzn0J%%0bE6CNEDg$pFke+DXOL{x43 zxH~U@{8SmrV1{pY7#phvxQ(`^k9T)XZV_I0N7pv#Lqc20Z%UsO%XlOIp2((rKkfCk z3WkE>u+(=!&_(f-G-&?f*>_g0bQf;6@8XL8GKJEA1&Ma6xgUPOBE{K3+{%=`RrT4^ z0FVBi8ko%eo%r7mz!pRi`X}uGkO}02Ak3K30S(}|*eGy(@+C9k{lJ_7aqphj`_h6lT=y{b!~viP)!^<$YBp_?r+6{| zk@;Vd)481$E3C}7+5ACAQH4f_8C-jf6P&s+v7Mkqo}i*?VYtTa&rWklRN>emfRlB} z)!qM2Y>flDwM3KNc(@$@4yHbYLZ|@zk))yxB^0)i&{#>wQw%^RXY-=Sk@TS%C573JG(UOsS$fyl6~ zqLe_U>;pTD>PHS758iJo#+WsrJg_9Nr8u#UbK0tJ#LLrB7&!DYtS`YU^dB^p>0~i% zCK*f%)9AUx)bv_x=wBfKkLDW8pcrFz(eSElF{4HhD8YDKIOB1^sc#Vh?;JC? zg^j%#P8zGT>nd*htv<={^8A3sHJ%%0eBv972J6CvyJpub^{b z+X<%f`E65`>FlL``Eq2E71Tm$qoRK(4Z1j$0gkY0&@ufxCr5nML{GtwQ?YhpL{H59 zJ^-=sYhj6;^`u3+1ldCghRa4OqbpZ^iRbH6$w`b*kV3Xn2FMXl$pdw80X>}gM$eys z^cs7vPm0?WlEN2BEL)pt2)6SKd*gx=D?w)Ts%fSMzexQslPC7vPQY7#K$d_E2R!@A zC|h0P)ik9cqRwR-Inh}Wb#-ZOfEh~TcAE9y=*=BB%dEDsq~RtWX7uh8)eK|J{}Rtv zA~XbEE3I?G!jEY+{WVPB@|KisxSg_?B8@RJyCL-)BGjF^&0N+#Vy`)Ir?x9b|HVen zB>OpD=ZcEU%Y+6f)Aeb0Erqk1Uc{} zdLM&(-iznK%&Wr6;A+d$clje2FAHbF{&S=*0$F)Q|yiT&<2kz z?M6y)^D%^rjeX$Q`tDheoI@72-nW;ZU}ZO@LsQiz?F}dw2`5Mkrnt0WJgjtKrhme+ zHEqkjYHU;Y^6(94{W+w%5nuCAH==jzLT6OF4RkRi!M(O(<4V_7)TB#G<^FN+^s?%HVeP2Qd%NuwpM`zKaIcpeI#eJVhs!6ybU8{cBz8QUUzUwQKf{d z$rp8f%XLMfV)redm!Yv%&n+Xww4DgaES6H`j_CCUqxSbZF*qsE`)|bSUsDG&WAg1B+4p?Bbg`pBj+{rv)`mH(8?KF4UR*%1RbBYn_GA=d_ny_rJc=tg3%C*GHh(g(!8e9>3iAQgl8WT zuf(HmeEXL0TLtc%%h&0f{+qXZh4m-hZS^E$4Lj$f+Ak5$0F>D4Cx72U>^sCQ5NuT3&i9BC??|}-y zS`8UaA|#g{LnYG`lRS`#=sC_($L$dx+gj&ZiS(z?>^prLj|TZm{i`!XuERP`HiL)M)r)jwA( z$NNNH()BDlR%tkE$O}X#<)!o%&{1tUb#XRmoEwj5*o)FfmQtt4OyIIrTPIJ z4YQgDT~&Iuhp1gJTN}pew)(h*`ne$W&X9mNpMtL4ydi@hl#KmELs8<@d%~sVFXyS{ zgyC3PKdJiurT&6XiIWdLHhPC_Nn&%ab+HDGf>V^9I4atG;vYp^rlOaLs2}>s`QBE3 z{KnUZ@`i7X*q(}LMFX|kAHoy>h|34CBsn??>^X5qu?uj#-?bkRZg}pj?s~ze7P+m% zKbgU2y$flXR3{j57VTM!X_p_T+tPFxOxXXBbwmhc`7Nc^0`&zjtt=r#11R5~Y-;hi zxtIf|@1Q5X_2lgXXzTBil$*o=cU?*w9yTMi-jJDEc%LC%8M#J|D{j~+@@mX6dTSK( ziyzEb9W90;S68LgHDJp_jazecX;_iXoF@~b%==5F_>=7;PausciI^&Si5D$QfEs5? zpQf)5(Ni(2)jK|F{UDqzI+a5~pRO6z_fz{qlXe?|S^_Y5^`k}|ZX$)^oSJQuM4ZG0 z2|#OT=_j&&iFTaki>UJ)E3~nMQC2vWtrl&18(wI@;7ezlt(;QVbeZ0aE12=qN)|2LJ7mlhX$bN`gOQqkcFtZTo)h;A)F4YIuRf<;lE(=gQVK{=LA-;#e4UhFw->Ft`gg&7 z#3l#vRafF1Fy^Z<^Qtays>Yn|}FSU-mD`W={b%Pu*sV_|Q#9Ob>sWNBq4b zuYRS`QP|%C$O|(@ieB?GMgLW>LaZ^4XE2T*y0FI3bC+^H^;sAfznko*Qo)&zr3uk5J8*vm{nYW$Cqv<@Fv;i& z$9D39yD^~RS?rbU*DgoWwqa8UItXuXQ1w5fU^K>QOC z*`A#SnVrFel4|c_K1jfl|;c`26{0#$Q>jX->eJH{- zhBe+LUbgrucEa_Q^=4OsSVb^fUX(5Mh)OhMn@2%0;CnDBc+)B^U)@IVsR%8v_AOpn z8{~E#N)zFd8E`pdQ{ksq*Il3`Pz(ec$LZjwy!` z8YGepWX@KjYGcHFGH)6*l5Tq1JR+0;g87wjamS(<#=EEoCX{6jszpKcGvwQVf|j?A zxCEs!W!j035;2(_D?Gz1x@60-bPR$hK?d{JIQ6$c=la0xW2aDoHHY_#zo>T6JDrgI z^z{2=?Mcqq$`wv|f_r{i3)F2mF<_t&4rd3y8qk=}ug17_!>2ToZCpxYzVVopz^U%< zsq(%Uma;F?7Fr7`2xzN1t6S|fX8-|uh(o8$zmn>!7aM;zaH@yYKRALIs`Qj^QBcAJ zPVpa7cQ3Knej;Hrof+Nupkhq~yhZBFDLrXDK0oHC;4nVFDOC{M8f{zeS4@&tseUYRKneG^5?jxnD4Tuk10g zp)XVt-8FcZSQ!c04m{~n5$cXzJ0#v)=U-YtcGIYQbpArqN=0eFaZJ{xtD3Zo_TBEw zClo3skd|@N0UiZMvs}8dq}}2Ks-01sSP41iy{@;mgKu~O!ulnJ>5+j>wY>XsLIv}x zBLbPVp>r<|RZ6HHw&L3WVs_p1+uE$08&kAMg8jXW%fhtE02t+;Qt=X|)eu`j$VmOppI`n5ocyY`4-a?RTP<{f|S0eM{@ zG3>7SV^={^o48MjST%KqH%@z}G^=bp)A%|FYq;G?_^2N5Ms-7I$-3D4VVR_kM3Qw9 z$4N5cyzC3bcf<+}E0EnZAxeKrY6d}a;1TdLlMa=Nro(jUMm@K$w>-_`!5aqK^%Yb8 za$p%MbAY@IF9z?Je6%ncBB-aAHyp|;mx*94jJRx!1ilbg>GK&{K4-{jjMmJu`b!&# zi@Yv3$KKt0$qFEm_sIs6HkQH*G262??w|CMx6dN?DkF9(){W)VLB7W1f#J<^_CSyP z>T95UJ$qv2*uuOqN%|a1?U0l6;{>9ZbTnL#KWlW;&iE4VRVSa9eB%6(A^HVZeLUid zh%ci|>IE-b?xb14s@3ajS4WSJSeEeV@kL&AsM9df15Jl~&`&tUaRXpsq$`_V>_~7& zW@kqWZJ&LYD0}iW@7(Dedad7Ol}qCWfKjWo-vMRksuV}b`ohh&Sr-u{>8or_n)Y^Wn#;GUM5ns0vn^BIURRB? zwySOQ>krPTy-GMQMzP!mEXl20ledwfMY}QA%$G5mmn^g9s^G(3X2M_tW%rq=Jq^)D zdZrnuI<8-UR&|-V!qr#$d>&EO?jp3Lg4J@o9NySGxB%}!Xbr+0tI5?yP*==UGVi^+ zsAhNKh(>T||2Ok>x&0{wr1r+vN>;zc@XlCT_taFki7-&cT+M`U7+74+MvpEMzBYUv z=1Cl}^yI+{9CB=oFvTSnC}wKw;opNXt`!A>#c8cAo`uA_$HyP=${x)L>W(^5RkGpw z%^IZNHdHX$+7EbbNdEIUKvpo^ePKu_W zwX+H$AwrnfMK(bIpJRA=fxq1LfwX_VB5!lTBD^EYL|R)weT>wKt0)%gJl85Qa>Lg- zU&G2nv@x%*LJtqkOc}6z73(c0^Hk8u_ITuZsSnZ$@4FpU>jzaMM!@#-WMiw+m??0Y ztOPHCqt=t|hyrs(oVfZdc{y*S&qE3woQO-_iePSp z(}(WyN}uL^0#o^*g|*NJzJCv{y?VQPxc`#-Ec|MO5?lM(O#1KC2epLOXvC9XLwFh4 z?RtTo?j4?B4rdpupoLcOxAvjNZ{2g+7-p8?!o%Ntg8_0^S@nwTJEyT0OlQFMF4gdum+enY!9o`WPif zuX>8&+;5FVK*_OBX=4zE13In9OF+ADBlv|sPi4@|%GJWg?L4!Wyh4&<}Aa}3)w{&Bx zqpV)AP3am|@Hb2&6+t&$e~jtCF-ZstK+r^>k0JhdG6txH!bfm4OVZ@(^7tV1+)cDU z``#wyCwrG{j)ea+!!sU0wxhSN8q%9c^f)j@MP0pt)Yt>xWXQ?l|NoMcMF4U#`~S1$ zWdFP=N{UFiUqemWYVzKu6Abo+Yi3vOvT#6@4ZH9*VhJv?A8IE7g&*+7+QD1p{$}=r6ehaOpBAaQJ+G@hKQuh@J z9f@daT12q4j8Q-sK;Xo4y!ft9lF_q1!;9j{ZWIMNtVYEjOf1;Eg7lmI5k1l!-z!`# zuHz)puETku;LejL1|t0N;s>}N7zYD>xSjRnccpNO2q@+e%eK|9nl;vspxA9pj2kXh8xNi5+}H?qQ$lE(r!rd+0${_ zWi_>sOL+}j0Ikc%6Y}uFk4e1+O4`1L5!^0JE;$~1mxj|!yuWS@Dgpc1a3yUoXtXo~ z{kEU-JAsWaMFpGxVxVfE&FxrH_?c$f_51l}I`+MSkO4`3@k8&-2ngni@$@M89aNp( zt3|J_#im<-E$t{VCU?4ltbfPxX&%YsKSO-hJd>D>W^vRJNM$;U%=jDzqaG4HlfJhpt7#5!{Yup z{kuZP4h3B@n(%)RxrMc>|8183%kJ3opVINginE%awl&tF6*r^s^vIn=Z9xY{BiBFa zaAKnSsAc#GYKiGPnE$F;trrJeflyNO^_K>vgBj@luLjgA9SzZr6XT8OfClQeUZa&4 ziEk-3=l_-cvBCx20m)I@VU)t|lbPlJ^Y$+x8@#;ib|-y<7HUfQ3fnwcTNMW3JM+D# ztELGLM4o>w;Rzxdf;Tud#;8+tnzXtpO}rN7^}5p0<8MZ21^6C=NqoQrjz-#eA1A`h z2sC9x5{-b7^qI)}C?y84C_q12+&&sm?^poZh^y(!#(-$18Um=5of@H}D(Y19d}>3; z=_|kb+wz!U6#4P(r3DI1+=!vd0h)G|sO{iw+{CvvK7J^sie~7vU9nTGZ90B3i6M|G z`Yw=aq(wT>wuF>q%b1w7Yr5RbM1FB^z{VRY>x&lAr0Rvb-KxPS2Js{EgZOEcB$m{~ z%p=^V7^I%^4+RcFjx-)aQ8qjUkV!*78pF7L+a;m=Bw%by_5a;>xl&k8EKY48ZrTi%gKRXluOU~wO3cv9Gf@EpPHn`s1$6DSP7;1ZdS~O3C$NZeS8%Z3AFkKw2BxH z*pOzcT?H$sJ#{;@Qu@4%KgV+OtCP6PD6P9uYXdw>z~)tI(YDjUR5{#g7CH~TIQYSU zkp6Qsk#03r{e%{_4@qJZPGae{HDk#9{!oHyO`2j(Kl%K2L=Hl3XVY!fa%z6A)LIAE z?k<)e)W5P>KR!9j#iiNuDi0Bp?@4(27wV5Uor#8|&R*|cI*7D4v^xgSzb zYG?`XkYSTekB#NFgY8}ZLyk&EIsCef-#${meSXsh)Nxa1>gBLo+m%*N&3PWhD_OJ< zw5(O8VU}!!MWPT`CZo3^S3_fjqbY{bdYtknmxycqz7z;zn$xt~IMv($4ij^1Xw(k? zr{lTb)Dv_Hbz7gFbv>xWQHjUjzuup(SZsj?G&dtwJLGbS9s5U~q?Kygu>#C(KpJAf zDecCBWsj%k`C6G!d@HI)B(IFEh?o}8q`@mKxOY>m*rZ6%3j*3+gM14{K0>u)KQ!aq zso`GuzsqY z=;TMMlJE;qH*|W$Wloa77c1nQHk*uIOtiaV&^cB+Lf}Q8H!68MUvAfO1R07nlj0iY zeuVFE>tEsfth^~d{68)tw+& z$w^q`L9pbAz_?fusQ8LPdfrOj{3Jg5S~9c~k-E~g7Ln;xXjHG>SaDG^#r7}2Gzmi&Yx0|X@=UnxL`~n@wR@DA!vl}gi@C& z2-sSY8eUcvN5+T&8;bHQaVK|)qF(j$oRUu?7;a^m{y*(q`#)6s*GELx;Sjl3Dv^`h zWR#e0XVg;}l29%~VhBT+nUK+ulxuk9HW?kGzGpW4s6FZiaWZ*&pgk*ETN}e z$gp8vQ8>MLJ#Dx*PhWtR1U?GF?`-f-2jV7d>Okp0*p8spH~CRH=3y!MS&7Mg9opGB znB+f*{KYFeil1TGkepqRkto8&x67D_^uLh3v?9Svl=Xes=OO4I)AtCl7fi=zZ)1o9 zAvvVYDR_-$pH5CF5{;wNd>RQ8MWgSC{z4g3r>Ao4WmUs8DuTza&a*IgEQxygi(P36 z9DBIonN;AO6Gu-x&IwhncZPXCK8w@JPE%Kkk%`Y#&+1kmJ>NW*9+~g*rNPER4|N$j z;7VMmbMQ84qN7Bv7lL5~l%hAIVPA>nA-Jt!0_?1nDy;N@DDsYM3T%>M3?0(d$-EHN zIYqQTS9u-c=OH%QrbX=+ zmf=O|{&6tkp6r5Rp(-wB@}A)9v%YS`BY)Xqfk~B9xctZK14vAFfA+Zj?Y<+x-U!so z##mmYASCKJ9F|W(_MA%@={~4@L(`6DlAvtf+6g31U%!(3oO>o@T>5QmKJ*q0`V3Bo zrQc$kr6#D2>b84}S^?HEuRhDH;kw}R0O7)$?VPDWprpUxoOM7+%hP}n=-L_;s9)k$ zVmq!h(-z}ygg)Xz%$2b=Fbv8IM^GhXdM_Jfg!&XLvt#pd-@c7s?W#LYA?3hA4)x#F)SUOij+etY^aufJX9XIL;>(W}Of#|{p{cjUhRf5To?DJJJOMx^e8ev`1m z-BC$9Si51*^IeYCm1MfT9Up0=axgS?a;>gyXAD{M`n_?lo*#* zR^Ea2#a8aIrtFJhVz`G>&4!5B`jw*(B$f6q>8VY?H$xM+YH3Zfw zIhQ@rd>lsP$s?SMC1puI@d7E;qz|W}J+8am;!&WYL9!Vou#W9nYpS)Wb*8lR&_fE+ zQhMj*$q+*v*9deWfGWwoEYb6PnnudoVX9UZC((AaX@N~_+Zr0V$W>^~vYbv7na z!pHWvl7){dI&)i>N!-PJ(U%&X=+EE_>Vg_i;Qa?=Now(LWhJJbyzy-oayh~oUEGW> zs*5L^Vig<~#;ej^8^FzCIwB+x%6|NH87G~h1*a%g8=_4qs}2p~r4KjAqDAPP_jVSbQEwjS2LQ(nPb`Yym-6Z6jH zt)zb`VejWgNnp|c8onY)(1_3Zogr_oI7#AL6LAsC>|s$wXkCcbZsuR5hx>-BYobyt z`H#m5Xj3)GW6+~NCPdU`0s9mj8yyC*2@vVNcJuNW+>P&#IJc*-(uZ;HS25Nnw^hn% zM%+n+eN))5ww$*bD_-M#0bS9o!=7TDR}yb+?Yrki0C2%elXR+W=!g}MG`dXr23>Y#E^dIX(V5%4t(l_<(Fz0 zksW5++@5E3d!;?YuY^#|eo#VaS$h1M5Uop>)>ydMbQaPP(Ib-tqXxM&%UP|?k0*e% z9@_BQ9pHJU8X7vRqD|&r1z3Cgru0KdaPj_0zthPTTdSWFtO_CKu+|#IpflE7??Nnb zi&_%nmY`V|PH4}RalQn1=k4wEQ8tqzu${seC|Y2BCKF{tCAcREwz360Aof8aHduNp?0xP`SdIe}ctHxIE3V=a#k!9r)qG>`r~3H!>>R@C%&Eo^1v zj!(N-5BnAmy44;5t*g^JWF-wbjZpC>i0Th%pxvai{*;k&>nc!5axXQ^G;O47244gn z%c|O3E~>kAKW;XU%!$R0-1;r(j8DcyK*Be}iU!Nx>Q5^x+$cEsY5*Z6U@4Ub$!$Yp zLww7_`S%#zKVbK zdn3v+`#VK`gwZw$VbhyIPr@C{uv;-dF`*qS=Z-!OphGcECjtt~HDJ6zwKvrYSnrbxW=CsO?Rd~Ji!@Kub;sY=~vMRS)|Rc?#B(T7b* zei&5O{>NP8rLH3FK8i<-HMMi0@{9VccwwkGP*3XoD=A47^X}^=<0yE}&ZK*sC%vh? z4)%X(-9>)KM+mnvcGl0^#z9}RZhuD(tTLYp(vw%cESi?qT}Ad&tf0f8{w?CAJLgE4 z43+TSw}LIqzvBOT?jssbJ_#?Ln3PRPd3*`Sq;JqFdk-U~!jtCW)-8uGBjgpyv~v*x zsha-dONgnU5=O5z2+zZsG(;r#AU*~b3Hu)e#Ki6EY!;;w1+wQ>=3ZV8MIm?Z7oGy&`V9;pGPaB1( zImGnNZ{zWa6f5^wTTlrCoHAQKEtpK@ZoU?({{oT~fXUQNXUr8DCbtZGXyo{%`Rx0# zFd`0=S9TW}66*f+o7){2M|qBm_qz!`ng|ZYmre}4f|RG;n|wbs%5F0g9iJY#%^9GTLYFFMkqc5rA>et^0HHXXO@38H|`- zOo|M;QJuHSF^I9`dBo;*{3DopA}OBjHcAhz0`WaYjY%ZUvEml#QDB%dMfM5n-|=O&FJiy)|YAy5cO+ZA)yCN_M& z?qgjSV(;qUoblNF#z=#h;1jlI!o@bPHPO%+ZdZ^G5DR-QHd%*zJDOmwoTxp#BlB$4 zrj!&|p+hj2H5ZYD>&Yz|pBhPlBEVOY*O$uN(=iu+_xH`zi#50BXIG$c2tnQW8`kXn zTig;*>F7A?sLSJ12D?y^O$=sZ+bh+tUuaZ!cphp_+pH>oC#%TFTy{BPN2`<(y) literal 0 HcmV?d00001