From 7258c566856ef02a8df273751ed5cc3144a45ef4 Mon Sep 17 00:00:00 2001 From: Marian Koreniuk Date: Fri, 22 Nov 2024 20:31:47 +0100 Subject: [PATCH] Upgrade proxmox-CCM to 0.5.1 and proxmox-csi-plugin to 0.8.2 --- .../Chart.yaml | 20 ++-- .../README.md | 48 +++++++-- .../README.md.gotmpl | 36 +++++-- .../ci/values.yaml | 10 +- .../proxmox-cloud-controller-manager/icon.png | Bin 0 -> 37885 bytes .../templates/deployment.yaml | 51 ++++++++- .../values.edge.yaml | 10 +- .../values.talos.yaml | 10 +- .../values.yaml | 54 +++++++++- .../charts/proxmox-csi-plugin/Chart.yaml | 25 ++--- .../charts/proxmox-csi-plugin/README.md | 63 ++++++++--- .../proxmox-csi-plugin/README.md.gotmpl | 34 +++++- .../charts/proxmox-csi-plugin/icon.png | Bin 0 -> 37189 bytes .../proxmox-csi-plugin/templates/_storage.tpl | 13 +++ .../templates/controller-deployment.yaml | 23 +++- .../templates/namespace.yaml | 10 ++ .../templates/node-deployment.yaml | 12 +-- .../templates/storageclass.yaml | 27 +++-- .../proxmox-csi-plugin/values.edge.yaml | 5 +- .../proxmox-csi-plugin/values.talos.yaml | 2 + .../charts/proxmox-csi-plugin/values.yaml | 100 ++++++++++++++++-- 21 files changed, 456 insertions(+), 97 deletions(-) create mode 100644 packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/icon.png create mode 100644 packages/system/proxmox-csi/charts/proxmox-csi-plugin/icon.png create mode 100644 packages/system/proxmox-csi/charts/proxmox-csi-plugin/templates/_storage.tpl create mode 100644 packages/system/proxmox-csi/charts/proxmox-csi-plugin/templates/namespace.yaml diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/Chart.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/Chart.yaml index cd2b2ebd..4213926b 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/Chart.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/Chart.yaml @@ -1,24 +1,24 @@ apiVersion: v2 name: proxmox-cloud-controller-manager -description: A Helm chart for Kubernetes +description: Cloud Controller Manager plugin for Proxmox type: application home: https://github.com/sergelogvinov/proxmox-cloud-controller-manager -icon: https://proxmox.com/templates/yoo_nano2/favicon.ico +icon: https://raw.githubusercontent.com/sergelogvinov/proxmox-cloud-controller-manager/main/charts/proxmox-cloud-controller-manager/icon.png sources: -- https://github.com/sergelogvinov/proxmox-cloud-controller-manager + - https://github.com/sergelogvinov/proxmox-cloud-controller-manager keywords: -- ccm + - ccm + - proxmox + - kubernetes maintainers: -- name: sergelogvinov - url: https://github.com/sergelogvinov - + - name: sergelogvinov + url: https://github.com/sergelogvinov # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 - +version: 0.2.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: v0.2.0 +appVersion: v0.5.1 diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md index 94a97015..64e1ef6e 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md @@ -1,8 +1,14 @@ # proxmox-cloud-controller-manager -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.2.0](https://img.shields.io/badge/AppVersion-v0.2.0-informational?style=flat-square) +![Version: 0.2.8](https://img.shields.io/badge/Version-0.2.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.5.1](https://img.shields.io/badge/AppVersion-v0.5.1-informational?style=flat-square) -A Helm chart for Kubernetes +Cloud Controller Manager plugin for Proxmox + +The Cloud Controller Manager (CCM) is responsible for managing node resources in cloud-based Kubernetes environments. + +Key functions of the Cloud Controller Manager: +- `Node Management`: It manages nodes by initializing new nodes when they join the cluster (e.g., during scaling up) and removing nodes when they are no longer needed (e.g., during scaling down). +- `Cloud-Specific Operations`: The CCM ensures that the cloud provider's API is integrated into the Kubernetes cluster to control and automate tasks like load balancing, storage provisioning, and node lifecycle management. **Homepage:** @@ -16,7 +22,22 @@ A Helm chart for Kubernetes * -Example: +## Requirements + +You need to set `--cloud-provider=external` in the kubelet argument for all nodes in the cluster. + +## Proxmox permissions + +```shell +# Create role CCM +pveum role add CCM -privs "VM.Audit" +# Create user and grant permissions +pveum user add kubernetes@pve +pveum aclmod / -user kubernetes@pve -role CCM +pveum user token add kubernetes@pve ccm -privsep 0 +``` + +## Helm values example ```yaml # proxmox-ccm.yaml @@ -35,8 +56,13 @@ enabledControllers: - cloud-node-lifecycle # Deploy CCM only on control-plane nodes -nodeSelector: - node-role.kubernetes.io/control-plane: "" +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule @@ -46,7 +72,7 @@ Deploy chart: ```shell helm upgrade -i --namespace=kube-system -f proxmox-ccm.yaml \ - proxmox-cloud-controller-manager charts/proxmox-cloud-controller-manager + proxmox-cloud-controller-manager oci://ghcr.io/sergelogvinov/charts/proxmox-cloud-controller-manager ``` ## Values @@ -68,14 +94,16 @@ helm upgrade -i --namespace=kube-system -f proxmox-ccm.yaml \ | config | object | `{"clusters":[]}` | Proxmox cluster config. | | serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Pods Service Account. ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ | | priorityClassName | string | `"system-cluster-critical"` | CCM pods' priorityClassName. | +| initContainers | list | `[]` | Add additional init containers to the CCM pods. ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ | +| hostAliases | list | `[]` | hostAliases Deployment pod host aliases ref: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ | | podAnnotations | object | `{}` | Annotations for data pods. ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ | | podSecurityContext | object | `{"fsGroup":10258,"fsGroupChangePolicy":"OnRootMismatch","runAsGroup":10258,"runAsNonRoot":true,"runAsUser":10258}` | Pods Security Context. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | | securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"seccompProfile":{"type":"RuntimeDefault"}}` | Container Security Context. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | | resources | object | `{"requests":{"cpu":"10m","memory":"32Mi"}}` | Resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | -| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Deployment update stategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment | +| useDaemonSet | bool | `false` | Deploy CCM in Daemonset mode. CCM will use hostNetwork. It allows to use CCM without CNI plugins. | +| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Deployment update strategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment | | nodeSelector | object | `{}` | Node labels for data pods assignment. ref: https://kubernetes.io/docs/user-guide/node-selection/ | | tolerations | list | `[{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Exists"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","operator":"Exists"}]` | Tolerations for data pods assignment. ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ | | affinity | object | `{}` | Affinity for data pods assignment. ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity | - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.2](https://github.com/norwoodj/helm-docs/releases/v1.11.2) +| extraVolumes | list | `[]` | Additional volumes for Pods | +| extraVolumeMounts | list | `[]` | Additional volume mounts for Pods | diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md.gotmpl b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md.gotmpl index b07e90dc..0971b9b6 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md.gotmpl +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/README.md.gotmpl @@ -6,6 +6,12 @@ {{ template "chart.description" . }} +The Cloud Controller Manager (CCM) is responsible for managing node resources in cloud-based Kubernetes environments. + +Key functions of the Cloud Controller Manager: +- `Node Management`: It manages nodes by initializing new nodes when they join the cluster (e.g., during scaling up) and removing nodes when they are no longer needed (e.g., during scaling down). +- `Cloud-Specific Operations`: The CCM ensures that the cloud provider's API is integrated into the Kubernetes cluster to control and automate tasks like load balancing, storage provisioning, and node lifecycle management. + {{ template "chart.homepageLine" . }} {{ template "chart.maintainersSection" . }} @@ -14,7 +20,22 @@ {{ template "chart.requirementsSection" . }} -Example: +## Requirements + +You need to set `--cloud-provider=external` in the kubelet argument for all nodes in the cluster. + +## Proxmox permissions + +```shell +# Create role CCM +pveum role add CCM -privs "VM.Audit" +# Create user and grant permissions +pveum user add kubernetes@pve +pveum aclmod / -user kubernetes@pve -role CCM +pveum user token add kubernetes@pve ccm -privsep 0 +``` + +## Helm values example ```yaml # proxmox-ccm.yaml @@ -33,8 +54,13 @@ enabledControllers: - cloud-node-lifecycle # Deploy CCM only on control-plane nodes -nodeSelector: - node-role.kubernetes.io/control-plane: "" +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule @@ -44,9 +70,7 @@ Deploy chart: ```shell helm upgrade -i --namespace=kube-system -f proxmox-ccm.yaml \ - proxmox-cloud-controller-manager charts/proxmox-cloud-controller-manager + proxmox-cloud-controller-manager oci://ghcr.io/sergelogvinov/charts/proxmox-cloud-controller-manager ``` {{ template "chart.valuesSection" . }} - -{{ template "helm-docs.versionFooter" . }} diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/ci/values.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/ci/values.yaml index 8e61cb01..2d59a034 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/ci/values.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/ci/values.yaml @@ -1,11 +1,15 @@ - image: repository: ghcr.io/sergelogvinov/proxmox-cloud-controller-manager pullPolicy: Always tag: edge -nodeSelector: - node-role.kubernetes.io/control-plane: "" +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists logVerbosityLevel: 4 diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/icon.png b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..36a30d2c730280a83dcd337645320d69a6832586 GIT binary patch literal 37885 zcmaI719T?Owmux&$;3`3obZipOl;e>jR|IA+qP}nww=7O@t@zh=bn4lUElh8t?Ipd z_w(%9yQtAa?0-w}9MJ#qm;?47w0{ox|LFhF?iLp0{|Z=p2@NL@5P0-|3Mfcg z1~v!?n2m+9y0f~BG?$T`4ZVS}ouLW6yN&%nED#=duD_~{iL(K*yN$K26PG(L>Aw(M zfAxRN45Y;Wf;e08lB&zd6ARlpnh>+mGtx7X^1%@k6Z1G4n{p|Ni2a-X_llR)+}YWl zi-Ez-&5hm-KyT-0#=ykM$;rUT%)rb{_ZLCu1<*8KQ-Ap{X4C{2{Qb1hk=Qnk>NkS|5ADWv2w|q z+d13)&C1cjNYd8X#L?dIZ-)QW#>dR_FW&zT;(ucJFJJ14CQf$NF8^Y)|2O@A8~-ms z{5Sr8+x{>9f8tTGwQ&AV z6Z{|ZzgavC|8&Uz>Y)GX{eM~ic0V5+55s?k5+7Wx<`o$ThyaMBh@i4NXmBTFO5!5! z(+5!qPMcI);+2>Xiiikj)5>v<`ieMjQ=TDVJNN*74I|3;?-0su?d_r1A-f+RKr_4h zj%}CD?LgkQ@NZ9TUYoS8Lvw{v(ch?Iaw8(ZyqOQ2FIH-wqxf-#Tb}y8ze(^;x^)?O zGvDS*hcK(;2!I}P9_?Vw~Zyi}$0( zzAGh1q-AYeYmv)pMgAnG&IJ0sCU_=01GvOrz+f-@Xssl^%Fcl{w?iM41o_omQK=A7 zEYiN&w%f}gyMDVM&^vRL#-GSn@qDe)aT}_E$j#{su|)3S$JFX`tuk2q%QoV=+u~#L zpjj^-X-JSh`%`!^2@#C12rIZ%N* zLFb_>r)wjcIRd@rTrcrc**J%JncXBDZD94SFXSICCOLTw4Y6`wRio1pH2o)hg|PA< z@^SQ(hv2ri?};08+dyAgDuTT7aCKM6|q-&CAE*~%2gu~uKD7aEJ7&}lTo0`f3 zw%{%q>vJ%9q~N>Ov(pPsY9=drm%-@q+Odg9DY+BaP*mRm;SxigjUoZcl>5D3chPuk zHy@YAP?9;*$FbFMsx7j|FIrmksMqh)_1$4aCiCCqmv0W*=0>8<_fyRo3>2*ff~j?; zfb$-T?t7A5>oT3P&1vQ--M0nnEa>D!@Kf9Rl4j3eFML(4U{MV*@>D4MpZ1wW4zJv2 z2m`SsqBX%m^O-N@Dpt|m`y)ME1e9Hc$)nL!;ZL(YubHCG4U-Mh7xaBx}-%Qa`^4xNU=q zL#X3!P?4jacAxh#sy_Q@(jGXvzC6#~{dUj%s`INBvKx|Ey`e~D{*=J(-rfcJx?|Au zCLJr5R7m5BvO^q$HP{T*CIpL%9&lRX$K z64fT#Y?O5DbYJp4>-PSKH-w`Zh*Sa`^MYtH2Ww#UpvLsVVbBp zjiQcr1SDD9VicI~w-86f_eYPy24iGA=oW>PhQ#R#)hQ765Uxi&i+h|O%RUt0_g(Q- zPz*K1&>M#1Bt8zd=K8jGjA1zt394VAIGiBLh;I|T6f)BLY<8Bcv<;AW>{c)_5g7Ya z5{}$ab?mMqe&-&I4j18T=RO~Wlo7~3<`rf%8i{6S#hYEYd?xg_6T14cwzniiQwncF|k73pxj;2}4M*(a3hQ_-J1LB6*Vo9Z? zgXsJBxUM!|bXFO`Znx6{DE=eC9eQe@C)krhvld%~csv^Q`$zPV6tC1imFHOf{xjT3 ze%dqoW$3-rxXgX_`%YM1=~xCJ{;dJ-sS{q4_bU-?XYR=YBVnz>xe?$vEip+{|yruwWi?nDQOqpFkzib561S|EjS?UT`Fd@{Y<5zs? zt@tgn_`EJjLJwRHl)2#J+kU-(;5gq-D(AbTWSqgZOF+V?qn>n3gn3U9DHB!_Pe0BJ zwHnpUKKIXyU98FtPjV=s%CW`Z1u3-p|a zqXPexcOVPLvafL2@gwJk5Hrt2j&C^)*~$PNO4+o_OX~M+R~-Ey5BRyPb+&!uTY7Z& z%1<QJ-S*7M}Z_EPs9Ava-anRcnI(B zv|^OzAzid}iT?f1gCI4^{S7`@6xz(}Pl7>+_KIEBh$*a{yMYhHj-o0Zy%fZ!?+~M= zlZrOZAm~^{iRX9xUvg{pGrbcX)9M}ipS2SgLZxE0w93Y^Om}Squ^nUvxD~FE%4GAv z_?_5Ga@Qm|lo3Qng72GD)@JWGzYKKu(vTFIfsxwW-!-PBG`N2^t&&&>;uFg2kuJJs z`1gJa_3r1ZW#K5GjKL7M_da^{n?O%Z!!uS3`P#X{F1y6xec7Fg48`coQI z3>>xbFX4*cU6hM_Q`koJ4!m%W>EJgd>N9x(`Vvj@<_WE81h6-I2R})E2A6m&Bqy2x zM_LYjY;~W7cDWSn`K}da zD)i^ACw+qz{L_mA8@K>WmyD~vsXMt~I+>`Vg-J=|ej5t2+rZN>ygco=iQiYAG&dZr zWZ6WmvM`r8f6bk#Jh|LRbJShPQ?<(C6yKEb!2SoUBEJsZU@HQAU+Ul(m z51&47jr_;@jLJ8LgDM3QsA5Qvinu>iBHAYGd*x3(11L-XwC&@pg#q*ZErx1N9ilgj z{Sm`ivhni?<)`a|4G^Vv)@#~8Ql()4>A-z-NF9D4er28rf>&$APW0Uij-6p}U$fE< zRh2gAC}Zlgs>xI~@lxVYyV1<|jkm!+SZHvv9Tzb={?f{ZLegr^2(uBxRm-m9Tcz=! z(2Qim)SDj1{9C#5=|}P{02J_(TsVb!YS>AU&6eN6HKt(8$Mh7_f!JMaH{ zikc{HTpk-8KirpV3bp^Xht8x|4*}96`B{9y3IJifWcVm~L3Yih*kA<^2RF-#8blM32;|7YENC2D!yMh; z3CGDUP~Z$geJ7y5HVCqwI+l28jdCz87-p-+7d$vSAC<_j z$b#RGNZ^s^T29A)i_>zpq4sz34;+Lpt7Tc4OlF;E-lsG+hBU$#sCTQFDbDjBjdt6z z-+y8(2Kc;{5C#7_$^|n1`Ur&x7$!AE`;?@?w}z&pb;#-qpBx^h8W|x$yFOYw!b{v? zA`)Y}nW!-Js*lVBvQ(YI0ek5Ng;4@g>73cfWX-w4@Gh0IajvL9YkuIu*g#7A70bX# z?l1?0>V9_!FOM9-+B;DZ!G+e=Lyk${q{;`fe;0f`xC?*b8`Sm)!b z{bX7O<3uXfhf*>Uhn$TTn_4N_AjyD2m`nuHQG=&UF}4qgoP0tzn+5ELj67dJJA~TR zy1^N&w&Nv6%K#466aJgjpaQMkrXTo~ao@U8bZ)2=E*AhPBOMhG zHiL6%Xv_cDOqIBJJj-+JW+i!y(9ycuVNlxqyY3RuCj%mkxo_G(Kv^!|^a$k7F_B6- zDR$U@=!+LdR4iyGA}j;EKB~lvQMNi(uGT2fs#Y#OZhDpUlftApH;L5tl_^xFm8q4N zfkPu%p4rW_ct3~Y^1t4V%s&N6Iq$9>m*}Lkm8o~J*dLr-@AeA_d7QCARXCpN&S4pC zNl&pqQ`}IR5N?{G4+J}~?bDA9djSAKJ@LWj^nW0fwk8PJGKH?18$-rp0k`QjzP2tv zAlWmM1yO%v!S)?sAQg5A_i#O~kT2aO9{FMJ;R z-4tz|x?};jE2RQ#Fmfixo#W&nBHgi6lukY@JN&jVeeI_EGhsiKi6449A?xcJ?0~u- zOkPo9zIQ=g*f&Mx@}pvzEcZ=T3;AAZDpi^?p~wUaWiIE9mWy1M{LUQGB1zz!D18G= zh7l9Op~!<0IjRq5Wm@g72#cnZ8HLDV-X*~9cj7bK#r*E7wgY^Zs}+Srxe{y`vK33%`%D zeF4|{_=HNBZiDj$DJL;(`?YPuYgEJi;|NGo3jMp46l!81yg>k2HYGs#Z}hlnrguq| zX^-m&J|C0jAI~bJg`2OLNtN1_h+0iM(egYLw&tzb^I>zrD7c+m zceS`}u<&$xhMCM{i*=kE1h1YqN!Bhd+sar#RZl6-K!Vqe*0__WV06>~s4xYn{Wpa9Mxabv-*PmZ{Prwq7Y> z=cb=6RiNs?N9uR9>RHhB`)KZMJf%=O`}MkrP)4R>^tbF0x9lEhFk>9$ifag313+FT zCw=2gcX|N7Buqi9$eT?}9SD~X56**gBaRPrx_tZx$JNm=Q{y6VQdc>!B!WC5B4W7w zT{=HkR$+>2ezVhp2!OS;PDY4)cDwPUH3!rLC2(-S8U?tVnMo?5&@49}u+G+DkL`+? z6VSXjZ=0STx^2(@=0}tJ2w4Ztc^qdJQ^=$f^Wv;EIOHc)>XsjtFPk4neU#}GM~x-W z1s!okbn;=;q#B&o-K4zAqUayhNRCd?RQR~ROJUN(4OMCsv&kBv9uiKetTGom8*XyZ zD0H+eRcV)2cfV>f@ZPE4|12weBW&0Bc)M4f#7&Ge35oF_$()KYZGmv`6`FzNC*9-T z_!YuZ)sy>XE6KJSD4_bVL(AgZAu7>l8@KGdo5{b6-qHa)MP?PT?Q$3EHo&Ei0z}~S zUJiL#ZGC4Hh$!|r8j5mXfi9%;pr{otI>2mvN z1p$6?n;L9JkQH$zFRCG-$rj9yFqh1rS5>=DX?Y^d5bsegbrJ;~GJsNPkT2#w->TVd zo2mLY$-;3p%c%^`G`35(N*xYi)->0-)8Yq(eM}kUTEkWWP1`Zu_AHh-L?^*DC+C^q zFPC?S$rP3$jfFBNxyH*4$;fmTwb;GEg!uS;Ls7U=hmThpt*VNpYK?LxqoI>ik|#0W zQ<2TD5rNFL%6eH#`#iYa96}y<#ywb#6gK#j8_e8ej4W-&3F-lWt#nEcYp^r();sJx zj@$?l1tgbz=ysvn)3b|apYUMu)yI!ii^iA1_L>lZ_;k^@_W}GsP(}QK`5L8FLK+Tq zX?6;5_^%d9cmr0N-|I4m$tN5L3OT%Hb9(R0!w{*&zW!-X6CO6LuZ)~q_ z_gOR__9M#9`|V=V=r071TaC=c>S{}pRcK_wxwS~V2GdKZN}YN!_?lV0=uZu9wP{K- znUC|3JJyRtvpnlU&r9dCQk{i18CsPx#Z*;|bN$fiiHHRveTZ7)Ua$`Yl4I#?6cgL7 zeZtGFb~&;wcj_xS%T-B&c2|Y`qDkdIgZ+RYXypp~Cfud+Vn>s4D{kMR7T9j{5gl76 zqlDJo?WZ%M4_T%D__K1xfv18rR*GHK!`_WA?udI1z8lbrZ@g&C^(h>qosB_0Fk3Gg zC^Jz_z|#4b(q$k4nFHti81w;Q``$jDw(c6i}EHE?%iZDQI_yX zRDe{JBOOH3H8Ymow1reVtGh~wnYP#%zq=l1GTvY`&1bXPA*xg?yI4#VnS@jo`99t8TsFm3 zUTwKtQY!if(_+Po=BPU4WZf@`oi_sX1%*!t>3Ae4U z7*UOJBtnyWiyhqjXB^$#}{plSIT;9`*%5n`8XOq&a*M&Wq!qAh;As8q7${Lv+iWg>!yPW|4E1z>&Y4I zVx9+}J+tI=0D4z36q{>Gr%s3{`dx9FpIf_d9AoL~0sbBsnytz!EhszXOTgjm|B0cj z)1XwT*_bLdGCzUSefqHrJbxPHZ^6xU*cH(6_VshIo)`Kqh4IIr_|ny|KGHa+@dHW) z#(Cvp2F%x=P3BE0%j&vjV>-f%Qrsfa3M=Z>Jv*yd5`A6h(gn6CExWYuftJBAh@N9b6<+l`i*l=am#?2A%eN z*>0v_wA=DoJiozwslfa=aJ*^`5}aNckHYllp0&+No1~v?8g5pnaG~h+?Im^<$r|OQ zYAl><3s1qQs;{Ym7-H$+r1Q*Hjl zEQn&6^5?*%oCTXiq9Y8tQ|O_h#-KM-w&+uxK%1zX5G81a;As?K>3Bn5#Sne~?Ljvu zkNKbrBe;$656!lNl;J#zCL#(NzTFy@-bxbdr^!-PfU8(wN7af*F>7+PtN(O9S9@C% zyK5j4fT7EK5bolz+Vg!E%e^%++Ic+l>6A!h4VR4v)gRCZb)^0)sFB@_A$U}FsNw*i zZE?6+wj6GMnbY)SRAqx~G;hr?tMtnM&o-Z$i#L#)j5s7tLJa^O`_)4_2$MKi5S1wbPK0p!s5EMiNuv!TIbw!UquZTt z%kO)f=)PVE{MEJ_Vztoe1g%1&LZ0=j4#KL*<0}Yz3%A!5CbC}}-FMk{GJ{u+$nP_; z%bP5q5uKuR*rHRpSoXu;3=4In2hpCKB7TnIC)`pGxCjSAkh^T5;o$Ewm2$R;jKag6 z-8Vb&^H2pMC~E>aUMcV|59){+*~9T9MM8Iu1TV&|Uy*;8R@6UaW`2z!mj4=c-enbv zMO$0&vI0Tp^#9Fce$B`Zi?pEyFP7(!Q~DA6>rcEyj!M%*h+5_VRZl0$ci~V75T&(p z!A;gEG_R+NZxO$Yo_M1+trXY3f|#jxR2U_4VJq}l+K%&zH#|*`Nlh(fGUjlQ-(62WUkYGbat+`{BzBDkAt^<`87^ugF zOo>9-j+euM$7I4AsiR;wS4ld7wQ?Pg_>~BU|SgXi8k9AF<1By(L}Z zTEvI<5=jx=7@C<2s-|0bH^r%Cv+kl#)6~*rvtIO_R@DLzDQhx3v(FrNXD&{p7vm;! zNSRsKKD8&cqghWLMQmkw=JJ@RYxzRM&-^CCLSg4u^VYnJL`smT0;3LM^Hua)oRr?y zmv=%Hp}k;-&0N!;vgMM(t}hO)!4#yeW-~bvsQ!0sJ``JanpF63O)%~ysG9&qQ!qe! zDru%;YR(Nxlltslnf4(>NSwx6SnJzi@+dC96H;!};F;$uC$9Hm;@L{B3ruo2ur0#w zi8Ez&%4gI&&bs3yB z7@@bduUp3JSngR?h1~3~=XnmDrxT}Opnb#71+_n7iHRyLDTH1ZOsrO(acuqg<**wU zE1g(?erCEbECTQa5Q-f+E{vRl&*#ke^nDxcb?Ilvx2DUqkGCJ4;}|s!fUV7s8Kbs~ zJ$RLB+shb7eir0{k*h!E)7!S&MsM4u?^Tppelq+%zm!dvRm+hmhiYyLpb!o34Y)Ih z8R?TO@J1PhK?J%#eDHl^O!n40AkYVV=5#$S?x{ zgt}H_MC#qg*y4JBd#3iMz6nN$aOIxq--cs~_iizOF!UhGRi0OTS83Fct~ zSV>FiS?FBEsa9w;_!jb7V>;=HM@@nyos$Wb>P9|$X$K2@@jb7*;V&bZ&OFb%)RwD zHZFSW1PVk^$iAvfci$%Y;$$L7X=QF`(XBP8ZoX2MazJpWxy9Ucs0p+KO_xf(pTYL| z%kNWSgV-3rB3j2!Cv9lzBl`xc(N+$Hj&9ax#!jjpUTTl7-9}ovmDqL} zpqL&DBp`#$rMzW5B1d$~zvPx~V)^~3be?KpaoFT1Bdhs4uY9M-b?M9Dxcigz!|0Vu zg{qFilA_j)`prm7SXdH)3zjzR?Sj^Ntxbl2OE)-REl(~sCu_4E5&KNn$b``mZZFhccW-fb3<8}QSUv7tl#P{}F-+l8_FUp+*SSKi1AxL0- zr7W6Dz! zqf$4QG&lK0+{OdgFyt;^W=T+QY6mx(_vH=@U<_k=6& zKMxIsXs|&K$oH*(S)_2f)$+ZZd3Ao?deJBrg&|dqlb|?9(x_Eopo=!$?Mf@qXE3YT ziepkt^fp*;)+%wkUd&c)wmZ9T6JBn1$s}GXkPb8MBTD;z; zzTSjpH~QY#;d-C*zD{>TD`C;bDzeBx{K9*+c(bKu+qGGayt(&b=^;X2DH{Hxpe@Pe zeDOqxh;MZ1f9#zX7aX*qI5uT(LM>PQ*c<0~{N$VVQ~Sbj z{W=o#WZnaLd=@0vHG>|#QJv^iWMvcYsu^jf-D)YbSf!+-LYtj4SNJ>B4`u({xw>?o z)x#9&J56Fa$@*+&`=iCMuIbx}{^_1*pgnZh0Nr+nl;4D20g>;!LUyOIOl=Uei_88Z zvXPsV`9!o4>*0Fz-uxR+AV5OzDeBT$sCAC%9YV=G3c+S0xprsNYEP{$N zFB~p`RabJLm|xbFINB{gUama%cG?W-r;b((aU7 zeeo7cbd)HSt8-snEK4mDe@eKFn$N=^j*4-+i_Ix@ch}PIj3amD|3KR;slRI76Uy{h zD=kxOEGq&;eZ8&&A7=3&!jY;~!f_*=A90FHEdYHrh2dSj8CejT!ylh%R(T9{zN3!75MW%HCkYthC;$lSEIQetucrW=u{+P?KT` zQcq$1)7}tiaCv)Z1#9iHFh0#EbP#*$!SeG$|F#Ax1et_INnPuffro&6l`&QD#{$WX zeE$zL+@9?tFo3@Wd}O5!8PZN-c{r{hYmREgr;# zwj=fyy>LHgBXCLlSkE~(jonUmgH)=lF`)x*toL_5f27l#HaBKhOmFt9cD32eTm17Caht5os@^HfO}8^m z0=(dKV%=RH)oe0IFC)H`DN_@Dw)aMbnQjRA()a%ny8~q$=*hjQy5P#v%S&V>2&|Tv z@ZVN~SQ8y{o`GHiH7ju=Oq=P&APkg`cbbD}2v)^t!hwYf69wPE7CaiN5Kv8k3wJuV zonT!-1!beDrPv8j36Hm;t+S7*cSEf3};au7NkD{~h5 z#%h$(iay=;GtrX9L}j|ghhGF10=Jg@X);^FnF9IrdW>>-(Q2_uw4jP>zBlsZjOoIu z5r&gntcHjI|3=gV4Rs?qe==gZnNgz=tB)u*Qe|A#ayscy;d0WAzeGv)wD)%b9EZQw zJwb2jsFK+Z76HYEmMUVI%I}kmuHNtrBkIrg*XQdEV&6V)w(9`0MTd?(Ef-Yq9y_8M@H7VePr533)xfG_sC|D+QPMj!l%$=a;Pw`d#0}$?61W6<-7CBnz z)S%RjUGfZDKo&V5%mKm=(kR#z^b1n}K-?f<#!8EA=jV_XYmBZhFv%%qNE``wM^aGO zXLXzr;a!XtacO7r?09s_`=AkPomjQ(pWDYpP_D)2|B!IL@dCfdBZj!5TB+}FEWrEz zOvaU~_@XZB;t5o8fg5lC>Nw;=^!q~Ze7LPwcp56Yyg@B1cdg_?7#tIqFI865x$RPK7#>rBR3KbK22+bnq}v=v#I9K<^K#q%l)E=A6KB7?yM zeorWf_ngr-RQw_*t(y87#uwg;J;kCVK)Zu5i7DN~YqFUY|ArSV=Q1~OFxA@GP1&B1 zn}iljK8Lme+N?=)af)jWZUWJ6m`*^Hyq8+`^KeYu2mRW7nrq)VkyeG2=je(5Gw=ln z+9B2Q`TLj>mE(59t7|AK9oytek57>E*YERHCunM5RQvr}4SP+k^qc_98!5qhqe-NI zln&q;?g*=EPAQtNg!RsMzG>)ErS_*vV!6B|Yxycdf|^AJ@3bU`@+AR}AJ9x9JTe>A zc=2RhxsKgBG4)3$DU0;F7Q2m^OrPr|`9el0a;?w2Sf$Rpc)~Sf)o^L&jF>J)o!orU zSCIpUE4RbW-`%TXT*e~G(z#mim?RWx(J&G8?*qq>BJdSOy(EC-ot1>^?>k~TQz*N} zF!(O&-~d3n+d++Yo(Ed-!9swQZ#-Bq^xr>*5@E>{VYB<^x_JYH_g# zH>&f{9}zm7A6v-9g9dvrDe_BA8myXUoy%J)$61{VCd+i2-Wl2BfXDY<#pg7>_z0+UlK0onMj2m9A6ss$-043h;cv#t)q* zhojH%h%4tRTYRh5ChvGip(ze7HQUpu7t#70lEu0f?q+jQ+J-Gf&l}d_k?DSNf+uz( z2_}RrAWOm&=RPjdfuVBou+#U{4P6rIcLzkA-*$>aF7-?iaWGy^Qr`rWSeGD~^~)3+ z4Q=h)R^6aXxbk5K3|;hiG{&$SbvzC5w!QD&J#4MpS)xy=!(+NPl<27~u8PhB@A)1% zS3N~%LOgW@gN6`2`symHi%YzdnJG;rCY!g< zqCM{NuN;5iFhI&$uNy5_ts?SpdE5?~L!XP8kxvhCrjiK#R$}Ojezc!TaJ*6fmB=yQ z%fl0)(V?7m-AwAW2P1}~^$}qVHETmIuio9_u(LPbM@V9sRbW7M!jy-aU=7;*Ve~-5 z#h1##c+vEogONkq6pn0acXy>xm^QT)Qhj4qNln+Se9PyOvr_B2_^g>*gKo`D*=neJ z@_bo{EFt>FFXX(p*K#`Hm=gGv5;zovSQt-}^wu4(uosAi`H7XvB!eA?WW9W(KxV!IaeNQETuI;s>jbxtWCSMe@($w;wQ zsc9{SwPVpF{KC=a^PX4b{o4EE`4~P-3d~8rn%R%$D^Lt}>4dD%JY2%P1&*~nUVw{C z{65)h_gz*tJhVv}xe1isuVXwakk}Q1Fh)WV&+fI{k-MJ_W6$eali@BA`|$kxtp(;< zjXFEEMYt#)hGFtiw$(dW&>VOfWNY3bUa5!(kVd=Iy%z3^Baob{(gC+hD zHt%6|I!F7{u_gQb;kX&S>ero|fyo`pqm(*$F?nXzFKYPrbT$y7Oj`iV(6~MnI$z?j zF=8U}5D%}lCZ3xq*D;;BEk{>Wc3_h8IwEl8hFk3l5*79XbjUT#jRUk+-f8jd0p%+@ zM4-BZS7;N)Z7P#nZ<@K1%ju%|#$vHEnalO6=<#x`RF|&9oxJ4d;cw5g8*!J1o&e2u z+f2#wP->^ylHl@LCpb1_<=aRwK zwsMsidgjhEB)r;BwAK4D{UL0UR@A~E`65dcOz&Yx=%*Gx3gw8oJtj@84eqd`<0+s) z&Sb{mI_{wB=Fxn}(BG++5+G?ZbP{2R@ybKg16k&VWW(2<#d6%WZ>xqi1aPc0123ji zn;u!JnhpZOCG1d+=p-7}h_%V3 zSY2zo%ZHNHZbJakQVqF%3*<5;2;hPZ%Un}9maxdm{xs*W6;ft7OF`r1UdZ*tP|AQ+ z^_zfQH}zcf`(60=9~xah5ziKt=+0cgR8}+ zT$SF46}i-T+_tS`9n#X-P{$C>WF(!TI_lNv3e1PgJHoXhlj!A)DPmKh0iu7?aiU-? zXc$&fvaGSHS_VIaIag3x)GGB_%iY?r&6W}nFc}#n$a6$UBDztj!qdT`#4&i!v|J;& zvy|3LJ$4tFLn#P~{Of(?k5H!-OO=dk40>eRFYVS#0!wnDt9qI{PtM{HMA_eVp`JQk zuwlCf2GO<=$HyBvZv3y({klG~QhwQG;rw5DkJg=*%Uwa5bq;w7n_MIoNHiWRd%Js$ z;0*J43?RlpHBo)DIB zmCX?7GF@L!+g`H7@B3!n7X1b0l5{H0^WmS6e4@|=xN?qYExrUz_kGiULfo=1QC;;a zCy?B0bCUP>b1+~bA1Kn}(bfA5yV__r2}m7lcuBbN@+coaoP&ceg~yA}Nkk{VbBYmE z^NG%w&l*NP?^z*w#kz})rq#~m|A068nU8oI{k`A#k8=z~0V7EqtnFe}p2rTsUcnw- z2;%GY9Kv2xP!eMWyoknpykF5e6Vin}xCK;Q7`L3DlQbKiP^NYyrIsNP@1gcen7uq0 zLyt4^=~EcUmSjjEy+mEBJ+qpp>uiPx4ARqFF@42?&2)#$$8+O^8#nD4pu)z}5OZeLo6GtNV+aHPCa zPehAp`8aEX-~d?%7)|u{?Hm!v#&bmlop$F%#ALm^JKOi@BpJN&_%ydZ5du z_h~Y;?P}>Qg|;LwJH;KB-6L=;feN)eu42&8hHr#5aBeD|(#r4=&2(#W#&v(}Q1HE- z$V(A<(-m-(6GK7BQx+Z?Wr64bQN7)`odB8k11{;jlyN9P_@zt|ulU=jJkcZBJJYL@ zj@PiytMf|vkHmB1;C(C%Xx=S!|2(8XF4JtyqT~^k7}A@8958z>En^oe>VtLVRNJnH z;V50MLP!=LyCIl)TOrN7ynPVd+${l!>6YmFz~{&7{(&YX!&BD=+Kcd9VjK@y-CXXS z_i^X1YX;U|Ig;y1GU|@JaQYhbQ_iQLJddv~=O<0Q%a#vot)4+P%8O}D3+_qrydKMl zZN~v`4;$^-XXzGqEO^Ib6s3~+P-W_+h7(tmjxF}?YH-^uWe zGOcUcc@bNFhZ;KL6^DEL#Wc{~1je0t4wl{&4iMfyu*t$;6u_rD;E}U{BjUbtLoZw( zu#+gxj(RglwFcikrh|Hd-f)q~xcYoS!Hun<7(>v7lCHTv2ol>7R(aq+(&PbED>UID z+7_CF97#J3zo=I2<|$7eYtdD97piC$OY)%}ffDvdYA(RJ)IwFxi@|NV%3TT)B@Oet_RNr!B=+ogu5?D@it+1(JX#Mn~sc+ zEbUZ!;3{^-5PIE%PU^Kq*qj0ub4s72RT)QyZ*XcrgI0Us_$_aIo?$3LEFgBhkvpag za*RIx&2qoz#FItC2FVZo%m^$p3hwSj&Ieidj{5xouj|FPI)&{421}U4>1|%UK3zdK zkttS`I#@O~+QVHK&7;xkTm1W`LPRE`|5eT6-fi3Pd|d%LQgLb3Z71cWVagFFH^&S_3aaHf@NDGV7#fd576h;MH-Jqp)t$^gXTyeMGdUD;|-%KYEO&fJD`@y2VHh^c7yyLzLf-%k$8gX zhjcHBfj4sMY5UvpZ2F{`@leA0MGf5)IaBS6)e==qi7Wcb2vhB(PHIO!jGA-wu{{6S z$`SYX#vIF4$ob?)TJvp2bJ1BU}@uD1>+ z(zc^{u4zL%pJ+lIR;#5*T-mIrEpH7e-!Bz_maB3-+vNhTSuIZPL74~^0SiqO<>uu9 zQU>Y*U&|)9!v-Q{bn2ymXyDJRZWwf^K*jvi9N7|)tk!Jj6z`=qiLW9$&DIk)-rIX8 zOYgbxS9hSorT$e8gn7*Z5z|-%THN<-e)+#sMBz^(ooA!bfZBTEFMu8zBu zS61^H>4{i;V?0aKE zjuK|xu-BhvR*ya&1!P8z^B`oo=anHP4wY2ofSM;eq`KhH$zpLy{a!pQbk+;zLWNdY ztEI~D$oQ>IFS#F(dKJ^JjdMlQ{Bc8FC9lCM1gLirn=9GFr;ois%8g$Zo{u((KA&^Q&C!s#;cOpOpzlrM&?lSLT~d{y z`%oGF(DCj#wg(so}M{Pr(9Jv`*Ch}ix%K|7i4Y}~z980_-^ zz1b(x=cb4{8S)~J%2(cg3q2b2@U@3^;M$-DsD`e!B23?kMG>zf#LEPPN6+z{l3%}3 z#WabUtQQX7@GMV>3092&rs-$E1u9=OVrz*vI*S;kw-!u4dyuLrMzRA@MdRO}3z|5Z zd+`|sc7~+W8GqjyflUZXzOR)y?vSiv#3`pJUo>4XLjbP{gAdmoIL1JcSlu-Rh6szVq@>0RmH9|VOkdW&y6P9>SV32jjNH$!z_vXM9kVzbKzs8k9nZg(3C0&$58IZ7 zJe&jY)MLSkr5u?MUH6U`(fXW2Vhu6^lQPObi0 z{oy!i(y-&J1xL5&t{}mft4BkvRvgv##HVJpTwiBCyre%RR%vOmy7o{(l!3+xO5tVaE&@*-bka$U7@}_0`VH$tTkRr@yLH1lttb4uaOPwdo37^A zm-X7cowa`33$cM?fd*WBvAUdkiay!{1Ht$~cyJTy8G>5ML7R3=nW~>|9jME0xJ4bi z_tf{p(0V7IqSB3t6QbbLmn002M$Nkl}4ueCP8-SyD5}6!I^!vC+ozW%<27oBOv{SK<<==PT^N>cv z1m|6O4MC4?YRu5BCPTG~ZuT`ToJN2mLo)+_A30WS=3i{OlH-M)h;-b{V?@kovQ@a=%LQL9dB z)U25rwQ8+Ol`82w_T`V8`iBm!-J_fCyh3N4eXf3;!K4yr4O-fEZdj#d^Bo$_CaU+4 zy0&A-P<3VyF=LLYZ(+`$1a0NkuCE7nF=`>Oa}cDOh6St&K)`|JE41d54>jrO2Lp!H zYu6F;FBL1A{h-go&#B^h7b>%QWmGe!LQ)%I*tCIP8DG?tg2 zjc1|BGmpJO-W{$+gKxP*gKrqbaJCdXh?7XIhvMP&LtpE*w7oZ;EZt@RYl4K}ZqGHD z*4A8@4I;i7OZeqb7fy27QNV_VYDoa}xpa<<6~KixXNCI|`h`*yD+~v(CMtLDeUEG9 z%GKJi0)&>Yr=DHg6WHmfHk{+vi0E4dkm3j<;gw*T(aa!Td~QEOlu8xY$@7P*oKTi} zGxW$~PwVNS52{+*)3ko(7~S*8lNx-@Ai~7Sl&DV}Das}apT;$3KD&=T`b4ii|5Q>} zMm4E84o{InI;ln#Et$1YH{5=;`t|>ZzWsTk#*ZDN14#Osl?(Oge_zlQEMBR`3L__0 z@oN`^I>6_M2~8gt9L(3Rd5PW5fM8aFdzLTPw$a~e?1Q&Oxd$G9O4qW=xiTSMr&UZH zKk~#g8lF0Es_)Ams#Nbj%B)m297L}Mw$NGF&Mlmw3V=)3#5NR_!LKgG^)58kXPub(aQ z?*%Yau$^#Dt98fXBc#X^PobhTf&r{f{NDBvXCVOCgTvJK!mG8>ha**Lp}w7)==)J0 zP?D5gRUJ=htxhL*Q%53v^=sFNXr2k@(ZgyEhM2~Q-3ym2)CCuuuZAbqkNN&Xhw^mQ zwbyCpf@Lfhe?{R0vER&CU#FGgz212?&cy5Wwyb<_2ObYiVqENofHaW+L*7s=Lg7N^!= z#k0>r`p^B3X)-IF%hqhE4rrR<-FhmcOfja9Ar!*35x;9QzK9R1IKZbged$Jfy-F9< ziTHujzWZ6%|D#vHa@nApH1xrHp+O%0OLBgIM>F>V$jQX5^DZ{$A zb@i2(=;BK+Q>}U@Y3z@)wSL)DO&kA{R;=5kbp%xoVDHU|g=n)1F?*lm(}{_p3M`xU z>Rcn-%s7=jhf|p=Xn;dmyi7T5-+O@R*WK#bqZ{yHlF}=cVI&`_kViP!3qX2w>#QsO zb%kowsjH8My{7V2YicKJ{MvNziK0dH+>S~oIJh0hgd$;%|n8U zP5WW-=U!)NG4ZT40+wb&A@9tVL{#%`UJB_tU2%yzAOvrZ9Ia*Vzo;Yg7N}^&YRax$McG9&+3lF2DxkC) z?bgEFo`8Vu#LkRj*f|B~^Mo38RJ%zh?fLo>P5gZt^BE1@et2O-N&vhjmEAPkI(3ZGyzAAf zh38&^{P-6D=;3D(Hl2=R1B%ta^BhfRij~hX89`NfM#mK_h0JG_de3qmkrPai2v20 z%vjdt(IV(f0y*HovR@FwGfk+aqeg1cJ8x^n+-YjerjeH(e?X^n?ij~v)OEOB8y;hm`PoE??7!(9ZjD(5`U!7hg&;1sw392ood$q-xuAfaygHZzz%;v0hb2ao2l z#QUcozQ^0YG^T{@wR;%l#RiVUw?M)#Jf|Nsb3L?cf1YMd8ly#XW^n}Ds_@456Kl8a zve#dj&}(dlgaNBT&}OaLYVGPZ`rUi@^7rWBM;}vd*6w@l|D%r%)i+;!sL@}4skdH# zm80N~s2r0;l~@>hkVPWikyDJ7!s|Eh)QsPkfS@CqH+`sdOfWjn1~yiPaYGAM?b&pz{^TK74P(MG<8Ju^gOr_bZ(X_~2T@1DBx=37;`WLbUk z{7|iANL!*(O_grmDu$gAwg4VT5$4vz$LyTL`eo8ARcX;e*^DN(EF7y+Ys!=j&-d^3Qz{IPTmPDkb2n-8Y~F7nQxI8l=dtPNby zW+I|$ROFLAnMO=;Thf>VDrOG&M}-LQ=F*b`bp8NCKX0!(ChG}4dhc!hJaL+){XUm@{MK>ij=|b{ zFk25l*iRc4|4UzgaW5L>WvzeB=IseoEzmVrT*|Su^Vz!ASEu4T>_ZW@ z?l(Y(i5l+R@4)cZ*mf3?Qmxj`oI}b0uT6TMqv`9n#p>o;?!2GC)iynR&mBlH4s*dO z+WE!%z{oCZkmn$ehrfhf8c!HvSY@LU8F$ z(8+#L%+^8>`&$0kx%aa2gpP#qF&#GXrdQZp?ji*djp6@E9y{{PE!e$GrMOC$GtgZ7 z#}9uVKS6y@JyTB&d7M={OHh>%0|c2PJt6eYtIuo3%vrke*1NQgg_vVL|3LTN{(zo+ z_P_ezv#%Js&0sI#>R4=2o?Sp*2UxFOors0otM&4#(|fnqgAa3T{P-C-kB8N#M`NI3 zRKTek)?h}WJD3S^oYrsNrlvj5P$zaF&9$=!W{qI0eM^2wKhl9O#-xqarIE=pva%Ia zgWyul2zW8)RH0lfeW!@lpk4Bq(?7-*vV8myrz1#LdIu1kjM_gKwz_l*Z!Zl0h7Bh> zBX7foC#g;2s>)+~o99rhbZrLh)WKT`EWm@it)fhSdlD_zOV9~2u?v&KF#n{SPdQKK zWr9ThLkgb`9N3>SGgvyqOn|>6C8HT++xE`3!VH+$zEJs5OOiE+ANN!kQ-^S+^Ha#@ z06IDRXt!ZI3og$(?Nse+)JR`4=50@u?!NmUmbXtk`TGFQOG}n)J@e!voXNjXPyY8M zL@#FTJrR(yZ8a>O#=V#T)5y`kXv+Kxb>ex2 z^~l4YQTriw)B5m6I%x&~dHxY7h9}yxVveq0%|TJt_sz<&qQ~1eu~Vu)LbRwvzcC{_ z#G4PpdmhG)uY*xjrp?e^i15_VA^MYD#TRvHtT{h_sWqE6sH9y0m!awOFMyWJ$kkD% zpck`ry$TCmzGUlq-qty4(y+e%#B_!PB8eGH#vQ@w3#O%QGoL@!sy@Kd!7UHRkzeg$ zEqiWlc3Y9g{W?ANE(U!m2l#&_7%B7!Ws{j+?tC5pjGm+bF&?WO1MUp=@a-TNdH%TJ z8oNg{n_N%+`q;>D=aq7;25H~*akZzwohkfo(XvDkkqjum_)RWH-+zlgm zpM8UqPSPE>4c6KXGxg>>Bcuw|HTj3H^w!gl>(y6Z()%BOqR9kqmNTyQc5H`nz2c}a zKEuhK+iB<{H)_qe7xWWOFDAZw;TgV=KnR}$!V6(CysdrR`gLmFq!DWvK2ZG=nH(DNj;64Wu{k4{>A&Eo zkleqJIIicgEq?csZ5*BRt^S-aT4yk)@Eu#?E3oEq=Bz(rO@b%gJXAHI?QkcMC4znxgAn}0;y82(2Ys-T1`uMYvs@?df;lC%D2odK~p$`vHgZ(zz~M8ZHiweGGW zGlP82lnNJGw1umXg|)~Rgr2nafBAdLDfEbKT-23I?)Hy1L>qC(~?d)@ntQa(A(eE zDx?_Kv$Dm95O`U5A#<@`kjz1*sWpQM?qOPtJ#BYrqzI8fCoj@4;=Mq#_gNR}r~BU0 zmSd$=0B$F`6P#tv^z!Tt8@K2Z_Snt(`72fcJ*xg3EK#p^tvETn1VNpPm^kW1{N3Bd zhrRcyzWQ_oKLIydmFhQFV?xO7+I2({o2X7rhnmYpM9`xTn}*MlP=W6;lBcgJjb>N?pvsWIo zu{4ts&Va-4dnmV$Jqodm8?Fq2%`QyX*iJ2L67WA9mbZYWrgsB=zl(z+ZPuf6{NW;k zcz#K5tO;TiV5HHO|HmiZ$Bhy5H;Dik|D374+(0yWDzcc;Y4M5`tg=1G7`&(+yzeeG zZc{{a?>|?weY*G9??7a-|IomCxwwfx=%bN(bK_REZ{Ap=k)~`qwj1f$h-UDQIrL@h z{NeD|^((7(uf6Ht+QP_T+^CQB%+vo3^Y9VJx=xrfgP)376Y&Rc#PH%4YpmFsmF_&_ zaVLAgM0FEYZ-fEAabtB)kK*Heex7EGJbTWz(|%6Boji1P|6BJsORJZ!QR`++bjek> z@S_sNRGnQ*m6;IpIR!V}aj)7D3jbr#N;U0rrm7Up=D51VS+qan`VKNj;-7W3YIYze zw2!e4VEGKQbN21lF8nGBoj0YpOa}d6Xce&du!|r*1%i(8)Kmiv@fVuXSO4Q8-o_uU zt>y6J5-zi3$K(Q)2R9ybwARyaea@b_MR>ru zYQ?(zu|JN|n2A&L@0+^O-U_yH^$U&Rb9(%%Uut)TIt(~RcQeP|_K~-A#l`2wPsI3; zB*T=$5iUMY&!On{c<#?X!-!(RB0c)Vf0f5X&SU~QFATX)Z@u=4-o+;W#E#>|Of&Cg zhmL=QAq!@*L?@L z9d65-9r+*>%>#3X32m=F05RTd_jzU{IAd^8>b((W&6-aTq5|jfe(=&gjH~A8nP*?r zShk6;Sid30o?SY$*WLfQQ_Gnl>(a49tmt+9;U&))qd%rE)^>)^droW@DA}@gbBzBD zOF@Qjn>KA`>GwXg0%2fOU0sfJx%;l$SbVZfZw-G>wOV%4)L*{WJIukq`pPSM^|d!O zl6b&29N~V~y+ick8}De$glQbmxHMP_YBqDn4u6*ZTJRF*^0E zi!}eYiTeEA*Yxu9FY3AfKC6+0ZzqrYNpHXPwi-0A6ZLQ2wne2Z%=Fm==Kpa?GKnpm zX$LUg`2m=7pPf7ubec7Po!-Y$o$})s>eaogru@o+*M8@r#V(2<78KNF=k(S2SKgqx z40A8Ntk?qq3nI_BeGFauCAh-)YG80!8I5xiBzPZ-sx33tXc45_Bxi2wT@urpb3pSD9&}FJU7tTPAKK#f}DX63h<7K z-0|d@y;R!8{@6yr98odAxQrPUr{|l|?AagkJOEYJsy`;_&8LRwv7tke()TrH@(j(x zPVSB06SdX8;T0J6S>)2fCVP)Ubdu!Ck!!&-vWL-Y!Mr~R#Proo}GW?CV_1HZx zYELe|+XHHyCNhpMOxG&Xha>JV@LSrQ=uHsXeF}mb1uh3ZEOk7FxVgFur*+5j$+{Fr z)xTyk;9u9MXZLPew|P(0lYwA(QL57yqkhoItTDLws+;4t49`2~ELH)J)@#g2I@)Q` zbObh!{DO_f{QL z>}Z#5j?ex3*JT4Zt9hxeyX|uQ_mwx)vP)kr`fa@4c}kuiNi=P}|oo;(W;RD$7#x-TX2~jix6P zetnPCHe1!QFx$vMXlOM!Am+wFQaZ?Kgc&dS%xP%u8kJ(dpFQdxJx4PJ(uv7CFE{wc)-2aFky8l1Sn-`2J(%Ez8YS{Z;)%%j>PW@TqPin0; z43pY2Zf?W50X5hm>~r#b9#ALzgP4(|CjZca)m8Zx4K)6{i7L~jJG(Dgc-pYJwyypy zmX&!fA_M1XE6c!q;z$KHjqKcwV+m|c*edqKWBdpd(ssqb8?}Px6__0?K;TIE^YzhB zlU41^v&9;W=uhm4Oldn4KC!`Q1KP;P@6et(vS~xibzLhb2(^fS=bd8uu@?_Gq-)F07(`Gom8_-V9yPJAA*^GF| z+!-@8K|zBC(tg?co?nIPT!X zr?y&?B^uoOE~(cHjsWB#^vwBq3~6UCSzl%*usXEba|(3`LE@H28E|8$56W2W_?NJp z+N0{SU<|L#^A_lCCwEo{&IcTP^_AfSz52paTD#wmSN4#N5BJFo zZp&asu)t(8q;1&qe0}jYCJJKQeEqfR(6$x+$R2(A$tSx0x@)5EjgfL|Bqy5`&uBXN z4CX2&3u@k^aom;XoFp}CWtm))ytQ<7PRJ(Idbj+~Xl$o}! z)hYAln{R$7YVZpR#$yUP$m0~nsm)SJ20n@NV4&9`@SRjZbY zl&Gj5-hNv93905SoTgs=&gK_KI)wx3A8GpNrRUVWPd~l#_{$ph=F`~AQnA3qVcVU1 zcE?ukHS4$Q&m}8Wg|mQCR_WN^9) zV$pI@p?a;=YFl}s{{}wt{=&@yFD;9Eve|^bYki4yD*Ia!0m|udYx1uk$mK`Nr43SxW{+ z)slyA=lp>$;tzejj%26w0v51-^Z#C4pZv(#HRq8BYQM8SUenI{pY_z@b+us03c5#L z$pihOXgXhBIEf>8d->KYmeqEbf1CM~CH3Vmf2pQSo`9f`H%bieV2?^9n5C=Q4ZkmS7Ty%PW(3x0gAP&gOhYhzqgXh`>pU;dVTe&^MX zFaKqocFM_wEmtvY8OA=nRf*RRhq?L^9^T{z)A{okFjV_>efHCzq_uX^pS|$G>rQt|lA6pMU;^dg$RtIF5A*W9_%I3V9U5G9NnTjREM(~c@0B8S0R1#8{gt=;qTV5r+$Fg`_^?ElQ{iP+*_0W>T9+ADQDKs z6Lzevw;O@qLHEP>3e<7}TC)WBLYUO}>kFQ$R|!Jh_U$hQ=zsjy#dQv=fp#6UEfYhJ z)Mx(sqPmgThwCFjINQ|U#U9DO{PbVceg_{^FJU#Vy6W2c)VbpQQcZu~M{DE}vuhP| zAAeXuqr@-9pmVD<`B*s_sq@FtBQ<=7?TB1%tkM7Zt$G6OKmSvotMfi`4h|fPa_APE z+Ks0VOSPcgr9x*&$pbo(){SfF;JiZM-_Q#_{_%_Kf7S3<04i`U-Zg08X_y{~Nf*=)*VVpv2iT-c1B+QH^4vWGpLmJ^aBbVK;fc zb;gl(?nggb`yDjB9$4^lJ@UJ2>aJUF;C1gT*@od8n1UNZ9KihvJMFk*?K5rfXm&q7 zho(^<DMVGEuyzdY9)gK?cw+=Y; zaE45~a30X|T0L@yTKUWWsEwm{t>s(c;34Fi-JuTAz%3Ml_FgWt-vBc**o9kC>%yJHZs!9D0n_P&846>;umsgX_`!F*Rc2 zYiRzz*1Wr}ucJ?5lI`Q?K?8Z>keTjAn7yb++Q=UjR^}@h-kZmuQ5zC^Z}*2k_lZw@ z>>|hWG5J2%Y#R9+txpvcQ&tdUq$?WdfxKAl!F*vLlDN`*m-u)hu-@x4vjjho_%F){oz*L z`*Y77^~k&h9LLJ3+iRF56CNBg`%__zPr@T7g8q#+hTMPq<+Wtd0)|G*>ZvCd)>)?> z$01T2@&IznSkQ4d^9hf!0%_K9C)UJ?6YHsGpRH{m-m4=<*Q($AI}44L*UJN=>qR#2 zZAS3Gl+i#F_{@Ad$4$E)ZnYZiT)z`@_ndUH_uXm z-}^fHJ`Qu}$B!BqF;Jrz?v48SB{lE9TNw78QJ?$Fg*i=K=6TkVv!h)cN7~3IudoqS zSKDP)8}1v_a^R=#w-Etb+La8t0Dq{!alRg6Ob6270m%j+co0F*I+zyAV7M{Op(zRl zMIDoR9r3PHYU1Gs)|=n)_WJ74ht$-)r_{$>)=eL8d%l@t)oSMNnQA?qyvNTzmR-g7 z*01+x;Yz84!gli(JY~2{@&Sg&uyX~IK>*kwouOI#Nin{)X zEtW8fwe@<|I<;*BMN{PghFB9O?7>7AQ@h*t)kMa8&-K5hmfdtijkx)yT6@}i>fwWD zRzJ(LwgRS+Bj{>|x$beROg4$LA=*uwd2I{=F?@gCG4SPoson0mt#1C@huNn7Gka3@OlxeGy>R0K!;8A%R@0S+iuNEtl2id zfzZ0^5Pj3V zqqXg{{cFVd$++YntR;&VXN+o^)2c6E>Rn9Y5NZ%5Qgcji<`)y%VS23to`=poS~_E*J-D{vmSl)QJ6NoCQV{J z03(xzj|6H0AQ3zhV2=rtY7VD-IO{kGCcFZJU&c~wyzJXGoWH(9XV$vir_{#X#@8#a ztw59CTqAhp-3oRc86J0ckf*Kq4&oIi#dGVIL%^eEpIKLa@*DN| z(!mUs_|?;Gsv;lrCA^-6o-jBDw=C!r8a)+I2_^BVReVv4!jA~=IY zF*7VfGY9Fqhpr^fFqG-u>#wNIPb{h-J9C;CzR2>;{WW#w+c|XWL$y1jC`UE=KH@c$ zk(bt1L#?8^luSj{A5i;S45vkHwX|KAAPtP+7{d2r4uCq>x4nUeRIMZ$PommlU*RSB zA`E_#N1}H9uwl#<5bd%b{(EgZb~j$EbVxR5PMNYt&0X+dJ^I71GF!HoBSGiX;WH1Y zqlpc8{pwf0VRz1)`q($VUSIvUpVTG)@VT1AzCD9Dz9!{mhH$Qe89#npP7nXk+2^p& zV6VFNifd{>#2CPkE@7-HUzrw&QoJkrP;hxZ{L+_0DT*+ZiWT-?rP;1{k>+ zfo~3$`ehYRhq^YTUHCUg3JY7ym(TyR57ha0TwUL}_u$KY{^tLDr|!J=SNYrjh+{dr{h&IE4JXrxka-N-V*HNV?tM6Q zON=aa=TkggIyMSouUNUF;fE|p6s?I&a96ZDiAGEsSL<&4S-pZUGlDJb>p3BOrPe>s8a~Ya*zvp8;O$q{ zy4$a;ahw>o9iyV>@GG`r-JdVP^tCxg6zx_$CrKFt^z{90ZKcAiiEqQa=H+wW@s3pS z$!cQ-(cIj}2e4@9fMvOmjUkD{V_qTzq}gvsFfT2H4o7RKX-gLn()uZF;|RfS%|?e` z{U>kSzViNBy82~S&3KOPkZd0HP-TM~&S@xh%Q%1km;d#%y5+f5b;Z2JHMn$XEoH0s zht4^d$&s-jy{Z27d*82*p7lOX;arGD_tlO&?*bu)5{6yI%HEOLH-Gl~POF)3Wy8tp z!Mfx6U)RI;G6hZk1q&BoiC(Sie|t^+@u_Ett}Lk;#~e==Fg0DkvZaed2-ng*P z)hlZiE1Xsn0o?S`(%Ov2Kb9lqhd=oH+IY!7SN}eT((Pvpzsl#Zm^ci;ITTMnZ~FkA_>Fh~w|KO1zqmC42wz2tEBP*iJ@0OZKP z_;)s+V849T%N|qqt_QBVx>n!x<9dyLeA9DJ)}MX!{Mvb^v55hk_5RP)yFPGcgy!4- z`=Yw|GB$F~oX)$3c4K_c+c%f5#H0`7#S{C~nWvsyClO#-w|Ss$!y-KX&;xbLwYSz2 zOIFpMXdP|evvyD5WOE>m+w?uH%4 z*T$Dg zhkL-8usMRZMN#Fp7em#?AB91a?{of0SGbM%BAt0=Su6l^0Z3|Qk9e#J$yOq|1uw0F z#K^dsrd0_gM{{C@_A#FQGe{peY0|_x@#w>9;*@E%coo~KZn?5ZWU1R?NyJj*=a| z)5}r;U$i%S-iY9G3*-xTz#WhB)TI)v)wke)vA|j*p-*EM)H~( z*l&M=Ktr<4ZQ&z#)$%2;*4xfJxjz55pRK(nPs%7oMU`J_xG(sYH?r3kVsC}ub}qQu-gqi9#KMNs%If(FvyB%$C72nDB4*UU#y60_HIq+db(o#M3dSOFx; zH&tko2C3Y+c-p67Rur=q&aL0RxcMlKgx_nw18e1mfx4RopufA}YLbi>0CG7elz|AQ=bfhMvoc8K7v<3dLRM-UQ&f6V=rW0 zVt}RJ%ZV;}jLKw$@Z=MZM{wTBN}b==5~gZbFMYX=IQpoX#7JVnqUUnzr$kkdC5BF| z*2ykLhs(=uP6oIRz{`M;X8>*F5UfovEU3*_z(|DE7ZGoA{LULpojvSlG|{&m+qFjV z=VVhq{=m{jHSF#iYRDzuDF%hLHU0Z5tSWxt@jq1mm|b~!hY+2Km%%dLt}I;wc@=Q|o=!O0QF*2-9$0eHhhF%JPh2FX ztxz)!eothNN|dhj`2Zx{C6@hLqzx14CQuzmlqK5Ycl`nd!I{9f;N#(H$VLorSa5ol;Qas(4a#^DjR^h+?}e&)=tyW)qng!6TL@9t9zpU+u=GdWsT zPyG=Vh#t?$VAtLCXl-7<1}BOM6IRD8Th1<8CRX;GIyEbnFa3WP1NF8w{m6rB(v+#3 zI{G~C2v{6~CQd*qbPgO6(|vUDiGW2yse_(1q@!$%-}!bn7uKd7cd3mJKU{s+|FnkA zeWV6hdpK+*0WJKWVVw3c{KbVeoY%w-2j?NbzO)AL7e-E<$ZX<9&Qf@iA@hE9_J==G zXS1_-`XL8$RNnT1L#r0aqh+}fz6b}j^3;;d+aLhWle8#xgHb-g@+d7|$PfHHGkpL0 zW%przo@wFvr3<*=qAY~)o&sj@v->l@l9kJJ8V<9O9=i&MgC4x-LJpF-C_sMAj%gm` zIF51kK`f7+e#ERAvE2@J7l$R>d;3lG;GC!9-TQ*&fng&uyXeMLhj4olI^JgV&UNk8 zch@{NQNFzJ!8-8GMVkGo38^QBNVWj2g8S3o&Iz zA6h@S(*){4A)a}vhW!4P>f%iK>_JR{;ovh5E?`IR{&nto zXVpn3oydO2Jy}Xl_o4zRaCB>ukgw_H3<+}=lIr;jOJV?8fM~iMf_d7d#r~5^oJ7z( z2#`t(D!KAHd4(uUPq|)3(TrwNb?-CQpjUx&7A+X0scb@^+15TZ2Ls<9WR*ZoWCQ`J zcbINH=AfQQPPjHOr>;Lp?GLJB-CD4*50? z$5?O6lCV9-rL2k}Nj23g>6)In_m8#jVF%VnzVd0hyuDe*#e4+{w4Nnr3VVimp*1bb z6s%0TT!lhL_e{Pm%L|1t-9qB~%`%IDdMeNS^K#Us<m4T@A7UB7 za~*;r$9R#w154;`wq}^f3nq_zN9#&tk#GZ-eW+K51GWjkBuqYf8j>vhYvuBpGWM6= z;R6uDrbrmxXsH-9CCN(~^ap4Yjfx^X&pv=vPrq0P9(ibe@b6A%I(t82CZl2%wTv=2 z$MIPyMZ+`xHM%Q4K0^>-_8a-p4cRSVUiekbk{B%glG;wPV_@QRwr8HUH4|6xWaQ(-*s1%PI*^iiU8=A3F)8-&h# zV-WE%&pKu%pJ|36@7_PbDcXi`0ew@F^1-Pbjx4mr1C|Na`xpu^`3K1PdBvt?t9coRwOGZhNm^{jln=7 z9eae)aQM|e-Dg^4-z{XcHEjZzDAMW z$^5Y2PyW2L5Y0hUKgkRJesjd*8&X_{r%*ie;xblu&8k>xKC1|vF>@T0P1S|||u(mF)!LDDSkVLMb zr~I&+8A5j*Ji!lx&DHLW8N>-xBb#~d0P!>Jn_D(+sUUX}i;C^+G8+|Qw*uDh$(Y&S zhA?=U(hx)rl~l~XOaL`L@e6<|uRn*Vb|c#});@~m4zRvyN_#2%crrzch9{hwg47%$@u`ZD$;65yCgTLzY(!sN=KXw3n|~azD9UW zyyp$QMx0)!Z6n(J^a3J@uRUFdAN!7)HS64(g3yihAPU-&=xYg#sd1nef50ZyP8V%7 zAtQnGHoR^$SN#%uASq@a`YNpLyYxYaA_UD+SYNw(LTimOoqEX{YnL^J!MD+0S|qo0 z@f*J!^<%gp5T>Y3gBb;w*{_*6}qJdt?`VghKp%d_KPsj=b&t}8dhW&a7JD#Q$wcDG6gpC(&-f+opW&GcW$)d0+rm zTx88Yn%e8abu=_@hIpG7+5|$P#R(zZ>0=f9{qcix2gok>^l);e_h zp*5KZ+gM)n<}9B6j9avPOG$S{kU`XD-zX5K$1)IuaPEBtn@OB~bQ*OXVd)nhpHGfq zb?W<1$w3sxHC&|O>S?vnW?qHk%+WNw-yy}Ot*`Wm^K?z=X#J?_IXZ2t!Fe-rZ&URJAbj36#&i#fy z4J&%df`kVFW;1bn5m0L!a{^jCSFHodR7h=H>j7qfkkn@UhWG$zo|3Gl`>VuBam|-t z2`E{p!|s5JxUpSZi@7#YLXb~^8pP?e4uehlCU2TLxu#5<#7f-5>+ZYnu3ukveSPzn2*H(O2q_G^f{9gk4cP8qp4{GyS-V_3AWH;z`AjrP5|Vhw%# z%Itbx$zqaa3+54~+_m1#boU|b2J$p=7h!l1g&SFOU}bNZ8F;}{S|Y=u+~_28`3p9X z%>54vzC!NPO!9coozG=d7tVFTT8{w~;~lV>?&FFM=&3PF#-w3%l-6b6J^QBs(i0BDIV z(0CB##TgG@r80Ewn?HZP^rz0$oPuv;ut{y^h-wv{aLcE!Uyg^@V=f~A5ds85#>zAV zA|7=F;q^B3`g4Imx*YQP>7Qldi3>QHtjC6V%wOwLl801J1XWlTGsXMpqjTzpn|@bM zu^Y#0{F~kknp&2s7w5iMXJ7FCoUSqFkB=m#|LXGBYBjTbYgvu^{9}u#=ee48bE1*74rlO&g>xOfqi zbVD?va14j>DyG`snCwIkWC+=$BQ%PVY7KavM~z;oha9g9f!`GhhldCh4W}D`rhQL7 zHJ|TP1`tiET?Wo<6ql0JX2@Eft}uz9!wo4Cz<^2u+26+VCy&CAcMHilE}5o7UJmq{!Y8@9IYP&#+6J_zdY}0pjcNkPdO#;H}oXZZJ3;L_!}5)2Y8`Q z@D-!L&4Z4ZGC*30ixyzZrz9m!nwhut^DUnOlx`GSTBhrx^#Np%rh5Rt!uD*NEXfxw z54U;9)xi@Xw=jGgN22-cbAMV zhg+4??=+F5+E(#;oTyj=TT)v=Fjj!?9#GH$XkBW#mk#GjHR4dl9tcX!r3k zc-~k5Jm%-tbNmdr7~7Uu_N%Li!9Vu+Tn?JJr|!SiWnnsl>Ya;0Tj+bIefF$lj(!X8 zGdw6q%sSKO>RVxO)DtE_3t?>prbANWr3W;yZ+B&JcgZBj`HlDh27GNCkMq`}r8}Er z=B*dt!}vGUpA9gyZ5=9L)+(f|?CS{)-{g-AakN0PHe{ha9d}`kh2&vi(R5M9k&XU^ zcc%C0Og=v6vCW>RL(Wv{>)DG5H!3P9sJL zC8*kI*=UvNF+&O#=@i(6Mg(XCNUgWekLFu9R|GOlCXKveti#%MH8jB^N?M*Y&8Rz` z))}5<-M~u$su5N0Oac4maNGBdB4c-AAto!6MsxC}Ojr*weP@q2>9PB%Cchr%5Du7v z4Dl4&*oNt?PlX7{pHoDzikXT9p61P~{i!ippJ7{%o?A3OE!w5EC0^ET9Wt;JKxv>4 zAtW*#Z?&0z?)~BjK%RA%`Sl%yo3G?=5kfLSBdsYB%6aqV*-9kaTsmB$uNHL;OEdwI zfl7b8M_UOJp*-Jh7zTuqN~cVBod9)GUIB<{SMoIFJu}vrjBtn&c^#EBrpi#Erd;5% z9hl4ZEqr+sP2s~XL?IF>o{`7y$F}^DfofH9i?mae5O3 zX`x0cd-mnIN1OAMygbB7gKpBq`V(AhsW?^EbN0t8I6iAXw)$Adru9Ck?vawSM3 z!(yVyy&21sQ3Gv6lxSbr@=RDL<#^kmQXdQ!4#`ig5iSW5JVRJo>%M(W;RC1qR zAIl&wFyKc<@!#iG!c(nBX6wW=c*|7lB$Yg|FfdLbvxrRU!m`$-=2_02(QyXJYqV3L zm6Mz4Ly7K3=m)`R0Nh&G*mSZ{*1vRvgmP^}$mE5f`(0SWc6HC0(sJ$&D3Q%*<-oZ zc6<(CRyh4HUdqG0%~oTwfzS6SHxnH3phRz6E;A%PMOr@Yd)9zh63<#12qZ2L zq1P(#qx@Sod5}21!g%}k_N*=SQrN&pvuPVz7%uUZ=KeL>;PdEQS_zj&#WZ+Z-Z$p= zyJb>WS0BzkR;yK*N>dF;_A&q|(8BOMZ~xS8%~l5#Uqa|e6Zw4;srjwXOJs*SN6b@Y zE6cz%MNr(mg=&O(Wnx~2$mbw!s*b`Da~@vu3=JBJpqV$)++(mXX-;$83z{o?U69!X z1o$CttcmSW#)uhJ1WsuuF2RR7(v^`eOkMvUrwy2cg(g~fd*x+l69Q17M$xt|Stph< z)^U9-rOFY(>gAyl)2&}J+Fe^$qn&jD4+&Hm+S%@wOTYypSNlvd_)&06wk=<}N2W=C z0p#k}lzF8t{wYoN-2#yiq{yK4Lg8>t6R#wt9RVi)ApL!N29daLo_tswVu4e%F#W2e z!8CP4IguI^8D$};s^Jp3-Pw)UPj?QHx$@c?n64$lCBO=i*J?$|{F-_yP@w#br6I2j z)yi~CAZrj0T;SzmmX0u*d2zKqVN~Q|`W1s76Vn~p6pyy#rAnFT)rUFA(kn{)(`hOx zrpCipOjHtKiC_VM+AkH9h=hKvFTkc+U=&gFH_IJCPdRWmttC?=2$Hk4Z<*k4Xs~zL zDWy=Bf`gpWs{0{(1k*%5F$bUUrx4g}No3Lx0}PK&)XGpW5Q0vG?Nk^7z?Y4&Xh zm?Bu>LpttqaI{Vd>ROCg8SX``bHvFEoD9nuwgwOCihxIvQmt8{3<{L+f)MoVDR-~E zi~>68m5gQxLu`#go=}?PioA;xgK2 zwB64zuC2V`o-)SDBj^&Gw*8(yn-ap+pH7oBknBT~TC|RP(6dW(7$`&1<)AbMDw`nj zjPzlVF6tBpV0IB~G@s|<6Kg~orNFl_Kk!q3gOB=o(EO*yO!;EnO0GTuWZ)jU!b{@> zUgkH!$fBRpPyE_?0IJ-gLm^NzSLyF#)?qg`20d&AP~nhi zT9Kytq{Bc3SKJ(W#i~%g8v<)A!hF*8_oQAh9#+|3e;QZDiE%a#Y$!mVY2uhGyP(!;K~!Ie@eD-K>*0|wMv z4v3Hl?P_cOBuva964hyy=~|1fZJ#S~9vsb~HX)YC*@f`0Ni$_+fnL065<*1v8@zbL zvtHi|aR`92;EMXp4-8I#Xk|c!wqX*_)OKnL6!w-mRrCJvFc92U>seC}I1 zrBncz6yfNeQok?+erT;F3mCS`B`vxuuyE7(1YKyumqIv^Zze>Ot=2_*f-39@pb!)$xi%mZNW5U$xdb&L!$(SGazoXE z$qiBAB%hFRN%R4kMZFTik&xbf6D*LF5E4x+c&@CuM$jv}W=*HxboqK)?82=kML12e zWA+;8xh}QwNw;lc7<91})F6%X(TF?=eBiuW;A~ zkf)wl0ls#oS-CJpGv95ziE@EpXr0Owe)lJEc^{zwH@<@g?KXjl#pZ!+B)@sZ%_8t_ z6YzDo#Ru@l%lZs7WZfF~K5vaTVkDFcquQ{ATDbJcjWBshK=YXX`lXqtE(O^ zHy9@{cUM*dOTaFq={!Mqt%o@BTDHVTfH-X)p}{Vj)dr!FF$%4HWAFe7M=?kmYz#oT zw=MB6Mo1Yv3l z?mUmzkD$1?q+19gRm4S5Oc$t(#<=&Arb>SlHW;@6p0u|;6-9q8R!N%l{)9d7P+Y}_ z4~e@_-4U^{8 zx(GB3C>mJyQ&TuKqP&RMx`rYxD_xx97qhwD10%sy?QNc1%65c+foqz)Wic{gwQ+=b;%4MO)&&P zSnV=WNy=)jg0CRu;+}FU$Y#2vSY~N$`@j-w7vhCFw38+R8;Pxo-hW{v@Z=INJVpT_ zL9>(PU`U7ep6wrRTk#Mn32GOBmpO=u*9&%^fUJ#lk)D$`l|H^h!_=cTXiscUptkg7 zHcY)C49`0vZ01$2Ir$1i2Z>pC%bu;%y@y^J8hU8zVp0R}T7U{ope+fa_BqR#Q3ma3 z)}?{>Gzo6pD_lHN4cap7-aVCf_o{}(vi>#Ul`&4cNg4f!^WOY`_HpN?o zPJ=wqSx%$?y+ZXrI% zMUrjAHu!6TZd;}+1m>|mHLm50+2y9TweSHi+b21q;(+7@WxzEJFwn{A#sr zONZzMg3$!oDg}@~m}{GAr4C=x;gn_L0Fukg?Os|(t%Gp8BrDdEGQz4rY9VAs)6O34 zsLSA2XhJ>d*~47&@)IZ4@+ydRNe|P>DRTxvho))Y3ty|=vP)rLEb(IE>5 z1O=^>p$b44EaX6xzRqvKTB4XignC2)0hysDdo?24uacL_6vhn@t!Zj=LQ_yH1;hXXPiFuFRVLDv0|9)^o&qbe{ot0&&!fZB*KTe-M3 z23W7`r#wGlAo+0t(tgKa?-6JInLrifQJ_uFJ^vD8ffm+lE-goBL*7&ezD*dor);8t zSPg}cTk?Z%TVZ0KOU0BD>1d>%U~UCAY?=htEOvloXlFW&+n|?e;@^GOL6q+8xd{Tt zv*hVY*_O4)>;_zNQju_JjcmY@omENyNnS()O>07fZt{iPdWyh4goUln5$LE=bBGfn z2nBU}I*4yci!}p%CvuE{GJHro;wnAN+y1OYOV=ZM54H|p8fZB59@w3d*ZUDjs zy?M5&$4sB(3hv3!%8{;?hxy6Sc;UU*7T!>|zh0rUU()Uycw;)xTJ3%|Yl8rQ5*(7b z{!lBDjh0FWYXzui4uzc^6G;i0)g);Ip8->1fiQ)31Ugz{nIMT~(r^2{3!G$yZV%U( zSiXB}IqS+$1}l@$v(+b6BsBBQKQUx1GZNl}dA6U$ECgtrs+JfL;@*T-TZ14|8xu`e z%d}Qm+({j7r4r;eiDMn&(9`4M;Uc=Oe_Vl040)wMq~eAN(2sE(DRFF*9Ac2#2P$ zNuB^`rc)>7)hgT9D!3rT@qA|qLJu3@O8%JHgfAj2u}WP#AvtX;6nxJR(fZItiD6y| z5kcisA%tbXtL10`FH3HLh5UYR8b^v@YPm!Ga7{@kt=(_Ir3b6+gju9#v;h1WmL*+U z$z18cH}MuWeFVxW>@vsh)O=~9hrh}a#*$rHHP|R>DY_iHfEMl4N=aJ;34ynI;T0d( zRWw?Hf71{f1+@?!h$!SSFm65&**1O_X!5}Tfs*;&+b|#e@sGSAwE03PQ4tB#{PR}^ zSe$?SHRq1}dB`W(&6B#)26?-SJl5z>%JMvYTQ5DP986CL;PzC zI2u73d@x^*@Mk{Xi~?Zo&o;dRnh*+$_afs*gDu}}Ha{lx%5fh<@rHY8vjtYlM?fuN zUaE~yY@tC@!k)UAsh4hxt&Akdf zQX&N`X5M=XBbolhLzXELJtC%rksnEpX-f~?NRg#xGK3lgr*#v8;1fupM-tO)`#yEJ zL|Nc7W-Y|Fr*#ru=?FN1XV6v5-eC4^Ap)z_;d>Ypp|vjVDJKz?G_}cnj9#u|Xxd?# z?Nhge6nB1xNJ;VsSIsu*X;O&|Db-YqLd#H{R-_HM4EFVgt>kQrJV+z6b!2#K!SXy>js{%r0C|s}qVa z#kK>d(D!ieJ!^Dp!rt}E%>vP$uu-RQ25&wUFo$Pe7Anv)*8xu zX%+?KxoMWSC9kw^9&qyolTCl+m^o~>mFZ(SSwz(G5KfDqvgV`w{|A+LNI@JOHXZ-~ N002ovPDHLkV1k~CbRGZz literal 0 HcmV?d00001 diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/templates/deployment.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/templates/deployment.yaml index 10eea712..d7defe7b 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/templates/deployment.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/templates/deployment.yaml @@ -1,14 +1,23 @@ apiVersion: apps/v1 +{{- if .Values.useDaemonSet }} +kind: DaemonSet +{{- else }} kind: Deployment +{{- end }} metadata: name: {{ include "proxmox-cloud-controller-manager.fullname" . }} labels: {{- include "proxmox-cloud-controller-manager.labels" . | nindent 4 }} namespace: {{ .Release.Namespace }} spec: + {{- if not .Values.useDaemonSet }} replicas: {{ .Values.replicaCount }} strategy: type: {{ .Values.updateStrategy.type }} + {{- else }} + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- end }} selector: matchLabels: {{- include "proxmox-cloud-controller-manager.selectorLabels" . | nindent 6 }} @@ -35,6 +44,15 @@ spec: serviceAccountName: {{ include "proxmox-cloud-controller-manager.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.useDaemonSet }} + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + {{- end }} + {{- with .Values.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: {{- toYaml .Values.initContainers | nindent 8 }} containers: - name: {{ .Chart.Name }} securityContext: @@ -49,13 +67,18 @@ spec: - --leader-elect-resource-name=cloud-controller-manager-proxmox - --use-service-account-credentials - --secure-port=10258 + - --authorization-always-allow-paths=/healthz,/livez,/readyz,/metrics {{- with .Values.extraArgs }} {{- toYaml . | nindent 12 }} {{- end }} + ports: + - name: metrics + containerPort: 10258 + protocol: TCP livenessProbe: httpGet: path: /healthz - port: 10258 + port: metrics scheme: HTTPS initialDelaySeconds: 20 periodSeconds: 30 @@ -66,18 +89,36 @@ spec: - name: cloud-config mountPath: /etc/proxmox readOnly: true + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.affinity }} affinity: + {{- with .Values.affinity }} {{- toYaml . | nindent 8 }} + {{- else }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + {{- include "proxmox-cloud-controller-manager.selectorLabels" . | nindent 20 }} + topologyKey: topology.kubernetes.io/zone + weight: 1 {{- end }} - {{- with .Values.tolerations }} tolerations: + {{- with .Values.tolerations }} {{- toYaml . | nindent 8 }} {{- end }} + {{- if .Values.useDaemonSet }} + - effect: NoSchedule + key: node.kubernetes.io/not-ready + operator: Exists + {{- end }} + {{- if not .Values.useDaemonSet }} topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname @@ -85,6 +126,7 @@ spec: labelSelector: matchLabels: {{- include "proxmox-cloud-controller-manager.selectorLabels" . | nindent 14 }} + {{- end }} volumes: {{- if .Values.existingConfigSecret }} - name: cloud-config @@ -100,3 +142,6 @@ spec: secretName: {{ include "proxmox-cloud-controller-manager.fullname" . }} defaultMode: 416 {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.edge.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.edge.yaml index b90cc003..36d35f70 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.edge.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.edge.yaml @@ -1,10 +1,14 @@ - image: pullPolicy: Always tag: edge -nodeSelector: - node-role.kubernetes.io/control-plane: "" +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists logVerbosityLevel: 4 diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.talos.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.talos.yaml index 2730ddf5..38b2e84d 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.talos.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.talos.yaml @@ -1,6 +1,10 @@ - -nodeSelector: - node-role.kubernetes.io/control-plane: "" +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists logVerbosityLevel: 4 diff --git a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.yaml b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.yaml index cf98befa..37d38de9 100644 --- a/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-cloud-controller-manager/values.yaml @@ -61,6 +61,36 @@ serviceAccount: # -- CCM pods' priorityClassName. priorityClassName: system-cluster-critical +# -- Add additional init containers to the CCM pods. +# ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +initContainers: [] + # - name: loadbalancer + # restartPolicy: Always + # image: ghcr.io/sergelogvinov/haproxy:2.8.3-alpine3.18 + # imagePullPolicy: IfNotPresent + # env: + # - name: SVC + # value: "proxmox.domain.com" + # - name: PORT + # value: "8006" + # securityContext: + # runAsUser: 99 + # runAsGroup: 99 + # resources: + # limits: + # cpu: 50m + # memory: 64Mi + # requests: + # cpu: 50m + # memory: 32Mi + +# -- hostAliases Deployment pod host aliases +# ref: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ +hostAliases: [] + # - ip: 127.0.0.1 + # hostnames: + # - proxmox.domain.com + # -- Annotations for data pods. # ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ podAnnotations: {} @@ -98,7 +128,12 @@ resources: cpu: 10m memory: 32Mi -# -- Deployment update stategy type. +# -- Deploy CCM in Daemonset mode. +# CCM will use hostNetwork. +# It allows to use CCM without CNI plugins. +useDaemonSet: false + +# -- Deployment update strategy type. # ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment updateStrategy: type: RollingUpdate @@ -123,3 +158,20 @@ tolerations: # -- Affinity for data pods assignment. # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity affinity: {} +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: Exists + +# -- Additional volumes for Pods +extraVolumes: [] +# - name: ca +# secret: +# secretName: my-ca +# -- Additional volume mounts for Pods +extraVolumeMounts: [] +# - mountPath: /etc/ssl/certs/ca-certificates.crt +# name: ca +# subPath: ca.crt diff --git a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/Chart.yaml b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/Chart.yaml index fd34e387..49aa7160 100644 --- a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/Chart.yaml +++ b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/Chart.yaml @@ -1,26 +1,27 @@ +# yaml-language-server: $schema=https://json.schemastore.org/chart.json apiVersion: v2 name: proxmox-csi-plugin -description: A CSI plugin for Proxmox +description: Container Storage Interface plugin for Proxmox type: application home: https://github.com/sergelogvinov/proxmox-csi-plugin -icon: https://proxmox.com/templates/yoo_nano2/favicon.ico +icon: https://raw.githubusercontent.com/sergelogvinov/proxmox-csi-plugin/main/charts/proxmox-csi-plugin/icon.png sources: -- https://github.com/sergelogvinov/proxmox-csi-plugin + - https://github.com/sergelogvinov/proxmox-csi-plugin keywords: -- storage -- block-storage -- volume + - csi + - storage + - block-storage + - volume + - proxmox maintainers: -- name: sergelogvinov - url: https://github.com/sergelogvinov - + - name: sergelogvinov + url: https://github.com/sergelogvinov # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 - +version: 0.2.13 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: v0.3.0 +appVersion: v0.8.2 diff --git a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md index c951a316..fd67aab7 100644 --- a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md +++ b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md @@ -1,8 +1,19 @@ # proxmox-csi-plugin -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.3.0](https://img.shields.io/badge/AppVersion-v0.3.0-informational?style=flat-square) +![Version: 0.2.13](https://img.shields.io/badge/Version-0.2.13-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.8.2](https://img.shields.io/badge/AppVersion-v0.8.2-informational?style=flat-square) -A CSI plugin for Proxmox +Container Storage Interface plugin for Proxmox + +The Container Storage Interface (CSI) plugin is a specification designed to standardize the way container orchestration systems like Kubernetes, interact with different storage systems. The CSI plugin abstracts the underlying storage, enabling the seamless integration of different storage solutions (such as local block devices, file systems, or cloud-based storage) with containerized applications. + +This plugin allows Kubernetes to use `Proxmox VE` storage as a persistent storage solution for stateful applications. +Supported storage types: +- Directory +- LVM +- LVM-thin +- ZFS +- NFS +- Ceph **Homepage:** @@ -16,7 +27,18 @@ A CSI plugin for Proxmox * -Example: +## Proxmox permissions + +```shell +# Create role CSI +pveum role add CSI -privs "VM.Audit VM.Config.Disk Datastore.Allocate Datastore.AllocateSpace Datastore.Audit" +# Create user and grant permissions +pveum user add kubernetes-csi@pve +pveum aclmod / -user kubernetes-csi@pve -role CSI +pveum user token add kubernetes-csi@pve csi -privsep 0 +``` + +## Helm values example ```yaml # proxmox-csi.yaml @@ -58,11 +80,15 @@ storageClass: cache: writethrough ``` -Deploy chart: +## Deploy ```shell +# Prepare namespace +kubectl create ns csi-proxmox +kubectl label ns csi-proxmox pod-security.kubernetes.io/enforce=privileged +# Install Proxmox CSI plugin helm upgrade -i --namespace=csi-proxmox -f proxmox-csi.yaml \ - proxmox-csi-plugin charts/proxmox-csi-plugin/ + proxmox-csi-plugin oci://ghcr.io/sergelogvinov/charts/proxmox-csi-plugin ``` ## Values @@ -73,6 +99,7 @@ helm upgrade -i --namespace=csi-proxmox -f proxmox-csi.yaml \ | imagePullSecrets | list | `[]` | | | nameOverride | string | `""` | | | fullnameOverride | string | `""` | | +| createNamespace | bool | `false` | Create namespace. Very useful when using helm template. | | priorityClassName | string | `"system-cluster-critical"` | Controller pods priorityClassName. | | serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Pods Service Account. ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ | | provisionerName | string | `"csi.proxmox.sinextra.dev"` | CSI Driver provisioner name. Currently, cannot be customized. | @@ -83,34 +110,40 @@ helm upgrade -i --namespace=csi-proxmox -f proxmox-csi.yaml \ | existingConfigSecretKey | string | `"config.yaml"` | Proxmox cluster config stored in secrets key. | | configFile | string | `"/etc/proxmox/config.yaml"` | Proxmox cluster config path. | | config | object | `{"clusters":[]}` | Proxmox cluster config. | -| storageClass | list | `[]` | Storage class defenition. | +| storageClass | list | `[]` | Storage class definition. | +| controller.podAnnotations | object | `{}` | Annotations for controller pod. ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ | | controller.plugin.image | object | `{"pullPolicy":"IfNotPresent","repository":"ghcr.io/sergelogvinov/proxmox-csi-controller","tag":""}` | Controller CSI Driver. | | controller.plugin.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Controller resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | -| controller.attacher.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-attacher","tag":"v4.3.0"}` | CSI Attacher. | +| controller.attacher.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-attacher","tag":"v4.4.4"}` | CSI Attacher. | | controller.attacher.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Attacher resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | -| controller.provisioner.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-provisioner","tag":"v3.5.0"}` | CSI Provisioner. | +| controller.provisioner.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-provisioner","tag":"v3.6.4"}` | CSI Provisioner. | | controller.provisioner.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Provisioner resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | -| controller.resizer.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-resizer","tag":"v1.8.0"}` | CSI Resizer. | +| controller.resizer.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-resizer","tag":"v1.9.4"}` | CSI Resizer. | | controller.resizer.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Resizer resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | | node.plugin.image | object | `{"pullPolicy":"IfNotPresent","repository":"ghcr.io/sergelogvinov/proxmox-csi-node","tag":""}` | Node CSI Driver. | | node.plugin.resources | object | `{}` | Node CSI Driver resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | -| node.driverRegistrar.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-node-driver-registrar","tag":"v2.8.0"}` | Node CSI driver registrar. | +| node.driverRegistrar.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/csi-node-driver-registrar","tag":"v2.9.4"}` | Node CSI driver registrar. | | node.driverRegistrar.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Node registrar resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | +| node.kubeletDir | string | `"/var/lib/kubelet"` | Location of the /var/lib/kubelet directory as some k8s distribution differ from the standard. | | node.nodeSelector | object | `{}` | Node labels for node-plugin assignment. ref: https://kubernetes.io/docs/user-guide/node-selection/ | | node.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/unschedulable","operator":"Exists"},{"effect":"NoSchedule","key":"node.kubernetes.io/disk-pressure","operator":"Exists"}]` | Tolerations for node-plugin assignment. ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ | -| livenessprobe.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/livenessprobe","tag":"v2.10.0"}` | Common livenessprobe sidecar. | +| livenessprobe.image | object | `{"pullPolicy":"IfNotPresent","repository":"registry.k8s.io/sig-storage/livenessprobe","tag":"v2.11.0"}` | Common livenessprobe sidecar. | | livenessprobe.failureThreshold | int | `5` | Failure threshold for livenessProbe | | livenessprobe.initialDelaySeconds | int | `10` | Initial delay seconds for livenessProbe | | livenessprobe.timeoutSeconds | int | `10` | Timeout seconds for livenessProbe | | livenessprobe.periodSeconds | int | `60` | Period seconds for livenessProbe | | livenessprobe.resources | object | `{"requests":{"cpu":"10m","memory":"16Mi"}}` | Liveness probe resource requests and limits. ref: https://kubernetes.io/docs/user-guide/compute-resources/ | +| initContainers | list | `[]` | Add additional init containers for the CSI controller pods. ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ | +| hostAliases | list | `[]` | hostAliases Deployment pod host aliases ref: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ | | podAnnotations | object | `{}` | Annotations for controller pod. ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ | | podSecurityContext | object | `{"fsGroup":65532,"fsGroupChangePolicy":"OnRootMismatch","runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | Controller Security Context. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | | securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Controller Container Security Context. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | -| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Controller deployment update stategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment | +| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Controller deployment update strategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment | +| metrics | object | `{"enabled":false,"port":8080,"type":"annotation"}` | Prometheus metrics | +| metrics.enabled | bool | `false` | Enable Prometheus metrics. | +| metrics.port | int | `8080` | Prometheus metrics port. | | nodeSelector | object | `{}` | Node labels for controller assignment. ref: https://kubernetes.io/docs/user-guide/node-selection/ | | tolerations | list | `[]` | Tolerations for controller assignment. ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ | | affinity | object | `{}` | Affinity for controller assignment. ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity | - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) +| extraVolumes | list | `[]` | Additional volumes for Pods | +| extraVolumeMounts | list | `[]` | | diff --git a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md.gotmpl b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md.gotmpl index da7ee0ce..5c3e60c0 100644 --- a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md.gotmpl +++ b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/README.md.gotmpl @@ -6,6 +6,17 @@ {{ template "chart.description" . }} +The Container Storage Interface (CSI) plugin is a specification designed to standardize the way container orchestration systems like Kubernetes, interact with different storage systems. The CSI plugin abstracts the underlying storage, enabling the seamless integration of different storage solutions (such as local block devices, file systems, or cloud-based storage) with containerized applications. + +This plugin allows Kubernetes to use `Proxmox VE` storage as a persistent storage solution for stateful applications. +Supported storage types: +- Directory +- LVM +- LVM-thin +- ZFS +- NFS +- Ceph + {{ template "chart.homepageLine" . }} {{ template "chart.maintainersSection" . }} @@ -14,7 +25,18 @@ {{ template "chart.requirementsSection" . }} -Example: +## Proxmox permissions + +```shell +# Create role CSI +pveum role add CSI -privs "VM.Audit VM.Config.Disk Datastore.Allocate Datastore.AllocateSpace Datastore.Audit" +# Create user and grant permissions +pveum user add kubernetes-csi@pve +pveum aclmod / -user kubernetes-csi@pve -role CSI +pveum user token add kubernetes-csi@pve csi -privsep 0 +``` + +## Helm values example ```yaml # proxmox-csi.yaml @@ -56,13 +78,15 @@ storageClass: cache: writethrough ``` -Deploy chart: +## Deploy ```shell +# Prepare namespace +kubectl create ns csi-proxmox +kubectl label ns csi-proxmox pod-security.kubernetes.io/enforce=privileged +# Install Proxmox CSI plugin helm upgrade -i --namespace=csi-proxmox -f proxmox-csi.yaml \ - proxmox-csi-plugin charts/proxmox-csi-plugin/ + proxmox-csi-plugin oci://ghcr.io/sergelogvinov/charts/proxmox-csi-plugin ``` {{ template "chart.valuesSection" . }} - -{{ template "helm-docs.versionFooter" . }} diff --git a/packages/system/proxmox-csi/charts/proxmox-csi-plugin/icon.png b/packages/system/proxmox-csi/charts/proxmox-csi-plugin/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..abe9fdc678f8578971a91744f478f672a5fb8bd2 GIT binary patch literal 37189 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