From c11e7b9596f8fde34ef8b3cdf284c549f626ed8d Mon Sep 17 00:00:00 2001 From: Daria Fortunato <10145007+dariakts@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:13:20 +0100 Subject: [PATCH 1/2] EN/FR - Add - Deploying an Enterprise File Storage Stack for Trident CSI with Terraform Signed-off-by: Daria Fortunato <10145007+dariakts@users.noreply.github.com> --- pages/index.md | 1 + .../netapp_trident_terraform/guide.en-gb.md | 518 ++++++++++++++++++ .../netapp_trident_terraform/guide.fr-fr.md | 517 +++++++++++++++++ ...rraform_module_architecture.excalidraw.png | Bin 0 -> 119413 bytes .../netapp_trident_terraform/meta.yaml | 2 + 5 files changed, 1038 insertions(+) create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform_module_architecture.excalidraw.png create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/meta.yaml diff --git a/pages/index.md b/pages/index.md index 6215dae30da..6b2a6db74a8 100644 --- a/pages/index.md +++ b/pages/index.md @@ -2331,6 +2331,7 @@ + [Enterprise File Storage - NFS Client considerations](storage_and_backup/file_storage/enterprise_file_storage/netapp_nfs_client_considerations) + [Enterprise File Storage - Connect a Public Cloud instance to an EFS volume via vRack](storage_and_backup/file_storage/enterprise_file_storage/netapp_pci_connection_via_vrack) + [Enterprise File Storage - Private network configuration](storage_and_backup/file_storage/enterprise_file_storage/netapp_network_config) + + [Enterprise File Storage - Deploying an EFS stack for Trident CSI with Terraform](storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform) + [Migration](storage-file-storage-enterprise-file-storage-migration) + [Enterprise File Storage - Clone a volume](storage_and_backup/file_storage/enterprise_file_storage/netapp_clone_volume) + [Additional resources](storage-file-storage-enterprise-file-storage-additional-resources) diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md new file mode 100644 index 00000000000..7fb4568d65d --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md @@ -0,0 +1,518 @@ +--- +title: Deploying an EFS stack for Trident CSI with Terraform +excerpt: Learn how to use a Terraform module to create and configure an infrastructure stack to use NetApp Trident CSI with Enterprise File Storage and Managed Kubernetes Service +updated: 2026-05-13 +--- + +## Objective + +This guide explains how to use an OVHcloud Terraform module called [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) to provision the complete infrastructure stack required for using [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) with Enterprise File Storage (EFS). + +The module automates the creation of: + +- An **Enterprise File Storage** (EFS) service +- A **Managed Kubernetes Service** (MKS) cluster +- A **vRack** and a **vRack Services** and their configuration +- A **Public Cloud Project** with private network configuration +- An **IAM policy** and **OAuth2 credentials** for Trident CSI storage backend authentication +- A network **Gateway** for MKS cluster nodes connectivity to the OVHcloud API + +**Learn how to deploy and configure OVHcloud infrastructure with Terraform to be able to provision EFS volumes with NetApp Trident CSI.** + +## Requirements + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [OVHcloud Terraform provider >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Access to the [OVHcloud API](/links/api) +- An OVHcloud account with sufficient permissions to create the required resources + +## Architecture + +The Terraform module creates the following infrastructure: + +![Terraform Module Architecture](images/terraform_module_architecture.excalidraw.png){.thumbnail} + +## Network constraints + +The module enforces the following constraints: + +| Constraint | Description | +|------------|-------------| +| Same vRack | Cloud Project and vRack Services must be in the same vRack | +| Same region | vRack Services and EFS must be in the same region | +| Same VLAN ID | Private network and vRack Services subnet must use the same VLAN ID | +| Same CIDR | Private network and vRack Services subnet must use the same CIDR | +| No IP overlap | Private network subnet allocation pool must not overlap with service range CIDR | +| Gateway required | MKS cluster requires a gateway to reach the OVH API | + +## Instructions + +### Configure the OVHcloud Terraform provider + +#### Generate API credentials + +The OVHcloud Terraform Provider needs to be configured with an API token to be able to make calls to the OVHcloud API. + +Your API token will need to have the following rights: + +- GET, POST, PUT, DELETE on `/storage/netapp/*` +- GET, POST, PUT, DELETE on `/vrack/*` +- GET, POST, PUT, DELETE on `/cloud/project/*` +- GET, POST, PUT, DELETE on `/me/*` +- GET, POST, PUT, DELETE on `/iam/*` +- POST on `/order/*` + +Follow the [First steps with the OVHcloud APIs](/pages/manage_and_operate/api/first-steps) guide to generate your API token. + +**Once your token is generated, save its information for later use with the OVHcloud Terraform provider**. + +#### Configure provider parameters + +Create a `provider.tf` file with the OVHcloud provider configuration: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Then create a `variables.tf` file defining the variables that will be used inside your `.tf` files: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> About the `ovh.endpoint` variable: by default, `ovh-eu` is defined because we are making calls to the OVHcloud Europe API. +> +> Other endpoints exist, depending on your needs: +> +> - `ovh-eu` for OVHcloud Europe API +> - `ovh-ca` for OVHcloud America/Asia API + +Create a `secrets.tfvars` file with your credentials: + +> [!warning] +> Don't forget to replace ``, `` and `` with your API token information obtained previously. +> + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Use the Terraform module + +#### Minimal configuration + +Create a `main.tf` file using the module with minimal required parameters: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +This minimal configuration creates all resources from scratch with default settings. + +> [!primary] +> We recommend the EFS `region` and the MKS `public_cloud_region` to be as close as possible. +> +> Be aware that latency between different regions may impact your storage workloads performance. +> **It's highly recommended to keep your storage and compute as close as possible.** +> +> For example: +> +> - `eu-west-gra` and `GRA9` +> - `eu-west-sbg` and `SBG5` +> +> See the [OVHcloud Regions documentation](https://www.ovhcloud.com/en/about-us/global-infrastructure/expansion-regions-az/) for the complete mapping. + +#### Full configuration example + +For complete control over all resources, use the full configuration: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Use existing resources + +The module is designed to be compatible with your existing infrastructure. You can use your OVHcloud resources instead of creating new ones. + +#### Use an existing EFS and vRack Services bound to a vRack + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Use an existing MKS cluster + +This example assumes that only Public Cloud products already exist: an MKS cluster with private network connectivity +and a gateway to reach the Internet but no vRack, EFS, or other resources. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Deploy the infrastructure + +Create an `outputs.tf` file that will hold all the module outputs: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Initialize Terraform to download the required providers: + +```bash +terraform init +``` + +Create an execution plan to review the changes: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Review the plan output to verify the resources that will be created: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Apply the configuration to create the resources: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> Resource creation may take several minutes. The MKS cluster creation typically takes the longest. + +### Retrieve outputs + +After successful deployment, retrieve the outputs needed for Trident configuration: + +```bash +terraform output +``` + +Key outputs include: + +| Output | Description | +|--------|-------------| +| `client_id` | OAuth2 client ID for Trident backend | +| `client_secret` | OAuth2 client secret (sensitive) | +| `efs_id` | Enterprise File Storage service ID | +| `mks_cluster_id` | MKS cluster ID | +| `kubeconfig` | Kubernetes configuration file (sensitive) | +| `private_network_subnet_cidr` | Network CIDR for Trident backend configuration | + +To retrieve sensitive values: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Configure Trident CSI + +After deploying the infrastructure with this module, configure Trident CSI to use Enterprise File Storage. Follow the [Getting started with Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) guide for detailed instructions. + +Use the module outputs to configure the Trident backend. + +Get the OAuth2 credentials: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Create Kubernetes secret: + +> [!warning] +> If the trident namespace does not exist yet, create it with `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Destroy the infrastructure + +Before removing the resources, in cases when the vRack Services to EFS attachment was created using Terraform, delete it first by setting `vrackservices_attach_to_efs = false` and applying new configuration. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Once vRack Services is detached from EFS, all resources can be removed. + +To remove all resources created by the module: + +> [!warning] +> This will permanently delete all resources including the MKS cluster and EFS storage. Ensure you have backed up any important data before proceeding. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Go further + +- [Getting started with Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Managing Enterprise File Storage with OVHcloud Terraform provider](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [OVHcloud Terraform Provider Documentation](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +If you need training or technical assistance to implement our solutions, contact your sales representative or click on [this link](/links/professional-services) to get a quote and ask our Professional Services experts for assisting you on your specific use case of your project. + +Join our [community of users](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md new file mode 100644 index 00000000000..cb8ef08149c --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md @@ -0,0 +1,517 @@ +--- +title: Déployer une stack EFS pour Trident CSI avec Terraform +excerpt: Découvrez comment utiliser un module Terraform pour créer et configurer une stack d'infrastructure pour utiliser NetApp Trident CSI avec Enterprise File Storage et Managed Kubernetes Service +updated: 2026-05-13 +--- + +## Objectif + +Ce guide explique comment utiliser un module Terraform OVHcloud appelé [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) pour provisionner la stack d'infrastructure complète nécessaire à l'utilisation de [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) avec Enterprise File Storage (EFS). + +Le module automatise la création de : + +- Un service **Enterprise File Storage** (EFS) +- Un cluster **Managed Kubernetes Service** (MKS) +- Un **vRack** et un **vRack Services** ainsi que leur configuration +- Un **Public Cloud Project** avec une configuration pour le réseau privé +- Une **politique IAM** et des **identifiants OAuth2** pour l'authentification du backend de stockage Trident CSI +- Une **passerelle** réseau pour la connectivité des nœuds du cluster MKS à l'API OVHcloud + +**Découvrez comment déployer et configurer un ensemble de services OVHcloud avec Terraform pour pouvoir provisionner des volumes EFS avec NetApp Trident CSI.** + +## Prérequis + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [Provider Terraform OVHcloud >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Accès à l'[API OVHcloud](/links/api) +- Un compte OVHcloud avec les permissions suffisantes pour créer les ressources nécessaires + +## Architecture + +Le module Terraform crée l'infrastructure suivante : + +![Architecture du module Terraform](images/terraform_module_architecture.excalidraw.png){.thumbnail} + +## Contraintes réseau + +Le module applique les contraintes suivantes : + +| Contrainte | Description | +|------------|-------------| +| Même vRack | Le Cloud Project et le vRack Services doivent être dans le même vRack | +| Même région | Le vRack Services et l'EFS doivent être dans la même région | +| Même VLAN ID | Le réseau privé et le sous-réseau vRack Services doivent utiliser le même VLAN ID | +| Même CIDR | Le réseau privé et le sous-réseau vRack Services doivent utiliser le même CIDR | +| Pas de chevauchement IP | Le pool d'allocation du sous-réseau du réseau privé ne doit pas chevaucher le CIDR de la plage de services | +| Passerelle requise | Le cluster MKS nécessite une passerelle pour joindre l'API OVH | + +## Instructions + +### Configurer le provider Terraform OVHcloud + +#### Générer les identifiants API + +Le provider Terraform OVHcloud doit être configuré avec un token d'API afin de pouvoir appeler l'API OVHcloud. + +Votre token d'API devra disposer des droits suivants : + +- GET, POST, PUT, DELETE sur `/storage/netapp/*` +- GET, POST, PUT, DELETE sur `/vrack/*` +- GET, POST, PUT, DELETE sur `/cloud/project/*` +- GET, POST, PUT, DELETE sur `/me/*` +- GET, POST, PUT, DELETE sur `/iam/*` +- POST sur `/order/*` + +Suivez le guide [Premiers pas avec les API OVHcloud](/pages/manage_and_operate/api/first-steps) pour générer votre token d'API. + +**Une fois le token généré, conservez ses informations pour les utiliser ensuite avec le provider Terraform OVHcloud.** + +#### Configurer les paramètres du provider + +Créez un fichier `provider.tf` avec la configuration du provider OVHcloud : + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Créez ensuite un fichier `variables.tf` définissant les variables qui seront utilisées dans vos fichiers `.tf` : + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> À propos de la variable `ovh.endpoint` : par défaut, `ovh-eu` est défini, car nous effectuons des appels aux API OVHcloud Europe. +> +> D'autres points de terminaison existent, en fonction de vos besoins : +> +> - `ovh-eu` pour les API OVHcloud Europe +> - `ovh-ca` pour les API OVHcloud Amérique / Asie + +Créez un fichier `secrets.tfvars` avec vos identifiants : + +> [!warning] +> N'oubliez pas de remplacer ``, `` et `` par les informations de votre token d'API obtenu précédemment. + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Utiliser le module Terraform + +#### Configuration minimale + +Créez un fichier `main.tf` utilisant le module avec les paramètres minimaux requis : + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Configuration de la région (requis) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Configuration réseau (requis) + vlan_id = 1234 + + # Définir à false et appliquer la configuration avec Terraform avant destruction pour détacher le point de terminaison du service vRack Services + vrackservices_attach_to_efs = true +} +``` + +Cette configuration minimale crée toutes les ressources à partir de zéro avec les paramètres par défaut. + +> [!primary] +> Nous recommandons de choisir une `region` EFS et une région `public_cloud_region` MKS les plus proches possibles. +> +> Soyez conscient que la latence entre différentes régions peut impacter les performances de vos charges de travail de stockage. +> **Il est fortement recommandé de garder votre stockage et vos calculs aussi proches que possible.** +> +> Par exemple : +> +> - `eu-west-gra` et `GRA9` +> - `eu-west-sbg` et `SBG5` +> +> Consultez la [documentation des régions OVHcloud](https://www.ovhcloud.com/fr/about-us/global-infrastructure/expansion-regions-az/) pour le mapping complet. + +#### Exemple de configuration complète + +Pour un contrôle total sur toutes les ressources, utilisez la configuration complète : + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Configuration de la région + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Configuration réseau + vlan_id = 1234 + + # Définir à false et appliquer la configuration avec Terraform avant destruction pour détacher le point de terminaison du service vRack Services + vrackservices_attach_to_efs = true + + # OAuth2 et IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # Cluster MKS + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Configuration réseau + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Réseau privé Public Cloud + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Passerelle + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Utiliser des ressources existantes + +Le module est conçu pour être compatible avec votre infrastructure existante. Vous pouvez utiliser vos ressources OVHcloud au lieu d'en créer de nouvelles. + +#### Utiliser un EFS et un vRack Services existants liés à un vRack + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Utiliser un EFS existant + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Utiliser un vRack Services existant + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Utiliser un vRack existant + create_vrack = false + vrack_service_name = "pn-1234567" + + # Configuration réseau + # Ajustez le pool d'allocation du sous-réseau et l'adresse de la passerelle si votre configuration réseau diffère de l'exemple. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Ignorer le binding entre vRack et vRack services si il est déjà configuré + bind_vrack_to_vrack_services = false +} +``` + +#### Utiliser un cluster MKS existant + +Cet exemple suppose que seuls des produits Public Cloud existent déjà : un cluster MKS avec connectivité sur réseau privé +et une passerelle pour joindre Internet, mais pas de vRack, d'EFS ni d'autres ressources. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Utiliser un Cloud Project existant + create_cloud_project = false + cloud_project_id = "abc123" + + # Utiliser un réseau privé existant + create_private_network = false + private_network_id = "network-openstack-id" + + # Utiliser un sous-réseau existant + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Ignorer la création de la passerelle (le réseau existant a déjà une passerelle) + create_gateway = false + + # Utiliser un cluster MKS existant + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Ne pas créer de node pool pour le cluster MKS + create_node_pool = false +} +``` + +### Déployer l'infrastructure + +Créez un fichier `outputs.tf` qui regroupera toutes les sorties du module : + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Initialisez Terraform pour télécharger les providers requis : + +```bash +terraform init +``` + +Créez un plan d'exécution pour examiner les changements : + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Examinez la sortie du plan pour vérifier les ressources qui seront créées : + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Appliquez la configuration pour créer les ressources : + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> La création des ressources peut prendre plusieurs minutes. La création du cluster MKS est généralement la plus longue. + +### Récupérer les outputs + +Après un déploiement réussi, récupérez les outputs nécessaires à la configuration de Trident : + +```bash +terraform output +``` + +Les sorties clés incluent : + +| Sortie | Description | +|--------|-------------| +| `client_id` | ID client OAuth2 pour le backend Trident | +| `client_secret` | Secret client OAuth2 (valeur sensible) | +| `efs_id` | ID du service Enterprise File Storage | +| `mks_cluster_id` | ID du cluster MKS | +| `kubeconfig` | Fichier de configuration Kubernetes (valeur sensible) | +| `private_network_subnet_cidr` | CIDR du réseau pour la configuration du backend Trident | + +Pour récupérer les valeurs sensibles : + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Configurer Trident CSI + +Après avoir déployé l'infrastructure avec ce module, configurez Trident CSI pour utiliser Enterprise File Storage. Suivez le guide [Premiers pas avec Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) pour des instructions détaillées. + +Utilisez les sorties du module pour configurer le backend Trident. + +Récupérez les identifiants OAuth2 : + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Créez le secret Kubernetes : + +> [!warning] +> Si le namespace `trident` n'existe pas encore, créez-le avec `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Détruire l'infrastructure + +Avant de supprimer les ressources, si l'attachement du vRack Services à l'EFS a été effectué avec Terraform, supprimez-le d'abord en définissant `vrackservices_attach_to_efs = false` et en appliquant la nouvelle configuration. + +```hcl +module "ovh_efs_trident" { + [...] + # Définir à false et appliquer la configuration avec Terraform avant destruction pour détacher le point de terminaison du service vRack Services + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Une fois le vRack Services détaché de l'EFS, toutes les ressources peuvent être supprimées. + +Pour supprimer toutes les ressources créées par le module : + +> [!warning] +> Cela supprimera définitivement toutes les ressources, y compris le cluster MKS et le stockage EFS. Assurez-vous d'avoir sauvegardé toutes les données importantes avant de procéder. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Aller plus loin + +- [Premiers pas avec Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Gérer Enterprise File Storage avec le provider Terraform OVHcloud](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Documentation du provider Terraform OVHcloud](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur [ce lien](/links/professional-services) pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l'équipe Professional Services. + +Échangez avec notre [communauté d'utilisateurs](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform_module_architecture.excalidraw.png b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform_module_architecture.excalidraw.png new file mode 100644 index 0000000000000000000000000000000000000000..2a0f9e4db7d197f0b7da359c0cf7f85103ed805e GIT binary patch literal 119413 zcmd?Rg;!N;_XaA6lF}fZn=TQN2I&Urt__HENq2X5i*%QifOMyHceCm4yU=s)xS!|u zA6&;CL)h!>`Kg;2}JF_Ux6on2`LlXE0pPodT3L_Kf72 zxDdahqc$Y%g`;BkRF@8@)knk1y8-xTnz`r^_QT!owS>m(Xng#)&V}Fxu2u$BbP^az z0RiZxRCqRey_f~F1ImUJhjc1gl6r@AHZ~TcC6}S3FPDl?i13lm{*R9%oYxmjE^Y%# z4kUCEsQ-SXJ;AWVF#r7?_$GqvLq&U5Zj2A<|IrWq>vXG;CydyCKP_2sA0bEiJL|gt z$3ssTYWpMH|7#)WN7T^3LQOb1aQ?5=co_r{nzFqFkHzasrP(3ij^+t2awmz!{$~X( zVQ{G&E{Jv}n}T5`P9xd;r0*={d%~QDOQSvQpvAGd7&VbZZ?*fEJ=kNV#Q(E=?#K^u z!SxkpGO(D(gS%c?YmuYSUZ5aC!3@n18W!2r#is9`{`#Q5PQ>fGB#9QMt`#4j)J>D{ ztY1r10|Qh;XLzP;N$2_w)q?$32>XA8^I;So39WSv1%XJMs+&tb##0L%;9H7W^e&8u zuz*9sEamUL$$NP^I;L{HizH+EyfYiVxoQ;u*{o*+>eX4(tmEZ5 z-odEW1xpx4IgR}pVGUl@W`@jKBD?F~LKmBZp;hX6@o3&O_8umD(Hw3XlM5j(DR{Xb z&4Pu*{{IlXD>Ql=StdO_Xc-yCESQjii>Y-s%=*F=8SduQ-*9e$0RSuI*+VNI`m8e?Q*hA#KP}wgKSHdQ>Lo*X z@}{G(jnecf|2j%95bz>J3F$U+D*;W#lM$_^BeqY8i z-365RqM}bvSnvpvHu0$2j~M4PjEoPpz7>FnMNR?x%w5j^Df*u_aWVt-lD70@KivJ zk9a&k`Ss2yRBhV#LtL9pGYDjFFq8^46PM5%7diKS&;HE2Qh#ps zZaXcIU9aIWyhd->P5Zj4?JxzK{Vf>&=vf#~?Frsr$Y-Mj)NU9R(<^(PiH>kX+u1C) zy>C|+-OnRHcbJ*vXONFrZ=oGG?&laQ)*zWs)XE@y_q#!2rlxu&S;GiMildoZyN?yF zjQi)L!Z0z<14_SX_rC}XbwxdhCKcqAx~_WR>_8V3imTLq83N)Xd;?}3N^N>!3KqQ_ zqIhFuW2)rAY0&q`b}%oerjYh=_d24Zpmu7l&l^J~f8l}FcAUXC7=ue+Wj`nozFGe< ztTFn30ozjYg!#Q4N!v78){3=5o#d5@Rzox*v@kQj2Pe3@E#mRkxiZD>uoQ>Ls%@bZ za6sxfnSfs`=irw9)FR!@5~-0tiR^(CXF&HajHxJTC;O|olV5ECptmIxU$iwFMC~v5 zuPZC^nqXe~tyP|kQtMFWT`;QEozeezrFtAV{i{}#Mk-@OVyf0f2hN1er>d@IiekCB8v`n34gpP+We8> zU@5u=nVPf130s+olJPrKOe)#cBJ}i>tvRv`{tE*>00xehd(T@kbCRb?=^aWAz0@a8 zSC4*~<||s(bj=lLG1I5d$RNUUxKf!6qx6rd77u#)hTrAL7&~olNWae$Yg0P#4IL*F z-Z5c$Qew&skU-@@SK{4(>R_abwW;HP@>jhkb#EVG4um_u?s{v(sW~HT#g@yN&Y{jve?g;K(he|-J0;a0k_tpX9s_qj zgjanuc2?=ojA(03w?)g6Y18}5x;oN)GJ_l}c&rV8J9U%rwch=wErKdqXdk#&^1(`X zDpYg}O_{JJ%KagRbi-NtmK*h7gAKjq$rZC5DT$c=wh$CCX;kwjpP4c;y6PRFgx`9V>Gtu%sH47x{dU4Dn4srU>q4Di5 zgRs2e7*j|`30_)BWtRvi(=X^NJgl7Qsc!1^7sOH;%OE^c*wvn%oVtpQZ`fQzkB#`R zJr;^mq8|J05^{OCKV_lhG@FIbmjvspG>J#9=c?V==y?PrQ9sx}$0Sfi<0_;pi@znM zpE1SqmA!8}>PvX>0#>PQP>a8g-GaF9aZ!88(lJ16K?Dae76%I#)Bkyz5ltD&7QwkG zimbNa|K2x|Z()*IX#?#f8?vSJ&HP}Z#anWx<(em;&6eyqk_JJpE+fbMoJfX!p)ro< z3+9oJk_D;`HOPcf(bLBC=+R`EG|`UVRdbB%teCk=E6TsFL>lC+QrMhb*=fEC8+ZD^ zS;J6R#@rE})o}AQwQra-^BuZ;%*P-mdtX1%EQ$LWPN#yV&O9$B+PeigM3ma+7Ta?j zh-)VhefHZ<<=9&#cnrhS<*rS{o{7pjWZ@`uJ|ocuA9AaUQ**d<=N^->MZc=7uH6Ur z>n`;xnw7QnJ=1EofI!0QA91Y*{xRon{#Rt_ge#%~AJ?zd1KI7dwmhc&5FWp@d6n7{ zaYA*Wavc<|mpYJVS$`cf+aN^OJ3MkC{9g;qGX*_gg^RDI0jW!@6wC z55JypPp^4dPP6|^J!RgM4rS7j9^ zx>DTGeu&<$&}pm0RAH)>$@@1UjZSY@`gTZf@B|@=N2V-D#ERJ6vWp+;)mboHUm{fq zHj0UO$m!J5=)Gr685nb`$;(!7`mlT8hBWm)y}MUsio{_qn)=>}g#h;_3|kFsmtU%w z7F32g|IxZCGkF0xV4hs>&5SAbI4NbruGIK>$7?PGKDk$&A``8pFJq##H=qmZ-AOF= z;k#D!BtIG*T5W8gg~pT>^LNcBRd01SB{pz|8d?_Z{CGgx?OAxfuti2Y;@;X#B-7~s zm*%R5Q!I(p#Uq#~4}5R{fgG2E1pfVP zp7wko-vdYCBf|=#4R~M_YwH}IAs$}B$D4ed*jd)CEd-9$PEl;2Rq!H6fFlJ<0JNRq!+D)2S2(a2L~m%LXJi-GAQ*%wzf0}4z8%y51zO?$k*D2yGiz}7(M#Q` zoSw`=NW1O@ylla{9K<2F+UHU7`{PMO#zmy8ij47odxMv6hYbVZ=7B-g67^gcKA z9Q2q)UN=I~4AtBw-o8*{LXGC#t!rY3l^g%l{C8RS_LFy_TNnjz8yZTDJhrA&>FEFG zKK%flF8LJT-sF}2r-D0wmM+3MOWTTh1slNRrg#yo})=VQt$dw`(P=wQo%C-JTW*@jsx-swf2IfUTmQCk8Cz6Pa zEgDppJY>3#0!P@bs@22A@@oA^Kyh44(VV^80tLlb)YpG|Pr^6I;m(wk;u$|Y0~s$4 zMH*fJh=EnYc|(aT6NL4!3wP+PMx2~ZJ>k#`7)#M{UBd;Wixly8{dTxEjzux*-}Lw7 z1~qCZg2eSL7J@Le(RV{wGSDWa|I$7`U?k#tycBM4b1bN)IpL>&Yac}ler|`-~2mCQi zdKRn%MlL?69LJA=R#q2{=kq9JGMXygsS@F#zQOYz8fi%2^{qFh{UzMgeK*&-fWa0h z*IoNbc@a6fq5W-Afnge%CMI35A#XV3gF}>5)g=-A%R&Zz9i}2-3M2O>KE3m@ z@g?F1)O}RmI>^^w#HmA<1Ma`=yW!p#1?bN^s_dcy`^3ph$(FgCru|lm9{qyx6?qI-2i%6D1 z{!6cT!lViU9+7QbrScXk;AIh%7RUX42>|yjua5#&$&o@_;*MH3f)Q#8moV+3sOLMG>&LmVQmZX!ouXzwEr>9Oa~K9Z%?0m zPI7zDHON0*!vc4UqTQM9rt+~-)n4FlCl?rs1$wo0sWy)oZ=3el4r%POH)gh`|BhIYpaCte9P8+Sp$<50A#8smf;|ZUC)M*$=Q2<0 zHU6x|{CA5wwx_;49>(>Tm|UYL5L?J!svQ&w2efeIo{s~Da!BL2_>W>ql>#;p16Adm z_Y_Td_q{mrZxqj`0DUjho4?Py1QQxNU2xd{y;m_`pan0{fdnvA!w|vkUkdjFw9J!_ z-0P{Mnh6PX=C`>+MC51wQb+zews19v)nD(y|jn#=~c@REECq7 zTI^@H-F!)A(M=-nCcF^Tnzr2#sI22~DB!kW8)RLH@y`+IzVtfV86$0ai}-YlF2PCVR@WCHxCz8D3b)m{&z%>hJ?q|_@-aKlH_agt?KK2-5@VCGLEsV7yYK49% z3?U@;sKDTh;0nyo$9XN-e()6E@iaw0x)}0&onGL5xm36|j%?#*Pphpg^UoN$=vMJ= zz)_AHgAHlKNR&FmyUaJ+9!DlH2^dqzo?fS6(vS7>L}uzUV>HiKZy^7lXiBO~i`mos zV|k&k*n>V41`%T95p;%>S$-KUS7mrYR`x4s{h!9(D?a@xoT{b6xvK_-|D09iD$Kxl z6l(kItFsFJ7`W`@X}NE!pg8(>ec5{DzXKv-DKH>w`3h)Kh|{LpR+2EX`u)9 zD_ST^!L>}{rHIBwJDKd?^3@8qVPNi$TA_!>WQ@fMa6ozY0%6KX;Y}s_KgbrdgZ?xF z`=q33X8^U89Xu_Ue+D!Eb1>@@VJgewZ;_&)^`z1~_m<)Ngn$JcmaYNCzlXI8Gf??- zST~B5&ymr^uqwzC4jo||`u~}=7_H9!*jk~*%I*CN@+XM@)?f)Fy8ch1rO1s=v+@Mq zC)lsY*iVnFSfM}Ru)L)VCMYu$^rF!CCKy@N_ zU!M+*Q!H2f4lEuo?y*KP>))`qt*rcFx7w!dy0?R2vsh#fyQ^akv)=Au4ZWV=6SsRf z?3LIa$%O+coFrA%9xW9jUb(eJfhJbAJ0no&0)U{xibt7+{da^#QE1Sz0L;LfPXp*& zHy6}?4^5JMLR%+sbJO2habof^#L!t?Ca0XMPuHp*i+p$mRaS1osI{8aOf_>5>fe0% zfGdU{y}f_*YY*qPn-nrb{B5pc(mwj-c1tJXgLz0ZC2@PBFqHD)!*WS-zB-5O{Nceu zL%_4@ZhB37?7jCdIYw67Yo8*TOnfT1#2(eKc|-G3_HM<05)3U)Faza)2-z*&RjX{_ z9gC-#jcoAGAnF2R3ij!YJENWM5#c{W81I#JuM1CeN19yrtpQ`Vz4q>1!)|~2AR^Vp zg>Wmh+S$3o;iBNpSw&idJr4rlN=>W=ut=(oSQ!jPqhak0bw%khB3gs+MHT%@@5j3e)zIm=`n zvkq$uqO3~z92b3_+(iU(Q+&Jn+)(Pls&Ex~OEX{1L7lI^Ikvj_?&A5hLG|$^@Ab^? z`RiXl_C^ittal(668TKQ#~2YSL9gF~iWt{6WtYmrCibB19##JUXn_0=G#jsVrD-Hv z^gF|^$7a82SsefRuu+-N?MH&ZcD2|#4f71uw~yw*6Mpp!Y^Zfr}b1(-?Z}rIXBThE%Vp6Df@844oZiNPIPk)EC4mFRwemjkLR9Anz4$L& z+GeVLCNr@2s5`H1J4#APxp9e#rr&|F<>^6P$eOH==vCj$ruT~JLY>FpWH20~jJt0Yiun;Vpj)O$|DecjGloYT z52_ZEYm#X{6u4(ebqaccYyzc42l|iE0xdZM#y3!t++3lEQ% zeS^R~!AyQ{6>k(U&agM#nf3hqCbHoQG~dXM#AUC;U&JW6idw8bEw|N*%B&h(@zY`& zJ-dmv5{NQ~c&#|@3^F+1$AP7-0-L*f?Q~pKVTbvY#LFDWkZy^8`nyMzxPxMcQ4K-s zxw=UmJQwKbTp)Tu-xtPoZ{NPWy)WCXo;&iLu4_c3En?MR$JwZUU9?&hvHMNt^xE3R zXMCx_MST4u@jGD<`ik&L45+iJJ>O&ev2gizc(2>9Qu7tgx5=X-I0aH+^mrROdi6_D zm!Q4n@+g9==aJ`-77FMZh}H+KbkjVj45?xd&& zJ9r=#|4v*f;jWyyGQK}d&>5eA>^u(=#R zufBA-42QCk&1(s*P$s!z==ewmZK#>XMuo$&!S>*J~2m*tuE!y5{qR zY)qKeNy9)9>E*@on14=(zNDso3ieM`=H{&T;ag0+MRTZYr)`~9K>TBiv_eoQyjG_m z{7oEEb#z|<>3#904 zTFj^kgT`e=2|p&y5!$FEG@TB5gWq2V;(u=>l}ccl9Mlwwu`#sS<)zoMMpmNRkOPZB zy*vD_8bYX{Y_A0F=Sjn45(wfy@#2?YG{osY%qk5XvEIkXOB>NA8lRGd7fd2V!0MBy zWb1qUMYQ;$ve22_3OsJ&yWfz_Lyi0;1%rxqeD)nqcltewp}Uz+eh6DsjwVs|a4M9S z2c-L&8O4{@rx~YOdC$?}1?}A!yh=ivBTpg!3ybzG8D7EQX83UGrFP`bgKg?c(*_|KfK-G2{=uA+bKG zuCA+jAaKnn4R4cGp1Ma;b4AEo)P&7&_LEb`?Uzeviz>0vhLPn69iVXgUO|`B(h}UW zltn+}-t;P`*&?$^tYev;jWIrI+~clODUhA0u$%OTAhhM~>F6?VvXoM{MHI6&^ymqe0&NWRQ()u6 zfz}6VIY{d)2pmw%ASdU*Y-#7fnVSi_5@Gr#8E4D2Gho!D#7V!X+W9 zU!sxLozO!ypjMNEM>S*-U~H`B;`s#bREqvQZ$)NsbUhX434C*UqM>02wm=Io+ed@n zXFhaql%!A?EV)ElVHJf}MKfV=+ekAY4aXeXtnR3SXU033?akAb7nrNA7YCJxjNG7ts(|ZFUgQfqdLTH`45V zV6)x#Z2ve)=D4WJh5h1PTJZK>l(W`w-US94@|kn#1!7ralC}P+@YTB$X+;RCW!D^S zc3)lv)2LBjpyXJ@GUT-eDG}vN;ie#Vvu2=j=8u3Ih7lLz3%nO+yw-XUqKy|$s56D@ z3Ves23$Lh(-dCwEu&o|4vt7cFt5kuVr7mMh>~4I*Fc)J^KAxzfivh;+^pjIy4L$Rv z5)M!ldZ5o3?Q)G=*`fEPXz4EB$QJJ%sdyhPbW*4F!ot^k@~3Q|WMEZ?$sX5_POk2| zDRC|@(YQ}fa@k40N;W^1J6_j|7QS2L4mK?he0DNfDc>}6!=Nc3+$jEVIEY6b$v3GW z6s-A}`<60H)x^9{G^dVAZmxGBNt%-~iga6sd$e(fvb{V1|dBHnmnnDwxE ze?u))tAqIW9cu~IAzY^V3!@mqFj@5qv!B--W{VX#^|ZlV4)W=vyG1wT>OllR(ko)s za?(fEO$SoU40Upfufe!_=7LXRQD^935|+mL$bXJ?zf!_ZP;*LQwfj@YNb9AVDNp&YqXD*Q?cWhWl)}nA-ZO+V zy0WFvplQ;Vru9p+WG4f!u259JJ}e;Py1iZL3C!u4sSAAnE+_V}iU%1*yST$&BfqA& z%*2v)luqUPZI*^HGiW)6VfKjORskPU$R@s|;%4aKTgvXEA#p@=Z)iLCtt%O-E(?dy z!~KOT9`>(Q;UEWm>R(h+A%Z`LCxp`NDJseqkj58z72&A^td47&W}h|xxO?|aQ9uiO znC$6d6$0E51M>zvyaLjYT9wk&#hWEEb;V*X$&A$~%!(}cq8IAZk!1CJ+HRSJL){>! zBnTQ8kog?B+@xcrIOvG?O@Fr5em9;(#e5Z19mGpLIg5R)A`yi!w#v=XL0(~;CD2E1 zNCyxAmKZAp1sMI(40$S*`;*NjA(3wUHVWcsD*^&G*SKr_X78J?doC;>B21GSpDqT0a;2aqo&O@QAccB3%8&T1WW2 z1c-^NrbInOWf!T!(EW3XkpBYbc;!&~ih6N;P4G`uM5l(>U#8!+hvTNrAx>np1a4q8 zZ|@LC7U$Ok!9F}&q@rowoQ=moqEQ`lxTwQiaGd(#liT{vM}z=a2BD$c&R86Il_m0T z09R$dJgaXh|3`Vkgd6z-5&5nDL;6N!{TCSmmrXvxzUWxgM4`vPD@nj~%tQZeOs|a7 zfH!17%kkiVqv@v102%h#np^o|O&7FU=zw;~CXQb9&)(r2@7q+@KmW|?!%}V}yE&)N zkyFRBKY9H2bB09p{F-J;t2alkSnU11+f3i-th5R^D957rSg$0om0EZ)GKgC4`|7*< zm&55~mUBNG7{fE~`vt=L<2XA^1$`sv@&dMLk%`@`)FrIXyA(o|Ilyw7;lhye__!r( zV#$iN$Hn5Hh{b{&L5Fp7^*b^mmJ|NYO5)LBgbf=#e`mp2oq8|)JSMT`PPj*D!o$5D zW40YdIGKfea;wiR0{1K0NSw?N|8b6t6Q$YQ6dtGMPpCbrhd|+OE);RFY+#4v5w882*~+? zA$_Mp60M|hR!$ep^YWGhLXb%7Acw%%*#`fWZziX+>Klet`D_>Ol7b2B5REJJRkY42 z<(W?ox%e1!=e9+Az!UK&#l2rOw{jl#vAVNnR~J2Pgi++7!|oPQwINQtPGPrziUAv8u6g2g4&gT+5ZEwYF}4xh(R(T?i*s*GKuiWWYbBI-L2 zJj+@w!)I#m36}d>Sxe3D!sM zn*_ttUm=8#kW$5q7Z@G}4=Z!O1H#*$BId8b{TGtf_X+o6jkc9oH=>8H{Nrk%@HdxlYH)9{y0)@<<=`iK{fE)RM=m9>Nw) zynBbjwKlElU(th?RxLop@J$SjDH4gJvHHkd8iHE(0bV1hd20rptF%OU@hfpR5uuLl z8cEZz;Ez)y35Zs|xh#(;r2-c4d`i=o0|Y@xWZj9GTGRJP za1wb(izOf@?XVvV*c}^{VttrR5AsT`_trcMr3714mZRA?);l6vqaN18rE;ug*j&YF zX1XB}z!mvD<>M&l@tdgf^s9T+=Qjy_$a~zR+I^mP0)9tl^7YakFSHg#ER-!z@oFX2 z&B}Zo0u%gv)dK_kj!CuK#M+QGC&^k09NxDahJ4z6HKFNCj5q-fh^i6{l{hw-9y3dx z0GX`z5j2Mf#!P*0rSg{O2>N(mBeVEyaT?dx>XDB6T_XY`?Ju%Bt3YfDd&QKmi=R6w zYglh!&*K#Zgf1LX3$$D}wrnyQ4Kdb^Vo&6I3pBG&?T;0@HofY)1-RcgA{vF9PQP)N zyW4-snR}DFE4Ycy%l^(P(_N6t|Lovp%sX=CbW5`^p4?x{l#8Tj-TIvs4J&=-YVee8 z+1vfqQ4LD)js>;*w{wHzme^|CAy3f^RAxy?pa)(E>+EC)GCW=EJfBElT5(zBrg%6- zR*y6JB1UwBU?Y)P5TSg=xTz&rapv`bZ+`7P?UcXlub?2x%J8L{l^1Ay+})}%Q|3ql zAwwZ0!Gx!|HFB#C@NT{bxh1XY@5J+ofSm1yF+DubPTNK032N1VWaUmXBWH$!tE>q5 zRIH=IPu9X4L2y6`&o`M8S7%Gf&k@WW$S$4v9S=4bbAqDigx0$YuOja-8cezo zKF2#HoX|z7bCY#c4XH=ni%jl&4%c+t&&orNZgc&xxeWNCBC|pTfi(wf$KJ;_mSK0STlB0O zk9*WYnEO4G4AhGDBa_f(OPGi1$0#0=2tROukvSfLbn>5Y0{I{}BN5w20Otmj9gbKk z#>~1D7xlVHG}esm@D$W>*```t*i)HgHh0=(r4-CAHm3W2Bt*pWpw{gKTJcm;do!J} zS9YcwD)8d9x)9=sPaAA)s_uAOWfS%&;Cto^be}1Y%k<1UpNnVvB z>%FSPO#K>maMjr}6E(sd9&}uR$pum?#HoZQ>~64AVjC}uA?A5mGJd>O6YPr0QPWU1 z1W$IY05YSd5q|rtKj037sZ8X7cjM#9Bc7g$8`h}xUO4h0>TB?EY@mxv9887a4O%m@ zVELO4WM(Nk>78#p)F2}D#bj|fv7>dto29Lv3zkC+HeLcWE7diBX$r2`~XXhCiW#h%7y}7FUrJ5U|3>ath zBv<-GA&|-kXRc^UOL1nqzaa4xU!A0aJ4`sb_x?gq->t+j*Evh43t#;DF%!@Wq;A44 zA!78kzTd^7vcE>-9OhZ#?Gli%#qqP6E*e8-@x5E`@4mdP8=d&HE%gBJWG}`ObSzHI zUy#asG(3(WA=Fpg^v<`y_ZhtGv3iuRUG#_2oRi|6#e%v|l=m2!pZwnry{5^`)x;%s zJ+Uy~Um&#gD%ZA{@{@7GxwQD2ixaJhsSsk{lkPzBh?MZ4nZLh|V zs*jA5d5<{L>H;a_P_(E}@ZG`Jx1Wpdr&Mt3A9pi?m}wYWqxZEt;Oj-Wc{*BRt+1T- zs6=}t7*TgdDvVU}ua3@U^$k?^r^l#5<(-__3}`Y$x3-`BfHON2GqOm<#1WeKD1sh>cUKa(56|n?8C^5at<2kOX>IAKqfAs2NUHaa!~<1$044-cUYDg3evxG$M&M zGZ1xLwR^6*EQRQ=F>=~%-;||7jFQ#Y96al1UhX}4C-`Dbx8uDEuj9%YiR^6DgU&>S z@J!8{Z`EIkO$USK?=&dv;yDfWu}L*MuyK8&LKPboatApJqO}u7f%sq`p-r3Wa47{* zfoQ39{4{Ag4b|m^LSB}^2x&C>4OuFvVkhH~pfiTa!WA$KU&96Mqpi9bgQ%-(x&uW6 zQjy4Ss~{Cz6Yx9$6T5AQC!DY;d75bTR?&{I?{o1b8PXKb8-cQw=mav^?osM%Z9xjq zU5J#h4fmPqywZx|FSe|YPM;hMl!-7ahqRNOarhj1cToUf%s^|Tpj~c;_=St~0H-)<~=#`LnGCzM%)->I6a2d#k zHCqObfXySKvaE{od1Tr^8;a!$hsBr0!m(MTP$(3C;@X15;qTti*J5*>q2+D)?`GZa z)+Cm7c*6Qe!6Adc_M*AR^CfVwE=urR_I*lo(?%MLSSrckOO=e`CXV(z%_!(Tp027$ zsSm_ia#v;=LVYcGIfznIw03nzD!%^S41V%jF#Bv@4&m`(L7r-vPQ!MSJR*wVm`cE3 zhlZo;ytSHSe&A)mgFS@MUG z9j`<`3Whq0hTxchNqFBfVg=hwwT%f^&iAL#W{KrXyo@9G4oOtzR1wycd%0;HhpLEP z)XR!8ktxK8MnNCqTNP-H*h&6yxIXyR(NL_yOb1CeNpUCQP7`TDwCgKlZ{lg|{SRci z{k%_g zRE!H%d>7mMSLPv}WWCv)wjU=&X`;Iey1!yg=U*Vuj0X5ta{0S}DV4xDV^AZwiiatj^ROBjBbCDP?ji?W#?5u6cp~v?QEoHwy*0?97@(6LS zf__yQMuEOXFDnLXD@?TO)<*>Pn6C$q?lq%_g2!*n)Ib9wlct0RIF^U#X#6&`xVJHm zq|OD6a`D189C3H~LC6b8H@9CGxkBw0X46S8gD<_$^7WN&yip8JU^x=|~N9y%Of zymBjx;}Pk?&60`L^Oo0;CGn7jF6IA|jW!*iaEbZ?ZNXsQW7VlUQ2cZKxzin4?>M>y zCaq=J`nGC6nMfXv;c5_x$iW6(guhNtfSdTFu~T#iPHQy1V(5n~9RG^O8Oi*>y;4^a z)C!U4e04-6=7TskpOY?@2l%%qryXrV=&R)ZRpF8mmry#hF>G;LaZqNd2jCeGG%b+$ z?s3eN9T_l>HXV>vu)5Gx)r4-#=8JCh0q#LMEo%=>F7urM}EP zKS1J%Vbuzgngya;`ybCYRZP>1$0mb|WpgAqM!IdOYP!VH=4HGTz2O%;R0c4O7tV$p%)-ejRsH zx(pLi3{ZZ*gp)nqMy=?r6gyECU!Ao*lDM~NS>$P}W31p2N%y0dKn+~VEis~IxYusP z^`RsPJ$01oo4)_4wCLC8vN3;&9)6uKsvy6+S`9dT2mc(u%K)p(H8oW2YcBSJKV*a_ zZ$k|XyVcGDA1HR#8DRG&zbxaVT>Nq*YAc-sJVl_yxl!?X=Qtr&+k^?_c)2dafQ#l5 z2zHV{U4s7THJ+{XCS~no+Rd|-sng^9?~q2JE#t^hfRRR@JV7%vKj3Ja2$3m&O7Wo| zk^JEkaBq8AwS9cRo5Ljcj~&w{mu;$}QPT^S*(NIb!&@r{SPB4r0hXA-;fXe;WfXq@ zn}vq>r~j4M3>ir#!=wO#`9k;7pNwiYG8D^iG6;)<8SC{E8Kg(cpi$kr{0(iJ-T zJIh(yT5p-yM9cXMW@xeRKTIb1G*2~v(GaefAz|Ob50I`1V7h;EF9C1Ev z(^mDl|5IS~;RJr9iu@W$&F2N-36q(@eT~8HxDHfkC{X!4VR! z4;yxgJcpo|c;~ydE~w~d@Sp@w5c&Q@*1N8U5djsY{0_&wKtj!o7%qjzjDHst?)irZ z#1>)Js|n3WYTpydsD<3!MqyO`*n*YHZcX?a+H&P&1I}Q0)9@fr?Ki=v4$bQ*@Uvn` z^lQU=n@sfy*X`MQ5W@N}9vie#2r$FKww|8KA791fLmNeHL52mWTQf{gy8}tr+3C?|1wEarCOw( z7&z?8}#X9t{X zE<#ER@k3_;&R={YA z1*xz1XF)?-8NH&Y=;%?Od9di#`MWPD(3?Juj+589avVFGOwfB`4+eu=H0^+@t}4o( zy`^~;Y2Ke_*^iweEBdCI0GBF}caL2_(2{C)>jbD-vh9wB*S0&ipV>AX-yLDsHBu_|xC;v#M&c>o(grRj9PJQk5Tr&!vc(@N#VHWZ1>02C>ln_NdXg)0>$qnN8x z{N$ahBAUH%NeG{<8k$r0$R<+rVAK?Ie2g}QsHyDZCh(k3tE(6;?oBWRcD=$_N-#ec z-8EKiM#al7>j>r<&IF$0C7iWRy3RBV^*^|uP7=br^miKgvA1p*G7;lR^9QtvZz+mF zSO93tq3_3c@TY&0!-+=d_&lx@9bKaEI~#g3CXZoJ1aCQRhgTU{e$@+6t8-vFo>8zz zLO#Uxb#-FVX!0X3DqkjA!K?57P}EhP|m!TjMvWA1fR*YbK3crj#`H zs+#V5<5)0c2nbS_>mY8(<`epdb!LMq@{>-uvD4z|l?S=rO+%F8B>(6Z5H6pk)e}Ma zK(=Flj#;&C{kuC?we1u|HOB&O~mBJEbLEAzO0D7!z7nCf$wF0T{SPBgzkVjtYelJ~~ zPT0Vd8=IY$J910x7O$VWyWqQNQp1#5^IOP=4~405hHsT!(jQHjf@^@%*9c z`tF^%D%@UzolJSb{eud?os-wBU_SJ@xzX#(V2B=^$^Y=sRcpB&vfAmYE7&b{o-+@K z^5t4EAj-1gO61AUZ>KhYm`vW>jq78*v5;DW$tZbN{d3B)zGahBxj}>%qB+GgvzJ-Y z?BFsbsIfPUwb801xv#S|6hLv~FwtmDTC5d)^h58EbLmGtlQN^2qg#!`(oR0ao1$u# zD#bPes0DT~NrBm`xa9b*6rpzO*Rwl1@0QOI-$c?Lht|L0O7Y;g*b z1Zbm~xrPsI3XW?F(sem70SylN!pK>%H2Xey6N+%bH|5t?&j5 zT#QY#%Q~}x1mp8WR>p=s;Na}1^nI$*&Zk||OSl906UeOY0s41A*&f@s*f$sjow(Q9 zg+jA&nX!Oc0m+`Fb$Btg76qxMVJlKiTC?%H?HmW9m@ZsI_HjjO3AFarx13Ab>c z37KRDTvXR%b<}QMUf(mFAeZazaByGG<0%$L;_JB1!YL`rq>s}AH+?C!y_K6x3025` zwC6Ppx8VY729hZV>Js_;W1%PX&c7B+CeUj7C0BwQo;W7_vj6^~EndsEF5G?zj%mGTf>K zBi!ys89ysFKg;<2w^!c8dHS|8sJkOS7cJ&@6#9ed2g$5rw^D#fiY?iobvD86{gbdd+?(ajp9ppWc(~ zcT8uz3%{i+PT~hQuTX|xd-%g!+ed|L)gDQiVGn+(Z6M_)ySGCXb}XMom-CXI)=DpwiKP1+a$NRAYm*&*%-4N7RydfUFi^6gln zI6Q#Lss)99M8GSE79+`-Tmaci>ijfXGHiTYQNAMnQP}wSjS#4>sDt;S?_0~V$>F|Q zZ-1Gu#^X_VKKuJL3Z=>MWhkK{FuA%y7Xp}?X9}=RF15?NfQX%RCV3JHg5?v6IlZV2 zhl7{V2xHD%_M3pKo06gf8PGmM^kqQlla=oWiQ)$FohgVD)$x5IKv~{(mbX}|CK6~V z`y$hLBLC{_K#sCg)Zhsb|`*pu$T+Ml*4ozc6~`h9OYE6$+MZ zx@!5*+WcdleIH@$ zZ&;HL^0iqYKJ8&@aWSx0Az~N)|KaK@gTm;7ErYweyA#~q-GaLZ3GVLhB)A9H;O-8= z3GVLh4m*5rU)9#~lPZdy?w-Eg=k__1#$L(}s8^)z{{5LxzQ+dfAE7~t0mPxalMu3m z&q;v>$eamGUVN>b9CstI`3j`|I0Mev*T6tBCbwxEdiCNBIf4yPu$M=zz2^x@UKiuz zp|B)bOgC<2E|IM2o0m9w{IX)r0Y8U#W9)rJt0>#7$e}q0X`e5&nr5^B$uAgF9(JXI zx8<#R$v+7$`43+lux)NtlV4JGlW@lKPjX!pbRL?^Ypp^2E#tz?2mOztTu$uqAl#%@}6hOYFGx4t>_E%TjA;NL*{ifedx`O;jjNfMp0@k>G-lGbwK0FB@*+{ z3=3jj*%lGw&^`5Cvm7<9HeN^sT)RZ9=tJRn(^<%D8CY)16wtHomImijIBhOe5J_b} zq0UyaySd)~Ys%Tk@b*4q2RpFW@?&rH`D_a~f+V6n`3)^isZ?{@#WMvC&=t;4%-u4i zTa=D{&(_YK5%2)q#NP|W{b5J%(R0k#``tkl9#6Mtb^FeNlGS(_19`t%*WG^Kdn0->6i}km)%7uFRVe zVC^go(dFr%y*|pptjTI*E`W;dKteE|hYeEa@!{Y$>4b|)RvvlDq>Ke@AD0ND)K`T{ zY{z`8#D>UD9&I2TU4$ual;?|3vhuMs0nDU}(#X`VM|yJZlfgZ`JD2(X*t8o3(Oy>$ zYebQtR*1_r^E=fXC!I6NjqJi|!@pYe88ZTv;|e~>R?K_FcE%lsdHEN4o;xkebVV*s z1{G`A;efzWh`dhFH=v(|Cs4u!*d|&AFDnL;)w^9z7DXaKoljR^vT?LP5Kb`MhwDrL zzP|hGQ_K%|y+nKS7YhGUBpy04Ky=7{zcoWiBfUO71dS>!gDgTNiIR~K7T>!ISEOSxD;|e20@n^)dTmHKS1ke}f0`fke`;R{shNFl& zt^K!?icjJP4La=#s&rcJNtay>BHuE+j-JI1&r8KnxI0dOs05rWndr9`Adw@5ox*LqD}f zes8Z#F6en!?>aspXI>0_M__L*)Cz^3bxBMr5^y-Aus#5jAo@Ko0F%!Y>1F%HM;ja^ zmS6?5FLo^jD0rW;CL5P??l*fs9=H2iZ&}!O;!<3=lKfd0^sET{UenYx+i#;)hWbbN zql6A(DVX1z<`wV~|Ens+@@RCfET2{7djAWHz_a7mZ_%U{;We-Cc-rf%G8gi-EKlw`#f*-!n3yC%KgLiH@a|?D?_oqk!*6qgD ze&y@wHfs*jct>bM>@y^+%DcGC0vc6qC6k8${h`d=*xkd%Fp{_CR%M;RY%G*fz1|XYN|lzeGVPZ`Vo$Z*lD#2U#gJmWtF6;uTyCv2+^#d5_uynAHb>NKuq*51 zeP=p7a#@!BHb~=@cq$L57Fm3gj6Agj^1=V3aUD zT#q;+y1%+`oW1~?C6d53>MUN5x5ZMuedaf6JJdEL-Q0~@ob6!jG39-E8#Ht3NdK#I ztGODVh3_`r_sW4o!3G%vI5F28mj`xurJgfeM=2aefL2{NGXtdgIOR=!^VMxQESKYH zI>&Izibr~s0Py5MM)BYAJWpc%W?K1g zWs_4a0z6HOklYTtOW!i?(&?z&B8EcH`*=w^7fE`fZl&iPcM2F=ignX6xylqiA`R$) z0V69MvX-+Vb>o{?3O0<4c=gX3?3XBAx;q6xSz?_E*h51GG5Oa;RS(VBJN(h1h6b?G z=W;on<~kDrsVQKUz7SIuQn2Pznxy-ly@rrQ*;El_THtsD+WYd!Haf>y?!rL=SXtWn znAVVV++aRqOu^vJ_V~9hyE9X4R&!r9|s`YRTwjQ;U^GYlEuHk^i580_ajidZRehl9Y>Jo`di5QiL?Y@a5>@oNWqmr#(q4{Y zl8V6Ej-eiU==?aUYUDLztzvem`LI(RT6b-PD=U4-dKvcswLGu2gBvG z)`0I-j_BlYc&Vl_)brlL6aY+EOZO!N3;PA|VPzSO$&-ZKq$$-+x;A1jK; zGT`IQgKwVy){E z{Gcv&iAY)VOj1(i6BTm~HvqOiuDz}nsZ~sh?stKOuRfFA8>HjkiVw=oe|nuLC%JMv zSPEhu-{Mtz#hj6iM8)cTX^oCQ4^bqShZvSFivuqd~&t=irYhpTOd0WR;5SP7)D+9&Wie6hT|g(a-C`Ub2_> zHxBU6I{&+4k~9}~hDYIm4-oAfVkBilS0`fhNjeC5uk3^^_rp>p#7(>KvRpi&qX}@- z{_^buTHPREL}xeeSnT(6tNX{sJU9vpAN-bRC-3FArD@42it`)j8Zs^}{2R>d{^5Ya zZ?gdfS-&C-q6YxdLNLeID2sdr`0dGA9Ze!4M*P)fJdgw1($vGFXPZq{T9Qn6BdJ&< zW{Ix@h|G-}e)*xkCJQE;GWAw!;B}M@v7<{r;}>f-K4|-?lbdWOqbo|*am{+hT8i(k z!miEi#zTebk88!+C`a-5Jj$sV7Cxno&V@JgU_+=K1?`5+iP-yh;?!6QcYqf5A4%On z>~7_x<8p+zhZmJKVsLqaM0Ec&q$)}QtEtq-R4Iw_WEQU*5lZ78A1ryRu>jAfe%|g$4`4l;jvjw^8JmAL`jZ`e z94n}v&q(?_I^BH5&mksP`!B%e**RL630*~M5w}W9_Dw zj;v|aehm4EQg&fAnR4S!g+my0yp!tt*|iCrD@EdiP?ON3VlhZOJ5^Z^UZBMuZfNbl zOC7s=@B^2aBWTD@iy9Pv;g$cgK;1EhU3B@{J4!iv0$?TC8TeS{F0kZiX`X1)9}IC5(SS(!`zlcyhD^0i*r3LZ-wd-e1NXWx3b%VZD+;)I(tN8 zh3O(Q&q`@`v@6vM=%MM1^Dx@M*_CtZUArp2XDM_XCloj)=Q3S4Uc^4@y>iA}ZN&dw z`O?Dip26lpM%7j49b^G7a~!`xbx+Bx^~IeP7f+x(W>G+*}8(r5P(US zOB84|d|ZQ(E^6;|WK@D>+yXqlA1R@&H~cigO>a8>0ad95OO zyel-9$r^^|!02lX^<8h|r&XJ0NrdK#(M;t$kpzgp&?jU5Hu*~*j}9}^MhJ>;##brR z@(rMkSYn)$=7o9VM5u}%V3$oy$5)-&QtpzoQQ0!OhD(O@%dM+?xXXS|N+EanA4AH( zNmW_O@s8yKv<8v}01M2a zGkm<~C6kGy_QNT`eo~fs{W1H;<+i=0Epln)vz4Y{wekxz(vg_5 zO5i9Nf=TT-_kG?&e0@Ff9pdfhl_mxOofOnTxad$@Ko&3}6sb!KUIz;Xe3nE%p=ZI~@wwcEzt|2l@f>|m%C zVomPTF`K2vLzH`enY0Vnxr?n?X?~T|6{B+haJTPO@FJ}2pv^4}C;XMFCc});$~ppN zQPHlu`lq>L(cxB;I=v~zg(8!;5W&-#X3N&8`yJRhC?Elyrv1XUTjT)-p#01_|G!V> zzcDUNl&9FxlN)jb|kl}2|W%5_~>(h=g5I?mo)+9wqVXs#rM zg@qG_T~M)}Rbj`Bz%;9vemdjj-az=J^5$;!Yt|Ye!7{r1G2gZ4=MIJxGbkVdGRw{D z`EbcvC=U!QK=0q556cDm>&WE{i%|KC4+X;2x&rB&ISOOAaJT~ z!x+K(u2;cgslq<8$3(PJe)DqLWU<3d5c1(-XPMyp1+d2g=s)Mm1ZgVPH_&;OBJH>Q z;&=TV+M?6Ad6gY~-fdpl*eq3{)M%3%GAu6(k)vO%aNjTf9GrCyUH6($O&C6n+_`V1 z86mFOofQoaQ@h}|_`KJd_~k@%e8tQ6UQ+)1!*4bt$LJPNZ!1UK+1J>30yXe?g#?6< z)|XtQx2iqYFoByxSr6An_V4f&{dJ$k;jWww#mETrfWs4$C6*Ec#&mQ)Bq3~UNd-^_ z;uAl8{1#GyO|(o$Z5KP_^yT}Eraq!1(Z$Y>zj#%A3300i&tl}B-$ELjJsrGiOm60d zZjZafob>CO(Ez4O_M*d!D>;j)6cQujgU5AWA6YzmIS)2>gt$WW&tD8#Hs<6l_pYYo zwWf`NnzHNl(rY-Z+JgB_$<_>xqQCZWJu8ji}B%qcLB)g`E(65 zgx+-9+1t1O@S~tKk$?(c7Sau8aB_y0^Sq}r=|vIDFE4dW5-n71h=nzdSNqNYYy;$& zK?JLvAp^?I>!fmO_4;bx{XY=|2}R?g!N)IGXvIIN6dBrIS53mBBYPSBO*e4NK~rJ(^nZQGlY~COl%;{79t8&x#f@D4T>Qyoc2yy#b$jNF{EEo@! zxnz)Jvw}T4dlVSVFG_VaT5kk79e^==OW9TEx8YDkVhMM)dn67ieAR`9AM70{pDHw= zi+*`A816jKDC1ggvW(2}%P3f(-qu0R&nC(Rr{|7+N4-86jXB66EW5wmg<-Vx7{3m# z;Wb(NS`?er(Pv`LzjbBb!t7qUV?LSY{92KAAJ7&>;Mh8%qY+^9fM$oNl#LH&&8yV9 zdb0&f@T}qC{^}+8THJYk{>Y+udi1qYo7#0XCoO+Sar4H`w|j3?<5rP2nK4Z9{ldok zX$|{ywc{c8DWgDu&!EKL%1aD^5uIE!xbh>S;x~!OtCZoa3 zCoUgK;HvQwu}tkx<{>|w`X4nShIgT8+zk7t+del`4E|lwtJIpVoh~&i=Z-aAx9*up z`B#?bgAHPn$D=mJxv;p=$K5D92bnu*_?g%Z zoBQmu*4tjdua_6iD2~19GEb$(G0(L)e6=fzaSCR6$BoVL_-`j3Hi}qj4*X-C3haE!KUcKKq8EGO1flj(O0{KCJOp z2g#vLsDU#to@;`-?~W(Q3k4m)j@e_OfP_xLpKZW^O zh`zXmGS`_bpBDDUkCnf2$UbY-9Sc^cAg6G{Y2*u^jdV4%IJ_Mb`j9?~nn@NqQdBE; zNBXX<5C{5`=#TSmToN>XAMyp!=IN0aqKSp;Nn^)rEWfYRZBy%xeq^aKQzoIyBnpd8 z54`__OZ`RC#Pw9r8MSJoUF}Sts$0(3!*2g?(q2`n!L5Sl1&GyHo9kb!;fEJf`VqMvK-yL2MfqK(31=4Z#{ssj>>3qD7 zg>W(_QHiew;auIf_JV}Ic(u{BvwQH8%IpQ=IAXp^k9LYpx*!pS3jvo>*`HLtP-8i+ z9DE0*vwORAquKc5kFlh8@^~rpVvjtB;^VXPMR0EZVEIgs1E~9>*$IbjPap-IDYFjp zKoq9Pv$LfS1Vb}PrG8UH=A)Vj49!N1q~L6+nmh-pnos-qz^KNw->}r4V57%vFb$!Q zzw7i+TxH2h0mk#~VTJ#1g0=^vo#Zp@#p1Rv#BmrUH5L=j5k0XnI8KWsP#_^Tysjoofm&tDUsv3Wu4>gZyBtwGZwV@1XDg;J452s)*pE5I zU)>$P)hmIpl^Lvnof`6&V@|3G#nJ$Oo{SZ%fX(I&PZ>)XdN`f`x73yzuW+!LT}gXKilT&OwLzw!3s8Pff4#(9OV%B$o@<139n)!t)M6QD?yN1{hvf0gKD~Y|8VD>riT^6=+3=T>qn4|-wh}*WE+?i> zv%O8RwVsB*J9h0Qj@B$J!Jj;hb;+wfj5tIQc;ER(>bL9*Wh$EwNa)=~-k`}`tIaWg zccb&k6ntDZ-^~|Zu0hkXDYq(vF459$2&IDGABcFj9`x?+-MEHf92bx-NFlHoBJ=b- z7A96ZhmVg7xt2o9W`FO5l^}QtBN?D@2xbqYD85MAf$&(ns1U~2yrV62qW?Cj_(J#q z@%TFy3WxA-2i46-#J3KVZY22>n=-=kl#$#Vg7t&q(AnZJGCMxm$`I&Hk7j{+rh z58_$9?_I0BX1jON@^4PdIglGOxlp~pN5Z}RN%AbN?AGKA^K5KXWac?&rA&Um9W%*<&nSoC=J{>>~<)PcA7^f)F7Pu4R{Ul37y9!Ds^SjB!IMDW*?K0E`64uiUOrc zNz7wLlN|ZEnId`xJ;;%xe)d zv8qaf#ICm6Q^x3DvylYGU#o-Q6A;&)4WD|o!cq8JkIjRjQP4}afjsRtJdSQDq5Cqm z4i+~12-N3nKJ{{CVGi9iIZ)n1xQ71zPz!W(3Y+5iJd0|G2$qt@V;DQJ=AcF!1y zx}vg;D!s0V&LBx@AsRK<8RG{=xGxKCQ}#f*`3MyFG42j0iw7vO9x(Jnf_P0Bw4d&< zZZZ@v=lUu4H(UfetjPOxek422>pFM2RF7>B&v(a;uRLs>EZ7|v_&#*zAJ1k3dE2EO zF5S7hgua+->G}xn8qa+x>_7k9KwCQg+V()i?E23-ns6CxeJ#ugy@`Uas5Dqj?&nkz zIx2^-1mpp2qxnpu531|dCfOnizo+W#Ph|933HJ?Bh#M(h4a4f-2&Idl3|AI*YBnB4 zOZRhNk6rACBo2cF_S^MpxyVY-f;%v!hc*Xo7MiP7pOs~h{~mq zgaALL^AB?)NyewE>dc*@#bLcIXNGQ&?KQ?;@2#!+@j3ZuL`Py`vOwDDijV2)(R6N1&p58$TXCa1d&MG&vgD( z=aBcd0?~J|`}eV7*muaSbSCcMLwn$>BW6ZKx0q@5QXKfUMrry`wqGk*{Gxr}bWse3 zFwKTEjojmpjAV;~2v~68Q5M^6ig^Ye{=S0pp7XnxEE4TVz)Mtth%)=mB7;B~m&F_h zh)ULIr4pp`yj{EkYE#`)3UGDlktb+|_@D}%fomBY(cGSJTR7kflrN}Wr z5s5LFOE&bAPfMAb*=mohyN{>wY&B@<28%9vFm}z0LPCH6k%<4i$N%zNKvW`Dg(?Yt z=W+iXfl47;_Cy{xep|Xc0D!rY*X>y$!>L{!T7BF z047Sdohmxxad9_$2wnkid$n#zQHAEC;(G{D5uh}#5HPAk}DQV zQVAl^JP=PzphvnszN!jA9hihl%4PB(ZG2bA!wg?|sfNcPM}c@GFVAnD&EdC#jLzZH z@R=-4LDBjGYTGLqRb66cD$K+S-va{c;`@9nZYezl4S(6W8k``1y;~XtDs{3@8615y zgWao1o*1M}$a{~EddZGU3d6N7+{=#Lczrpo0s-6fLtXMHROusdVXopD30mMs(H9pG z+WIkSa3)A;cX%Ai!8=!U`KSgwH`=f9EEI70&B4`j84Y50QN)w?dQc8Biv-}t?N+Sp z!u0}I>)IU2qC*qVecP1F998DO>})rDev3q5r{8MV3+#t8KrNBr`-QIGq9b5}5`sry z!U9~eLx*^ne=Rm9dpXQ#<}_alZK9sb_%l;rWWKQm!xOB%>mzA8tt0%w~3x;zx{%o#lKWqE@5N#ZML!j{`Aha#&UqY;!qsS2OYo3G|t8@lBqCOT7RgIAz)} z*RL`xo8`!pyVT;?c@onI6biGQzv;#X;Y;14Z1B!e{u&tXAVRdO%{g{_zD!m?($8VfcSGCC=%1~cv|bd zBqnU!MvJhe87dlnRI5OOzM)~uqF~%Q1J z({?0_!pV{cgg$czPFM_gDs@37hOl)(+SCcflN_Z2IfHYY)jNGdaj?;(@q@@@D%k-| zb{jMjupoT3y3RN2U_hB(Azd_zc+$EdUxF~j!^S&+LlE2d&X4$da{-R+DqVzbLPwYJ zB=wV&x+u^=Z!k@;-FHw$F%TtvxUlFzE)*&Nem%;FHV&eGir&(g7X+!2rU-_$5F4%# zw<&E8W-}NOLz|ghSHGjDnt4WC$Hf1ZE||xmP$0xXM=P6$@HKN#p8uuup_{qTB^Rg9 z9Qxj3kMHI9!E@cgmX;{8O9a!vR11 z4nqD_O1vtH{~XH__A}aGKBAApvlqYNxCdv6hs#kWX^m1hfIE3~n%ZBN~z?JRZn^XcCZ<8en#n zXIVS_FopiEg*@acCL6@J*fVP|Fk+oJkfUUwpq_Mze3M(C=k-vo6pWKFM56VNd|iOq zmzkH1*eKR|`BvalFlC1Uj3q9d0wDkR4dyG( zSJH}=`6?y2er~wr5_`0b+9W2qpmaRk(Lh`T(0Ehh!d`FMj~2$J>5qFVPHeoIRKmd! zQ5wK<_XurtP_7hPPIoMoVot7nF=6(zQh}lG?cqQD0D|`H$$={s^Tf+P2B3u%!|2sP zV`;po5``f!PX{g62&ca{pd*=sLoy(`vOyYK%)5H>%HzM?ttFlcyjwciHxH&q+3JAv z(lZM}%{iFgV}cUEPcjWaQ!}-b8Dv{`S;nL~`Y6$wRN4h9Z`?L6XMY}i%ldXccGDSD z2pD8!BJJXxnDjIx40XlmVzuNyF-oqsb~tD49HbVts~iqQ5I`^xWP-<}c8>RBv89vq zTpQ3+`6#Q#JWPAvx<_0drVGwcAS&sz)v!xzVOh^=cK@KSG#0VB$5F$ixSImgU=a_# zfv?CFEN}G>BWBfCs)*`i5ju&bh#AIj1*@)dxJghp=}Tm`BYSx>Cdkf{39N_;r+>nK zCAn^IPGbq%NVVHkA-aNFW0y`lC{=&Jqbe{f_tHAU@gd!Q(17d6)&DKsGJ?b0?Lp+3 z)}wa63eHC7ssGq^WUrCqot`bxY2#t}E){oxD$_$xQDy3Mc7KG%<9ha|pUP=(EH*fA zz=&Q+rrW=G10D{C=XVM!^&A^7Hiw8XJ19*$^C@}7R3=XHRtn0O&C;jzyNq25Cjzpt zTdb{_5?Zqs@ivC*f3RVVf6~hmd?SY}wQ>3G(ix+Z@xr~C^lW&rd(QEb+Fg*&~1H&^?}S0-vYgw?vhl$yBV~Jb9nJapx1ZM2q2RC^E@|z zJiqW~!xH9edy!C5n1+?fV0(te#v3@aH}d9U;|olghD_0ygj^E_na6Fb3Ilae6*GN} zha!|i;!WXhaWEm!p^W*qC`8xCjix$qMIGvoywPO)OzXxSZ5q+xtKx}82Ln_%@7Lf} z*BT`raqog~LL6Jv>t&ML=d!JqRD!oiPylin=)8GN4Ps&ZLVDnBVSh_(asx0F)*$6h0hW!q4RwVRn_X4_8Iqp)?U$&4kc zvr8bwWxZe)Z||X|R2#`{yf=~`{eF)(vuOGgoH7FScd-Gli5$_ZRq|NN)(mU>O_3Sl zRfd05-a}#Ov;hk_K*VCuFpP4U>&M|27=phg=~8B*{m>|Csi6i%FmbpkJ4MN)`QV7p zNQ9-z;f@Kso{K^ty6|J@8X6jNh<_?v`L*cj7Hn1D#!}Y_vsRjtoqb`vJ0wj0R3ob# z#S$(Xa18(Yy&U#}`~`>8GQB@ATj~2qGA#%w5nC;)6nl|i^!Ov;^2U-t)zbHhBv17= za}$)5Lc8dpsKDRe0?{$==JRR&5vXNKq_}mJY&L7(Ky=`ProS*2HFWqKWak)$(Uh7$ z>AtJ9k{`oR7f&BQc`GZq^d9C)+2zbHNFJB^yZ;ICFtwJWs^E{(cE$M`EKYYY!^&iR z>u$7>`JhU~TE~Pg)wIDcgwj0r#35smlF4&gNxMPznY~sGF4aM22#2o~g0ihp&Pa!Z zm;VhD&rR}v$2@@q8kJoV^PqTYXtXJckquE%CbY$YB(R8IE$0 z4x}_1^n{xqr?Ol|zV7Cx9_|a0Ih7;>={d}z5v31CG6wevxyWp_rnnq-Cq38D7F}$+xP26s!>2c0nuh0A9vtcImtuLyVXN5mIAeyr2&&r(pl@1eyK7y0KPYhWN({tf$U z{`E(Sy0Y=4-j7P*Y0gV_O&_ndF!R>l;Szt4=o*JIOCi*-BZQ}xh&L0c*JNP6yS^Zt z64M2p!iQ#B3|dv{`vr|XasD=VpvUH>E;i;sT_moqwVe?iASUT{xKRFDx}XL^2F|5G zR6@SxU8AZ=?-BuRo5}Nn`XpmJ5Z}4P+^oo<`lk!&yDX*1Nzwgqyg9$^>T^rmGg@rJ zCBI8`pLbYivS`7GLf#sAoS~BunrgI#FF}!RZU92Zb)jg+X(=CrW#bv!M3;Ne=+{x> z)xQ~V*VkV?W$=y*J}A02 z8x(x;>L%7gY(4(LR{!Ff>PEbGE5~Cpz~(S2e954|v6TCOFi2$~_f4MeK@`+0z^YD! zdh9iw2m7j4T6la{N*MZvFX*8ia&}nc)t$^IRNbcxOvcIA1^RKHe(qTUn@@EMO79x( zCKk=NS=dQ!=w>yU!#*_}Ooj$^HbuVNO7lmSHNz6_<0<9qMl>mc^r<#i(Mp;QAs)$S za;!KR09uv(MQn4%=92h?_r3|E`(B;Mq+B*NSPG?RR2Et6S`m`DnuMwnChS1U^Qw%k zTW+vL;otpt;wDC%U7{oC-^kyZtg1(0^MeTX{Q%-L*nBf6gcx0(IonMY=UrqA)`iJx zX-4zPyc5UYvj=j7xAPmW<&pwpy%FpM$`8b>jlP9Xj>gs@eC!f)Gi`Dh1&80h@=P$hYvgBKlRA zTWJw0%9`6S$ci}H&RJVkUK@twKe6Jze`*itbwTj)n#_IqN=r83=*(=0)^x?KWz4*f zydaU&2@E^K4wBQq;L63sFZkW#exfmK?VmNt)a^_s#2wC_6tvzSR>D%JGG-h5iOE!J z*53IH-ObEVymGV#bAAXlbHS-`!)Dc1#^?~``^2H8etjlJr<+S9ps$k-{I=@lB}L(xQUZ=d>h}d;9*3_nzOeKN~8R>t6}DaVQerq2UnO z-_V)8q+B<;f(RNg!j`kDn%N#izZUr}sZYPJfxSQYvtzFDEN*>VO;yeE|Mnt&1Y&Vx zt8|MS5J7Mv6Q$%s4`FH{VUyrFj%0K)K}D@Xio#Kqh<2Q#rNN-<8*-{;>|xI5| zSObv_4{D8AxM}!djVYqJuaF=Y8dW&I2$W%xf3)I9oRV%Gjq^l`Z|g}ZDB)x6aGV&1 zd5{gm6TgU6lKblm#@h+UE3k7)P?AAHlMZVkLY5G0 z#Dez&8&$u0f)SNAi_KFk7@Z`5kJM3H*gsB{8NRnPVEoiDV_%AT6cNUfhK3f}kCrtS z(KYqK=b!9nlLz>+o3MH?PX~$@l#kvM;`0avH$l=gSw}cNk3`|mL`C#@z0IfUK=@-I zjVd0Ra6>h1{lcKN())&)_lww9%!Pop*#eVS-Mz5Q=#}$~6*dyJorxpa&ErlsQS~MI zxAYkHmMS)axH65!^IMxRT5vk)=mEw+{4|zoa`L7b&!W+Dcy`iIX;3v(FZ4N+21^Gk zTon7+E-TjThBxYH`L1YZaF_CERqGY_8>0T;l35`NU7#>y&2~B&t>~zVk$XWb4unaR z`ISX_ixIufIiF-o2NtqSclVT_a5AH68`g?OS88jVqD$>q4k&MGQek0KL1}W;xwFyQ zZf!PsQCuG(eRu3##yMH~Zx6YI!i>*^YlX621Dn@$UZGvgot$iZXFEQd;lFePF#4PG zjVf zs-^PGFG80TU=V)~gw9zeUF>O8mi;~;NgVfuK*eXG#Ht||?%Hr@?Zxg}{Ve3(Z>!?6 z9s&6;PE*?BbDjhL(+@ELX8$*n-acvhZMy&+QZ>eBfE$uJ-)zoO`3wC=I$6H&-x)5s z00@(f<_64!+VZrL>vvt^-l`JR8QM#8np$$t^RD1N#Y_y7z`%kSRw|99Z_%PUzEX$M zl@MNrM091wf!I18Fb<`*IhsfA*mylrBbKOn;`0VjkFj}YKmDfl@$Ga`VMx6uB3mAE z$#|r>M&)73uSyl>Kh!jd@9P@N>zho|z>9oP)g{+bLV3@B9@bl^n{BwC>BK|vDr9;F z{AfU^@q?lmtg`3<58(EF?)dEWfGH&zD!Hm9&JDFovm^3*szqaF3Ep{E}EG3IZa!K8H_(<92%0h!g9Qvzm8Q}9H3z$dzR&VJ(Bk-Tywrd_y z(H;nL^`c(oBrYTVU0Fa~t{_ngA%YFBQNffx0AF$^74%DL2yc5O!&yc~sr)ZFi`@O; z92vSqN0E&73{XLY9AQDPW1*Rw%hUf8bT$FU_tBAR~SF z$56(^$A?BJS1!beVL`Y^2arfRpkQTxY+f;goi!dy@GPP+`B!|grqRlT)@R>iT3o4Lxv1g2?&{Tk$ zHe=m?(L60IvXf~{G>YPnrD2!^c)^+9P6Ism5Bj5kmP{UU*^SG9=E{FPv0YaYGcOgN zW)fZbvtz9_mMmQr_i1v#c$w4`@H=fzj75q6+&Lt#MH!{UWBPYxGJ4^#`+yyQFZ(P> zDE3waTutu=aMt>}BwwUNy{2p#U_oellXm%CO0fP@=ro9-P;HN_766_3ypu2!y!CqH zCxosvl+>DD*vu4;qPh_#L&5m7rTA@{-_f60$saASw9ojJe^Nr}{D>Hbk&p)=2*s>|+M>@KRSF+_<#Tda zcy9i-mY9HkbWjvR1|>~rW;az^+N_5mkKqFxC+uW;tG?0-6-c)@tSs3|; z;YOH_^&rUOIy;B%<9N8i1)Obq{GPvBd;U8e1)Z!4&PjLr#}Nj>Y4w}As9o-V?Oy-? z7!+2`wM)?|geh3iRECxLDvJhb!N92guEF_P1>d8g&b`6*N8J)W=JJN6Ol&DP#s}5c zO8{KpjdgwY0(X`Fk~4r{S(7CJw!zm^lGVmpGHR1zDWg?C%<{c9L^({%;QKW%Sb5NC zY&Q$RDKx#}$-^{o=xkO2M>^J;AMfI{Uhqil->5{1ju`yj%|p_>?iqH8c zZBY8Ky=x-_@vYuY?cF!(K!wxQ>&n$ki}{tHDW<5PF1{)rIdx1ajCMH_>20{ zc%@U81qa`qq=E6@{pKPICpLCi4>~gA;@LfI(lpJyV|azSp>0LoOKD^5laVd-u#*D4 z%?9G(AOh#4wil%S1T53TsplC&_qbSJs?RhUyX#K7nHW~_j%u|&*q0ejR$KoE!lt9Z zZ#Dju)*F^3b{c*4u}bce!nL8xlf>??nBd!T9?<>Jt@Xs9n8;-tn9MhxMN8Fyj@p>0 z1wc}&cz2%8NZ4N8*rz48Xz;WAQ zD1_T&2;w?r3C>x0?7e+9+Km*m%^-?DuYcL6Qi8fgn8yCahK>v1gj&t5X4#7ilB z3esOAU6;b>i?2Cyx8uu1Jyg;i>>l1m!PVVjc0h;Muz#>!JLQ1k$1*yyDirc)Qs? z%`u|t-(Or;J>Nj+Z29|g&8zGm#wERfO7EP+5j|e*_z@oO?my^ui2%pn0Z8YqNGNPFu)>$@xN* zF&iCjX-w>TSMScUjJ#}E79xud;rgd`bL+QBk^Z(#i`0<`iS3%RJJ-~OCuu=+tm4C- z_z@BujsRP4KYSb`;;(GF@bt>1E33`zk-_Gl!BtGr1B=a;o#dJm)YFGDRdm?k5maxX z6)VpX>MH6z>(I&&$wy;|be_*stXLK3_B*>#obIpd2nK$nc>-(7_qNa&q~x8W%wpJ2 z6yDSXW%b*ahiXtLK-l*gm!~G*9LXJGOt-eD*nX~{aK7x(+Hx#}54mV@Gb;4>3*+_)cIy2li5Se6` zn0Te;xjEi0t?L}C&f2lREEU#m<>GGPuF?J{qU#swV6K1K6O}U0m$5{|Rv^c&ck#&T zW_F(?zdPCkjokESs~p+wY~4Om>Q`o7OkKagEAxx(pI`9xze+S$SI411h@%b)k68RP z#Nq};m5lUnM!B;qd&;jgxN7p;EL<_?b9n;~i_5Y9$f83ObQ}D`Np!hCdSNj$2=cqSHNW3UK6*RBI!7|sL zdHB3w06-FNE0`*kvg|Efq=j)Y01a--HA+v4zk}SCeJQ|h!gjc}ienw$Jz8^5dAkkz z&d=`yVxi3D`OosKiY#%S5B;m+erNH{B(Z)zJnZSEwp%8y<>k>i9#>UY5dDkQj$_1} z6l*?uFI*pK@Yw(1>Ye{1`Pan_(D2K-3!*iEzt){8c7VK81&>PtG zl=oo;)|Fdetc|@G3^8TVG{m1>?R{V^%cl{J(yxTZY-Zv`8>{R`t z`2Ji&NefeS5L>_g`LT%;ioPSU*=#H;!I%gKFb*62xP(oz)e;SjA_RAE7an+HXHG1T zG!IRL94g0{r3;_<*ou$@o(7C{Ra4EBs*Cm&ebaM%^Tu!I%u|T2KQ^njllG%f9e2YPOBRiKcP$1Ds_v`8TU2 zxSB_l3eY|v3A*9C)C(mK-_#>(ih;8?jl{>Z$?O+uR1INwWgDdZS7WxkjHbKGS3g$a zf9Y-Qbp(=T4M(G4GqO<)C;C1H{Br^wnZA&Xq@knc-O}A05O{AgDagY8Gdn}!kF?u0 zGn`3T+a0BbqHs|xpzkxhA5o6dX5%2D{Eo-lHodTC>O_2=wC~|IBb1k(l8v%M! z?9v#Ve;yr#D?M%XIgPuiul%mUPqLSkOn4iu%sb+42zj6+*4A3eFVLovnD~aXt@jU& z&RI(UO@wr`L+Y$qIhm4mKi#^0!JRqzex_I?@p+nkcNjR?V3UodM4c>JBClipoxiWo!?>#8WxX)|yPx*EJ_RdWAXNH?oe}JI z@EY{L6Y3qR1?6mGdgzl3hQLu_2-igLqW=P*6^xJ{`kEv|eTAku{3bxC|#Pm7a@k;E3#7&bMU7a#UXj6oQv%XJVGGvmOrv*@Ph`7$Do6H$KZ=Ta^@ zn^XCzrCHl}f^umDtK<#pCZ%zy2F62CF+|q!_lgg5N;h=L3LVHj)8|AbDVK>LEkp3T z3ws8&^3U#?XWz=Yj0it|Uhvy$wPJ(r1YkM8r9Wog|2;{M$*B6T=DcNK^odv!3P5f? zo4sJT;?sR{yB6bl1B9N?V6^z@hk7L>a=S(b{fu$T^ZKu~} z%Gq=<5x#i(H)D}o?z#Uw?)^>P>S3rS1 zbc(@PUUw}RQOkT&Y?DNL7ATdcz)TW{4N%6$BH7UGiv=AFfzn2 zTc;4$`|~BRq}N28?^%aEJb&)40CaiyD@{zWQ0GXjFQI-c3gTRP@L%h0Lh-eCcx1TX z@iKFcq&c4_0n8-bzE;zI(n>|Huwa`sgc$v}HWiPG)Z7o)_7A-1 z+_Y|k;5TsSO=y2u*dM0}aUc6-K@6o;xihcGCfby5A9=_7>;0&sf z39m0+?F(D8PiFDm{rU3-e+%eG(IbUi`j$;(4wsmx~p zLWWf@&=%mTN87CNd%itybWn*VARyogt8D|QQXp%zwhiIVf)6XMjQiK94me^rA7DxG zsxL3czx`O026?Um|MSU;iI2YCw0g?5-)frh8tk3}H0PQ%GmaytQQ4Eg-s8*KojcQ= zH5wH+??3Xz`$qX~c({dZ4UMw~p5BT5vKVIxv>)&LBJyO$)8`}ViTs!~2rmCyjTQu7erou|WJ)EGW&-Dz8tRs8ixDIvNNWAEbFVXVy( z6$W!EG85-gwqurtLOzN2(7DnB+-|*tU(5LreM{C;J&D4JwL{H)s>c)cj%iC1VhMdP zRKsXANs1Cp#-D4{fVX!bOOk%R)dJRqX|Mys;##MUQU8Uwxo!c0c(oA~om^64i|pmY zt$QWrNBtMm+Nf9rSM8U{Tb#s|$_J$D)vtKwMzcehmXmcVk%#NOz*kk9zP9>pG^*H| zPkGVZ12RxZ+Z=!V7t%F3ZAdTC*dk48;|jOuoA@4y6GFcuTfX{2MNQ`FJg6n29?v6N zV*&{i4*2u+h~m_f4cH3IF>~1e!Ihy6j#cofc@tn#Bg?zhC4$%FbJMOhG&i>bnEQ&Y zJ|{Ucos*U5>JR}iBu2g}eo=x=GQyXV+K979N3ty*-laT6gFAH|GKs^*g#PAX>M2_# zx;fnbqM2aq4M3AZ=tl`ZFx66530rRHMyi(K;^~#<$BRz^=$ipdLWe$xBGj@uKzl?? zI8PQ^>Y6}a51q?!{WsgcM`LuchZp_So?I^iY*#fwv#8tsX6J&dzsIWr<54XLZ?wSD z?;-ZuCm%d?u0&^I;?yIN*U0YMoCHm$R+-;ncSGR^8uI#Db`acSvAZl&a)7G&-N9YX zZ_q3$=8W1n0_nWQsezQIka><&ED_K3oh!)wfVc4=tQE&$U)3M%o$;P{fu()n}FjQ$%RKXodb5^rn2UzYhH~=ih z-bY;aneAa)aH*nj#Nu^x+Z86g{yGJIihboDsdZ}DNySqAVJXMTwE%_p#JJG_lky^i z$#AXrZC`-4#Lye}6{r~`X*!kn!rjKh%VRt}koJ6gh{!g6+_*RL2*%&F6|tg(&xuF) z=B|=$|KQTgWJFkv&7kQf9Zyz1tj+F)=>E=aj<8299|+raMQ$hMqgJJgrK{nPobtx( z>H0;=_oKUJ^t6L~k6JeH599Zp{@gdu&u2W@ROYZjAC$d`H90uSKIu*D2Xsue+PDyTJQzoZpwQNBR|b1ia#7*Vq6L!C24lr|fLUQ_*bd zpErx;WTi2?)72|uhFxgbin%dmxjJ;jcpGmXSB!Q9*&on@JYzSE~xvQ-_{vXg&RIPxh~P> zb~;&1C&=x>x5Xb;^9j#etGF=f)S+k>%0`wsv*#KVFwhQGJI!!p$D3PSkHnVzTbs2y zlE*TIad_&S_J*O?C^DT*r8>^AZWQx6me|tsh5Wt|n`x||!69OBAvGP%#3y6P`rP&p zSh)n8Yvzf0spAC`?!(4P9S3cq3k@)TG$9%W0)$Z)eoe?2Wr5{E>6mPBx)I$vbR_PI z?T-F3%))v%_!$rk27!n6&Ky@roYXubI_2D}rBv@B&=+y1sO;vO#^?WYeetR&WcRoI zGJuBSt9pq(5Kb>IC?9|3Ltj9bl!ru6I`euwfjTe^jV ztSS-xdk~_DAd1pO>a4gV5_wJfLGLEJeC+k}<7)~S1+-)1j`Na6EmJAvEju1qb5lhF zQHSuLABQkquga<3XFea{BJ%u{jUbeM-j|0;5KWL(KNhe6m6lF6NLFsu72ZUfZkJ&Z zSl}MPn9-cVzRav2!X>!=wn{L1%#6nEFA#c9-MrA|@1Hh^)pTz>+HAx}kI0j*L%0aE zq^Tc8p*pG6-bp7?hXTQwLzOrc8XE-+ewIGGn6#Gt2S6cD?@dD3mUWMDa@$g~a7g#V&#*uPIoL9nb`DI!%Q;48bF z?sd>uy62kU)V*x79QX^|&Bd@Cb!i0J4{k_KJ@d z&sKnI(UPdu1$(KjPUl3iD@zAfU)Z!gj{$jF&ifob$O?*=?Qb)i8|>f?Jb$N)`IIRt zVe|gZH97LwZfCNY?$q#AU-ezWgo{fi&-*)jJvkO1xy=HZr_>APfsXS~9~O^|BHw{e zXU#Kg39{J8k|IQF5`x$Owe$fph6d=ZV8@YAO+)^DbY)|B~Ve09C^?pyyiMhS*}6mXK*5XV`9NrzS1s6G;J99s6%&FkKY?V@b0 zTE19SL)UJGBJe_`Gm;iLI_^RV4;j#K{;tdfMlEK~wp?v5&>v~C!dmL;UJ^q%t<mSJAd7eNUoJg>qLd3_3@FIyx-hwwxcr|O+ZEO+O@}TdxmbxEZf$1e{FbF z9AIxclcwIt;<=ut@hR6jqyV5(t|!+&0yQ^&WKgiS)^7w$jDH*a*x(*E-#yA*!DH6| z2_E!v^in@ZOWARtLp@`F-}EU#X{DB`XfI{nPZ^4K9OR zH_~Fzsq>Vl6?w8PbyK$}8g zcG-<(RYj-v*YkCD6K9*RboM$$I>uq%rRvqJ(T6^5hV!K9n*bHqu!rNiRgafwtiE;0 z>TAi>RFz_B$>|ZdK97m~)^iBi2OPcRg2gi7IRel_-N8q4+fd_v<^S00oLyqFI$H8} z`rpiX8j@G@YLI<=T`ZTdoa=LemF2fmM0~eM<1Gx;dic^|qOe0>re!}NaFsDTSM)Zy zByo)oaoEco(_QLC&D}De94i{Zv$4tAA4~RD<>+zB#iK~Ij)Mrm@J7VDn+_M1ye2xy z=7ICwOfg*NG?}Ks#4j#*411PD!Vby(AdP`VlET#7_J*NXkjRIaujnDZnP zi;uk7#P%!6dQdj{yrh4BF+2k);z4eCXY|Xzz~$@Glaj1B%N&+FS)k*|zIl3BIMY5%GMM+F_BXJd`0WRlcm@PcDNEp(lIo|`Un5ShGfcbb%nWIg#S7W z!I@t|Z_p)0u)~unl+wgll}~yHN~0?u@4h$Tjn&M*4*3XqJwweB3#KWj2S-cpFL9Vl z&!YR8Ef9%;!{|rA=~}ExxZ?d2w{o*IlCE;CT+&MRQ)w_h6Vv>EEPw=HSU!`*5y?C5 zgql>K&GGd_1}m@lg;XpQ&YGYT^}MzZ?sb~~14DA-mvqLy=uWZNv@C?sl*a5@RLH1W zhWz25C9LMbPWL7~8bH655v+L7vwX=9@=7JjuJHU?-7XzL3p}W)+nLxmNmh*}-t-xr zP^yb;@*}162#=Me#CBf~t54;Zth5K%RjX;QmBkK2=5n7t0@M?uh|{es^3ds*+XNu< z40^zNY=1m0ITe}J#6bmFO^2JDW_1WeF#gCC3K0Zas5uSgu|*RU-p?P{grad%w>_Iw zfiT*+P+9ePy}>c%v$RyysAS*a0>yT`2LJvZ=#j4$!_tn3s}b@dLm}9X`h7f z~QZC3WClBPT!!SB9wWCOqX`RIqgVJdu3qEKX=v}Z7wt2OQF$s zIn-1w%a=va<%A~qbfq#C8Q<9@r9-ArL5-Cx!rJC?u{#FZ1|6YdrqO7+mn0ThD8v4E z@QAv=Ct^)9dReN31bXIey6yyb-k&~}Vb?+r6ok%5@NIA=n4Oa>@b)4d@H46GG15nv z_Ksf8g9_K3+zyQ@VxsLT@6Wr%>m03T>l(SQmQoD|ag#QsDWZM|XI9D)qL2*jjZfbB zejATF6CH9@0&e*2H)dM!I6pyWp8@JNB@%jy5Zi%{@ugT>6sE4dwP6gxh}pB$JdX8g zdM*;1JfO8I@O56@RSKJC8r%c0#$ml7(IP-Z+YrKsmMy_?p9uyF7$U}##0mBO4u#vU zVqvJ`VN)Im7v9c-8MaP3;@9o7&js>NE8w8j3fCbimE0J#>4uiY{3&EaBaH6K( zGFP0Hkw-(oiNd5r?*Sp>?TTU89>5F1xcGB-ASae^Dnu zT5ZJXyh`B*WuNl+Z5}88bIoSYZigY%5Ra7U@SN;e^SF;UXWXZrSRe`ldX^2SZcN+7 z7#KVS(*DPQsCJpsh?BG=gB4BP&a0LsL-d*k$kz`AQ^xh9#BpY@SdkHIctANEb}JOD zfdI*Nnq#Bz7GG>+3Tv-KKk0_zuho8p5~|hyC+WguNzBOECsyqM-v|nYOnE{mW$CD^ zR+ihD2Fiy0XA7fue(~iTMrWhpkm^1zP;r>wkMq#)%i^C^Kcx+8E^@bqG*kQEEIzmg zcKM%Qw4yXqW&C1t+|^#wTJ2w2(E13WUsaK$sfxX0phC=;2^UNnf4rRJjur4H)HS=L z%8(@2+EnD=;ydCfdCqa$B^t@?s`RJo+&_ioE*(^1v?IIcbA(Tj39xQQoG;1Xu zGie%Du3g`D)4GyR4+~74WiW?HV)Z@t;a6kkPIts0pvGXj-#%kj{bxl#rffFMl;Y~V z{#GUCP#3xVX4bsu>>MCVN{rj&MQvC`7`8qORz$hl)!fOwS!Rh z2?4Sg{wA$f88}GpQ_R;Am70_Xe8e`Z!?^l@(~}Z0Zw^&IM!-omRive_!_^t*V^pKV z8dLp%(>6tml$l)NSM2*`(t=KSP(ZoSu@gKmTkE|xTXe;#R4HOnBS{PE!ief!t&&OY z=5~ATy__X{`Jvda3uUvR`W0v>Cp1EoX`m^(LTgz0t+4Pt-?Glf$i@9@4xVtxh>)7! zw{3Jsey`_tYGSkkazl*shBabLOAy6T)?&z9?9-?BUpn?8 z(xvVoYcJ%Y*3I_vVCinrY!F{K0!h)wvKZ*D1R%BrVvXPsg3M+T>WKBQR272=2Wm>t zfdwO2;#!;y#U@{MbUBUg&E5zUD_f(pp=Rx>92vd{)g0Z_>9mz*OJr#3-_xOP zgFh-WfqvybI*ww3HCO^5v@=o>9j}TvrZwHP_9ktkQp9`tIG)bPUHLrKv8u^QMoq!_ zUH=0kNIbm?CgR^H78i{(=YFy|YpvIGoS=Z982`2AB;h_xw~pzt0b>Do-|_CW z1q=J4;)t)@Bx#nt7~7^ygvV;z<$+IAZQrksehWHn>rUkJNBh4AZk$oT3CC(9T9{F~T zA6TULM>VDzw0eIm6Rq27IUZwAwBwU&7(zc3pT*k-K}<&N^A88<>)SxeN9p@W%0WH) z#nm7aYNR*OGxFqGE4gJ6w${zGDLY0=`6AyPilh71H$^h<=>~~lWGK!vI9yRudp54| zF$UFA0;U|k@|HZBzk20fkn^rOHClum5Z|XPIlWe)5;)HJxovTdq#+(WmS+<+&fHkD z@g7PC!Vt?*5Gn*EVUGU=SPWbg<4;8TV+|U8rrO~Yo$A4}$}&#YnSuYRxbxr!c~?NK zlxFneFzX4EtJYYq>XtUZYl5L}cNVSO(DR%=BV0Bm#^bOGWR=NLWF?D`G znapetWa?0&sbKGc|0Wt`GPw{Ov?8Bo`U#b)ln#dcmr9gPCch#ZG`|4`{mhQvIji>g zfkrDp#KCNKQ>WuHPe{;@GUD0#4cfszm-}^JVr37qLbKxkqE#a508extQz`6`qimD^ zGNe_+e|^i!|7A$Qhw6Xe{RpqJt2VBr!tof>*X`ij-!iu&^EEAjB1-aH=KN)ksUst) zgYj3%xpF2*bVs?N1-JoqtVrE#dtFVac&%fOk|xDJXou^+QoB=Cs|@N73uJ!$MiMr~ z-OC5TLf3m5j9*7F-y?JoV-WR!KX)MB#vf8u8-ekwRdx7s;Xld(Os!oxBJIh0C+U;j-( zgLZ<-oUPxau%}BzQ&8;UK}ZT`Iia`qCS;kn2rR$+L+Y`!pQ+1qVjEJ^74a#mAMw|w zdhY~3D$5%}a{~*MS1c)DleihwE#~3vh*DmaJ?yh+I~!o?G3$_9OD7zvT_H{)HCF@H zzp@jpChYEwvnWNb{F;n_fcK|8yHOk9aK5U?e@DZd%iyxRpbj&VCP25;)jRuD)KzBT zSmVuF5>2#L4F7qW@Oz_vrQV06fQY8&hQ+?iAN4IG$*D0&RJ!jc=r6W01`~qk=IbI> z?$dV?7b~2wrp0_A$r(#LNvfShqz0EH#}>6sg%FX~jP>+V#^F9D7Q5tJ&jtj?F;jwvA6N;E*g{}#LmKH^}!C!Te8%d}E?JLyZRUtW;+2g7GruL|=0rj%WY=dn2?S zZnkg=0*)7bu(!6xW&fN29?Rpq-Rfv087=Ezg<2c=-N#Q_Y8n-Cb+M92Y&<_DJ@p!l z^_O1`5|%e)TEg|`zZQrTD16OVOr&FZJTRWN{3UcMT?}q=e%L|jS;pO?0JQ?Xc-M*l z1UCPcBXK&2#PvQ3|I6h`-a;FGJjIYj_<}Js&{M8>!f0n@nveOV-%)S8vtgkaX0WzU zb(SA_Z5RW2>^OXwYc1{v9|s_I;HHV06Fa{hr^fa_dN^}MeLf3Zqs8riexf7Hc(i@9AS3;d@Czt#kkQ)e`uq1QT@oFxnTEa&4zhdo0(*r_Q&MCtf2 zANcs`%o{LPugp6$jiwARKN@`m~l{KEA8|60YG_d;{;`5+VLp!s$Y*dm285~CP(*1ENGC{ z!i19M2n;fUUBjNDajG@28pfWl`5L$3q0A!H!JUBx*Zs-7b_yk(@-3VocJJ9r$`+ss}b7&d+wxLAXUMX4CVSYd@ttGZ8Pg((wsUxT4(s@f0x zInfi>XR_r;T)KV~gpSt(3O~Y>P>Gu0cj(IP%M7$ zLnGAA-}9o-yxe8uFLzH5T4ewAd#*R6{nIii3o#MRwsx4R+kohICxH=$Oo(&GQ(2r+ z%dMu19BB_a`1lBNt^tJknzKiYZ`ilus{}7evVjO}+&UKWyYN6D5?%5y8(T9Hc-%#T!A>^~tc}$2 zXdbm95d+4>)y=WPaKN`CF?V@0Kqs1G;U~Pp0tD$Q>-jn)vEN@sT&DkCs4Xgmb~~YA z*mz5Wy!)a|_FPdL^(ufCamGlRb=-Lr_a6$ISt?Q=JUG_eHpt-Sgtds=v_hFqGW)H~ z@D7KTOMdg{@-qJFmf1Cf1w!g0+4<{Ma%*oDneS0_{04|D}?dMC3@IA9=LUFhEW z{^9GuM#d*Em>Y>rW(9HLwjX7WV?L;^p@WU(Lrl;u72dFh9 zIB|E^@E11!@6qf1)b*CFxYlWBC9Q|wS;2~hxDQd>B))J6!2*p+amDf9)x~Be6T-R2 z=O?_j5x2L468As02Dop2bNPSfLDX37yk@uJCL~B-l4)U76WVKsmYBM%ZD27B(GcGt z9}{fBh#8hk)>EdQGFZ9Ah3#GwLMSBQf$W|)`r3)|gLD^%+W!myb&sw&iCEZ%zl^!L8gO{QxgL~hN-cEDTZ_o z8wOCDq(JR1Ga%Cg8XEXaWi)EER&2q}zFFda1=;y%bT}|x?hKS^!v~>4Kom;m?F~oavmn;y2W)Z5xh?h=3}!+uxTfO!a*>_6D8tduFnQ_RUm6 z=^mc1NaU|5$|52h;65-3#37dReq~~LeBMYde|V`mYZ+Eml+w^Bq=lNVyy+ z=;TsECA-DfdmSO`j+(Xl7>8BrDqvIhjTo4?O%@v{U7l1|WkmWPCn;7&qen|NP9L}G z_xPOhOVYh|2F=(epV`sNZr_d8_g*4#$6c~qgSqX_xFil}R9MV*_1rd3i$_^4COGbi zxU}LZ-xl3O3@PNSJcYe}Bhzbmy-gvV{8MX0`2#c!h*Y5SeR~AQDKf)IrtFUpYpGYca?vibsa!9Ktuj6eA&L0ng zg%#qHwrD23K&64C0S!W%|tjx$-fZi?h?2_VP(NtnkC zDTIh|&}8W%fl>JP=xvs^prj72?5CD%SZJ4PigM-;XJL~&#RAv4%5yEpyF#$g@#7b52^5?;qdHB$}Jo}Pm~c_3eka{%s`xc-y&AgsqawT4VOV+ z-UY>hp*ECLbTX-M?VF1N(?q@YwIPK5USro@25aJMAV;^vf8V_Fs^qIgOc2#-RFKom z$a`G&%}bJzt*qZ#qV48nxY`Nd?i05!mMVq&<7bnzd#rPHw0>K{Gvx|KRK^??>Q1(v zES6J)Fo8%blab140a3_l&nAZn+Sf>-k0c&#wj2T9AxNO3=OYqi=Y3xyyvgqU06IJM zXUtbRlf*OJ7O`m3TA%x9TeJ8Fwt}fk-d_yF;c64A1Omt=T)wCCIPly~a+?`o#b!xT z+oy@}I=5{!-Cnic%Uz-Lx%m@*7qsW$)&^s}6gU(o?+Tt981{6QS(wqOBBH|!^djkwAx zE`q8fxR$tb8ylhfXda+qXA{cVyhok5s3;OY!u8$$e`z&UrOZK<6hB7Np-BGc9fZVo zl=8_A`wCWH{~X5m-@JSlGI926e=D{tRYa*E!4bYUrzp>c^hrnoei9@)qMqsDZY)lE zu%7*61Xllq!ZX1W+IYN%=8I8`pt>EG|CSrC7aYUFW{Ct2@I(s2MhLbpq+UcV^baq? zE82{xK`zV7rFtdFY81|-6rYOh!c(DEFy`3wP&6|rOvBh#4!v)MOC?J6NvQ=)k;t?- zX8#4!WbzORAr!F63kjd?1S9?ZjAbpR4O*c7<}SXg4vJ~`&QHm^h%I&e>ppw0I()HaNLLOQJ$Nf5aMD{U@KG#JFYJOueJ4qWZ9LgX4d@_me^>{a>DX2!$Uhl2V+xdR(# z1UrbA)nbRdl0ZCPDTC;GvI%)tJ}vU=(=Unx%pbfaD%m0PU2`?D{d2zrlq&ebzAYrn!tf z)%MZP#HzwWB!mh9j^<|-lm=p;I2T+H))la{nEciKB)E~ijLv+ruTC(LQrdl(q5%Ei zl*H&qXWnKaZ|5$d=m-+XBZ=E_U#TD*m>AOeNcT7@b(2Qfj}nYxch329ACS))az@;b zz=rQ@?9PzGsym=QQ0ZPWn0I&5Y?0lU7&b=Q#WCHT5;ds*74Gr{o z{G|GR$sk+3XOHban$n^(#U5e$J01l)_t%FfpFIvNr*u1iawdK5 zTD*l7N~HfiIZa{Y^Z2No2we@*2{(gP1ZCNT!RxDo(39;i=zn_1HcIu_%m$X3`=1eQ z4#@J{a=JQij_rPv4WIWjFi4TG5jdAxEQX2no4)rTnVi<=t`;@^-Hos~BZ3^Jl?%X2 zf_;qY%)AVCYy6(gaFswBNmuJWwIS_07ZM3*%f86wM6l@TTR$m3{v z6yPM5_oD|3TN3W2_hew}dZyyIAEQ5Vz;!MbEJ_ni>@Aid2~NuF#Uq&QUm_kpcyuIy zqDK!~aAYKwF)3_%_ji{@xEpJ=0u6Jeo#*zov*87k{Vjihxo+&nkS*iL6UQg8uB5xv zJ!1Kj3zoUUwS}J!>wZz{%GdblNtwCMr;m)NLAL?xHcc5%J0o-W=Oaj-1)iDD*pU(i&Nc`Gv_(8r;CkgpeIdmg|M!oeyofTtdskoNaB*>FfCg4jqFf zxzEMu*JXG2-3>D(1PmEGVPQ1h2aMBz`H#mrmlP^)toJwUX1M|CQz^zMFp03(;$ktIaJ1YeZDnZ^ zD+myV^?lwEB*DYl)wq)6?7$(o-NaxQ4#z47n`62 z2F9ft@+Iuje>*Xz{(mT;W_6IaZ#UPsAw*9WjkduRmb+W=A*}F0ta00-Y%>96uQ#V0 zoWex{CzG9dAMUPie|QGHD@=+&N>SZ=5p#fcH)gt8_SE>b!@NAU%^rx{g>v;rp;;Bp z1z~YdJ|`TWgd*F0C~Vj|h#>_}bD|jn)-}dZ%CWcUEaaalDLy9PsxCxG^+uz4wHuNv z#+_gY7o{_axWcYbe2-^AQ@s9-=dtI+{El#BQt_ej-9B`2;qc-S)zd=IAR)K4`XcCO zqnvuY?xeuki_1RG?ba-mBz|=2GGo!*+=gL1BF0c?S79Q&7qHfZk%~&nf=mR-M8qHE zR>1vIN8r~`oc2dG{dhcXIkw>W3pe`wBS{0}mCUO|XzPVZ0V4boE~Uy*d+olL5Z=i6 zC0f*5L4@D;LyfT3_>lTDNk9L%O5sLBxT{rb!n%|z;sDmKz+w1Xu5&YQeV-}E&T@&n zgz$CnOmb5tWRhueQ*j%ON!|Xm$f~(L_Nub#au~Jv)am~ru!zqeDsU?H#mwY9&itL$ z1o9zx`T-jJrqRu#X=)KT?S*3R?j&k;N;kjpo!67WVf zAj@viUa?IsjRLO;NCR#>f%`nYBOQFL0rLd+_g)`ne`GN*Y<0iIV@)Ctyzsh6O62lk zE~Y_>0divTE<%~~_eg^DapC(h%(u_D+x^~R%HI@n&lqah3T)bVZVBNEC#IigB_A3A zgScl;O8Ndq2XNF&Jq70NRF|ei+eGu^4yd;6> zalj0wfs-F6+Qb`Fez*ty@fhU>1v(dm6CM9KBqRlYs@1W5Cu-swyQHzjfwlP@w@HD- zQNtg`Y+o_#m9{O!{FSc!y`CYhV4b;pvws2dw|m|II;_R;8A<2hx8VG zs;_0c$u%tqK4Dl)pr_{*k<>k2V3nHNb(Wvk$>k47*#(}I;=0zHRrQLCR;KQb%}P|^hJOf=Sa-~Q)-!Ib2d8hJ zuKo?5e1^<<9I$kGpVmmQ1}m*$w6_G2WRVjcf%W-IpH-e$N>^#JI%PAsTp=Y ztzl5Bdq$+ogfRsENFqmkE5@RV!wti%{OM)PP+;!y|5$)h+_qe?JS4>On{RZtD(n0r zewQhkknWb*Uqj=`MI!TLH0p&pu&bimlHXV&rQG51=rCCsb=T0MTfJ}CT7ZiNfz|a0 zK$6K2B%-Z=omCYfgw)%P|MrOusy*K7L$QQ%1M(WARSf~p^4fcAb0evwwEWx-H%5!L zNvy&x9-uq02;ytcxgw3u%^vWAa@W2T(RWvW6fMoGf*X}J#J%%BK|Q*GgY(yLUct1Y zzW>RGabK*)fus$U5rvVQH&#(D5TQW&{tRL2-i2vC$_H>yWx{~wb&(pXNK%X>7Dn=h z!)5i&AeV}l4MaZQ-s=lWpwZ)DvtEj?tE1eRHylvr^YCZ-0y)kNGOsr563V8WO5Hy(r#EK*UiR97} zrjtaX>w6SaY~~XPL1hXiAMU+APrW2^>2L@Hq#y)&64mtt7uMs_w?BRQsxOg{ni|~) zJ{V+-vrOFb``hwueIOCiNi?kp?4S<92?MGFVSwH$0g|p4V<2o}Tpfh-Vv9UW*aNK2 zC0b2idT0|G_;IkhQ3JqerkPMXVUm$7eXmjvF%u zj#69Sbkzm?8qd?c!p{6X3Nar&(GN3KKB7#k}$raz(@)p0byn}4wY_lF7x&&VOz zu}tr3*5>m3QgN-$>v9+K#}tjI(&Yv$BN?*2!z&ILO~Gcy1gvy>8xi=&nMuIng46b4 zP*r!tr&b%yLIkG7b%#1zL1`XsvAv-2YLTOG8&@ic%f!23I%~7jPa2$aM5E2hB$eSS zVKl!69b^ak=5~fa4KIf$=ocMGa|5yq+HWnHOjQX|S#v&A^Dj#Z8X!N2{mYFEH1eD= zM!&yD242(SBl@M%DOiIiuU9?JG2GZT;0NmC++Zr2J}^}KropW92W?XHy$Q4IZ>8Y4}W;N*eBVgbHB}fBhJYMVa>ijc=-GW zZ_ONhq4;&a^1JT>ZO&fzo|RNg+p(~owtUDg)t?O9>Y0Am{$8&A(m7w|v)ROds`Ihg z^tq~~*^`hIfqu_-F+pP?p86{!_R6CyG`@1TzvG8it@Ju;Z7#jYg8$6*#k6W%ZqeZgUsPzfJik ziG^G9@X<7Z4+2gh#vW~ii#2rJ2Jv2n_i@Djpj##1@wb5tyJ3@i0s}G@Q^IHGZz4*yWenglh1h z;@PrX^iNE&+vEH#%#jChpkM#E9G=kos{SvJ5P)>)L{!=+EVm%gNO?~(N(v{5J0h3x zu#{YR?;Jn0cSJRK5!`@IUUEB`A}S%N_^-*KEHQ%Bf?z&#KBR1#`+!3?k@}j2@s=eE?>6p$I@hTZ`E~YD|O8{FXawH{Tqm{?6!s0|_EMw{Ar2-fhLdk7hvsf;f+G5t!x9vKIP&=R=vCqDa{tO0H}R|AZri}H zrhG2R(ECq?5R)EUU+k&Ul8xILmE=rL6pL5#On46~n0C_vGyz;si(R%@T#&d5u5-i1 zeQI;aXh)Wqb)Cvg{PhPkTE6uzF8I?}#9H#Fgoc*j?duhGu;*t9gq@cIzH^Sv6+zxE)e@ zj*LP1gT$mDyJ%?MXTUVA0+c)Msvy%sYXw^+1|6no^}jznR#ruUG-ywlTHY5#-j~9N z7F9;~E$7rLz9wmCAoF%5Y{mhtSbch4B}_DE203uKV8RYW#v;@OV!uwtA5{Fe!A8u; zk0@{#UPS?U5fes%;z~S0)ZG4Yh_9y@Ug1I--9!@_&npBp4C*sP_p8oL!gJQ2M zIF$%~NW`PF&Brjp?M`B99~sXMFti7&*ycpLZzlMUk2hG?b8VsUZeSzdF;Z^ZQ>cEA z{=U25SW}1KFJdkhzL0*r-GQ~UTe|%Q+zHKjCz-KOjl)QAZqo4AdpUs`Mp8xPB^bnh zYnkXk1hO>Pj+faF@Y8+$X)(uB8_yV_!_k0YM2Lhaqi-&zku}e%4KWMa17MDUAQFwC(F0E5XZ8JE11{lrezEUYY(pg1M;qho^{l=f2 zCn<%>PvpjWIfx7y+Dr8rHu;OWP;1`!L|hx#0j+#=-!Bf+zp$VR9v<`oOKP~~n`B=< zsmWxr73|d>@I~~RoLgkdT;#s911?{B8}Tn1lPS1It%;?H;ey>_wlA;SXYr<1r&TKC z6?q^-$n6!gOg=Yujs0k6Vu>D?+rK6&BqasI`~4mf0f$bWa+1h+;NZqukyf=#q8uex zxk-W+-+yv!aW4zv^yp-#yf6NwzN>P@B8YH)MQ;WT+E)F)Wk|2N-KW%hHX$j80o|fz zH1RBJxy4aVMFs6{NmeXMehg1SP^g@^aGz409$G&=YLt!@aapT8y{4>3E9h+)wAQH7foLriD4Uzjb8O-0ddaD!{FS`A1 z7O^WnRlw*zbpor?tpo(~3`ZFhX@kjRE2GwLZ^|;oPuLi2=7Hbmnyl`N?Qq=h-9At} zF!!Q|vg*pc_I?xcxk3XbYly{nZMkzbRxYWGs@R(Wm*M_?uk>@DDR6$XhYa1Tmz^(ehIo3{Ch(D&)$DMQc#+o0P&Y^(d#Xg$_S zjr-$!I5J^4GCsG_+ss7$b+cf*GdzI|A(-*3W_W0xcL^l8yL)hV z*PxBNy97<33GUXoTR5A1-~ZRSRj2B{bQKTX?7d{JF~%HoF4XH+$akMfO|H5w+#tMx zjwc9H3Rj+`IWhP)Q-Qt`zrMeP7+x^^&yf; zW+00ReINq|@{@0<TIaEL3L&W!(6cP7`hYjrPB)xQ33YlE0%kn;b6mxt z)ecX@Cxq+1iv7AD{hG$3$xp)kZjXzNwgYq4IxOqe;dne=)U~D)k?2P}%8v&OXdi`G zU2%l5h7_j6%AGNJ^M$Oab19%}6&G1;&xmDKQQ;bj zi5)tr4S7-UPy!%+^`f_?$JSfd&qyY_&M=1r3&~yUczv+@5qlP?>p zY;U9Es46q5wMlkjv$kN}2_O#iB@KGKyD&NF>?l>LL{P8Ri^6{%k7Vu|Y!dX6VIO+E zCQI@m6DzQT_OgYoH|F7>p&XC(($&do6_b$Dy0GYzM)!N-*#qInU^cm{|Urye4Pc7F^wsWwDoE1Y|mlnTrF{4R%zh^Yr7_UI@ z5FGtd+wJ>-6BZT40-4wCRu_G0QBq?cqMFgJ6cSJZ`6{>;%u346EN< z@p{@!tv)7XV0rq)HX%O$61?;(dS90~QQfk89#=Jc5Kk z7i#HljY_Tm0EUhI>7&r&Q5}=pVWYj@2_3@U{jo}2p3V>>NjYJv_IuS8G;5t$&`G%? z*L|ZEV?#PbxHOPF1D0AH2{EYoBziTsYE5KNEZ*>H629z#m&F5IfK#uHUqcQY%-Xbu zDA1|<*0Jlks;=-V!IR$(-;L>_>6on@%s$zqin3wXw+p_7O<>9Fd8HT1AO4`{m zCo}Fc=8L=ZaP`XH`zs}g%%nIOCPi>ZqcxqA6sD) z#M7vJaeB@ptTi1e({FRz{}2*&i={&OH|p09mGa%|L=yhX_L=37C1 zugilAy6vOk{C8=|^hz_yE2ONrO0R%uu?h!#%qs$KY_A6+6GV*lED)$6nAHt zE7Y|@aXJ`DQQ%@|ZmiU$FhF^oIQyHD@#$@O;-P?sKg?8_mCgG$q`$&rB03X4Td7mfW4fFMIc^ys&55T|8&<$h09C*j%AO_)F{ga~#OX4$2$hO38GghV zB%S^;%F@5$r?nC&m^qXB!L@lue>EP4#%3 zd3>y9pYvO+l2Lf?(YV5bBdRR~3|R17K^Ci&OoNeA*ho{g$j~Wexf-)d6it4p+am;n zVkw30=|tZOdA?qrvO2gMJ%IxBI^XXn^?Tqlo}y1z_g3hTvq!C0oi?@DxD$e+$GRhD zhcV)(&KH@33d$28crlow?%E_y=D#O(%`VG`@Tf(-wd@VCtVw}i4m4?@Yshn@b?CcH z0<%_C#?;5uilsudP{`6SJr)kc2uEw6G>OLW3cNXm$@J-Ki`Gb|s|vB|2Uls8jBa!l z?8FNICMpS8LTcOwwvOBmt;9wM>_`Gd zZ<3?+PYx|0?iLb6EF^zM%g}5OLr=$>5S!%2b{li7bK6is|xzAN6|_u_~dM6-2P%nVQpI z4#AKpM$1~=|DcaIayz%5Z9iGHBKIT?$);1EQowHv#e`m!ALOfs*BkKs+M929iGN0y zti$0o75}!v`)uNxcDf=@rS1UG)H@ew5nQU;!2#d&9DVg`SI$}f>H7Ax8Z|&Ao7Hpr z+Jv>ac++6jj@l@W*?`H{dY~nCV-PG_rt_8HVizn+L=7g|z?RzF2y>=8{NUMW`Xwh9_*XLY#G3y9{*`7AM-th0*qWEv zx!KSJ2bpd;lGklLMca+8|K#(*p%@tG)Iy0U8WBtpv!V@@(?)k=_#U+j39eV-Kg2v9$Uc zAZ79NTj3RTqaUvFvc8@LMhM`WmwF#@#9##eSGD(%8r=?)?I-&YG_w<%F~UV_d#UeDa|M`IXE;wv zSR6_THwIoOSGK}v-1{~t-(7ymikv4G9MASe?(n5SKt$wCc<>OrK~O2qk+cI>p;;WL zMkf|>V4-Zue62r9o$1|!(Y_7WX2OZAUmUO?Mzul4LLe|ce0>n{0|vjy zz@Lmnj?Ad#N++HK=NUkXL`-;*B8w$m+fw;BRH`S7yQ446bMjmouH23nv=ZDQ>2dl` z7)BETW2v7S`FQF_uvk0BH1u<=ezUtdwUIA3FXqi+w8c?rpj;lR$*Lgh&mgvPWVssu z-bgRYDWCT~?GlVJ+F4DCixdz`{d0Zn8z#ZfWVnRnYIbn{h7`Elgt*IzDRR{V#6H^I zQqTO2S=~cA*XQR@{woGvdy-uJI>cx77z zGGKZCra6$PP-PAr$;4NaKk}a8dk1C~tQlWES8}OWwS=2Ivx`68wmu7)ptvlxouF1t z*&iC~6w1a)T|@+vxZLtR!X2qswtW`b=3*qW#b;gJbD{^6^L)b>;L!2Ga5~X~TlS#^ zS)2SP#1`L08fDq784ckaq@A z*PuPiR)i6#IU`?o!tu^oH%A#2C~OQ?rW|C}^ex9FZOphE#H86FT;S;SB$WKMSm8pX zjG>FUBhg4gL?)di`^ffORj7Np=(182?fCg9?6OK;lcx*e;L}17)_#tQ-M##Qv{4C3xC$xku%2@_MP)!l;c-^vkw z8QK#ZE1Mz!@J1Kvd5UhxeN^rGjgeWt^|&U)DEiQ*9+8PE47MiMFZl)$me<$_rbtHa zC2$By07wSP!14hF0#M^Vbev$LP<6Sn41ApcV!x$0xyp7%jKo0oDO?TOQRnpiVgxhyl9lf>Xv_xPncx%v^p>iO49wLBAs_y?N3 z*flPFr^p3Qu=AK@&jh1D>(e>ucO3cPvw~3o6|E5~w$6M5(I$UC|DhV)$gW}-Iyb*; zfuS!CU^QWwe|)UJ7gjnY9e_rnz`ZwwpCbX#{(?_#_!#Q5%pBJiuU3kK1ZU3~>J&fR4^)f0J)#%TZeCy$)%vU~8x zF`fN^q9fYQr+5df8yheBz+~@50{kH2r~`AA$r3V*c!J-oc_Q2z&hn-g!wGcUKBS7uSxu&Q&W{3* zTva)i3}Df~8{sRDXQ0Yj>{K%^P;vSzptlwPmu8{>DBTn{3^s9R<8{MuP^q#j+cn9l za%iHf>%gFzv+SJQVX7T)$t&k<2qk$oF(p&Y|3vs=rlOjcjUrixkb#-wP+)Q9o4k*r z86BK&ra{ewf=)WkiB9!(o|d!tQEeRy+ANMNEh@qpuM#k`G0J9q4~^im&rRb=q7yg$ zx$7_5mToxSKU>Dy)6cRk0`2r9t>`s9m>&uFzCB|?=k7_AcbYZ@TqOw`L-7fEs_DVd z>vQ{v4QJI@Rb6twjzXiW7Gfl~_k}uA{P{j*r^nEA{IvGKj^u)K`KI?m`ymD_S`z$e z6SQU<8b}jh`@3tpD+L5G%G_~KUs4k?lw8vDOuM6ke-YB(!18V}d;qAb2k>WVCob?& zm4}0aPT~{PD#y9LlH^immETD$c&F*^s>{2mttK&&>54f=Um0AM#9FGDR6s>yGLT=b zN{tknO`op!rlD&z64^JWPxkz}*)G56+z(Iox9Z%C`@r|YL0`met@)SNogJiJ4g!vd(CY{x*^~H@d9k|=_tR%^0xI> z#r*|Y{491YLY+Wjm_*Yky^xbxxt#_}rn6)3x6q@8&(WpfYsUQt*r(p24ZE{EWZoWB z*cp>759sL0YPKtyae!1_o_Wj%=t3I{M(NkI|Ikvn1Sa z94;o6Gxb`;@gxN{qJj`BkfC9(Bj{D?@qpRa99JF|GFE~CRP`9rhrFN%2a5IO2!?fO z&X2_$mchjOF^^!=0e0xh!>g3NVkq{2#6^_OmcMjy8O3e{YzX$6@|5mGe3$S<4i$Wv zvT^qugF_#C*8a(K>MvaY5Pr+>@CMjM`*p~~)_0o6>|ZHqZ@gs{V;S>*PsnQoB=a*t zk$50fzx?gdwbq%jy*;1q`Qtx+zSZKi3Wf39s~yb*CFy+d+8?{`uR@?Y7tp5TJQq}c{<|a)&()KU})od!<0*s)na-#`l7x;T9z3N zuu5v@L?y6zUx*@?Q$MPlwvGD1(XuLH(r8*bLe=qKTBy(T+=u{5gga&s36h%=X`;aVI%a=Nbos3R521<&ziRL`&90?byN<}D$( zk7!;m;++}-If~eS4?WWit#W{5pjBj2c)Ac3h}m1WLHjqU{?4`Tnl9yco1+xk+XoG0 z9#HGCMh*NZ07TJIb=~#vi|O0WYsX(&snP)s2v7){hY>$9m<;9j9ELB+UXBK8R{RV# zAwW>}C+29Av+^;9<*h(+i6nAGF`>#5BpBTU za}s^iIT7GaI!XYdudFB>?<06Ql;4zpH2Ks7JZlBex%+E}8U;xbB?_b!HgnkNXS_BJ zo7@Z128jG-L&D3KRe>)vRF#d7D8DeYA9UoK-#@=BWEd#5nh|!Dj7@Z^mw}W)O@&Yu z(TJUwZ=EJdaFyrFZv_7T{stG+;`xa2v29;o_856z1_VZeC;0XAdvIOZz`Z6AIlBO< zCvsjMARAUn00C%hE@P#V0fK92QB`Cl9p%dd^?)~Xv~Zc%ZVFghNDG;iy7NJJEQM&T z-Wts6Lm$C?Za`x&yy~n>8Wc!A@Xl8DYG(4uFNdy-9zMQ?EbafrJJQ|%%RA;K-<8!Y zwLhVl(N;_xOZ58|$+h-#n#vUK_$0OnTqm~%VYmR0J0_wqd9 z?nBRpE_+tTr3;{%0m%L=pX~uDx&aQN)OoKBXbZZ53t`Ag z-L2Tvse%;fP%9$KgcnLKc!`8 z0Wd=5y@VJ{gwlT(3=VlIniwcd>;-QWURGGKTdKW;W?W;r479Kk`2F`fHE(!rR^5Y* zkLfC%6-JuHVSZwBc{g*{nuQaepfebSo@Crm>$)%m3>#TaHV)dk$XnE^zwCn7F2E(9 z|8@a0aKTR~a5JXa*0Yh%KAwsJ=j8Y+m7%Mmi@q4%)}ai`l{sV1|E%A+{H91Y8@d`ApZv3s~?XfAeCt8Qs- z4%#;znm7Wo8u%-n-VwUoj(O%W263PEsixe{X2fN4Sl%#s>E}wVf4JS=&6Y|%#j5A^ zJf{DfCV>6-?_WD7C$XCdetpATB35eNSbVx#q!0%r+^NUs#U5KTV5gWREp&h4tuMge?6Il7?eM4T@5La zZ03AbvESTz(;q`h+VE{o;;>qWj=1w_JtKA#3Wc8TlJ><83t$$@KM*!a$=KX)7O)OA zd&ydLzvP-W&k07CDkc8|Cp9Nq$E5mR4&?6WFl$I0>!vOo;>Atgj2MiPA2wh~Bgyu3 ziNJG2HYXJQ1%!J954a`)ZGHT^)>iNNPc!M~C56w)-J-8$L0cAUM{!2_faO8#ZUbFqgZK=Hy;C7nbwb< zkW{Fi3ntnechUb6v48>*_XbD1Frb1+3w34~HN1wWuR!AluYP7UbdPB;A$u%|>?;?E z>aW(jlfPsPRz0o;x5rXgtOo^wG@cDoX^Vn3A8?^w*2UWT>&xQ@!eaS5#B1auY(VI% zp&uvW+fS=Af3G!TDwV;(@c8(+u0KaSlHlu*ap|=d z9#n&=Sy@8Aq3O1dp z2oP2d?v4dr`>MAZ;sXZ>I`8i9X}ei0@98~gvhO=iY`xd-)?iSuX@lrZ4OU@azwX(5 zvh3v=PiN6__mYZu5xi=7#r#tNu}E_KD+9k))xX0}&Z;;1-L`rFU5(U#^yaPMY!DR& zKqs{T(975Ya2@tfgCZ7?9({ak-uj;WI}(scl3(u+*y$>h#n`R|fk3qD<5K-fgvX~x zJ7_-(JO>dGk?PGZQ|8cP@WttT>e;~wkT^G--Uuf1y>OI_CK)WGN$6fDSu&5w@#wCM zL}%Vxyx5(@d?eF!mkUCVo9-eZaRH}D0~wz`O~5U`T6;B$PrshMf!%w#zlx|;_eDHy z#s*UB%og1GNhIr!v&j9{JU6{KY3oe+WHsnuMnIMtm2`Za5ek#Q(-09r=MmfMXy@S2 z+xdJQA39>VHIje}6=wSewSbQX+Dc%UL~4~cJ46G~u6Bl1K}Hc+LlhMOkz|c8hl3%! zF_uf=2oJ`|%IB5^h>wZXb8?Aahqo7B=Pb=2A|<%bX$1a-9I)W@db&LR+LU~}KC~T< zr=UAt=?Daz1}5w6;$+3$HED8h;s@ZW&8P5%4t-UoR)&)Sk zl&W?=&)@9n56K6_R1jneStyz?%>#86mY&0UOJz&22- zOZd-wV#||nd*U-JlZWrPJE>;)p81sjo9eT4u#er0@`Osyh+s=P^5V{5ci^N+n>UTD zY0pyd=xdX+nE|-BL`bl3Ylk?My+H|HUnS5ixHypl;jVKHtK$OTQF;T{#^;W7)QUjf z>^N0KbthfkqgcVBTFo<&IbAs@ZFj5PtC)BoJXS{ZMSS)zg#q|P(dQ;jIf{|F!9F(I zNPoaosGQ!;X&jY*a?ymN!xJcjRP{za+Z8BO3p9K0a{T>kj^dtl`=bVjPFt5E@V956 z*Vk_wG;V&qwI~s3U zdnS$g?Jg+n%|CH3Q->=JtVa6}!=aZi!LnK?13?YGCz=QzcXQ$5)k5lvFVG+MhceIF zPA~^cSxhq6Ht~x6azl~jHCfZ zvzNGoqoKBA`U4m`@UNse`+-8>K%+-;DIDiYd6(-QHgc8HDF#!n{NCr$4baxPC59>} zpqfsPG!hT5??831CIP_@@?_XV!Ce3uO>PT?_TMR=!;cS2`6MI*(sXnkOLXbC{tZn-p=|D=dIL+ zdM`s(brnCY{f|_7KAB$rp$0OH2u>hK-p`$PboqYVAn+Fm3vjKul|tM{=~}e+lZZ`H z?JPL)oP%Z5#kWRN)70;TSOTQikE8M{<(2%H5er_)YX*rk3LQ)N0cR<-H8!^t2u$$8 zJAW#V2w4jOFU|oDV}(z^275r(kB&m~&5~)!_^Rtg?w#Z*BR+upOp$@asUZh^1-=V3 z?;HKkzn!opx-?VmU*%25V{h5AAe(uwf;~Z$QoFo=rcywU8Bc2RC zEJ~bMc6ZE@=rvIHEh{l3|7+p!?qc`aAwEvol!;a6uc@VA4?4QZde9i#uD1RL_?pcESh=@-+1S70^=zBgCcXh|UTFcX*@ z<--VBI(7GN@j_UI%fk9Ekad}C^x&~7_+98yT_sC%V%3iqS)U|Az;&vi?a!73%l3Um zDDegL5{0t?ZlTgl@Ev`c!4=9l-PgrafajsMXsJXI2|ts+Y0mUg;p zt1>L!gm`^%e+ybeEO6j%CWrecbCQvDdl;9cmZ^7XtX#guy`6zEiVZ6})ZrsZEXJ)K zvLnVn?Cm_gWwU)SI}k}DX1EF*03(swRJ&5+BzlMY1G@vRL3l~i;>KK-2DRR{LA_1( zYmz!za>u`Br(U;|v^#x731l5u>P%(P@5EJpe8;UIySea=c@3#ExFP*)WkGlp-amsp zhsLW}D^%vPA&0GnrpC)6p$yohntdycUQ$mtp{hTF(IP+NyW3!hwtCMR;U2GgL_P5m z;FDWs3Q%!z;rXHwhWkHxnCu?&11t>*0b>sp5fQOyEY%+CZBE(YS@foxg%ak+le5&=7(=5t6dtKcbmSi zYm8=b3gwef%$B9g?W0IINxH6Y!(W*|o^J;KvSY4#&*G27$34V-s-siP8{`2hUE%6* zRU_05G-$@FP8{`+mhvqASuG3L-MBSDVHE$(#K}ZZFQ@;rG`t&xhn)S@qT)L}@8gTH zGy*}Ma&RHr7c$lx)SOPw9Hj4x({GAI*}eHqJj|hhjk#bjXP^RJgT2oC%9PD?EFP|J zX#X60Z!zs+vc_jtkLZsQsYZ2|Sc%QEkx=yqyuV%X)N1bh@|ivaM=Wlu7EzxVqapQ2 z0_en764w=<&z$R^qiiGG%dm-#G7+yA4`}uZLrJHP`$H7KE|4CXKCo!{KOf%+U|AM7 z_O%@`$;Ifga$Ux~RI>5*SSi!QEl& zX9A&tS~Wrly3Sq;#@6WBQiV!qK04^<0;qf3Cm^rZGGX-)2^G+O{gR z>*U?N!Fnmbew_BXt^zfs@5c@H{6qC)V#zw_cp7cX+r@XrGh)mE=XFOpogVon4W#GQ z&aWSAaA;V$q7NKWN%0nV4Pl0eT^!$_1{U+J*c>)10k{GJfIQNV@#*gsA%_x@6;2|p zmPoQ70*G4M1)f%Q#BX|YOuW2FRMq<%njRx&uVwe}!35b40Ki5*E(I*vsDqhUzk67q!&2FdXoQ`= zWc`VQQ49MQM5ESg9ufX{H!;a-R3+-pAI9a(BwcOK-!<=XI39qOYf?Ae{E3a!egk=O z2Ay}%Qu(DT_LgebJXnsaf;3ML=y1YmsxS8ZWFyBANB!4~-3f#4w7T7?PHRheUR_;X zu=%9Ge6e z%Ak}B`vMS;froA(CyPbESRgOjckgWfaIDAYeINPmhGXzNsXUHWO&YSW5X{#!WfBhi zp#eFU-k|3D;LMx(s@3iV$KC0CEi5x$K4`P+35kEgWwT^91@f?ZpocTEjTInFt@aJ= zQp8irefNGoqOvU)`c+wh@SewxPeu>RWM+fz|XtsN01wE!zSw67ZmHH$!S+3S(By$w+`3C;+ z(%YxK;G*+s-_PT?ng;jOd$+wz`E|~0?JUW*-o{qyD<=L$qn>y|3td4}Q~B=8PN+1lQMtn z)k4E}Cy4l>E;5Ut6-OOMoZaOn)0#CD)-^$k)viBp(+%9XqT>6t=l*e2Y zYZ`{yw~lDdmH)>YP~l42e--yqX7hRj1!}lvcSEu)>}B=X(`x=q4r#d|^XlN~UZ8{5JzrX+N|##BTy?dQ`|qEH1pU_ ztYTB6^N_`x=?3}mqn1x$AdqJ?F8A$)?kT_T6Z$9zyLheAR1?Uh6Gg0xJ+a}f z4ZaT+9;x!i`0bckS0K4c&Q)6uBaIF8{^iG5KlV0wymlmmMUFWgDxKwO=u!&WM9#4c zGLn4BbR1Ygz=`3{x~doE{Ks)mk3|~32)wjO3ZeXjhwsqbLVUVNB?lb#nNOSY4_vd& zZ(Xb~Viw?SA7SlJ!#J-M_uftpO$x@ogQe7<;ORO{#dXBh>k~$CT(?VE50uH5d02up zj$vgqdFGqn1fUpuUCjE7Yq>F)c0kxn4=MmV&rv?C6rhYKRwDv#q+3iIFx9KARF}>G z0#tL=d|MR*6SSxreD?&^@oi@k_#30Dep5QoWfzkMd!{5aaEwZ)CuyyszLc(;1S=GsR4MPH2P96= zKwxx}1$Mdf83%B8p}*$kk{on7zif86A_xxg5`C^-5}l(@+i#6i6ppvYqBPn&2^5VF zV*|>t^4uMEQTzdOtAOeq|G|8vTnqPg!ftTPC}uCo`^TlmBi^1N)gQXy=k`{Elgn*o z$Tb=Wp>=i<^pU{^yHkWA8@5O;vKicj);hkG-6)HtS87qEs2?Q>iu`bcCwAy+Ko~ia zf_G<$8r_Vet{G{`9@|t@c@|NkhLZJL@qqw;_~*xfbcci$sDP0nH6F`y9}7IS{u-8u zN6>*c8H7=;)u%WSFrk>;`q+=_*@Aeyg=y9AEI7(i;4N`AB%jHs5=(?{nQ;IM*{!E* zf4&*#>7if2sA*a}BcyqQ4qmEEL%zCuFw$M)w2uk#_u;)=tdYs2;VC%bfcu(bZ@w<< z{5z!c!5@|oYSjB#q-CF<{1Uvmlt;Pc9uN9WXrr|9?*6*y>@@UxN)Cfp|JqjdKNWN%M=1NVu@LcWi{k{>n1 zL%n&vzw&I}(a#^RnMV~I@+)!+c0RZfGYy@W5e%7nqLhn|^HWmjRf!**O_pUI&^ZHIsywaM6WjW;iLN`Z9#2cceGgI+y}-w??ouYc^*>&K zs|cWr3^l_DHp*(VOpIiGQTtwrDBSPjm3A@$A%>c|eU1j1?w=S-=LQMU!*Zyhw?iV&6d{Nt~et zf#mv~9z{a1R4BijipDhZb+tH6DNiER%IEXnFHEG8z5X(hU2X{17i!z;q^kdM_RDzw zcUp9(EZNfdh+164U91+*o9y#PLxot{Bs$tzXiFaHWU}=lO^PIK0Bue$MRVlNWJ z;m4YEnG|_q>KfWBg=`8d$#i#YJkEWz;_+s`v8H?jvaej*hg|aV!FQ#8zrD&POl1L| zU*tE3Xm&b4gh%W3HDLw4t|hV+e5 zmZ%mU(kbFOjBn;Gn#-?>WK5m;U#deP*Xe7g;o5SIKSs&Xc$?=s1YpWYTJQ#whdzv`idZz=Y1iODgb5EF2Ju z$nv+YXb0yO4!2A7M2B8hrjekW3G1?d+1WZri9F>@Z^v0;-O(wd{ZmMxKyZCN#fhHq zb&<6sfY=wE)<4?XfkuHyAcZhzQlBqe7tY1&t6bNmhZyH_36g`XkEA>8u+TegMwf*N zA))R#AJ=VGIF1<`%x*U!M{nu3Ln$Pmk$uqeWn35RK1+EjUj>W82;s~aDwpjkbSh;< zg(*B)=@~HHQw^Q54Ju>?Ol18b$KP%+e1+L*KY$a0>9ss-pmUr0zO39zGD-Wk_UzjF zm0kgn03B-e4R~$y%H{HUp)IgSVh;xoPYgWHI9`Ls(fpR?2D^2CsG!YefNiR2;&sr& znu$atNqJelU9a-j9kpEbz9^*PLrCk-XH;L1fW=1O7Y{UKrKXX9(Z$G4)V^DYz zv6?7Z^HVhdOXyG@xxU4WvIcFErGVp+`HQLj{?$8LtH3KX3|^ecstN(wl8GJRwDZ-O zH#PiT$4x3mIB1-`ocxfrw@B#AYsJ3NbiGc;od*2#Wm@P-Lz@pIh&4us{P4WRKU*Sg zx=56(Lqm!0eegKyZIe*DZs;VK2MFKjOmjxYMN&Q9=D+6kxSr`buVQ!0XZ_B6h5Ed7eT6wHXIjJx9c4ZDVcApv1ijA!nX8?gkwf8r&gHH6@1&0qHr*!d z9vGf&k^`R{QDysE87H0n4`WL8hTq)Af8Z>uY`Xzn9;T%H8}(e)$Ae3_TpG>l83al! zO?G4AN)TxpRGpaOF!fvu_}>DaUoh*7_S@%1~W9<|Iv za?gK^XDbW4ljyby8~j$D^>hJqB6&)H=U?x}ta%YrIJHAtb??(V%qYp65|OUQ%)P|j)PiA@K-*8Y(sLs% zqL(Aw3lXKt+*!Cvk6Vtay;DYkGSrHFQ3+AkP}fVgY9x~9nU2o0jfA^=V1XNo7wP0Fj=WGkh+E-JDo??`wRwAme-p}pU0Hg^;q9WyL^Zrhgn zNRA0#ArDi9rrt2&5s9aRbHuwHaeb>1A3AS5T68S?OnS`G>pnl_%=srU7E26>wk1V5|4xmO(d7}ohQB5;JbCTCiLt5Mn3#i_MW3)P zy;oc00Z}SD_qY!TUd9Lw`dhyv- zAZGrMK~0{;G_-@GJ?B>C(JK~Kw;jQ%%_2{g%Y8@XDvcLcTls?!@3tCNYt0JZ+?3^G z(UZxb-!Ks?6qZ$Qh%w@_B znUycTzd3c)9h1nHxK|1sYpIo>Cr6P!pqEx(vR70mJ2yEG3RnYi7vAW!XDx`|iR+gc zwD3Ze=T_56cHp+A5rLQBcDgAUl)r8z7A6rHLHe4wlk9jtgeWumfR@aJASp9b0qqm= ze%iV{ni09+*N-+yF>OPPLf!Bm-8ZAFdr%fOh#C2BD1~Lm%y=TNFU& z^HlSm)m%DKM#GEQqnBH4bZ#btp(om@=tW=xk{_{H%b@+Wb5Lh4H<;2quef3Br{gXVzw>@nd z>x_JO`rf27+HC76iJ=vlw-hMjml$KB(ry8Uvce0-?DqfT9A_!=10KViLa!!hsScM= z>FY;Y563gP>iNImf~ng233Mgyfe+DNWk_v0Wkg~(O`@Z#Nnn`vMHRk|er4_MmuAnR z;hdP0b5%<1ZT^d=N}xvT(ySA8b(u z&v8VNC@NlmPe^+Pourl6Vn{N-xi%o^Gn>;`+1Nezak)RTP*A#vk(IHk)@f7L+X7`Z z%K7S>zd??T6+*AnjZqKb=YLhbJkV`J2BA z)5aAqh2J3fl`hoc8wqBL33T_-Ir8q7C8H;ZU#TuPh4cDc?+T2J;vCyCS(y7U83Py*je z9UEU3Z8jW>hhK`KO*wjJS~d6G;mXdexD}4;*<9pS`}VL(2k2Vl_mkbch7Pzs6_`$j z-yoeizzE!pj+66JeqtD^F8!TYNyzghHE74Z+iNx-(D`-%s54^uAS_Y`+|>Q94@0;A z{t#nrBN6Ec<;#HUfWwBK9kYI?cZ^eFpUFl|x!WVF@`hak@en% zn&Vi^AWH;?u_`DG6{W&Uv?a0>1tQf2hQc6F;A3 z3P}gcGUBOr`e||KiGd3cx6ipm((R9%107K7ojTY)kmPd+04(yX3cXJQm3aV5kk)f3QYixDOWQR(tI# z(P+Q)F*4LaamxQD%e2Rzow>5P_$iWW+Q8LXh9NDA`fUvmZ%tjpV1Wt*I}9XfY*Pre zVav;T@#l|S>Bwz?hLI#b=M(H}B|bfr@p26WSDMGI!-mkmDxzhL;VQ?n|XK%o(7q0=fB$Zx~~So2kH?l2Ti;1GExy7otleP$b z4~vV&{(sne%dWVZplvh|oZuQiaFR`n-V)_~#d`wrok ztB%kmu&DrfEL;$PY;4)Y|B~>>2Y7JOZ^DR1biEK=PES3ixVzwma6gtDAUw*Eg8tT9 zJJYkKu5H`+E`vu@**Q%+idiicbq88jBkr+VX{>uM9q_AQKiiNtN+@He;N0Sm# zKzUh;Brx8WxS6~tDOi_NKW$~65he%s-Q>*pB+wjLT&^S{c_0Sth97jN3j4HnV&bRv z7&#8D5WFJ2PV0R=oi$dNQ4 zBu7S9>pB9>PloU}+_$h*Pn+C5;dJL;(4X*P)q8n-f9$+-0ob=><@MpWix=(UFWFaCgBt1o|rel;KH`fprLc z;naNd=2Htgup#rY@n0~(iiYMH!n9EBUwsQ%>%NamrAADD$gONu<`YH5gthuVSQNmz ziHP|VQ=c&WH);s+prW9^c0G!0`q<%tv8f)OS5>|(_t>rV_j%l&sE~YQem7dhy~Xu$ z?Adc38E#gEO07wfJ=vchb?N$mjs|2%eHGAp*rn{z@v(YtMP=Xnm{4?Ic2vL-BSnut z)6m!-og2+D-uM4B7jj^uMM{BK2%rT~t+hBrb7qwdLanWAQiHAO4aWX&HW3$&V>J8G zngt!2-W_?NF~z%vId2c&;}_8Lcg4%!UeGJ5l1TY^QDreaza?kV1s#71Q=q9}!-j{0E3U7+F?3)VZ4O zKbnl;gL4~i@Vt%N!s+?i)+?ig8?4?9&V8ECm7`enQXDFmfcp4(jn=(}DIZC;QFv#2 zt(xx_RSxsE)*;So5)HtDAKQHQe5GBp!p@~E0u)lA&Lijfp==$+vL-jxMyt+D_&Zr6 zuNjT_MyJ(@UvD8?d&aoN4DBvMr+>T<7+Pw4lU30UYVAeSUPE9qma)fh8Rc<)y$RA2 zJ(svX^}Zpod8=Zq_ryNLX-zrqrHbt8wUYB3@e(T(PT95!qg0~F47Rk>p}S8?alpbD;rHjmosO({ELBnb5&M`Qd4=t{V(jWE_*1R zlc8mWm!Ey_r+x)y?<&75vW+92UAz1EOgV>{yrFJ}?vI zHc_f1&`2{NsediA*PI_3V6GC6Ou`|YErvJ`9nQD4vq)iPp-__jwc>}?-=o_(ewtiiGXJt2Rp_yGJ(bIIL{drvGp=W^^H`o-oF;YIE(0W=|&8 zKs+*HD4m`T9BFi;Yx{fjIO0f^d+pOVt)}e@0%05e5(9CiQ+Q}J#owzh4EnE_&dpGH znVZGMZsWd51HQfLhnlGgP{}m`${3s-}tJrx#=|$P$KMI52nIFr}j79tlIE<8IV1Ck!fS55; zDifk=NPP7A0Qo3vo+-7)#l_^IR$zlF4DE%G#jfz_3%17mt1MN8^}E?cnZ1pm9__UC zXZ^vr60;95oycMVTj8fh55!Bi&N1EH-;0xB=cPaQh323kcs!v_G_FdufG*{^mJ{23 zN&ISOk`wSGzgBU>HtuTMY|i?<#2QsJp$N6FgerfsS6Y~i>!BSiaMZbrCIJL7UQg>;Q?QN`D=JU+#^AHj6Q+ix%e-nl6}u2a>BRue z-zRaLOoq~XKI6aU#&w#vIiA`SPXmSPJ^(CvC~F)8yOg*!DK>}nQh=(e#Mr6`)DydS z_orP!x~O=}%1T)XL44pOz*@ZHS~5%C|6ct2PN8YanA^MfM#6t4`gCUrtIc;OW=oBI z)2n@E=w8?rmMrU}Dc{FT31gLx9Ld@|U^94kz4u|lU+j4s<@A0}e2LT-ny3TQZUjD8 zkRKDzMYMzJ%I^EH17|^AtJa3p#InpU3Kq<7GLep)>ZNQv+aF;&Mpnp9B-^6OW|2=sF>9aR7jU1u|5jt&nd*tmmgjxh@Hj2x zT_NMN@fVFAXKJBW9sz z*y&fjmgbx7LLQz`_PrCzcxd3lTy8Ix}C!EsSzGGbr zTVqD)X^aGWpAWmQS&Kn!w~)oPd;k0+b|S)ReA0;DQ9c7XiMNdB{Rs+A3nqa}fpsS7 zehaqBT97tW2qg_^H=8t4oA*{Ee@dqJW3Yduo1{D60D1<(DiGx!nO6Tv#!KdA zE)wZ?K~hD0gDN%X8!o+RW8r!wVv!i!Yv==Hbt2)YhB%K|TTE zR2MuWbkF)tlhbYedV9}2mj5;NEG-E%|9$cpd0427WuKWvA7-CXvZ^;x`*% zCmFBiI#w&hl=1B{Dw?oGJ5H323<#HqUGPh23#iwg8Lm8QBHqSXs&E3Wwq8-sZCN0> zRGGnrmg*cfyngGMsI*S~C@`@pH6iFGNHt3aXK9IeMi zly=&^hv6@EJNm3gqb5vEw7pd%=$fI@fS1*oFTjuQV)tNkVSiLWME1)9D1Rrn{Q}7l z*Z^zQm-2f$E*OFb_TWl{U@;(Rw41?~;mWvUOsfdB!(4VNM^aabBje=TP&()93~|*7 zxVyk$xw*wej?I>!-Gg}J%VIIcN4m-S3P0Es*u+P+2{>g5yunjQ(v1q*a?gD{6Xt@0 z=S4(kokZ{<47yQ#8rt!A$D9V|j`v&HkmXx(-p3YDaBQh4Du4z;+0yE4IXuY2aFjB{ zL_TbSxNciI+h7i2EcA$!Bm!zg{#`lHz+T2R&P*foSC zq9upRr+~8;^b|^xYh=CrtP7NK;^HWTHrBbCeFu3>aq0PnVT3Z5vSQgpUzmI{q-`!4 zMpBnK^ZFB`_3@@umQHl5JuX6k)+2d5zm2=eo-=te>C-}maJgUa@W>5oo-78o6QcG@ zTv@Fhc;s@SPz)~Fw#8=YexSj1<$7RUfm5vWY0~(C4!aQfT-!tV{n2gkKzB4&{^u)j zpt4$I&^xwh^I7jKaW(6d*y#c8S~*DP-q8w?|HV**%=dvn4U#1ggwax$>p_^oZAfqU z>nwoodn)W6E<6Q5W9hwt96u=k4mP(*ny0POR$ub};Q~xzDx9Z!YXq}aZQ^VnoTfSI z!N1)LG_ex_FC@5x|50;8;BLTU5p9b##%K1*L5s|_+}wox zE?#XY?BZ%JC~AuNC(Q$qY`($h;PtcQE1Rq3qGzMxZe!!2{DB^C-$&hc1rL}9Uk^bK zi-qGU0LAh`OapqzB>TZsnQ0rB*C~dz*9q>nNLaVyev;P8UH^B1^&48C>SJkfyyegPr6Km>^3tpg#Vo=bDbm1``N3I1 zItGGvpk-2Ws^C1wXN#M%GCLBuYn^lV3KJJK@wm$}PKj8YMzbUwpB=DgsuRlIFO&)k2H2-Krb6*v$ z0V=E&ipyv&2j?QRzbWQ$Uc<;7cF%NBmtss6uj*KJQXiz}Rv$UUUgY*Cm(T+rhNRG8 z-$nJWkpM`MyXD^(`2oC0OTKXIBFSEnVV>!TZg-e8S45Ae4f^doaQ*3QlNb9Jpz<41 zVmCEH8TdXBF!Q5ir73lMuvR^_o87(KcDdzGsqB1~H9&6?jyPqYehl~rT*E;+*-!WI zYDr@W==eC&BR{V59ctBoj+h$JcQM6jHh>`5mOl@`Fb46o-P$`HK=W_x0R+`vNV}@d zGh^XIJN*i3=NqGsP2V{MPjwAK+dfJ_ji>=nhA(>x8lFPU9cDz^H)ARlQ;8Ki#iO{5 z14|`1-A@a!pfB+#IUpc54FCxO39JiPK{GH=w9+&y z-mg-eC((HN-!pzyLRWrm;o`EOgu(RZtSL}DnuTO+9R=lEQBQtDk$(JC)gld?micCi zS%WuC2&Ctl2hQ!Z^PGnnH6!&^)6&lGs&9Dw z_;Fb8=H#5x?7DzQKBovvE&Jz3JqAb(vj{e8BlLid>zE*QH49Q-5U{F7Vy64O(>PUh z6TqQOa>w%X#EPb$w6m4{qoM%01OhpEQ)_E0oa>xQ5!2Omy|?j1p_bHLuy~x$`icxa?^*em8bxa_l>iVfc{ZcLrmn3A95x#MOc;lFnmF zT}6y0z$Xp=?!YGQat9-ybRDcuXzFBEf}1aGof>?hjKPEFj$9H$(oGkWW{#Uryp5Fd z3QI|fjExDlqk@EXCzW*D3!1flMk)V*tG~@MQPk@_7AqE1(qZ6u`<%gCmiDy6y-{jb za}z6+Hd&XEG9)S&I@Ob1dMSH)f!280&6Sy^_ewbnwN?ZIF^eimA*G1o@ zjruxgsc0HaJ$}&PF4N<^H>u-{Ah!LZ7bdLmM?{%LA7=YP^sBz_t!LONI8etG{UA9d zEm`0q3qF*Rl6iq7hC`3V(!J#yB#L+M5F_!zYw2F-Haih}8doK{mY1PU+DT7gT6t?J z#$*X;PDLd2}#hSXpevubi_Cgi<@$Ucv83KxBnVf5&?A z8|u-^0BeBzD15H8ez+Qq(Paz&?P?ANG^2}o0p&bOK0+1PP|`@+pyaKL47!<;gL_Dq z?+YQqOMpTO`yC00IP%-c%c-#;xyw>WW6W!*7-ql5)t0l{4zD|+)2myu$H!m9I&CSm zCqMMYh|{^07X~kfl?km}I^QIn4x?1I*!1dTrfzelduCw-m#B9oP>d zqTD3p5cBItjdpt1YKRSm%g^3zRx$+I!1+SSCza7VwEY(PolB68f`l$c@Y(h^j3!4K z$x870&JG!DWa|5q%}G)F3RCJrEoav^q*_xo12z(x{m~ED126pwad!8QXX!Vw0eII@BdZo8QBO?Q&FjINXn3*#a z6R+mV_d&No(r%|@I5djy4EiI?o%Ys(ahU`~7tK(K!g}+9U!=gWZ>0Xt-aJ5LbAOYq^^c4bizcP?a}_v_Qpc-01X!`$ z+;J0i2YEmY44C}%zcWHl!$wI*9hZ9vn&bLFNo7V#1!3;=&mE&4=%KfVTl2KJZQa~>$OHu5M)u+2W0E-qON6gb)Z{DYU%qFdi!gp( zRc>-+*$y89-3TLeMOT@OW_go(KiucYs=3ZT-@GtHrE@2oT}-&HZ6Ub1^KXp*!M;4& zk2Vr}rO9+ee32$B^t_im1b>dO*@4=VC5TpSZOLe^JswKBBo+at7RR8~kBN-^<1nR2 z#@h9I7lg{nK>eRQHhbGYvK{vLl)t^zI*wlBPkn_o3FEJDL2V#2e}CIz7(;Z|Ya|V_ zJL@N)05)R?UxMyWPN;M|eu^L-rTk|BM6#o$S1_<1TLdA;QXeH6)gMWRrakWFOVj^E}=j(Q^?c?@#-bDrz&sMvP5GbVSD2Ls1vyhf(a!z((Q zYEOt9PJm7Ba4yk?txYRDl%n3d#rdmfbujf8A_9`bz~1gtftzx1?E4;DDxeY~v}QTx zIU%b(jY5ioLIs^VPv-vWCQb|yM_*t1k$s)HLVve7>uA7cUuA`-jluQ9K}{Kd8Gs=U zG4Y0-*(^OSIbYc}VUPyzFH3E$ApG6U^5}c#H!P?2E`w*!*;_-TfS`gRS!U6JEx_?R z^+>h?5!?nA&C+jueg)g+7f*FA>ZNJxRGkQBbGrOeuHijn{!p(WDplP(#)Q^!TN5iM zcfXB?k-Bq~Lqx1b-)cAr3RPJu)|f)6Y}0yW+wLxIqnN8wUz!efh=->M3KLZ(N$d=4 zXo%$zox&|smo%QM2zApBBV5P$nL-{E{rShm2dK@b8yneb~+GAe4u*n*mmT)mhv%~hVBaXoJ2^9R$5+;N4)%8>;ut+?>P4Hd> za@UlNmUf7vX-j+$$T)hrD!`qZG(=;370I(q+W1j$SJ2T7pSF!cqLhJ3h3X5(MI2#r zE+!1Dz_C{6pL+`He_f2iTJTKm`ua{7qEK2Rr~Zck*TwfcI%&cW@eFx2@woQR4Xu{dl}FML167eZ7P z7WgQS@e_L(*!Gj%-5~YgCgrYG#IIsULz}ViWkGJ$hEJV{vSpv_dzI`7khgDgs>LaW z3O?*NbI}$_*_pBQ^%V>kM>eip!)L;X1;-a;@g|TpPRTu9Ff;2bh=pS^yFH=!rv3_q zNgNu&eoH>xA}<8od7{{%K+~Fm=gfkA$9o_4hgCk^BO<8otHUBnI9KAYz(^lxUj=i} zbNfgNPJ(PT<+UMuDW^`vC;QQ}*(*T_5`43KZ{_9`a^p{t!~>%fj4t?s0!`4=Id7qx zaroufPAuT)`SZR))6c;Jp24Hoe1TU!jQF=Wl+eNb2O1Y5(n(w>5}N~ht{m#+z!0c! z3o}$81@|moxa2#Y%IWA{gjtgKA5+B@N+K&BE#lE6q^lgGMVuobewZK>n^VnHY_wD-P8T=J zw*d{W6A$Q;V0`mCxZoNNt8SWW!B?Lbb}cF>AQ#)pcXq%G{45HYnB)IUj255FqZGf{ z2##5LIZoY;r!`OV%mH7cP$(x`Yb|We} z+dAFZ^h$nVE)VZAl7Clur892~5os~>%muS6GFBDrKbeBXVrrvPF$}6HvFNipD==5v zgnAB`<&|0u#__xd-qgn@?S>V<5<32kA2RE}g2>t{eVZG=GtH$2V@yi=%F{amN(8 zPA%p|p?_RZZk-fqlN9+Dmp{?DTKML{BEZ1vOt#v%xq zaIKIq5hJp|qX(TVTuSL-@SYzmG}9h$hK{L^Q&6)(RnA(|QGW0NH!45!lVo$9+^1-# zfmhXS57bj8eY%VvvO-EHd|Iyk(WMtg@1TCQg1W+RepT13meJCB{nU6CXd|Yf=sEQ) z5}ml5pWOa6+3<-9m%rSEqZVvPMcn-b{04}DU*qyyeP5iPECRfK+|O8A4twG}%!D(^ zKze-L<^oOlv7SP5{HI~A+J>LeY(RX>de?}%_lxo=cT~r8x@6?m+>}YfS3*lI*c~<`Zqm2O)qoflr;MK;G>%w> z9c`u>5CL^sd>WiBBZs60L?7js!?e+`SigI`eJoOt{>y6pyd9M&ESPGdtp7Iv8TBhF#DFZ8_=egFtRV^%lpp$6Jq$>EO3Cs&M{MY zvm10>e}QpoDZXxP2{u1_ZT5mZ&WDV&h=;+(W2#4bq=hfh@P`XpK=+1c;4kQ z>4yUrSj>%lHB)mIh>=3+-0ZHzE0BwaZj79CeVxGWi%rTX)Hn~iQuzB)q$ zGx9=B)Qh)?w!4Pfk%(xX-ZgkKH=tdaD*R!MkUwVq1UZ*>b2B_aT$?`7O3^5k?c#kT z@o7Xsap8IcdG(C2#G(lmE3m0>?_Nj4$GiozUM;m!4jg_ zps1bJk_f9~(bbgtwl~b}IZNK@xiV-JYD1_X^-zY($e900XrNhODgAwl+$?xiSXYY-)L7q~82G%QxiLDw38 zCTW+f0A=A=tpEDMVE0)<$7E^X+%Q3bEG~e8ej%|OK^EQP%m?O+D``?87>Kk!P((Tg zLn~$_vmf^9DQ&@SBbVTPQjy9KV95i*dLqh}Ay5>rH2cD;4&3Cbao)0ZFCi$400>0WDobhd0TMKfor^L1{mizaf}SP*6%j^ zs(2UUqYylpf8_F5oPxgpSg{9X#JNB{Re8O0W5;03HA&BseWS`%?SZUW_ zQb%Ix$QwbgLP0(}j)gbExZ-)Pfh8@BucpRVYi^x=cW8&)RuD^*{bFds^C!_-v$+mS|!IEyk&9Fq#Pg@%M`D|Bc?$wa$qA}HfN)R~KlZCbk# zxh^}1Z_mj2ZFlTd=nV1g3D36|eQHt5E-H-iME0gBEm-&t3s++cOugZ%Hx3?z`V%l5 z;yGG4!bjlAWuxcBjAki;%fgL8T(vW!dQ7QB`_my}4)b=E+1f9fc)yE}ZJjb9u*I85 zVky_~u}>msFA7dlE+JwVxXd6>jDGGPYGxzk$m5pGIhJ9p&r6xQ5}*3Gs^zJ$69Pg- zV0?%2B2#i+iaZ7ToLj`)Ib_NwleX$UH4_iSiaE!jm_%0W)e6_%>~$19y)Urt7~n(L z`h3I+U@*iIU?l3CY`@_vs7PXg1*@c2k;JK&I`JB@?k_D`9ga>S+SuoAT<&Sjd~Fhi zykQZT`mY@gpUJkrNveWKlDzL*13ims>N37+&NU^Gjp;1xYt86q`4`vXnQl^B7Tf@#mC%Q-afzo=H zPe!5tAfs7om#8IntX4{~s;Zkv*;_{{3xrAie2MC@ex}|MY72`UtrU@2nENo87I|n{ zV~a9F-X4<(cW!C8(|)-wF_=#kXc|XV|1u3gL6C#SaF2SrPh~g|E_-X%q@)75z6Y$* zWcJYLlSs(Qrm@YOw##)$q zB#ryzCd7`*`NcNrL=S&jIiyBge1Fm#=bAXI3QiRaN1c->66gVCbSP_9=)BXwzR>g8 z=32}BVXB)+Ni<`$An$)=13&-EYX7Dw^Yj(6M`unRauX_b7mQV`h<y#f8|XW-5j8S^Tbi@n{uGwt3+Bc5TTi`Z_1Y9IZzVw$ z=Ee&WtYofX*v#|Xe>C8*GI;bVbYRQZI#S{k-pyvmwHY73t+J=#V9*=47(gV12<VFPw`7d{1-~^jBoBFVpO?TZ?5;6)LC_YA~J)| z0587Ia?ecazH>U^^>RGT6F6qJlBlZjP*bb>`Vn8~>7Gm>v!k+9wjvZUC0ZnD`0i{! z)OqT=DMoGmS95X6@0D=Gx_36qHMix4u;R8O*DcZ7wmG^t&gU&NA6s)=egw>~BrL-M zmZ=nQFc*$5R|(aR!}bM2vVmnhJ{*c!0vka@y&$GB5P9bWFcD{rocs{gKC?`Pr+uv& zzMV$WOv~5uY$rPl_#JVGDRKW~|K*6sMwSlZpu*s&jv3crn_3Y1#qEE-wBAaQQ{jj+ zU=KD%m(f+|$~&u92zHI~?p7J!FzK{m2g6tYw4ev}p`RG^oj|5?LljyXCv%WtAVZFc zJ*T!fb{cJ&hwBaED4#3Ju>z>+#et@9hDF~IWf|To-q}WP@pTfz+w4#=Aa^=aalb65 z+u1EH;ITsCkC_C^6ngh2u|ZKA2*O0T-RG&rouAsDu`bX8_D71aABPp{J-Sk}kU@3t z8{z@^lpsIqK2!>E?SoADQ>xXy=t0(9E825DesYuIv`rfM>4dlR@-i~r<;{3@kG}<% zIKk4vws%fbkf5a_s^Lo6T^nYVBF!5l{S=RPs_|R7h7zw26 z-oy(>(Aq^m1W~1e0^ZyOF+Q___rJVU=ccy%1${CKyncw7LLXYZ%Tgw>cS+f%-wM4_ ztegyw2AC8As?%T9k@&v183>uHdTMz(dk^?eW8r;D6*N}fpoc0#iWjE|gAFA!y=-QV&gW!sh8{^ITMG9AGlB2zO z%)(-}zc746*Y;khd4oyW(99WvbtGP2gw0jb!_9I~g4@mJ>zb9SSPVM{cAvw{{~dCe zKb*k?T24e227+ZEq4Vc!{)c6_q?oU;jfD~G8EF@_M(*F2?QLB(5oQMk99QtLRb}oI zY@`9;VikhFg(LTxix<#_KKz|iT?>{5JKy`A%=TO7>9@DHO&d#R-Lj9Lnp4=4z=j8R znuszLK>)-qj|sTTvJXl}i97#N+uY`LLvB<63*zzFV5WZbz^?54glMge%k^P5vk5C& z%J(F3QS$(HYcOIwT7DW;eHhptcZg29^@Q*g$0L6jJny+BIe|+*@TZK|s2R1rQIhC) z29uoy6YFySttHV#EoQ6^BCsfF?+hY<)9Kc^fz+{$ZFp*|kmYBDT9r)BTm*X!?yzK2y0J zi(W2<>XS9=y02>3j^E3|(E%^b77RA5xSKc09Kd-GY=&PDDKBuKbFBakW&dXM+`Uqc zAPcdhTZ>20$MZqNFc#A|T+ZQw%-@#VQ02{->W75(p-efTx_o_|Lf# z^*%=Cp4Tf-y{>BdD42kGzf**DdwEECdtElLx2O$tOaT&n)iC0njBNP@cO70}-drEL z0IMw@V37X@^q@y2en z{Bn9~onS=!&%m2ZZjW16zsGO@vPf1*3dnL4))WfPT^S zp*l`X(5E;MLk@^S{pfad|4bSx*2(>Krl?FY*wzo<5vwUV7;&8mC%y@Ceig%tBKf?s z)y`$LjKSDsC*H8Rc@Q=K=OEukR6n6{1ceolAd$a#V=30V|K$Quvbpv8NKjFaMBFDc zM5Pj2yj3spcU4VLMnh=>ca3~v{vt>2qG9C2g-)zL0O$-cIwVem2ZJS1{uvUbHdetSIRp3y;i0oGx`qj^)If&F5s*H6K`g!8@Ndx^Eyw$T6(Bo^+P)%P`XK_ZKA zh-zq`XIt0n|7TiHcxs#{I4NEF28(ixqIqRxWcokm({J365@;6K`UqeK=!5hIm?F|2 zizeyVo^2|M8RJtM=(NxShjBvF6Wl2j8KM0NO@R}~*x2}xPG+6n?~{u>O!1(V4>Eni zqD0g2V(!bV-@njB0fdOr}of_ zg;hScdaB*bGL!k2u0~VK~Bycr^A4AKqrS-4=+#Uec-#ZB!^3P5V0J(bog8B}AC@V-vFc zehkLYa$OdPDHbdBTA}l-)Up2mcDX>ERg&NLK2Ylo=INa}{OP$P4$vb`v}`}YyOCo1 zCsV7 z#z&3ltj##sAB)e!x6=)rRVY`K$9%9-0-pB`^1Kfr(14dbO7r90)oq0v8(;jtVNr9g zn!rckUW1F~*BgFVkm!LGsun#*1_WxKGu})lJilGU5N9x4+C|yE=2OK6ChiykOg!C) z!!A>yiCu24k`gEUFNZpj&O!PqlU7Bvxrd)wBx;-T<1K z>U0V(l%cTdu1D0rG5yrlayP%zrWBmr(y@ z!U`Z%Ut3??TQN&I+B?pSG@k9-q4qwldcf#^1=w{g9$z+sqywg8cRpF{n;zM?qTW^g zpl_*F5EHC@w01Wi^g6KY3$%+^7v@DpW{xShb;iH_!6k%$1oi@Q7khg;gyU*Vvx#NA zMXht7?;W(pvnwGs(rMMEjoBP93szYF*s|*4UsiNW%bC@;Cm>q2=|$`@0p%jV-!=E6 zW@XC@2{Zv~=nkEn;>wAZMEo1(9~RBQ_U>pJ5g6ll85@P>TBLD<(MSVpvu#Jt?f0ut z`zy98#jmYLPA+MGJ?ut;UnrtT-ygT87QUWezxqu8Hjh>%pv*SafxBi`o3WNA(AN@O zDi;-kY+v-Pzx|s>13&7~vO_C6e{n)W!mrc2rq?L~f9j4L`N(s<4=Ga4EwMo7RX2)I z4-+s^WMnSoWXx<&p_uV$t$>6y#2^w{q6}FyhHg;on!c#`gJptt^q&Q}W;LqY&tC@4 zwY*CqBhyTv1SM$`tbFy+=O^{uEtNlyHKOTh~RHW%%x=tDiQ=OZU) zXUE9)>L86w){74`I4YYtUB+_;3Y3fk04Y(QGWr7+t;(%mZB!dSVEMt;*zTp~c0HY1 zMz&gj2{IH!U$uQ0t6}B3(hxK*+AQTWz_`@0IRBQ!En}V@suhdhi8v|k9-;MmsqZYo zmCege^7g)|s~5-4(O<^IqHOu63lMVU1a!?`DD(Inbfl0Tub)UQWjWZnV%gQwGR*1>vYo}2RHBofkI26Z7%gSgb;qHZ*lQe&_1Ix)e#5uG%pA3-B_H_heWp-v;Jr|K4$qeCn}r*V7|Y!1^NSCp%FDJE zbvAzj_P`x5_g8et_g0$XkdsMYuYm8ejXjmoHN~EM$Mid9yk?$!X8e^(*{FmXa9Qr} zvsV#^O0RNx9OPbhCt}_EV<)1?vp2^U_fNX4+kF*flZHaOpDulE-c$pV;<9P?Z->A1 z1%1T6=$nMP-!0-a%HmHP6EGWUGa6c@5J4`*!-|n(IW%$zf|C)zAMQM#YNGr~kzn=1A*^wSb#BSR()Hq2zgPsDcB= z%Zz6av~I1lyjk4q0)ylkydSK1*jXi&N`ee{b<&5p!L@CpmA8zOQ_=G??>8rK_ZDkE zeg76m+)qC~##K!*pI@0p$W5AO6@3Rc^WN6O(g~T_rcMyqtWnhN!6h0$N#)mcLS)4veuR%Ww?IQLfMi}tVoU!T5ZzlU zdH0CiG&1q>3vDfAl0oD{RiDuBY>tq}yfeM;PWNsT<@oo!LM^Q{!{5dpFQl(_aI%eMNm7^F z91OHwKb0g3{~FoYP!+kxXBW2CSwV~@g!`hUsPN3ZpPub7eFEQjBeEUQk-CtO(AkLP zYZF240h60k<4eviYa%(T`bIMbe?kBLUXaGuwx0cjfL-{EQ?6_JKP1x0*5RR<3OFm{ z+A^=MH@Y%CTJT2BHAL%EWbCo&qhM1up&l*3X590aFKhMpF;kOjZ+crcr#G|6?%mt; z#a$hnB{>U$t#;aVQVXa!QMDDktZFc~k^WS2^ljUjX@RM``Qo0EtfnkkM=uO*KyP%{agX;h3&OgmF|mFJielx`hA-Ef@g?y z=1fP;j2&ll>cv@V0N`X2UQSBA;Gz|hP*fYP!DjI2bkqPX9kUFSRIKN;fvZ|Plc(U{ z#n-Ai zb>3Z-wYZ|20M41j6bx|7seghh3AqDIUWQw7zQn*RwVg>&0YGfLT8IZ5?mfyq$s1F* zx(Dwx-_`Qxc+`(dif#Pr7;zvH&K0hq1ipamz42p5xvNXk8q`IXrOB6OjAz>klQy%q zpXi9D+MKyJdGlY2S*qV!>WN|5lNWzX9SEib*`|^#$f1+ zFAG_@zTe)YX1_`8{OYsN_PJ9(Fo>wRT%`6`jR>vQ&o#|)0lA!A5OErhwU=SE{b>TdkNM(WK%})5C3+Qy;Pk&7k4_3z|fL?`MFs zmEMDvAQU5LAi%>{5CQT9+6IyG+X0n@>;|21V~9C@vhH* z;jr+glx0>8IJcg})ED@wiUAtPMS-K%nMp&lzhR-ANbkQ5HhC&C)no~9Xxakj1%bip zxRawTBgG6)n5yUqqGzKdHk>D0V zY_oAm3TkS^k`g0o9}_IyJ}CethZ zB0#GPkaxOY4}S(o7jg0v&a1bApr!UGOd(h$o@^G`2V4;-wCA1f&+r0^V=y%ob~MLO zViYH90Nq0;x+QV}R@U(AV&e~zl+XR3F>Ud)tHx0KI}47D4VCf^Qm_cHS>!%;_4Xnb z%DQa^x*p~@k5GKKjx=T|A2W)+D&^^FOe+~gS=@^|wV*-Jz&jR6u+{R4PLfjDW^$Lqt z1&qbgsf0rrs#fD;JTFFVK>iQE(J01h*35^@6}D%pm3rf}eME!*)H$Er5f-pIU}}Gm zqpuWGr%KB77HpX_#3scX4aQ)B3^x*0!y**wv}UdFfpwXc>>6CeVG&S=HP$aP)D5Wy zyfM;$I{=n=n0hM$a=K~|DH|a^({H=Ed;NN{$$VeOe>)vwX}qCZd&N%gTiki(4?S<2 z+%yWs0n?L=$q$F3A2X)iTOQ9s2m$1-uyU-Ke8{8k`QLS4BGND;W4$ep+_Ue&H=m)#Go@!O`1NloQ`gSn7Xqy3WEV@Y~?g# zCMK5%AOkVs=bwpxpYMX`=E1i)y`S4~_)2>m2KzsVT)D`O^9v1xDm3(9bBFi=H9Q4h zpznyd2L*zY>B8t~0PR1&R%lEfpd7Lvky-*CVU)^+!?G41k6B8SN|7r9c!fn8rHXPi z7pnu)2T&EfTo=MWeZil?@G6r8gxzfvDhW>pfy6R_rM2+fyHjs4>MtF!VAx*x>sS;q z_7!8P!$%Uwi|9CDrj0$~E)UO%ta}MH5#mJx3@nPuT889nZ{9i54ExsE zoUm^!A)hT%4*9IE2Gr-q`!DL#aSQHf7P6WB3l%1PxT_7Vs)u znv~-hLJ`B4523I<$Ja$xk0k^MOcu5dmWF?W02za;nu=oGU#neZ zckI+T#E^=HB9{4tC9Jg}kQ}%g9LMak6cH`;t<$%gG!ri0MhVfX(*;WS&uUP5wKDCd zHu`G)el!^dti##>j#rI$a}->OYH<+wdLwKhIKo)tO6u0>0V(nP3dm$=Y*)K{`<>_V zPevZ}D(AFpY{`{P*QS5&sg|Jbgj=&HprYcdHYPpZBz7U#>iZT@tc!r|J#$tVo+Y<5z&Y8{ zcCw8D=y)oBaL-psZ8QU9#U9`4)QcuRPY8RX`x32$fD0tBFUDgO(_Fd<37?Z+T(CQu zkkV@`UI1I$*67YQzS16yDdZENjTnR^)agnPgx1I$+?wznwA2Cu7$A%XPZR)u>P@S- zcx+-C#h)~?$4mQ*p{F-pu3tU^8_x>kt&^x-OcIaRR)gr=x#Zs_tHv-i0o1RG^GIHL#cfh*5B zK`ew7*``wj`~Oh(mO*iKO}J>VV8Jao4DP|*HMoR8a1Ty!hv0)d1a}KA!QI`1y99TF z%iWXrJ9X+--9PsqHPr0ct5>h?r@No-m6RnM3{ZD_#4g^DX2nJ1j1&$Nk=t>ZGr&d% zXnLJ~xQTvJ7TDMCY4XGXxV~#xg1>fFFywiv@Ex0lL!M6ESpm{q9jyvUo)wp52A#fa z3jqTE$Kzs#7r}z753>l25At@tH8#B6r2PhQJnnldtKZ(~alw&{GcT|n>k43lWUo@z z4YiUt2loz>N?s{tIZ`fA+AUU*nSu;z_^;zu>ak+xk!}7wk-e{r7us{QAGtObaJuK9 z(}^*+zj(1}ZGW+&^8n-?XCnRLJInF@L{>csG&$`kEy=&z_sWl?U6gCpbQs5vHv_@C zZuP9JA8GY%xJahp;HtqZn&8fnk-ms>2Q~T5OUSwQBCUc;0xTNjTz|JE zL>Bz<*u0x)6ktpOUq*Tz?4_LL?Lg{-t3pgkt=vQo!kp9LqmzX8pj{U_CQexokUd&_ zjo0R83nM0$)#x8gWUn$ETox0tj|WKr-6y87($3^!F$>jYXAG*ejUrpY;OhmByD`Q* zTs^%jJk${Vp25RN)3hU&tl+E`8fsUPRDi(d4=0(L|9sW^*W-C^`j4U5x9oZuuTaH^ zfqJVw*6JDbK#8?}6O1o4wi|?B9(>Q6q9^shJlG{--7tt;FC_Q*3iu7x%4ye=^64dY zSm_~P^JEXTj_wAKm=xX@u_+?F(;#77{uPPb1;i700g{5=KRYKMR+PXnlJ&|a?+}@E zx(srA;aQ=H-YJ(Pt{8rnIM~t5PSdCkxDUZ@rdUkBp75p+vWOJE`KUv*(ec8$z8@xkUw9 zlYPaG5ty~r!;nfJqD8a8L^;!jr%L>ZE1%f#X(e3%YIPPi$?1S_0tOZKqDqbk8EUu;;%f59ZzSB< zZsbL|SXy7Ciw!i4lIs0q!&p)ZH0DqlWK1ln-_~&juav6jrHKHU-F1QL7*E>+*m44F zbulCO#rZE1Bg#4TbYVfVh<3t56)$!6M*K=?1F;NQXPTi{VxyCiE(zCkWS2fp3Ad9+ z6dI#3+WzKp{> z1Cu)yn~7oh{)@Hq7slT3vifRe@0sYcemnSv;gb)9ZzKCIz{(L?ylPyMu}s*kxyxIZ zb+3`(N&Qpj%5-JQ_^nPzmN@j(L75OzXv)*e-A_}rrjuSjBa1Bhgv#w01J=*yIr{+r zmCe?8h}MOX-xpi|OfS3~#1~xOKFNi@G~ErbTK5zHq3>z89>1fcE+EjymAe?{q;lmpoo*eWu1`Zu8d#W=!16zT3ib6ErN%iz5jFl2>^izn}IO z3K9C-jh@I+7po!qE_U;NF*YGJOlqdX2P75%B6|QMgeUbeY$P@_iJ~nhWPeI_t99*L za+4OARTGLPy|GJ(MZcc(1%c$HxF!YdkVFFkvO1S5GRuYHT83&#n&cp zvqW@@_Jt3cS2dRP3)qFB)?% zLCRg<>z|c-`vXy7lskK{(t=j&n1YV85u)2cn};(&65(gJww>*S$trs3ZsOX( z2{C_BVmktQqvnqqVjBcyWIMx4_XfeZVL$2UL0^Vc_) z5SbSJM$(JpC+YXB4jb^&@8<+AfbK`lbE1AccrxhWe4<0t>a3o=wM7wKP)-Waow>ga zWp>sXw@5N4lsgcjOV(lIcD!OsKjUH-HGQi_1pwdsd9<$8zSvsnU*0>%&sG8Uo2u^! z>hxmi$|6VjbA5&F+HhJ51j4s^=0v$cXM)JX=&by zn$MXJbox{oU@o~9p|^&>^wl2W1-;yEk}5-&08J}hmqK((zO!fN5gd+(Wi2u+{swwt*4(r{N(XeRhCg;#(ABOtAL1WW7 zs7ts_&f#GSHfrMe0j4Bin}X)}_$kF1|0bFf2!1{l0E~z)j(5MVz4-c*9u)94mYi)u zvZ>ebq3~iON}ZE`E!1rP!5TcAW&9qn+)PeIg);6l6WM2R^GKs)?!OnDD81I10uEPl z&wXC^H4jXdQkS?GzOol&#O(`n+nRmJWF!AlNuE}1{ri{oNn{)6yLri)CfUEZUp>ot znax+o-n7iQN|laVRXOi56)05PwJl@9J5La6)86qGYaJJBc`~1_L^jB}{EV0mCC=d{$<-|A$SS^B$yuY- zpVPiFf%a{!Ty+-V_gF z2Qf`wPDBAf*Ru^8z}G_2PnLsDz&_jA^lNHOvjYl|(m;j2Gr>qY{-(4_o04?58N4%Z%C5Ieaxg=<`rz6(0va&((b5( zA^6Qeo2x>EL4pxd@yxw7In{Fcq9j}##I0WrJ<&Se=+1zOC+Yv?0ar=iM7pvojnz&| z&cgTkGlR*Ff5jvh&Sk-4r^01HaIS7xdUoH*8cc(z5xn3&4fyyWk^YX1mlx%TD@d?C z^Yq?O$2)>ROOHr@FGAD4cSD<$B<8UxRNrX<-5z$6>Kc7uarf3)^578p+sijQ`7}qU z)qwDkvNNEv;I`f7{X^iYwJzsVsF!9-qu_9Y>^igC@s4*>q**`d*kqHq%21+LPCCK1 zq(iGxJ6~J@iqorGb>i1i&-Id0R6-<# z@X;%xMJ|%NJ$}&*r3;wb-!Ff?DnQG7-*u(^-aHg0#*4m*-43}^%S0#8?+vP-Lcb#Q z6^2_Pt*q27O}}$6#Fm`a5fJ3~}k@*zKDk7+--RG|C)dJY2HM3Ed-Km5XD*xs`v z*jXY2y5B`zw_co`R?nGkq8~oY8{A7la?YaJFSGWVQ>VJ0M)XJNiB*9jB)ob!@y)km z#!zA_uE1O=PT`C51CXPpa+9+mSzO;uqTnONWT{o?fYCq-Oj~|uwdJ$({lkWj>G|Sa z9)ysWZ39nB**v>*e!x;)Olx~Z>6^b^k z$+PnvUA>O*s(x!GJ?SJv;%yhWYgeMibYq(ZZDa*q+QmisFa7<+DGj{+p*&^b%M$k5 z+W0v$oA#eLGV(u%e>GE}I(#dq&DSWEA99tBvu{5Vk>&WEj%jXD1aGhO(au`e$hWUl zex+ON?^Id-V5b7c<~Ls+iQT^aAPL5ph^CDuP=C(%orqivwSO(AAYCa!zA*aJ8h*E* zk*a!LqT|a7%8L^*LQ2e|Io%A=SNfPEdb_j~X}I8eUf-HUa!q%J5X!Te{1)_)DClW= zK~VLH+#U>@vZucuG_U_NVlPCavu+WuO8a{G@Grn%EVCx-BHMA(r(5y5{B1Z}dJ+xQ zCYSfQ)>QRwP}8Y>GKm^9+2tg%^Gt1AXstbWf(tXm$vB`MYb@PU<>7I6;1`t|X38Ku zJ(?}5q>~d{*r#-w`@?#~vD5`3@rUHDhcQD{vcuU5@OyUmsbA~;j48@3T6C1Bx_jGS ze@$l`hd@CRegH>s*0NcCd{yU%hzqRKvPf+Ub1kH;++S;~;4J5}GHZm@ZwhXmdlEoP zI7Bvj#^k>3e5Q@Mx$C!VgOsXi04))vDoUYT%;R(hD<0pyB*(K^ZsxI|%2oS2XepDR zd3>Lsb=kKrf`?Y=&A>zv|hSh^ztWSN!6CXT0(&OHX ztt+dSr|X9ae3Hq|8N|c{T`v|A5(2&HKCKF1*ovxJm@1ojrn+}}6hTQ%YT5|oU%6k> z0Vh(uZFu*A+@F%X_^FjY)tZ7+Lc7N-Nv+5BfVjY6CUMCIWrT6#8qS2fn&h zbeYy=y9krXP?S4+g^)b-ufK)^tR8z3?muOKHZ#Ybq%$BH))|a=jEvm%!};n%(*d%% zetz?Bk6a-0t@sm{-|6NHlL%b!L2ndE0GHwVp9&Bgxv*+4E?6$vSUK-P6@Mrji(h7A zp`(DoGK?0TZ;g+W6Gag;0VheuVO^^lM(k{b;|5Bh6MUKprMhNX=oBho{YZ&Yz=Y*= z%^}#Sl4Ez#@z5BxvYg7gSYXS55=so1Kpgz><&h)yOfE5Jr~M{9>u8GzXdheELpci48rEix`iCi_Y?0IMZ1;zb!enrouw1Q+T%pEW@+(L zF6-K`F+^kODXrzxeNb82tF^gGu=s)7h~FBoEi&lm?Zfk_7aFbhxt&E?0=$tj0mPs? z74p~kxapnx=+RzOZ?4wMIg-T=Z_k7{muZ)HfO_d?=ff9!GDxq{Pv}U^jrV-Qavx8Y zH^D_fNU6yCpy-)<3ZvbU>kK z9lm`Me4;$gLRRE;?*W`e>xj-EPmH_uH548q9~9!S&jUNuESkUIA<1ppaAMxG(+DH! zp{@IG_Yx1GXm!80Mw^OhdQq2Z*gRDo?>{`f_@WKNpCmj|0M{XR7{O<3h^f47j#D`X zx^`X3=|ABXB?qp0(NaL|r@3SD(+xR%7w+~NHI`n)F__?F$DxRid; zo~GO53`nYZJO(qVL3*G>5*IM=l0kcpOSVHnh&u@)0KKo;{BtSMYCph>Xk_kR>2?Hl zZyyHm%V04uYXA+cHtDqi#!({wdMGrx{qA-s^95uB0`9!dl<3PZHS$ENSfRCqE`G*Y*H@!4xa&X5-?w*4IV4#z37lEJMbA6KW$tW zO9x@9izZcrsP&gbpC?j8?1ZAtKS5AzEO6cdq&OM0^)}e~MeeNImEo5; zKS&a!!}Cm+owOO^9To2jN+M+3m3FR+wOih-k*1OSPRLjg{itc7JqGx5)6&ak1p7FOV|$ATnw{Ba@Uuo6y$oXpaM3vr(g4 zu`>gYxRir676vvYn{tz@uu5j3D5Bi*t!4;k_)^|yXWcox5`reqRGUDf@imz{{=drrgBXTC5e^LWa%GfDRqgFzt-7v{9O+$n_7`I8 zdLB*zsXaUdGO-auP6dw9Kq)9SHck%c(CtUhE^oC5ZPw=m^`VLb*K+@>>@WZ=n5^Qb z)eD9}8R;#L{hx{l}9Nt~wN znG8Ouru1=La8hjCH38M*%YF0=TPQc)Hp2d;6}~ERIB~G@mes$S=V#gf_&p3KCS2jb z8&d%_1!ezOhH4B*QMf;hSc%4li@STYH%e)(l&*tFvz8ni=m$%>k72XDp9v*Sc%?H| zWafj4%;hVFI0L*nAnqk?ksTVfcr<9zLLNJL!8%dt9hzCzV6s$ZChYL|Ng9Utcl5>< zm%m1`7w;dVsSKb__W@1fbITLfkivdHgzV)OtP^ko>0kKp`FK#n4cAE0mO(BNz(cYd zUgGJkk{HBJ4nLS<8^)!UaAnK#|(v;gc^JPf}a2<1kaG6+eq~1svzA&1$*mQ8~LAX~8r{-Ldz}`T(9EKcX6`jEl`o((+7iDNW z7ND)FMu5p>GSnQ>>U$eArrEmn6C0)&yHen_I)&0@l694|O%0~@k8Zc4vCHrYtz%Jr zXUtwhK-AS7jZ5p*1ynjO9#ym_sZcS|;rzwG*X`(GJ{FRbfNU`mxBD?cwx+*m+XRF2 z!mod5<4&VQ1{2@6GASPBVl@)XGSMo{YH>B7G{fNy$pk`PI0`f=xI zY#-qT$8#s2c%xC8PC9UV9W&6XmU{wZ@rLFPBseTX6y@_~=J$Jl4Y5yzw^9|L6WpLP z%R2{s4E8~gZRsD-8q z$9jdDg;*v~JEVJp+Mw-!XKu~MYy?p9519Zjp`U$+z#77_^J6s{Q0mC)UO>Ci#$K5* z8aPGCP!X4)-$9X&4$L+WK5H+&4RjMV8t{A-{O+)2!psMZCLFZZ;hU4DWb+2kudOmf z+t1Uu2%LNfg=dLeWr`LoGM@h^kivK5-x`6L8uwjUmlCV!gc(Tor+02mf59!hKRc|+Z{E9)$ z1^abEI?vKnpYGdaQXKG_!;AJicY<^>UazKtqv@U)J^D-Jd9*K?YnS*$2@`n|iT8Kg z1O0A>5^(n~zmL#%ZsPu?^@#9F6ppojSE)QrI6D9l%5dah8Ps6$2e*^us=TyQo>4&s zL^ZOg+jL>MOwJ{XZBaH9$<4nI#!k%O0};wwJUniBs=|+U)cLl@lu-k|Z zHVJ4c;8J>qc8G;=PWd)MrQ%A`BS_(3@ck>P!ni_K47##b}BwYwo{aV(H*d zqDz9rgV^_Xs|16|6JMkZCRG~uSS01DgNA_s^I|>$*L>NA2}m6F~b!KPYJatYU?;*uqY8q-wX0Ju!OnlRZ=(XCRDZ| z-~}oq(Kq`{%?pJSCmj;oCPNfF`}=?95{WOc6jEBZgxG~&x;?=uz&{`g9&!q`0?SOG zV=7fm@uy!oCCeW($czzt(ca|i?SMNcP%H=9>#M&S)Gk9Q3rmmk_oF zW?Ym@s7}Cd4QgX*(b64;an1+1DXUXcWN@B=gkF_wQZy*8`^6b?wWax7Y2Ow-&6qp_ zF?MH57E$j~WX=M8efphSOLyrYj&f5Jj_?afa_Vj=S{O^!wF; zmcRb#3U$LW{Us=zBj)}lWR>W3Eul&#zIrB59^L-Si4|W?c1Md>R$$btmpxE`)Q!yz zwq-zEyj%^$5_98$#?+CCpwnKGTN7Va-lxRJWZdUjWQX_g%T+5rULy4CM}ao+i3WmE zbca?JzH1$phMxW5C;als7Hvcxo}Jid@mT8Z7grsr>UXCaZ^y?`FIB@m?$f&={qWAl+2T7Wnt|e zt-W*cKj0_UO+|DZ4|0EHJZya)kg@EJlQEjEZO%IlqOSb5Rx+yzu8DQlW( z4W61F?42e>z=8sEDgakI3dpKZvDV-0sX0MvV`G?S)lM?1ob}IIL}cQ94%HTm^mc!x zw1ag(JE0E1fn8c!<5}8a$qx&(3dSDrV*bW(8Wd7=YUaV)rti2XLiCfBV)^jX#ZWzY zJJ|q)d&J7t-W3cw+71>E(T_6AziJEaG>Y?lT4T!m>uSGcZ(=GQiq=Q5>Xq)yIAdt zyd6A+n1Lavi)4_!?LI+1RZ;FuR}LFefJ9grJ73t*YJTNjaAhn|%f)|p>(K6&@PN?p zD#Q?k3Xdn956*YS(_8tzu-%Yl5UX;G;8Fed$up_v!Ub8``0-6T=`Y24-OG`}IQuw* zPdkxIY(IM?>qy&fgUi^XH4_q_+n5AO!PYm5?%)1)v=qGRj6$eBSJi)#7$J!rvIYQ~ z_@;L++}>)Fyw%SB2%XT&dHH}2j7VKX12y9l&)4(3}E1iY7 zq`HZeIdav%+t`xa?3Ia*{*(4Pe8Vdr1*{)O!d-qWwkVN6x{9-@5>Xi!adhvI5;pm_ zSwUXtWW9C&!Lj)bl`gbQPGn#VTNpxDFH0kbVx9gQ7IKM%tZAqa%W;t=;UysdOCr`G zOcn%%iNM^}hLgy)ARUWInQnr+NZtoW?h^AnYr7k?8ben9YCe1Zf4Bgxy+o~4Cqlm+ z@wdiTJ*~B`D?WVEThWzr)OmEM#CAjdlpZGQ>nv5~cJjdesIuQ=d2ahjGwj3ta&m8| zV)zCv+gkjq5L4J;q|;O=aYJE-M3*0qee(btrA~D0NxHACpi#6`_A!f13}(vrkgsPS z38Q~KX9uq=_?&0TFsHSCZBYd@(5Hi+5>ve|5fY#th#r^99B8sqsN$pQNx2%; zlNjwXe0!Mr-mezqkqbuGBnc;O1EyYxp#)Cw{4Mhyusy=zcY>CmMEztawMlS;(nVP~UxF$-X+Pv>`?lv7nC6Ku8N*!_cL;V1O47slGn&B@;)L3O zdXKw$dTK{wWp7H%M>4Z*!HzMz>z@Jk~WXV|9s4HOI`GS}=-kBb1AfdbU~c44u-< z?Z-5h?hBJqX~sUt@HHF66d8tgHS}Yjh^J}fza33+Wgc0vo8axqQ*?`rpm|m#qoSu1 zKc1{-mr(eV^|PXRpR^Ywes{paiS{8YLvsxEPuAJAHiD_q$JMK6Nv-g8YVN>{i_tA5 z2NUQ+U6MgnCzq}oUuW`&6{};UG?v5ct%kqs3$UbKQ4$^IpHi13z;d}sU}>IAQ~@fV zip?e6S?*28Xk!&>C1iU7#e)txIor3CE(t`Q1Wk8{GEKq&L+@@rT52@wO(^j_doGE@ zcLa1lRRxjZv3KyIvBU)rF6iS|A(l9w->`EEQH_|mu};kfzUpm1H-gD34AK6yf{S1n zYEr%&gIjke!Xkulz1^lJ6N-D^rRijE7$MmGTsoBJk-<2i#E%T6{;72+)~KwaHsls9 z?e$Ig)9k{Xe0~+aI$^K^!;>p9`-RzG6L2Sr0MvQ~6h*5~skyuhb1>_ILAxsQ1XbBNI zKr$(tSd`V`bjeLCynS$}$!gy0htY$`-?N^!s#+t#%!n(y%x9*vmFeh!1k)Kg6x7iF zJq>>K)3D6WMsQ$!M#z_)qi%VfHw*Pz9YTaIHg_?|2^Rm29sZQPf&TT zjk-Fotn$NHG_Ye1N{}53CEk5;0lksPmWMn}o`pq$nGlNZ79PltoD@XB0>9O-PM!sR z13VHFGsb~k+$bavS-cSVK$#C1$WOZ(7bA{DNw)hUve+Ayj-<|jZd$^fLCT^c&+msb zGycg~=k#N((GLC31Gs_kme>WAm0k;he{al+_3v@gtSlrb(!dI;F@YD*w4X7ck{20% z_NxgcR>+L#?qLpzJ?HuvNH-$v^*d`xd}LgNsHbATPq-bny~Q+RgIN*{Y$wP`kYc+{tG6 zh0uJNaP#21+7{R&;Ndg4@u5)JamPpK{y2XnLgttj+pHN3(Ew!+1VEk0tMjhQ_}ygz z;dCL!EU0`lbCNuug2;Lbn2eu-O0Qu1ZVc%G{IrbrqD>lR4t0dV4BR%P%jh2#Oz-B@ zTN;`?x!_INiuZ()msBq!C)1Ut-VnP%nsH=waU|w@8)*7^2)=bk>(F0Swzu}ah#{%^ zivfDQz?;9^9$|XmrC_4Nv71{He>wu|*bp?-8he+DuF7C-?zLg;KS*4cH&?)jp$dlV zb`r>hD)_%rbN707gxIIaPS(wdpLgvwEpeQkz+Ppl$6{kLL@7nP6CmMms%xT@KyBB% z$jHfwZz#I9cHH0=>Yn7-=0db-UOl6?-#Oa^dtNY<(_7l){SgPICJsm7kF<-#&OD$083cP36~S?VVYLfC8U7 z1`!97Q?|wc=BDq%#_CjZmHsqRq3$upGZ}(?CI1Wnwg;B?j2=bgi+rEV4^m zGS%%kL;iLsf%Zo=fyR;k%k|^8S4u=VUHxv8Mx;MStzyZMc1)s+5*D5(v0t=F*f2Vw zgB5Jf@8XSR|{M8l9A1b1AG$TLnmvPxg~pzqiCj)3?Z zV^o}-TLj!cXFkS)L7V<4`i|rG_h9yo5^fjv)KJbaA0mI(0l~{>U9xHleTiAWf4bfb zF`a;}JFO${2m*G-9k4_Jr!kij5HkSkL(ThKUtC`h?k4gF11BlKGW)X3tZ};rhIzmv z93d!KKSR201O~%n3Cr&DI);DuQHn+%3~TgURodb^*Q1kBwd3E|>X!uY*KUC)3+Rq9LwCD>w44)xx=@xoRdNJBf|A6f{mIFk@&?gx;!5RIPO@mH{0T(>hvPF6CI#_k zst|8>&>f?VL=LgAu}1Kf^IfD7_u@j8o|}y|<;8vW9rq+%1zlq~TRFU2H7t5jZDe{Q zI^Wdjt9xv<)b_cnjAG$v7C%x~Z*cPFYNjILY1D8(HzyUlXNR1}B6Fam7+{W0OPUx- zAJ-}i5ML9@Ng5iVgj2frDn^x@+eM<2G{vYnYOO=*xP3eGCi=;DSbQZd?Dpyg(^^#` zss9xNvFmyJfL-VKgSAn7rsa$!X`{hTRUN0^guxUuV@)0|R`{Jt)kN?!^V3LVvZ6Xx zWBPt%cH6|cSs&9T?pc<$RVQqwW)jKv#TZ;QwE>-s09BvmH-%03uheqJo6f2ZTVLEi zU+MIrGB2EC;|o)>4b9Nj{QuCf0Ez|zEi9Lrv>F2>ocyX(p!ZfNx|rY3h_g)C72{0s z)LwozXCo4i)_dUs9TUdbU^W+&&gIm*`p_bwfQ+M_`1(1vpx}HfJCY=-Gp|CrSLIi0 zW{{brckA62n*EMt9(-0&IBsZ3adiW~Q-*>hxw0Po&d}GQ!1HrIg>{)(zFD>Wr1J+{ ziwiopf$7g)$?KTi(0Ke#=?cAG&@PSPd}L4L`U6w%E2(w;gPUxV_?dVGG8aFZO;NSw z=njdr;@Ll!%ivELwa*zH2mr8CCh{X@3G0M(CWZoiI`95Q;Q}6S+#BvX~+;-(IG zw?Pa4O42y!r`U~?v358_rW~9+!%&e$nrvIMx8?LV$Jo$>=8NhQb=on5(JTj2M$#WE z-$d%C!{)D$Vka*E;V(8PE*?KgOend30(OJe9$MAbY&dseYX9XM zB^=z=SlOZs(mVQ#zaV(9h&x5Lg$>+tUwDq8X;2G_j-1m25J}Pc5VZdIFOm{}>3byW z7JHE^`3ePrcp?U~8UGCW5(EI!Ss8`QOq>`fPhgY4yiKY%rSc6GNuk(qI)9T(65M6H zvWuBU7)nePocWd+>c7x{)(4+@ii{{>hgu;u@4L)^ksgu z48e<9fnnSAjY2d+0ts}Yua;ke1hN33PoYFQ5KBo^&16$Sa0(Q#3w2-)KqgLTz(Ey( z9cKSuD6z*M`bQBKTM1ZnAA2DN_ta2eNWI|xKS#R#6x;h*=ny>ikc-}b|S)<6j>Q|7mDxkfzbe9~q?vSW0 zyETmX0i{gYRMD~VmX~~<>C=&c5+pScW6ZL9SUIQ&0HI=E=MN+@WVP*G8seUtYk7F)+y?%dx@yMaZtDWDErrkM82C){VRo9= zg3Wan&_$mwal}x(y$FPD1Oo*J#`6l*a2PX$-Zt|seX|wRthg}An4SHEaq9E7{J}@t zAcwNjZ}$4{rjr|Krt8rcGGDj7T%9!c4|%93hSLprtsM&bcywtqIc*3!x5&A+PfQJ8 z+TQ-faC{Z5cxD(+@sn8RMp*nsqm-t45xab0O?S}TNIFo-EEIS`i^3iiT0*wV~GkSH~meG!_{$%|zRA!fV`-@N>%}ZilnyqV`;R~^; zNx|Wd^VzB5R2aL}7Qg`OM~jdjz!kMulO@i^lvVTVZv#6Q21UTc^;}6j9d?}bnyD0A z%p}hpDd9)1Bwthb@c7Lbm;ISMl|tu>yx9@h2T(%n%WW6#XXLMsSHxOhZgpL~*tXy= zu6~dUR+}FtPfpKv622PLk$%9)!8pSKxfG|RbRTT!2^=kycglTEuwq9un?Az&adQec z5u1m6EbfD6zNjIZ+aWx?6S1Pg&5E(5q$fbnqzmqC@IiRkofim64pZ`R96foqEQ;D1 zOTPzu-xXI;hY1K{@?-mFMqv68K@1$NoKeWndcHF0W|0|Lv`xHLNK71|^(io{kO0K| zh?K;qu8^%i08M8AvN$hQu&wZ92kw+CH?V; zt76rM62$-Z+B_Qml;oS>Lr4`>?c-H<=-qnzjOMTVHv$zWJzeX}U4I8j7usx5*McOo zzf@KtQ@Xsbw}D9;!ph052!^#IRcZX~v+WUh>?FCPKi^5(OYCYJum@(@a55*|(svgt zl{E#NRF~DYW zzxvTpnIcmQ|ItrW`S*Ol-Z_i1`(KB-0SpU9U0U<)N-&QnYE;ECdX*)U(P~!qbng9R z$)8a%)mijLvy2S`K_AA5X6K>vFC7+G#rTBeRBV_z@X=(~ojGVcgT1IPna`CSWad3m z@9S)X?vhE4Q+qy`PZ9kQhu>`fK`k z@rX2O4o^Eu4LViDlfhdN+dSDRpoeAy2<@uS&hQGoRx%M;)+)N0r%m4JA>sJ>LT%q4b z`$jn;Ej@C`nS_isfEn709Scc8cC0G>!UP__n0md~CbEiJd)Z$F7IhMvVi$5oOU2v& zb5s8kjV)?xy-}$r!K_e*TzssCxgVn|H+<}qWsL3l8;HNMtao#>YlN#Kx$slCKkr4)aR`u!Leb~Jc%Y3^J?^p7o@D&NA|wim~YUwdOs)QyO7KY2~hLH%wrcC zVbl41iAT6k`sQ|LHb!%0*p`3K&vXT63{=^^xPJJVLSn&cyrL}s?19dBcoU<4Y|t(G z*Rg1m+m|)>Y{e99hY)>&q%ppyCuhACUoV;f<_K{++d>=TW#n@hyu<5mDTez2TlyD{ z@2^{?j3?WF;9X05<`m>j+^8NbKbMiMxvu;IZp!21{Fw*bj^M^={=+RpIRBAJ^BoEy zA+?KB{}D@v87P#*t*)yURafQt=?wpc_jDnwuD4gGFUqomSbAlq==|9bx2)d>t_SsG zgVU_+oZox~H;|aOpJYY4yUJU;m4FLV0Hx3N-UxtDH0d`d!LL6#Cu=I-<=vbFl4`lQ z6km?;QNxak?Q$|)Se}2&50ndj2ga$$_yvAC_4?;>v?eVy}*Q?e}!&QANjFx zfz+k_Li1;&@7)<txrK+psJ_A;O4HTy}eT@E0D}-13cxPv4t< zJci?)XYj$Ozt<;G!F*XhT5)W!~;XwFQwL3ehmv z)KGErIu2CnyjZEjE}C`gT_aw)FaJ%~Gj^+ubbFc1am{%dU=)H8URZo% z^>xLjDm?U#t}1Qnof#?rhDvgex!c$G0{!|Dqw%iAuBI_=3Jpn3==`VL>l6}*$?@J8 zS3IzKwUxV#NI+Vo_>ETLyBv$0fWsD{;E65YADYAry-}VDF5!FxK(^Tb^_67vB(>$6 z*1D*KjR4_|XHH+<1qdkLRFq?KS@^X0HVH%ZSRs=G zmt?W44^{8@s!#tB9fvslr#d}S_4ZUy29N75m(**O*xk$FgU{3dQ`T3;McHj{E7B<~ zEsdn4G)N8I!q6!pAR(pFokKU0(jW{i-Q6G#NFyLUbi;dt=e*}U=g+tK!2a#H_gdGw z*0tAinZ#PR*wG`IF0i;-UOBlT^ODMK_@P!l$b>j21Zj-QSY6wGwbJ~I!9vlnf_iYS zssP%zApG49Eq%wX3Rb39!t6Ec^t5Ed17mV_K2Vk`%kndBXvZC!{V;ZnXgg(PrpqN* zN*U}SN`PFZ8y39(jxj0(#p||WSHuxL{E>UoLK523rUTiK3P}*I*JWp}#D)JWVvzX> z2Umf0^6}Q=s>hjV%RaBz8M;JViPgxsppwIFk46}=J9F=raIRNlo_x=PI`{^Ng&fIZ zvTO3&E@DPKmYlGIACtLuzR|6fmEuNxY2yEi{q$V%_Hn}cD4}VvT-4r}{eXH*Q&acV z*7`c?3>3q{|FR0@*4bC4i5;YiLo9Th#zTY3kPW(6 z@_o5A_1L6W1sy849v+m3DL=IOgGse~j6c>nv(C}}v1J^ifx=J!>n zVjhuD@_O*2eU8d&(Fw5-aUF(xXj~dXVIfk|VWP$|R}`0#I1q>({MN3kwd9)}4jY+g zmoP@4mjQ-aJkRH0$d*t8b!gs~-$Vz`@rC?wL?v&?B*BPA!YfTQ#&ZpL02g68POj#l zKaUMik_4--KEY$u?0f#L1rRX2gA;d*eD3smtw2;`8CLLQVp6~A6~Jayo>86gGc2s! zoPdj!9);8OTPy32_3KwjuBUk!D4fN&tcDYaLu6o-$|Ysh$$KBxc_5J8 zniBY>!g@CdC6>B@bc9iG?ok&)H}L1mTEjhWZ7Ma?kmZ2yhbIv<52@fuX2SJs_dNdP zAhscJ!q41=ts<(;kl)t@(bNk5IuJ$0$r*gZc7jT5&B_@iQ8{u~auiaZdfOez^$JfY z{-aCZtA}_J@$YB)l}Ko(WM6{(s#AB4O$@r)yAN8?NVHHdIP%63>lE8X@M;Kqb7Pp} zusIyp+7T=51V1Ilr~Cv-XU`FTPrewSJ5oAEk8y^BF6aH|+Yb}|)K{f}t9r!Yw6-64 z26HXT#~K#TSv59#yOqx!Z%}AZ_np1=-|>_gX&mFAVoQdLEIhKFpLLvd!^H^vMOb(rDg)v< zn?7>@GNqkb!jG1vBJ?JK>wWEj%037T1qXbVg z-abq37m_{L4)r$L76xs8`r3UK(R)nG%+GH%;|r^puAcCi4OqtyB$!+|sSN;&$oN0c z)Tn5A*|8TEJ#nx;gtH#We7m zq2cna8@oZ#@r<39a7F_+Bagf7hsP7DP5N^x!4Gh6e<`LuqD^$|$mPkgpEuD@4Ds?% z9>1HzLwHn`v5fCsxKX3Jk|9F8Nr$b+N3*q`7GkQ#=vwN9My&3x1c^V}Z_i~;kD|gm zT5mZ@B{R%zCGx{1W{=RRMk5w;r@$*O@8zVHSoQyYY{dCq1MSUvU4Y)Nn-$Lur7z$BQ}Tt<7TT~#i}#_d z(%oxT_UHDlX3~mA(D)?Lr9g3w)fvi=U5bU$CN}h>L)loAvIz|}(gn&Ofa_hosi~vM z3j)1wNC(d0v#Z9G`0ex^9fELaDn|GvMUUNXfIT(H zsADrp`K7g9=QQ4q>VN~2mJH5U`L!r{BGpb^3 z|7|U8RZ_FPEBhQH+q$H=<`7EXkWwVrapFwJ@D<+_aZ5Ke759)Qqc(bghK=hLp%Q~u zMet{x)y31JVCMyMG3{j0Hw0Vpytj`=X$jo%`BM0)2enr~rTJ0?RP%%7C_)Uct~ME) zlIguGv`vr%-r{0jTN-A?U3HXCmT42`-&~p>@b2_E!bZNlP$pbfBPcpJAX&9I)pLzu z#y3~j89-K9T*kQ)Huc3oYkFk!{?<{9AD^?po9s+mY4OqYBKJX9iSk`7_*9(A^;im- z<2EB1f1}q+Yt7Z&QJbi!!!!D#u()$Qv)`+MyHw1Q1pi614AzJA&!xXQOU*bNNv@sD zZuY@57jS_Cm*t<9qK_FF7r8zRH9Z%YS4sIPb|s<{YZ@F1CCU&XXC5s_JE2B+>vzu= z0lZ}&Q4&ZW-awK<#$h~ww99i^XE1$U#9)0VQ+Swpu_&0v>C$b@oT3L4ut(he*zxU# z!%bVs$lr6Cv1-)ojT$Z8&Hjk@sbx`CYx9~~S{%w4& zTYKXl=&G#^<)6^ckp_48#^~?!!R7x_a{%P*Q{R<)##jc|6jXu@T0UUTfwco<@J^q# zI88K%Z!CdOdNJwhY-Z;AHm%EZgtviz8Pb6PgP2iacVh)Kf&>m$13V#g1<1F*tPI{g z=}tiH>T$CBHeLA3(Z}O3DMiy@n$1`{8dZLTH*WTzca@@)m9$vljVG5~kJG%ZwdXn~ z+@-R*fSYo!VCqVYK_2l3kR|MIo`_k3;GQz7N_Pm$%lM(n3=mXO*ox3-r~WCh<< z!j>m}q@EKaU<=jKZh5g9j-HpmNbD}ZQ(PW9Go3mD3jv7LzZ|!EiR|jS^gYKd_Fo+L zkZEstZ>Mn=vzNlSZLw|Kk8klE>H2)7!Hrof^|L$AhFY9X3Y3A(V#@G23N>?YT*md& z&t&qdP^5*YRz6;!^B`hzCM}ghYx2$vdFSGaK}B;N?zJBWQ_C5Y^WTsV-|U72yCJs^ zs3#Fc-y=S8MD*9sLnuCI)g5>_@=MhljRTn@Bn>?xixFm5BjI0U?4{rYf-hS* z0t*7ONg$Iy>@Naun(Xc7XT}0ll;Vbn#YX)81vlQ3KycQLJ}{+8rb31JVw%(XC5>t< z;#_7x&T21Xm*b|1J&16I5XiwqL}N1f_)LURSR~X|tzJ&RuRDgSH5lU_zJyAZ zr3HUu=lvTpp)w7mY07j$37}mPUn*9;5T76(d@gm;cDp<>KR57;{Jr@=p|+ z_32)p3OU&(ybI6gC{DwoeNTdS2%Kv{!QHfS8cSI24!PtsN!P z`(q3R^jpyLeO&2Npe7g%E!`9J=ULT2H=<5upmCG&cF*ab@p;4lp4k-8nUebyuX;vc z)3-eQerC*XK1ge7;w5t2qGsZhQKNP3HfETv&!yeZ3^xvvuw30j>rpT&0fZt*-{UXw z9>iOKbuq59MHAvWpy}Wk@HVf|WM|bGBhM8re~}u$&ZudDw?EZa4dL?)^@&!;F(?!m~kmGV+pXvOLJd zq%AL>0#X^g2(u9Eic42==j~~8nqC|CcyXwy87-TzH&1nGcHYHPUtu&>BTpQg>Bja6 z2^0=0Y<4cT|2|*dt$mQVDr=9o260vXEA_Uie!7Pcc?Tcdw1e%naEv;w)!=?>98HJ+ zZSneLlLrl_t*lF_{)7Zx+FYL>eI3;C$gF>d5O`jk%bCts9h~@uQxkmaq-%;N1QNw6 zlIus}l=QsUV8!_qLx?n|rlNbc?&!{C+RWzYyFSYFeXOaT@9}y=_Q8@bW|~Qd7C~Ow zcq@Vo*1RuJtjXu|Yxq|BH1WTV9h930f^VIC#@yMDsA182VZ3D?`w$tOqA8|-!a~7r z4#@S#-80x{><`d$6ZHk{W&c?yL$AG=eT|pKMVs(ta@#lFT*Gqlkd&{+H^0VEuHm&A zzAu;3^BB);!iy-eScT`QEZkr=Hs13larZU+0w_kF??&sKFbPj~HwGg97@3+tgl_0$h&cVKPEp0SaZUY&#{7g6} zj;($C#|`->m~&hPi_P&8j3Z||5D{^+hYtC296!ZC@?aN#%VgQxgKYJGCO*RTbpkEL zwX`npH5TjheR)y~34%O}s|Vi>Is5em5pQwI%Hf4* zUJToX;=fXxyMk1`Rm3KLrrL>u-P~fjGV@CI%q~=LjI9bolcMs9p2W^TNl#9n3pbtH zxXB^}M*xOL^&M(*vej}5*^ezIUJMzCynNgD)Av#`3@gEMCqTa|f0|$HIHtj0zA*H7 zybXfEG+A}X>0VWNWs>B&*m#bMRYg188M3kkbMu}s&9X~(wi<)u#Uc{P|`EY3BxQLoMb{X7^pRx=M zFrq>eL4?M?X+2w5vyYp_M$@~jiK8BMg zziVqrQBf6TjBCaPftvpvxO>NQbXU1X;>pG0ExZ z3XK$g{Ri*O!8q(6eR-NvKl!K)}yMlre zA@!fwkY9c4HJ)?-@Mp7#hMk?T)z&?@qJn^0F(8N`ye~|k>WQdvn$FHM&JKb^MX3tt zc$@E&aivt)hso2|Ov! zO!_X1!+y@stvDR*KO@RELB_%�@;$&Ub?!%16PMa2Z5Clb8(r#-WuaVy|pJ+Bo2M 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 literal 0 HcmV?d00001 diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/meta.yaml b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/meta.yaml new file mode 100644 index 00000000000..f4ce43ff431 --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/meta.yaml @@ -0,0 +1,2 @@ +id: 6858ec7c-b540-4fa2-8a51-9a133d000dd3 +full_slug: storage-netapp-trident-terraform \ No newline at end of file From 16883916552c13405ee030b7c93e78a82d6414c0 Mon Sep 17 00:00:00 2001 From: tcpdumpfbacke Date: Tue, 19 May 2026 16:14:41 +0200 Subject: [PATCH 2/2] Add PR, translations --- pages/index.md | 2 +- .../netapp_trident_terraform/guide.de-de.md | 518 ++++++++++++++++++ .../netapp_trident_terraform/guide.en-gb.md | 26 +- .../netapp_trident_terraform/guide.es-es.md | 517 +++++++++++++++++ .../netapp_trident_terraform/guide.fr-fr.md | 68 +-- .../netapp_trident_terraform/guide.it-it.md | 517 +++++++++++++++++ .../netapp_trident_terraform/guide.pl-pl.md | 518 ++++++++++++++++++ .../netapp_trident_terraform/guide.pt-pt.md | 517 +++++++++++++++++ ....png => terraform-module-architecture.png} | Bin 9 files changed, 2635 insertions(+), 48 deletions(-) create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.de-de.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.es-es.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.it-it.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pl-pl.md create mode 100644 pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pt-pt.md rename pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/{terraform_module_architecture.excalidraw.png => terraform-module-architecture.png} (100%) diff --git a/pages/index.md b/pages/index.md index 6b2a6db74a8..38564573b01 100644 --- a/pages/index.md +++ b/pages/index.md @@ -2331,7 +2331,7 @@ + [Enterprise File Storage - NFS Client considerations](storage_and_backup/file_storage/enterprise_file_storage/netapp_nfs_client_considerations) + [Enterprise File Storage - Connect a Public Cloud instance to an EFS volume via vRack](storage_and_backup/file_storage/enterprise_file_storage/netapp_pci_connection_via_vrack) + [Enterprise File Storage - Private network configuration](storage_and_backup/file_storage/enterprise_file_storage/netapp_network_config) - + [Enterprise File Storage - Deploying an EFS stack for Trident CSI with Terraform](storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform) + + [Enterprise File Storage - How to deploy an EFS stack for Trident CSI with Terraform](storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform) + [Migration](storage-file-storage-enterprise-file-storage-migration) + [Enterprise File Storage - Clone a volume](storage_and_backup/file_storage/enterprise_file_storage/netapp_clone_volume) + [Additional resources](storage-file-storage-enterprise-file-storage-additional-resources) diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.de-de.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.de-de.md new file mode 100644 index 00000000000..bba0bbba632 --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.de-de.md @@ -0,0 +1,518 @@ +--- +title: Einen EFS-Stack für Trident CSI mit Terraform bereitstellen +excerpt: Erfahren Sie, wie Sie mit einem Terraform-Modul den Infrastruktur-Stack für NetApp Trident CSI mit Enterprise File Storage und Managed Kubernetes Service bereitstellen +updated: 2026-05-19 +--- + +## Ziel + +Diese Anleitung erklärt, wie Sie ein OVHcloud Terraform-Modul mit dem Namen [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) verwenden, um den vollständigen Infrastruktur-Stack bereitzustellen, der für die Verwendung von [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) mit Enterprise File Storage (EFS) erforderlich ist. + +Das Modul automatisiert die Erstellung von: + +- Einem **Enterprise File Storage** (EFS) Dienst. +- Einem **Managed Kubernetes Service** (MKS) Cluster. +- Ein **vRack** und ein **vRack Services** sowie deren Konfiguration. +- Einem **Public Cloud Projekt** mit privater Netzwerkkonfiguration. +- Einer **IAM-Richtlinie** und **OAuth2-Anmeldedaten** für die Authentifizierung des Trident CSI Storage-Backends. +- Einem Netzwerk-**Gateway** für die Anbindung der MKS-Cluster-Knoten an die OVHcloud API. + +**Erfahren Sie, wie Sie die OVHcloud Infrastruktur mit Terraform bereitstellen und konfigurieren, um EFS-Volumes mit NetApp Trident CSI bereitzustellen.** + +## Voraussetzungen + +- Sie haben [Terraform >= 1.7.0](https://www.terraform.io/) installiert. +- Sie haben den [OVHcloud Terraform Provider >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) installiert. +- Sie haben Zugang zur [OVHcloud API](/links/api). +- Sie verfügen über ein OVHcloud Konto mit ausreichenden Berechtigungen, um die erforderlichen Ressourcen zu erstellen. + +## Architektur + +Das Terraform-Modul erstellt die folgende Infrastruktur: + +![Architektur des Terraform-Moduls](images/terraform-module-architecture.png){.thumbnail} + +## Netzwerk-Beschränkungen + +Das Modul setzt die folgenden Beschränkungen durch: + +| Beschränkung | Beschreibung | +|------------|-------------| +| Gleiches vRack | Cloud Projekt und vRack Services müssen sich im selben vRack befinden | +| Gleiche Region | vRack Services und EFS müssen sich in derselben Region befinden | +| Gleiche VLAN-ID | Privates Netzwerk und vRack Services Subnetz müssen dieselbe VLAN-ID verwenden | +| Gleiches CIDR | Privates Netzwerk und vRack Services Subnetz müssen denselben CIDR verwenden | +| Keine IP-Überschneidung | Der Zuweisungspool des privaten Netzwerk-Subnetzes darf sich nicht mit dem CIDR des Dienstbereichs überschneiden | +| Gateway erforderlich | Der MKS-Cluster benötigt ein Gateway, um die OVH API zu erreichen | + +## In der praktischen Anwendung + +### OVHcloud Terraform Provider konfigurieren + +#### API-Anmeldedaten generieren + +Der OVHcloud Terraform Provider muss mit einem API-Token konfiguriert werden, um Aufrufe an die OVHcloud API zu tätigen. + +Ihr API-Token muss die folgenden Rechte besitzen: + +- GET, POST, PUT, DELETE auf `/storage/netapp/*` +- GET, POST, PUT, DELETE auf `/vrack/*` +- GET, POST, PUT, DELETE auf `/cloud/project/*` +- GET, POST, PUT, DELETE auf `/me/*` +- GET, POST, PUT, DELETE auf `/iam/*` +- POST auf `/order/*` + +Folgen Sie der Anleitung [Erste Schritte mit den OVHcloud APIs](/pages/manage_and_operate/api/first-steps), um Ihr API-Token zu generieren. + +**Sobald Ihr Token generiert ist, speichern Sie die Informationen für die spätere Verwendung mit dem OVHcloud Terraform Provider**. + +#### Provider-Parameter konfigurieren + +Erstellen Sie eine Datei `provider.tf` mit der OVHcloud Provider-Konfiguration: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Erstellen Sie anschließend eine Datei `variables.tf`, in der die Variablen definiert werden, die in Ihren `.tf`-Dateien verwendet werden: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> Zur Variablen `ovh.endpoint`: Standardmäßig ist `ovh-eu` definiert, da wir Aufrufe an die OVHcloud Europe API tätigen. +> +> Je nach Bedarf existieren weitere Endpunkte: +> +> - `ovh-eu` für die OVHcloud Europe API +> - `ovh-ca` für die OVHcloud America/Asia API + +Erstellen Sie eine Datei `secrets.tfvars` mit Ihren Anmeldedaten: + +> [!warning] +> Vergessen Sie nicht, ``, `` und `` durch die zuvor erhaltenen Informationen Ihres API-Tokens zu ersetzen. +> + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Das Terraform-Modul verwenden + +#### Minimale Konfiguration + +Erstellen Sie eine Datei `main.tf`, die das Modul mit den minimal erforderlichen Parametern verwendet: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +Diese minimale Konfiguration erstellt alle Ressourcen von Grund auf mit Standardeinstellungen. + +> [!primary] +> Wir empfehlen, dass die EFS-`region` und die MKS-`public_cloud_region` so nah wie möglich beieinander liegen. +> +> Die Latenz zwischen den Regionen kann die Leistung Ihres Speicher-Workloads beeinträchtigen. +> **Halten Sie Ihren Speicher und Ihre Rechenleistung so nah wie möglich beieinander.** +> +> Zum Beispiel: +> +> - `eu-west-gra` und `GRA9` +> - `eu-west-sbg` und `SBG5` +> +> Die vollständige Zuordnung finden Sie in der [OVHcloud Regionen-Dokumentation](/links/bare-metal/regions). + +#### Beispiel einer vollständigen Konfiguration + +Verwenden Sie für die vollständige Kontrolle über alle Ressourcen die vollständige Konfiguration: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Bestehende Ressourcen verwenden + +Das Modul ist so konzipiert, dass es mit Ihrer bestehenden Infrastruktur kompatibel ist. Sie können Ihre OVHcloud Ressourcen verwenden, anstatt neue zu erstellen. + +#### Eine bestehende EFS- und vRack Services-Instanz verwenden, die an ein vRack gebunden ist + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Einen bestehenden MKS-Cluster verwenden + +Dieses Beispiel geht davon aus, dass nur Public Cloud Produkte bereits vorhanden sind: ein MKS-Cluster mit privater Netzwerkanbindung +und ein Gateway, um das Internet zu erreichen, aber kein vRack, EFS oder andere Ressourcen. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Die Infrastruktur bereitstellen + +Erstellen Sie eine Datei `outputs.tf`, die alle Ausgaben des Moduls enthält: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Initialisieren Sie Terraform, um die erforderlichen Provider herunterzuladen: + +```bash +terraform init +``` + +Erstellen Sie einen Ausführungsplan, um die Änderungen zu überprüfen: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Überprüfen Sie die Ausgabe des Plans, um die Ressourcen zu prüfen, die erstellt werden: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Wenden Sie die Konfiguration an, um die Ressourcen zu erstellen: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> Die Erstellung der Ressourcen kann mehrere Minuten dauern. Die Erstellung des MKS-Clusters dauert in der Regel am längsten. + +### Ausgaben abrufen + +Rufen Sie nach der erfolgreichen Bereitstellung die für die Trident-Konfiguration erforderlichen Ausgaben ab: + +```bash +terraform output +``` + +Wichtige Ausgaben sind: + +| Ausgabe | Beschreibung | +|--------|-------------| +| `client_id` | OAuth2 Client-ID für das Trident-Backend | +| `client_secret` | OAuth2 Client-Secret (sensibel) | +| `efs_id` | Service-ID des Enterprise File Storage | +| `mks_cluster_id` | ID des MKS-Clusters | +| `kubeconfig` | Kubernetes-Konfigurationsdatei (sensibel) | +| `private_network_subnet_cidr` | Netzwerk-CIDR für die Trident-Backend-Konfiguration | + +Um sensible Werte abzurufen: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Trident CSI konfigurieren + +Nachdem Sie die Infrastruktur mit diesem Modul bereitgestellt haben, konfigurieren Sie Trident CSI, um Enterprise File Storage zu verwenden. Folgen Sie der Anleitung [Erste Schritte mit Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) für detaillierte Anweisungen. + +Verwenden Sie die Ausgaben des Moduls, um das Trident-Backend zu konfigurieren. + +Rufen Sie die OAuth2-Anmeldedaten ab: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Erstellen Sie ein Kubernetes-Secret: + +> [!warning] +> Falls der Trident-Namespace noch nicht existiert, erstellen Sie ihn mit `kubectl --kubeconfig kubeconfig.yaml create ns trident`. + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Die Infrastruktur zerstören + +Bevor Sie die Ressourcen entfernen, löschen Sie zuerst die Verbindung zwischen vRack Services und EFS, falls sie mit Terraform erstellt wurde. Setzen Sie dazu `vrackservices_attach_to_efs = false` und wenden Sie die neue Konfiguration an. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Sobald vRack Services von EFS getrennt ist, können alle Ressourcen entfernt werden. + +Um alle vom Modul erstellten Ressourcen zu entfernen: + +> [!warning] +> Dadurch werden alle Ressourcen einschließlich des MKS-Clusters und des EFS-Speichers dauerhaft gelöscht. Stellen Sie sicher, dass Sie alle wichtigen Daten gesichert haben, bevor Sie fortfahren. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Weiterführende Informationen + +- [Erste Schritte mit Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Enterprise File Storage mit dem OVHcloud Terraform Provider verwalten](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Dokumentation zum OVHcloud Terraform Provider](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Wenn Sie Schulungen oder technische Unterstützung bei der Implementierung unserer Lösungen benötigen, wenden Sie sich an Ihren Vertriebsmitarbeiter oder klicken Sie auf [diesen Link](/links/professional-services), um einen Kostenvoranschlag zu erhalten und eine persönliche Analyse Ihres Projekts durch unsere Experten des Professional Services Teams anzufordern. + +Treten Sie unserer [User Community](/links/community) bei. diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md index 7fb4568d65d..d67194d0339 100644 --- a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.en-gb.md @@ -1,7 +1,7 @@ --- -title: Deploying an EFS stack for Trident CSI with Terraform -excerpt: Learn how to use a Terraform module to create and configure an infrastructure stack to use NetApp Trident CSI with Enterprise File Storage and Managed Kubernetes Service -updated: 2026-05-13 +title: How to deploy an EFS stack for Trident CSI with Terraform +excerpt: Learn how to use a Terraform module to deploy the infrastructure stack for NetApp Trident CSI with Enterprise File Storage and Managed Kubernetes Service +updated: 2026-05-19 --- ## Objective @@ -17,7 +17,7 @@ The module automates the creation of: - An **IAM policy** and **OAuth2 credentials** for Trident CSI storage backend authentication - A network **Gateway** for MKS cluster nodes connectivity to the OVHcloud API -**Learn how to deploy and configure OVHcloud infrastructure with Terraform to be able to provision EFS volumes with NetApp Trident CSI.** +**Learn how to deploy and configure OVHcloud infrastructure with Terraform to provision EFS volumes with NetApp Trident CSI.** ## Requirements @@ -30,7 +30,7 @@ The module automates the creation of: The Terraform module creates the following infrastructure: -![Terraform Module Architecture](images/terraform_module_architecture.excalidraw.png){.thumbnail} +![Terraform Module Architecture](images/terraform-module-architecture.png){.thumbnail} ## Network constraints @@ -51,7 +51,7 @@ The module enforces the following constraints: #### Generate API credentials -The OVHcloud Terraform Provider needs to be configured with an API token to be able to make calls to the OVHcloud API. +The OVHcloud Terraform Provider needs to be configured with an API token to make calls to the OVHcloud API. Your API token will need to have the following rights: @@ -154,15 +154,15 @@ This minimal configuration creates all resources from scratch with default setti > [!primary] > We recommend the EFS `region` and the MKS `public_cloud_region` to be as close as possible. > -> Be aware that latency between different regions may impact your storage workloads performance. -> **It's highly recommended to keep your storage and compute as close as possible.** -> +> Latency between regions may impact your storage workload performance. +> **Keep your storage and compute as close as possible.** +> > For example: > > - `eu-west-gra` and `GRA9` > - `eu-west-sbg` and `SBG5` > -> See the [OVHcloud Regions documentation](https://www.ovhcloud.com/en/about-us/global-infrastructure/expansion-regions-az/) for the complete mapping. +> See the [OVHcloud Regions documentation](/links/bare-metal/regions) for the complete mapping. #### Full configuration example @@ -295,7 +295,7 @@ module "ovh_efs_trident" { # Use existing MKS Cluster create_mks_cluster = false mks_cluster_id = "cluster-id" - + # Don't create a node pool for MKS cluster create_node_pool = false } @@ -480,7 +480,7 @@ kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ ### Destroy the infrastructure -Before removing the resources, in cases when the vRack Services to EFS attachment was created using Terraform, delete it first by setting `vrackservices_attach_to_efs = false` and applying new configuration. +Before removing the resources, if the vRack Services to EFS attachment was created using Terraform, delete it first by setting `vrackservices_attach_to_efs = false` and applying new configuration. ```hcl module "ovh_efs_trident" { @@ -513,6 +513,6 @@ terraform destroy -var-file=secrets.tfvars - [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) - [OVHcloud Terraform Provider Documentation](https://registry.terraform.io/providers/ovh/ovh/latest/docs) -If you need training or technical assistance to implement our solutions, contact your sales representative or click on [this link](/links/professional-services) to get a quote and ask our Professional Services experts for assisting you on your specific use case of your project. +If you need training or technical assistance to implement our solutions, contact your sales representative or click on [this link](/links/professional-services) to get a quote and ask our Professional Services experts for a custom analysis of your project. Join our [community of users](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.es-es.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.es-es.md new file mode 100644 index 00000000000..04443e35626 --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.es-es.md @@ -0,0 +1,517 @@ +--- +title: Desplegar una stack EFS para Trident CSI con Terraform +excerpt: Descubra cómo desplegar la stack de infraestructura NetApp Trident CSI con Enterprise File Storage y Managed Kubernetes Service mediante Terraform. +updated: 2026-05-19 +--- + +## Objetivo + +Esta guía explica cómo utilizar un módulo Terraform de OVHcloud llamado [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) para aprovisionar la stack de infraestructura completa necesaria para utilizar [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) con Enterprise File Storage (EFS). + +El módulo automatiza la creación de: + +- Un servicio **Enterprise File Storage** (EFS) +- Un clúster **Managed Kubernetes Service** (MKS) +- Un **vRack** y un **vRack Services**, así como su configuración +- Un **Public Cloud Project** con una configuración para la red privada +- Una **política IAM** e **identificadores OAuth2** para la autenticación del backend de almacenamiento Trident CSI +- Una **pasarela** de red para la conectividad de los nodos del clúster MKS con la API de OVHcloud + +**Descubra cómo desplegar y configurar un conjunto de servicios de OVHcloud con Terraform para aprovisionar volúmenes EFS con NetApp Trident CSI.** + +## Requisitos + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [Provider Terraform OVHcloud >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Acceso a la [API de OVHcloud](/links/api) +- Una cuenta OVHcloud con los permisos suficientes para crear los recursos necesarios + +## Arquitectura + +El módulo Terraform crea la siguiente infraestructura: + +![Arquitectura del módulo Terraform](images/terraform-module-architecture.png){.thumbnail} + +## Restricciones de red + +El módulo aplica las siguientes restricciones: + +| Restricción | Descripción | +|------------|-------------| +| Mismo vRack | El Cloud Project y el vRack Services deben estar en el mismo vRack | +| Misma región | El vRack Services y el EFS deben estar en la misma región | +| Mismo VLAN ID | La red privada y la subred vRack Services deben utilizar el mismo VLAN ID | +| Mismo CIDR | La red privada y la subred vRack Services deben utilizar el mismo CIDR | +| Sin solapamiento de IP | El pool de asignación de la subred de la red privada no debe solaparse con el CIDR del rango de servicios | +| Pasarela obligatoria | El clúster MKS requiere una pasarela para acceder a la API de OVH | + +## Procedimiento + +### Configurar el provider Terraform OVHcloud + +#### Generar los identificadores de la API + +El provider Terraform OVHcloud debe configurarse con un token de API para realizar llamadas a la API de OVHcloud. + +Su token de API debe disponer de los siguientes permisos: + +- GET, POST, PUT, DELETE en `/storage/netapp/*` +- GET, POST, PUT, DELETE en `/vrack/*` +- GET, POST, PUT, DELETE en `/cloud/project/*` +- GET, POST, PUT, DELETE en `/me/*` +- GET, POST, PUT, DELETE en `/iam/*` +- POST en `/order/*` + +Siga la guía [Primeros pasos con las API de OVHcloud](/pages/manage_and_operate/api/first-steps) para generar su token de API. + +**Una vez generado el token, conserve su información para utilizarla a continuación con el provider Terraform OVHcloud.** + +#### Configurar los parámetros del provider + +Cree un fichero `provider.tf` con la configuración del provider OVHcloud: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Cree a continuación un fichero `variables.tf` que defina las variables que se utilizarán en sus ficheros `.tf`: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> Acerca de la variable `ovh.endpoint`: por defecto, está definido `ovh-eu`, ya que realizamos llamadas a las API de OVHcloud Europa. +> +> Existen otros endpoints, en función de sus necesidades: +> +> - `ovh-eu` para las API de OVHcloud Europa +> - `ovh-ca` para las API de OVHcloud América / Asia + +Cree un fichero `secrets.tfvars` con sus identificadores: + +> [!warning] +> No olvide sustituir ``, `` y `` por la información de su token de API obtenido anteriormente. + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Utilizar el módulo Terraform + +#### Configuración mínima + +Cree un fichero `main.tf` que utilice el módulo con los parámetros mínimos requeridos: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +Esta configuración mínima crea todos los recursos desde cero con los parámetros por defecto. + +> [!primary] +> Recomendamos elegir una `region` EFS y una región `public_cloud_region` MKS lo más cercanas posible. +> +> La latencia entre regiones puede afectar al rendimiento de sus cargas de trabajo de almacenamiento. +> **Mantenga su almacenamiento y sus recursos de cálculo lo más cerca posible.** +> +> Por ejemplo: +> +> - `eu-west-gra` y `GRA9` +> - `eu-west-sbg` y `SBG5` +> +> Consulte la [documentación de las regiones de OVHcloud](/links/bare-metal/regions) para el mapeo completo. + +#### Ejemplo de configuración completa + +Para un control total sobre todos los recursos, utilice la configuración completa: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Utilizar recursos existentes + +El módulo está diseñado para ser compatible con su infraestructura existente. Puede utilizar sus recursos OVHcloud en lugar de crear otros nuevos. + +#### Utilizar un EFS y un vRack Services existentes vinculados a un vRack + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Utilizar un clúster MKS existente + +Este ejemplo supone que solo existen productos Public Cloud: un clúster MKS con conectividad sobre red privada +y una pasarela para acceder a Internet, pero ningún vRack, EFS u otros recursos. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Desplegar la infraestructura + +Cree un fichero `outputs.tf` que agrupe todas las salidas del módulo: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Inicialice Terraform para descargar los providers requeridos: + +```bash +terraform init +``` + +Cree un plan de ejecución para examinar los cambios: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Examine la salida del plan para verificar los recursos que se crearán: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Aplique la configuración para crear los recursos: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> La creación de los recursos puede tardar varios minutos. La creación del clúster MKS suele ser la más larga. + +### Recuperar los outputs + +Tras un despliegue correcto, recupere los outputs necesarios para la configuración de Trident: + +```bash +terraform output +``` + +Las salidas clave incluyen: + +| Salida | Descripción | +|--------|-------------| +| `client_id` | ID cliente OAuth2 para el backend Trident | +| `client_secret` | Secreto cliente OAuth2 (valor sensible) | +| `efs_id` | ID del servicio Enterprise File Storage | +| `mks_cluster_id` | ID del clúster MKS | +| `kubeconfig` | Fichero de configuración de Kubernetes (valor sensible) | +| `private_network_subnet_cidr` | CIDR de la red para la configuración del backend Trident | + +Para recuperar los valores sensibles: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Configurar Trident CSI + +Tras desplegar la infraestructura con este módulo, configure Trident CSI para utilizar Enterprise File Storage. Siga la guía [Primeros pasos con Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) para obtener instrucciones detalladas. + +Utilice las salidas del módulo para configurar el backend Trident. + +Recupere los identificadores OAuth2: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Cree el secreto Kubernetes: + +> [!warning] +> Si el namespace `trident` no existe todavía, créelo con `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Destruir la infraestructura + +Antes de eliminar los recursos, si la vinculación del vRack Services al EFS se ha realizado con Terraform, elimínela primero definiendo `vrackservices_attach_to_efs = false` y aplicando la nueva configuración. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Una vez desvinculado el vRack Services del EFS, todos los recursos pueden eliminarse. + +Para eliminar todos los recursos creados por el módulo: + +> [!warning] +> Esto eliminará definitivamente todos los recursos, incluidos el clúster MKS y el almacenamiento EFS. Asegúrese de haber realizado una copia de seguridad de todos los datos importantes antes de proceder. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Más información + +- [Primeros pasos con Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Gestionar Enterprise File Storage con el provider Terraform OVHcloud](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Documentación del provider Terraform OVHcloud](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Si necesita formación o asistencia técnica para implantar nuestras soluciones, póngase en contacto con su representante de ventas o haga clic en [este enlace](/links/professional-services) para obtener un presupuesto y solicitar un análisis personalizado de su proyecto a nuestros expertos del equipo de Servicios Profesionales. + +Interactúe con nuestra [comunidad de usuarios](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md index cb8ef08149c..55c29c8a487 100644 --- a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.fr-fr.md @@ -1,14 +1,14 @@ --- title: Déployer une stack EFS pour Trident CSI avec Terraform -excerpt: Découvrez comment utiliser un module Terraform pour créer et configurer une stack d'infrastructure pour utiliser NetApp Trident CSI avec Enterprise File Storage et Managed Kubernetes Service -updated: 2026-05-13 +excerpt: Découvrez comment déployer la stack d'infrastructure NetApp Trident CSI avec Enterprise File Storage et Managed Kubernetes Service via Terraform. +updated: 2026-05-19 --- ## Objectif Ce guide explique comment utiliser un module Terraform OVHcloud appelé [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) pour provisionner la stack d'infrastructure complète nécessaire à l'utilisation de [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) avec Enterprise File Storage (EFS). -Le module automatise la création de : +Le module automatise la création de : - Un service **Enterprise File Storage** (EFS) - Un cluster **Managed Kubernetes Service** (MKS) @@ -17,7 +17,7 @@ Le module automatise la création de : - Une **politique IAM** et des **identifiants OAuth2** pour l'authentification du backend de stockage Trident CSI - Une **passerelle** réseau pour la connectivité des nœuds du cluster MKS à l'API OVHcloud -**Découvrez comment déployer et configurer un ensemble de services OVHcloud avec Terraform pour pouvoir provisionner des volumes EFS avec NetApp Trident CSI.** +**Découvrez comment déployer et configurer un ensemble de services OVHcloud avec Terraform pour provisionner des volumes EFS avec NetApp Trident CSI.** ## Prérequis @@ -28,13 +28,13 @@ Le module automatise la création de : ## Architecture -Le module Terraform crée l'infrastructure suivante : +Le module Terraform crée l'infrastructure suivante : -![Architecture du module Terraform](images/terraform_module_architecture.excalidraw.png){.thumbnail} +![Architecture du module Terraform](images/terraform-module-architecture.png){.thumbnail} ## Contraintes réseau -Le module applique les contraintes suivantes : +Le module applique les contraintes suivantes : | Contrainte | Description | |------------|-------------| @@ -51,9 +51,9 @@ Le module applique les contraintes suivantes : #### Générer les identifiants API -Le provider Terraform OVHcloud doit être configuré avec un token d'API afin de pouvoir appeler l'API OVHcloud. +Le provider Terraform OVHcloud doit être configuré avec un token d'API pour appeler l'API OVHcloud. -Votre token d'API devra disposer des droits suivants : +Votre token d'API doit disposer des droits suivants : - GET, POST, PUT, DELETE sur `/storage/netapp/*` - GET, POST, PUT, DELETE sur `/vrack/*` @@ -68,7 +68,7 @@ Suivez le guide [Premiers pas avec les API OVHcloud](/pages/manage_and_operate/a #### Configurer les paramètres du provider -Créez un fichier `provider.tf` avec la configuration du provider OVHcloud : +Créez un fichier `provider.tf` avec la configuration du provider OVHcloud : ```hcl terraform { @@ -90,7 +90,7 @@ provider "ovh" { } ``` -Créez ensuite un fichier `variables.tf` définissant les variables qui seront utilisées dans vos fichiers `.tf` : +Créez ensuite un fichier `variables.tf` définissant les variables qui seront utilisées dans vos fichiers `.tf` : ```hcl variable "ovh" { @@ -105,14 +105,14 @@ variable "ovh" { ``` > [!primary] -> À propos de la variable `ovh.endpoint` : par défaut, `ovh-eu` est défini, car nous effectuons des appels aux API OVHcloud Europe. +> À propos de la variable `ovh.endpoint` : par défaut, `ovh-eu` est défini, car nous effectuons des appels aux API OVHcloud Europe. > -> D'autres points de terminaison existent, en fonction de vos besoins : +> D'autres points de terminaison existent, en fonction de vos besoins : > > - `ovh-eu` pour les API OVHcloud Europe > - `ovh-ca` pour les API OVHcloud Amérique / Asie -Créez un fichier `secrets.tfvars` avec vos identifiants : +Créez un fichier `secrets.tfvars` avec vos identifiants : > [!warning] > N'oubliez pas de remplacer ``, `` et `` par les informations de votre token d'API obtenu précédemment. @@ -130,7 +130,7 @@ ovh = { #### Configuration minimale -Créez un fichier `main.tf` utilisant le module avec les paramètres minimaux requis : +Créez un fichier `main.tf` utilisant le module avec les paramètres minimaux requis : ```hcl module "ovh_efs_trident" { @@ -153,19 +153,19 @@ Cette configuration minimale crée toutes les ressources à partir de zéro avec > [!primary] > Nous recommandons de choisir une `region` EFS et une région `public_cloud_region` MKS les plus proches possibles. > -> Soyez conscient que la latence entre différentes régions peut impacter les performances de vos charges de travail de stockage. -> **Il est fortement recommandé de garder votre stockage et vos calculs aussi proches que possible.** +> La latence entre régions peut impacter les performances de vos charges de travail de stockage. +> **Gardez votre stockage et vos ressources de calcul aussi proches que possible.** > -> Par exemple : +> Par exemple : > > - `eu-west-gra` et `GRA9` > - `eu-west-sbg` et `SBG5` > -> Consultez la [documentation des régions OVHcloud](https://www.ovhcloud.com/fr/about-us/global-infrastructure/expansion-regions-az/) pour le mapping complet. +> Consultez la [documentation des régions OVHcloud](/links/bare-metal/regions) pour le mapping complet. #### Exemple de configuration complète -Pour un contrôle total sur toutes les ressources, utilisez la configuration complète : +Pour un contrôle total sur toutes les ressources, utilisez la configuration complète : ```hcl module "ovh_efs_trident" { @@ -258,14 +258,14 @@ module "ovh_efs_trident" { # } # private_network_gateway = "10.7.0.254" - # Ignorer le binding entre vRack et vRack services si il est déjà configuré + # Ignorer le binding entre vRack et vRack services s'il est déjà configuré bind_vrack_to_vrack_services = false } ``` #### Utiliser un cluster MKS existant -Cet exemple suppose que seuls des produits Public Cloud existent déjà : un cluster MKS avec connectivité sur réseau privé +Cet exemple suppose que seuls des produits Public Cloud existent déjà : un cluster MKS avec connectivité sur réseau privé et une passerelle pour joindre Internet, mais pas de vRack, d'EFS ni d'autres ressources. ```hcl @@ -302,7 +302,7 @@ module "ovh_efs_trident" { ### Déployer l'infrastructure -Créez un fichier `outputs.tf` qui regroupera toutes les sorties du module : +Créez un fichier `outputs.tf` qui regroupera toutes les sorties du module : ```hcl # OAuth2 Credentials for Trident @@ -363,19 +363,19 @@ output "resources_created" { } ``` -Initialisez Terraform pour télécharger les providers requis : +Initialisez Terraform pour télécharger les providers requis : ```bash terraform init ``` -Créez un plan d'exécution pour examiner les changements : +Créez un plan d'exécution pour examiner les changements : ```bash terraform plan -var-file=secrets.tfvars -out main.tfplan ``` -Examinez la sortie du plan pour vérifier les ressources qui seront créées : +Examinez la sortie du plan pour vérifier les ressources qui seront créées : ```bash Terraform will perform the following actions: @@ -398,7 +398,7 @@ Terraform will perform the following actions: Plan: 14 to add, 0 to change, 0 to destroy. ``` -Appliquez la configuration pour créer les ressources : +Appliquez la configuration pour créer les ressources : ```bash terraform apply main.tfplan @@ -428,13 +428,13 @@ Apply complete! Resources: 14 added, 0 changed, 0 destroyed. ### Récupérer les outputs -Après un déploiement réussi, récupérez les outputs nécessaires à la configuration de Trident : +Après un déploiement réussi, récupérez les outputs nécessaires à la configuration de Trident : ```bash terraform output ``` -Les sorties clés incluent : +Les sorties clés incluent : | Sortie | Description | |--------|-------------| @@ -445,7 +445,7 @@ Les sorties clés incluent : | `kubeconfig` | Fichier de configuration Kubernetes (valeur sensible) | | `private_network_subnet_cidr` | CIDR du réseau pour la configuration du backend Trident | -Pour récupérer les valeurs sensibles : +Pour récupérer les valeurs sensibles : ```bash terraform output -raw client_secret @@ -458,14 +458,14 @@ Après avoir déployé l'infrastructure avec ce module, configurez Trident CSI p Utilisez les sorties du module pour configurer le backend Trident. -Récupérez les identifiants OAuth2 : +Récupérez les identifiants OAuth2 : ```bash export CLIENT_ID=$(terraform output -raw client_id) export CLIENT_SECRET=$(terraform output -raw client_secret) ``` -Créez le secret Kubernetes : +Créez le secret Kubernetes : > [!warning] > Si le namespace `trident` n'existe pas encore, créez-le avec `kubectl --kubeconfig kubeconfig.yaml create ns trident` @@ -496,7 +496,7 @@ terraform apply -var-file=secrets.tfvars Une fois le vRack Services détaché de l'EFS, toutes les ressources peuvent être supprimées. -Pour supprimer toutes les ressources créées par le module : +Pour supprimer toutes les ressources créées par le module : > [!warning] > Cela supprimera définitivement toutes les ressources, y compris le cluster MKS et le stockage EFS. Assurez-vous d'avoir sauvegardé toutes les données importantes avant de procéder. @@ -512,6 +512,6 @@ terraform destroy -var-file=secrets.tfvars - [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) - [Documentation du provider Terraform OVHcloud](https://registry.terraform.io/providers/ovh/ovh/latest/docs) -Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur [ce lien](/links/professional-services) pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l'équipe Professional Services. +Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur [ce lien](/links/professional-services) pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services. Échangez avec notre [communauté d'utilisateurs](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.it-it.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.it-it.md new file mode 100644 index 00000000000..552c8a6bb27 --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.it-it.md @@ -0,0 +1,517 @@ +--- +title: Distribuire uno stack EFS per Trident CSI con Terraform +excerpt: Scopri come distribuire lo stack di infrastruttura NetApp Trident CSI con Enterprise File Storage e Managed Kubernetes Service tramite Terraform. +updated: 2026-05-19 +--- + +## Obiettivo + +Questa guida spiega come utilizzare un modulo Terraform OVHcloud denominato [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) per effettuare il provisioning dello stack di infrastruttura completo necessario all'utilizzo di [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) con Enterprise File Storage (EFS). + +Il modulo automatizza la creazione di: + +- Un servizio **Enterprise File Storage** (EFS) +- Un cluster **Managed Kubernetes Service** (MKS) +- Un **vRack** e un **vRack Services**, oltre alla relativa configurazione +- Un **Public Cloud Project** con una configurazione per la rete privata +- Una **policy IAM** e delle **credenziali OAuth2** per l'autenticazione del backend di storage Trident CSI +- Un **gateway** di rete per la connettività dei nodi del cluster MKS all'API OVHcloud + +**Scopri come distribuire e configurare un insieme di servizi OVHcloud con Terraform per effettuare il provisioning di volumi EFS con NetApp Trident CSI.** + +## Prerequisiti + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [Provider Terraform OVHcloud >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Accesso alle [API OVHcloud](/links/api) +- Un account OVHcloud con i permessi necessari per creare le risorse richieste + +## Architettura + +Il modulo Terraform crea la seguente infrastruttura: + +![Architettura del modulo Terraform](images/terraform-module-architecture.png){.thumbnail} + +## Vincoli di rete + +Il modulo applica i seguenti vincoli: + +| Vincolo | Descrizione | +|------------|-------------| +| Stesso vRack | Il Cloud Project e il vRack Services devono trovarsi nello stesso vRack | +| Stessa regione | Il vRack Services e l'EFS devono trovarsi nella stessa regione | +| Stesso VLAN ID | La rete privata e la sottorete vRack Services devono utilizzare lo stesso VLAN ID | +| Stesso CIDR | La rete privata e la sottorete vRack Services devono utilizzare lo stesso CIDR | +| Nessuna sovrapposizione IP | Il pool di allocazione della sottorete della rete privata non deve sovrapporsi al CIDR dell'intervallo dei servizi | +| Gateway richiesto | Il cluster MKS necessita di un gateway per raggiungere l'API OVH | + +## Procedura + +### Configurare il provider Terraform OVHcloud + +#### Generare le credenziali API + +Il provider Terraform OVHcloud deve essere configurato con un token API per effettuare le chiamate alle API OVHcloud. + +Il tuo token API deve disporre dei seguenti diritti: + +- GET, POST, PUT, DELETE su `/storage/netapp/*` +- GET, POST, PUT, DELETE su `/vrack/*` +- GET, POST, PUT, DELETE su `/cloud/project/*` +- GET, POST, PUT, DELETE su `/me/*` +- GET, POST, PUT, DELETE su `/iam/*` +- POST su `/order/*` + +Segui la guida [Primi passi con le API OVHcloud](/pages/manage_and_operate/api/first-steps) per generare il tuo token API. + +**Una volta generato il token, conserva le sue informazioni per utilizzarle successivamente con il provider Terraform OVHcloud.** + +#### Configurare i parametri del provider + +Crea un file `provider.tf` con la configurazione del provider OVHcloud: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Crea quindi un file `variables.tf` che definisce le variabili da utilizzare nei tuoi file `.tf`: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> A proposito della variabile `ovh.endpoint`: per impostazione predefinita è definito `ovh-eu`, poiché effettuiamo chiamate alle API OVHcloud Europa. +> +> Esistono altri endpoint, in base alle tue esigenze: +> +> - `ovh-eu` per le API OVHcloud Europa +> - `ovh-ca` per le API OVHcloud America / Asia + +Crea un file `secrets.tfvars` con le tue credenziali: + +> [!warning] +> Non dimenticare di sostituire ``, `` e `` con le informazioni del token API ottenuto in precedenza. + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Utilizzare il modulo Terraform + +#### Configurazione minima + +Crea un file `main.tf` che utilizza il modulo con i parametri minimi richiesti: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +Questa configurazione minima crea tutte le risorse da zero con i parametri predefiniti. + +> [!primary] +> Consigliamo di scegliere una `region` EFS e una regione `public_cloud_region` MKS il più vicine possibile. +> +> La latenza tra regioni può influire sulle prestazioni dei tuoi carichi di lavoro di storage. +> **Mantieni il tuo storage e le tue risorse di calcolo il più vicini possibile.** +> +> Ad esempio: +> +> - `eu-west-gra` e `GRA9` +> - `eu-west-sbg` e `SBG5` +> +> Consulta la [documentazione delle regioni OVHcloud](/links/bare-metal/regions) per la mappatura completa. + +#### Esempio di configurazione completa + +Per un controllo totale su tutte le risorse, utilizza la configurazione completa: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Utilizzare risorse esistenti + +Il modulo è progettato per essere compatibile con la tua infrastruttura esistente. Puoi utilizzare le tue risorse OVHcloud invece di crearne di nuove. + +#### Utilizzare un EFS e un vRack Services esistenti collegati a un vRack + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Utilizzare un cluster MKS esistente + +Questo esempio presuppone che esistano già solo prodotti Public Cloud: un cluster MKS con connettività su rete privata +e un gateway per raggiungere Internet, ma nessun vRack, EFS né altre risorse. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Distribuire l'infrastruttura + +Crea un file `outputs.tf` che raggrupperà tutti gli output del modulo: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Inizializza Terraform per scaricare i provider richiesti: + +```bash +terraform init +``` + +Crea un piano di esecuzione per esaminare le modifiche: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Esamina l'output del piano per verificare le risorse che verranno create: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Applica la configurazione per creare le risorse: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> La creazione delle risorse può richiedere alcuni minuti. La creazione del cluster MKS è generalmente la più lunga. + +### Recuperare gli output + +Dopo un'installazione riuscita, recupera gli output necessari alla configurazione di Trident: + +```bash +terraform output +``` + +Gli output chiave includono: + +| Output | Descrizione | +|--------|-------------| +| `client_id` | ID client OAuth2 per il backend Trident | +| `client_secret` | Secret client OAuth2 (valore sensibile) | +| `efs_id` | ID del servizio Enterprise File Storage | +| `mks_cluster_id` | ID del cluster MKS | +| `kubeconfig` | File di configurazione Kubernetes (valore sensibile) | +| `private_network_subnet_cidr` | CIDR della rete per la configurazione del backend Trident | + +Per recuperare i valori sensibili: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Configurare Trident CSI + +Dopo aver distribuito l'infrastruttura con questo modulo, configura Trident CSI per utilizzare Enterprise File Storage. Segui la guida [Primi passi con Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) per istruzioni dettagliate. + +Utilizza gli output del modulo per configurare il backend Trident. + +Recupera le credenziali OAuth2: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Crea il secret Kubernetes: + +> [!warning] +> Se il namespace `trident` non esiste ancora, crealo con `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Distruggere l'infrastruttura + +Prima di eliminare le risorse, se il collegamento del vRack Services all'EFS è stato effettuato con Terraform, eliminalo per primo impostando `vrackservices_attach_to_efs = false` e applicando la nuova configurazione. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Una volta scollegato il vRack Services dall'EFS, è possibile eliminare tutte le risorse. + +Per eliminare tutte le risorse create dal modulo: + +> [!warning] +> Questa operazione eliminerà definitivamente tutte le risorse, compreso il cluster MKS e lo storage EFS. Assicurati di aver salvato tutti i dati importanti prima di procedere. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Per saperne di più + +- [Primi passi con Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Gestire Enterprise File Storage con il provider Terraform OVHcloud](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Documentazione del provider Terraform OVHcloud](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Se avete bisogno di formazione o di assistenza tecnica per implementare le nostre soluzioni, contattate il vostro rappresentante o cliccate su [questo link](/links/professional-services) per ottenere un preventivo e richiedere un'analisi personalizzata del vostro progetto da parte dei nostri esperti del team Professional Services. + +Contatta la nostra [Community di utenti](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pl-pl.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pl-pl.md new file mode 100644 index 00000000000..775198fbc73 --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pl-pl.md @@ -0,0 +1,518 @@ +--- +title: Wdrażanie stosu EFS dla Trident CSI z użyciem Terraform +excerpt: Dowiedz się, jak wykorzystać moduł Terraform do wdrożenia stosu infrastruktury dla NetApp Trident CSI z Enterprise File Storage oraz Managed Kubernetes Service +updated: 2026-05-19 +--- + +## Wprowadzenie + +Niniejszy przewodnik wyjaśnia, jak wykorzystać moduł OVHcloud Terraform o nazwie [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) do zainicjowania kompletnego stosu infrastruktury wymaganego do używania [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) z Enterprise File Storage (EFS). + +Moduł automatyzuje tworzenie: + +- Usługi **Enterprise File Storage** (EFS) +- Klastra **Managed Kubernetes** (MKS) +- **vRack** oraz **vRack Services** wraz z ich konfiguracją +- Projektu **Public Cloud** ze skonfigurowaną siecią prywatną +- **Polityki IAM** oraz **danych uwierzytelniających OAuth2** do uwierzytelniania backendu pamięci masowej Trident CSI +- Sieciowej **bramy** zapewniającej łączność węzłom klastra MKS z OVHcloud API + +**Dowiedz się, jak wdrożyć i skonfigurować infrastrukturę OVHcloud za pomocą Terraform, aby zainicjować woluminy EFS z NetApp Trident CSI.** + +## Wymagania początkowe + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [Dostawca OVHcloud Terraform >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Dostęp do [OVHcloud API](/links/api) +- Konto OVHcloud z uprawnieniami wystarczającymi do utworzenia wymaganych zasobów + +## Architektura + +Moduł Terraform tworzy następującą infrastrukturę: + +![Architektura modułu Terraform](images/terraform-module-architecture.png){.thumbnail} + +## Ograniczenia sieciowe + +Moduł wymusza następujące ograniczenia: + +| Ograniczenie | Opis | +|------------|-------------| +| Ten sam vRack | Cloud Project i vRack Services muszą znajdować się w tym samym vRacku | +| Ten sam region | vRack Services i EFS muszą znajdować się w tym samym regionie | +| Ten sam identyfikator VLAN | Sieć prywatna i podsieć vRack Services muszą używać tego samego identyfikatora VLAN | +| Ten sam CIDR | Sieć prywatna i podsieć vRack Services muszą używać tego samego CIDR | +| Brak nakładania się adresów IP | Pula przydziału podsieci prywatnej nie może nakładać się na zakres CIDR usługi | +| Wymagana brama | Klaster MKS wymaga bramy, aby uzyskać dostęp do OVH API | + +## W praktyce + +### Skonfiguruj dostawcę OVHcloud Terraform + +#### Wygeneruj dane uwierzytelniające API + +Dostawca OVHcloud Terraform musi zostać skonfigurowany z tokenem API, aby móc wykonywać wywołania do OVHcloud API. + +Twój token API musi posiadać następujące uprawnienia: + +- GET, POST, PUT, DELETE w `/storage/netapp/*` +- GET, POST, PUT, DELETE w `/vrack/*` +- GET, POST, PUT, DELETE w `/cloud/project/*` +- GET, POST, PUT, DELETE w `/me/*` +- GET, POST, PUT, DELETE w `/iam/*` +- POST w `/order/*` + +Postępuj zgodnie z przewodnikiem [Pierwsze kroki z OVHcloud API](/pages/manage_and_operate/api/first-steps), aby wygenerować swój token API. + +**Po wygenerowaniu tokenu zapisz jego informacje do późniejszego użycia z dostawcą OVHcloud Terraform**. + +#### Skonfiguruj parametry dostawcy + +Utwórz plik `provider.tf` z konfiguracją dostawcy OVHcloud: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Następnie utwórz plik `variables.tf` definiujący zmienne, które będą używane wewnątrz plików `.tf`: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> Informacja o zmiennej `ovh.endpoint`: domyślnie ustawiona jest wartość `ovh-eu`, ponieważ wykonujemy wywołania do OVHcloud Europe API. +> +> W zależności od potrzeb dostępne są inne punkty końcowe: +> +> - `ovh-eu` dla OVHcloud Europe API +> - `ovh-ca` dla OVHcloud America/Asia API + +Utwórz plik `secrets.tfvars` z Twoimi danymi uwierzytelniającymi: + +> [!warning] +> Nie zapomnij zastąpić wartości ``, `` oraz `` informacjami z Twojego tokenu API uzyskanego wcześniej. +> + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Użyj modułu Terraform + +#### Minimalna konfiguracja + +Utwórz plik `main.tf` używający modułu z minimalnymi wymaganymi parametrami: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +Ta minimalna konfiguracja tworzy wszystkie zasoby od podstaw z domyślnymi ustawieniami. + +> [!primary] +> Zalecamy, aby `region` dla EFS oraz `public_cloud_region` dla MKS były możliwie najbliżej siebie. +> +> Opóźnienia między regionami mogą wpływać na wydajność obciążenia pamięci masowej. +> **Utrzymuj pamięć masową i moc obliczeniową możliwie blisko siebie.** +> +> Na przykład: +> +> - `eu-west-gra` i `GRA9` +> - `eu-west-sbg` i `SBG5` +> +> Zobacz [dokumentację regionów OVHcloud](/links/bare-metal/regions), aby zapoznać się z pełnym mapowaniem. + +#### Przykład pełnej konfiguracji + +Aby uzyskać pełną kontrolę nad wszystkimi zasobami, użyj pełnej konfiguracji: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Wykorzystaj istniejące zasoby + +Moduł został zaprojektowany w taki sposób, aby był kompatybilny z Twoją istniejącą infrastrukturą. Możesz wykorzystać posiadane zasoby OVHcloud zamiast tworzyć nowe. + +#### Wykorzystaj istniejący EFS i vRack Services powiązane z vRackiem + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Wykorzystaj istniejący klaster MKS + +Ten przykład zakłada, że istnieją wyłącznie produkty Public Cloud: klaster MKS z łącznością prywatnej sieci +oraz brama umożliwiająca dostęp do Internetu, ale bez vRacka, EFS lub innych zasobów. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Wdróż infrastrukturę + +Utwórz plik `outputs.tf`, który będzie zawierał wszystkie wyniki modułu: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Zainicjuj Terraform, aby pobrać wymaganych dostawców: + +```bash +terraform init +``` + +Utwórz plan wykonania, aby przeanalizować zmiany: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Przejrzyj wynik planu, aby zweryfikować zasoby, które zostaną utworzone: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Zastosuj konfigurację, aby utworzyć zasoby: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> Tworzenie zasobów może zająć kilka minut. Utworzenie klastra MKS zwykle trwa najdłużej. + +### Pobierz wyniki + +Po pomyślnym wdrożeniu pobierz wyniki potrzebne do konfiguracji Trident: + +```bash +terraform output +``` + +Najważniejsze wyniki obejmują: + +| Wynik | Opis | +|--------|-------------| +| `client_id` | Identyfikator klienta OAuth2 dla backendu Trident | +| `client_secret` | Sekret klienta OAuth2 (wrażliwy) | +| `efs_id` | Identyfikator usługi Enterprise File Storage | +| `mks_cluster_id` | Identyfikator klastra MKS | +| `kubeconfig` | Plik konfiguracyjny Kubernetes (wrażliwy) | +| `private_network_subnet_cidr` | CIDR sieci dla konfiguracji backendu Trident | + +Aby pobrać wrażliwe wartości: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Skonfiguruj Trident CSI + +Po wdrożeniu infrastruktury za pomocą tego modułu skonfiguruj Trident CSI tak, aby korzystał z Enterprise File Storage. Postępuj zgodnie z przewodnikiem [Pierwsze kroki z Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi), aby uzyskać szczegółowe instrukcje. + +Wykorzystaj wyniki modułu do skonfigurowania backendu Trident. + +Pobierz dane uwierzytelniające OAuth2: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Utwórz sekret Kubernetes: + +> [!warning] +> Jeśli przestrzeń nazw trident jeszcze nie istnieje, utwórz ją poleceniem `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Usuń infrastrukturę + +Przed usunięciem zasobów, jeśli powiązanie vRack Services z EFS zostało utworzone za pomocą Terraform, najpierw je usuń, ustawiając `vrackservices_attach_to_efs = false` i stosując nową konfigurację. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Gdy vRack Services zostanie odłączony od EFS, wszystkie zasoby mogą zostać usunięte. + +Aby usunąć wszystkie zasoby utworzone przez moduł: + +> [!warning] +> Spowoduje to trwałe usunięcie wszystkich zasobów, w tym klastra MKS i pamięci masowej EFS. Upewnij się, że masz kopię zapasową wszystkich ważnych danych, zanim przejdziesz dalej. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Sprawdź również + +- [Pierwsze kroki z Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Zarządzanie Enterprise File Storage za pomocą dostawcy OVHcloud Terraform](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Dokumentacja dostawcy OVHcloud Terraform](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Jeśli potrzebujesz szkolenia lub pomocy technicznej przy wdrażaniu naszych rozwiązań, skontaktuj się ze swoim Jeśli potrzebujesz szkolenia lub pomocy technicznej w celu wdrożenia naszych rozwiązań, skontaktuj się z przedstawicielem handlowym lub kliknij [ten link](/links/professional-services), aby uzyskać wycenę i poprosić o spersonalizowaną analizę projektu od naszych ekspertów z zespołu Professional Services. + +Dołącz do [grona naszych użytkowników](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pt-pt.md b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pt-pt.md new file mode 100644 index 00000000000..52b9375984f --- /dev/null +++ b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/guide.pt-pt.md @@ -0,0 +1,517 @@ +--- +title: Implementar uma stack EFS para o Trident CSI com o Terraform +excerpt: Saiba como implementar a stack de infraestrutura NetApp Trident CSI com Enterprise File Storage e Managed Kubernetes Service através do Terraform. +updated: 2026-05-19 +--- + +## Objetivo + +Este guia explica como utilizar um módulo Terraform da OVHcloud chamado [efs-trident](https://github.com/ovh/terraform-ovh-efs/tree/main/modules/efs-trident) para aprovisionar a stack de infraestrutura completa necessária à utilização do [NetApp Trident CSI](https://docs.netapp.com/us-en/trident/index.html) com o Enterprise File Storage (EFS). + +O módulo automatiza a criação de: + +- Um serviço **Enterprise File Storage** (EFS) +- Um cluster **Managed Kubernetes Service** (MKS) +- Uma **vRack** e um **vRack Services**, bem como a respetiva configuração +- Um **Public Cloud Project** com uma configuração para a rede privada +- Uma **política IAM** e **credenciais OAuth2** para a autenticação do backend de armazenamento Trident CSI +- Uma **gateway** de rede para a conectividade dos nós do cluster MKS à API OVHcloud + +**Saiba como implementar e configurar um conjunto de serviços OVHcloud com o Terraform para aprovisionar volumes EFS com o NetApp Trident CSI.** + +## Requisitos + +- [Terraform >= 1.7.0](https://www.terraform.io/) +- [Provider Terraform OVHcloud >= v2.12.0](https://github.com/ovh/terraform-provider-ovh/releases/) +- Acesso à [API OVHcloud](/links/api) +- Uma conta OVHcloud com as permissões suficientes para criar os recursos necessários + +## Arquitetura + +O módulo Terraform cria a seguinte infraestrutura: + +![Arquitetura do módulo Terraform](images/terraform-module-architecture.png){.thumbnail} + +## Restrições de rede + +O módulo aplica as seguintes restrições: + +| Restrição | Descrição | +|------------|-------------| +| Mesma vRack | O Cloud Project e o vRack Services devem estar na mesma vRack | +| Mesma região | O vRack Services e o EFS devem estar na mesma região | +| Mesmo VLAN ID | A rede privada e a sub-rede vRack Services devem utilizar o mesmo VLAN ID | +| Mesmo CIDR | A rede privada e a sub-rede vRack Services devem utilizar o mesmo CIDR | +| Sem sobreposição de IP | O pool de alocação da sub-rede da rede privada não deve sobrepor-se ao CIDR da gama de serviços | +| Gateway obrigatória | O cluster MKS necessita de uma gateway para alcançar a API OVH | + +## Instruções + +### Configurar o provider Terraform OVHcloud + +#### Gerar as credenciais da API + +O provider Terraform OVHcloud deve ser configurado com um token de API para invocar a API OVHcloud. + +O seu token de API deve dispor dos seguintes direitos: + +- GET, POST, PUT, DELETE em `/storage/netapp/*` +- GET, POST, PUT, DELETE em `/vrack/*` +- GET, POST, PUT, DELETE em `/cloud/project/*` +- GET, POST, PUT, DELETE em `/me/*` +- GET, POST, PUT, DELETE em `/iam/*` +- POST em `/order/*` + +Siga o guia [Primeiros passos com as APIs OVHcloud](/pages/manage_and_operate/api/first-steps) para gerar o seu token de API. + +**Depois de gerado o token, guarde as suas informações para utilizá-las posteriormente com o provider Terraform OVHcloud.** + +#### Configurar os parâmetros do provider + +Crie um ficheiro `provider.tf` com a configuração do provider OVHcloud: + +```hcl +terraform { + required_providers { + ovh = { + source = "ovh/ovh" + version = ">= 2.12.0" + } + } + + required_version = ">= 1.7.0" +} + +provider "ovh" { + endpoint = var.ovh.endpoint + application_key = var.ovh.application_key + application_secret = var.ovh.application_secret + consumer_key = var.ovh.consumer_key +} +``` + +Crie em seguida um ficheiro `variables.tf` que defina as variáveis a utilizar nos seus ficheiros `.tf`: + +```hcl +variable "ovh" { + type = map(string) + default = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" + } +} +``` + +> [!primary] +> Sobre a variável `ovh.endpoint`: por predefinição, `ovh-eu` está definido, dado que efetuamos chamadas às APIs OVHcloud Europa. +> +> Existem outros endpoints, em função das suas necessidades: +> +> - `ovh-eu` para as APIs OVHcloud Europa +> - `ovh-ca` para as APIs OVHcloud América / Ásia + +Crie um ficheiro `secrets.tfvars` com as suas credenciais: + +> [!warning] +> Não se esqueça de substituir ``, `` e `` pelas informações do seu token de API obtido anteriormente. + +```hcl +ovh = { + endpoint = "ovh-eu" + application_key = "" + application_secret = "" + consumer_key = "" +} +``` + +### Utilizar o módulo Terraform + +#### Configuração mínima + +Crie um ficheiro `main.tf` que utilize o módulo com os parâmetros mínimos exigidos: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration (required) + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration (required) + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true +} +``` + +Esta configuração mínima cria todos os recursos a partir do zero com os parâmetros predefinidos. + +> [!primary] +> Recomendamos escolher uma `region` EFS e uma região `public_cloud_region` MKS o mais próximas possível. +> +> A latência entre regiões pode afetar o desempenho das suas cargas de trabalho de armazenamento. +> **Mantenha o seu armazenamento e os seus recursos de computação o mais próximos possível.** +> +> Por exemplo: +> +> - `eu-west-gra` e `GRA9` +> - `eu-west-sbg` e `SBG5` +> +> Consulte a [documentação das regiões OVHcloud](/links/bare-metal/regions) para obter o mapeamento completo. + +#### Exemplo de configuração completa + +Para um controlo total sobre todos os recursos, utilize a configuração completa: + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + # Region Configuration + region = "eu-west-gra" + public_cloud_region = "GRA9" + + # Network Configuration + vlan_id = 1234 + + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = true + + # OAuth2 and IAM + oauth2_client_name = "efs-trident-client" + oauth2_client_description = "OAuth2 client for EFS Trident integration" + iam_policy_name = "efs-trident-policy" + iam_policy_description = "IAM policy for EFS Trident access" + + # EFS + storage_efs_name = "my-efs-storage" + storage_efs_plan_code = "enterprise-file-storage-premium-1tb" + + # vRack + vrack_name = "my-vrack" + vrack_description = "vRack for EFS connectivity" + + # MKS Cluster + mks_cluster_name = "my-mks-cluster" + mks_cluster_node_pool_name = "default-pool" + mks_cluster_node_pool_flavor = "b3-8" + mks_cluster_node_pool_desired_nodes = 3 + + # Network Configuration + private_network_subnet_cidr = "10.6.0.0/24" + private_network_gateway = "10.6.0.254" + vrackservices_subnet_name = "efs-subnet" + vrackservices_subnet_service_range_cidr = "10.6.0.0/29" + + # Public Cloud Private Network + public_cloud_private_network_name = "mks-private-network" + public_cloud_private_network_subnet_name = "mks-subnet" + public_cloud_private_network_subnet_allocation_pools = { + start = "10.6.0.8" + end = "10.6.0.253" + } + + # Gateway + public_cloud_gateway_name = "mks-gateway" + public_cloud_gateway_model = "s" + + # Cloud Project + cloud_project_description = "EFS Trident Project" +} +``` + +### Utilizar recursos existentes + +O módulo foi concebido para ser compatível com a sua infraestrutura existente. Pode utilizar os seus recursos OVHcloud em vez de criar novos. + +#### Utilizar um EFS e um vRack Services existentes ligados a uma vRack + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing EFS + create_efs = false + efs_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + + # Use existing vRack Services + create_vrack_services = false + vrack_services_id = "vrs-xyz-789" + + # Use existing vRack + create_vrack = false + vrack_service_name = "pn-1234567" + + # Network Configuration + # Adjust subnet allocation pool and gateway address if your network configuration differs from example. + # public_cloud_private_network_subnet_allocation_pools = { + # start = "10.7.0.8" + # end = "10.7.0.253" + # } + # private_network_gateway = "10.7.0.254" + + # Skip binding since vRack Services is already configured + bind_vrack_to_vrack_services = false +} +``` + +#### Utilizar um cluster MKS existente + +Este exemplo pressupõe que apenas existem já produtos Public Cloud: um cluster MKS com conectividade em rede privada +e uma gateway para alcançar a Internet, mas sem vRack, EFS nem outros recursos. + +```hcl +module "ovh_efs_trident" { + source = "ovh/efs/ovh//modules/efs-trident" + + region = "eu-west-gra" + public_cloud_region = "GRA9" + vlan_id = 1234 + + # Use existing Cloud Project + create_cloud_project = false + cloud_project_id = "abc123" + + # Use existing Private Network + create_private_network = false + private_network_id = "network-openstack-id" + + # Use existing Subnet + create_private_subnet = false + private_subnet_id = "subnet-id" + + # Skip gateway creation (existing network already has a gateway) + create_gateway = false + + # Use existing MKS Cluster + create_mks_cluster = false + mks_cluster_id = "cluster-id" + + # Don't create a node pool for MKS cluster + create_node_pool = false +} +``` + +### Implementar a infraestrutura + +Crie um ficheiro `outputs.tf` que reunirá todos os outputs do módulo: + +```hcl +# OAuth2 Credentials for Trident +output "client_id" { + description = "OAuth2 client ID for EFS access" + value = module.ovh_efs_trident.client_id +} + +output "client_secret" { + description = "OAuth2 client secret for EFS access" + value = module.ovh_efs_trident.client_secret + sensitive = true +} + +# Kubernetes Configuration +output "kubeconfig" { + description = "Kubernetes configuration file for MKS cluster" + value = module.ovh_efs_trident.kubeconfig + sensitive = true +} + +# Resource Identifiers +output "efs_id" { + description = "EFS service name" + value = module.ovh_efs_trident.efs_id +} + +output "vrack_service_name" { + description = "vRack service name" + value = module.ovh_efs_trident.vrack_service_name +} + +output "cloud_project_id" { + description = "Cloud Project ID" + value = module.ovh_efs_trident.cloud_project_id +} + +output "mks_cluster_id" { + description = "MKS cluster ID" + value = module.ovh_efs_trident.mks_cluster_id +} + +# Network Information +output "private_network_id" { + description = "Private network OpenStack ID" + value = module.ovh_efs_trident.private_network_id +} + +output "vlan_id" { + description = "VLAN ID used" + value = module.ovh_efs_trident.vlan_id +} + +# Summary +output "resources_created" { + description = "Summary of resources that were created vs used" + value = module.ovh_efs_trident.resources_created +} +``` + +Inicialize o Terraform para descarregar os providers necessários: + +```bash +terraform init +``` + +Crie um plano de execução para examinar as alterações: + +```bash +terraform plan -var-file=secrets.tfvars -out main.tfplan +``` + +Examine a saída do plano para verificar os recursos que serão criados: + +```bash +Terraform will perform the following actions: + + # module.ovh_efs_trident.null_resource.config_validation will be created + # module.ovh_efs_trident.ovh_cloud_project.cloud_project[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private.network[0] will be created + # module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0] will be created + # module.ovh_efs_trident.ovh_iam_policy.iam_policy will be created + # module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client will be created + # module.ovh_efs_trident.ovh_storage_efs.efs[0] will be created + # module.ovh_efs_trident.ovh_vrack.vrack[0] will be created + # module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0] will be created + # module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0] will be created + # module.ovh_efs_trident.ovh_vrackservices.vrackservices[0] will be created + +Plan: 14 to add, 0 to change, 0 to destroy. +``` + +Aplique a configuração para criar os recursos: + +```bash +terraform apply main.tfplan +``` + +``` +module.ovh_efs_trident.null_resource.config_validation: Creation complete after 0s [id=xxx] +module.ovh_efs_trident.ovh_me_api_oauth2_client.api_oauth2_client: Creation complete after 0s [id=EU.xxx] +module.ovh_efs_trident.ovh_cloud_project.cloud_project[0]: Creation complete after 26s [id=xxx] +module.ovh_efs_trident.ovh_vrack.vrack[0]: Creation complete after 54s [id=pn-xxx] +module.ovh_efs_trident.ovh_vrack_cloudproject.vrack-cloudproject-binding[0]: Creation complete after 52s [id=vrack_pn-xxx-cloudproject_xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private.network[0]: Creation complete after 14s [id=pn-xxx] +module.ovh_efs_trident.ovh_cloud_project_network_private_subnet_v2.subnet[0]: Creation complete after 1s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_gateway.gateway[0]: Creation complete after 32s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_storage_efs.efs[0]: Creation complete after 3m58s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_iam_policy.iam_policy: Creation complete after 0s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_vrackservices.vrackservices[0]: Creation complete after 56s [id=vrs-x-x-x-x] +module.ovh_efs_trident.ovh_vrack_vrackservices.vrack-vrackservices-binding[0]: Creation complete after 1m11s [id=vrack_pn-xxx-vrackServices_vrs-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube.mks_cluster[0]: Creation complete after 4m11s [id=x-x-x-x-x] +module.ovh_efs_trident.ovh_cloud_project_kube_nodepool.node_pool[0]: Creation complete after 5m23s [id=x-x-x-x-x] + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. +``` + +> [!warning] +> A criação dos recursos pode demorar vários minutos. A criação do cluster MKS é normalmente a mais longa. + +### Obter os outputs + +Após uma implementação bem-sucedida, obtenha os outputs necessários para a configuração do Trident: + +```bash +terraform output +``` + +As saídas principais incluem: + +| Saída | Descrição | +|--------|-------------| +| `client_id` | ID de cliente OAuth2 para o backend Trident | +| `client_secret` | Secret de cliente OAuth2 (valor sensível) | +| `efs_id` | ID do serviço Enterprise File Storage | +| `mks_cluster_id` | ID do cluster MKS | +| `kubeconfig` | Ficheiro de configuração Kubernetes (valor sensível) | +| `private_network_subnet_cidr` | CIDR da rede para a configuração do backend Trident | + +Para obter os valores sensíveis: + +```bash +terraform output -raw client_secret +terraform output -raw kubeconfig > kubeconfig.yaml +``` + +### Configurar o Trident CSI + +Depois de implementada a infraestrutura com este módulo, configure o Trident CSI para utilizar o Enterprise File Storage. Siga o guia [Primeiros passos com o Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) para obter instruções detalhadas. + +Utilize os outputs do módulo para configurar o backend Trident. + +Obtenha as credenciais OAuth2: + +```bash +export CLIENT_ID=$(terraform output -raw client_id) +export CLIENT_SECRET=$(terraform output -raw client_secret) +``` + +Crie o secret Kubernetes: + +> [!warning] +> Se o namespace `trident` ainda não existir, crie-o com `kubectl --kubeconfig kubeconfig.yaml create ns trident` + +```bash +kubectl --kubeconfig kubeconfig.yaml create secret generic tbc-ovh-efs-secret \ + --namespace trident \ + --from-literal=clientID="$CLIENT_ID" \ + --from-literal=clientSecret="$CLIENT_SECRET" +``` + +### Destruir a infraestrutura + +Antes de eliminar os recursos, se o vRack Services tiver sido associado ao EFS através do Terraform, comece por removê-lo definindo `vrackservices_attach_to_efs = false` e aplicando a nova configuração. + +```hcl +module "ovh_efs_trident" { + [...] + # Set to false and terraform apply the configuration before destroying to detach vRack Services service endpoint + vrackservices_attach_to_efs = false + [...] +} +``` + +```bash +terraform apply -var-file=secrets.tfvars +``` + +Uma vez desanexado o vRack Services do EFS, todos os recursos podem ser eliminados. + +Para eliminar todos os recursos criados pelo módulo: + +> [!warning] +> Isto eliminará definitivamente todos os recursos, incluindo o cluster MKS e o armazenamento EFS. Certifique-se de que efetuou uma cópia de segurança de todos os dados importantes antes de prosseguir. + +```bash +terraform destroy -var-file=secrets.tfvars +``` + +## Quer saber mais? + +- [Primeiros passos com o Trident CSI](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_csi) +- [Gerir o Enterprise File Storage com o provider Terraform OVHcloud](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_terraform) +- [Enterprise File Storage - FAQ](/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_faq) +- [Documentação do provider Terraform OVHcloud](https://registry.terraform.io/providers/ovh/ovh/latest/docs) + +Se precisar de formação ou de assistência técnica para implementar as nossas soluções, contacte o seu representante comercial ou clique em [esta ligação](/links/professional-services) para obter um orçamento e solicitar uma análise personalizada do seu projecto aos nossos especialistas da equipa de Serviços Profissionais. + +Fale com a nossa [comunidade de utilizadores](/links/community). diff --git a/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform_module_architecture.excalidraw.png b/pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform-module-architecture.png similarity index 100% rename from pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform_module_architecture.excalidraw.png rename to pages/storage_and_backup/file_storage/enterprise_file_storage/netapp_trident_terraform/images/terraform-module-architecture.png