// Module included in the following assemblies:
// * edge_computing/image-based-upgrade/cnf-preparing-for-image-based-upgrade.adoc

:_mod-docs-content-type: PROCEDURE
[id="ztp-image-based-upgrade-installing-oadp_{context}"]
= Installing and configuring the {oadp-short} Operator with {ztp}

[role="_abstract"]
Install and configure the {oadp-short} Operator with {ztp} before starting the upgrade.

.Procedure

. Extract the following CRs from the `ztp-site-generate` container image and push them to the `source-cr` directory:
+
--
Example `OadpSubscriptionNS.yaml` file:

[source,yaml]
----
apiVersion: v1
kind: Namespace
metadata:
  name: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "2"
  labels:
    kubernetes.io/metadata.name: openshift-adp
----

Example `OadpSubscriptionOperGroup.yaml` file:

[source,yaml]
----
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: redhat-oadp-operator
  namespace: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "2"
spec:
  targetNamespaces:
  - openshift-adp
----

Example `OadpSubscription.yaml` file:

[source,yaml]
----
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: redhat-oadp-operator
  namespace: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "2"
spec:
  channel: stable-1.4
  name: redhat-oadp-operator
  source: redhat-operators
  sourceNamespace: openshift-marketplace
  installPlanApproval: Manual
status:
  state: AtLatestKnown
----

Example `OadpOperatorStatus.yaml` file:

[source,yaml]
----
apiVersion: operators.coreos.com/v1
kind: Operator
metadata:
  name: redhat-oadp-operator.openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "2"
status:
  components:
    refs:
    - kind: Subscription
      namespace: openshift-adp
      conditions:
      - type: CatalogSourcesUnhealthy
        status: "False"
    - kind: InstallPlan
      namespace: openshift-adp
      conditions:
      - type: Installed
        status: "True"
    - kind: ClusterServiceVersion
      namespace: openshift-adp
      conditions:
      - type: Succeeded
        status: "True"
        reason: InstallSucceeded
----

Example directory structure:

[source,terminal]
----
├── kustomization.yaml
├── sno
│   ├── example-cnf.yaml
│   ├── common-ranGen.yaml
│   ├── group-du-sno-ranGen.yaml
│   ├── group-du-sno-validator-ranGen.yaml
│   └── ns.yaml
├── source-crs
│   ├── OadpSubscriptionNS.yaml
│   ├── OadpSubscriptionOperGroup.yaml
│   ├── OadpSubscription.yaml
│   ├── OadpOperatorStatus.yaml
----
--

. Add the CRs to your common `PolicyGenTemplate`:
+
[source,yaml]
----
apiVersion: ran.openshift.io/v1
kind: PolicyGenTemplate
metadata:
  name: "example-common-latest"
  namespace: "ztp-common"
spec:
  bindingRules:
    common: "true"
    du-profile: "latest"
  sourceFiles:
    - fileName: OadpSubscriptionNS.yaml
      policyName: "subscriptions-policy"
    - fileName: OadpSubscriptionOperGroup.yaml
      policyName: "subscriptions-policy"
    - fileName: OadpSubscription.yaml
      policyName: "subscriptions-policy"
    - fileName: OadpOperatorStatus.yaml
      policyName: "subscriptions-policy"
[...]
----

. Create the `DataProtectionApplication` CR and the S3 secret only for the target cluster:

.. Extract the following CRs from the `ztp-site-generate` container image and push them to the `source-cr` directory:
+
--
Example `OadpDataProtectionApplication.yaml` file:

[source,yaml]
----
apiVersion: oadp.openshift.io/v1alpha1
kind: DataProtectionApplication
metadata:
  name: dataprotectionapplication
  namespace: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "100"
spec:
  configuration:
    restic:
      enable: false
    velero:
      defaultPlugins:
        - aws
        - openshift
      resourceTimeout: 10m
  backupLocations:
    - velero:
        config:
          profile: "default"
          region: minio
          s3Url: $url
          insecureSkipTLSVerify: "true"
          s3ForcePathStyle: "true"
        provider: aws
        default: true
        credential:
          key: cloud
          name: cloud-credentials
        objectStorage:
          bucket: $bucketName
          prefix: $prefixName
status:
  conditions:
  - reason: Complete
    status: "True"
    type: Reconciled
----

* `spec.configuration.restic.enable` must be set to `false` for an image-based upgrade because persistent volume contents are retained and reused after the upgrade.
* `bucket` defines the bucket name created in S3 backend. `prefix` defines the name of the subdirectory that will be automatically created in the bucket. The combination of bucket and prefix must be unique for each target cluster to avoid interference between them. To ensure a unique storage directory for each target cluster, you can use the {rh-rhacm-title} hub template function, for example, `prefix: {{hub .ManagedClusterName hub}}`.

Example `OadpSecret.yaml` file:

[source,yaml]
----
apiVersion: v1
kind: Secret
metadata:
  name: cloud-credentials
  namespace: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "100"
type: Opaque
----

Example `OadpBackupStorageLocationStatus.yaml` file:

[source,yaml]
----
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
  name: dataprotectionapplication-1
  namespace: openshift-adp
  annotations:
    ran.openshift.io/ztp-deploy-wave: "100"
status:
  phase: Available
----

The `name` value in the `BackupStorageLocation` resource must follow a specific naming convention that aligns with the corresponding `DataProtectionApplication` resource.

* The name must use the `<DataProtectionApplication.metadata.name>-<index>` pattern.
* The `<index>` represents the position of the corresponding entry in the `spec.backupLocations` field in the `DataProtectionApplication` resource. The position starts at `1`.
* If you change the `metadata.name` value of the `DataProtectionApplication` resource in the `OadpDataProtectionApplication.yaml` file, you must also update the `metadata.name` field in the `BackupStorageLocation` resource to match the new value.

The `OadpBackupStorageLocationStatus.yaml` CR verifies the availability of backup storage locations created by OADP.
--

.. Add the CRs to your site `PolicyGenTemplate` with overrides:
+
[source,yaml]
----
apiVersion: ran.openshift.io/v1
kind: PolicyGenTemplate
metadata:
  name: "example-cnf"
  namespace: "ztp-site"
spec:
  bindingRules:
    sites: "example-cnf"
    du-profile: "latest"
  mcp: "master"
  sourceFiles:
    ...
    - fileName: OadpSecret.yaml
      policyName: "config-policy"
      data:
        cloud: <your_credentials>
    - fileName: OadpDataProtectionApplication.yaml
      policyName: "config-policy"
      spec:
        backupLocations:
          - velero:
              config:
                region: minio
                s3Url: <your_S3_URL>
                profile: "default"
                insecureSkipTLSVerify: "true"
                s3ForcePathStyle: "true"
              provider: aws
              default: true
              credential:
                key: cloud
                name: cloud-credentials
              objectStorage:
                bucket: <your_bucket_name>
                prefix: <cluster_name>
    - fileName: OadpBackupStorageLocationStatus.yaml
      policyName: "config-policy"
----

where:

`your_credentials`:: Specifies your credentials for your S3 storage backend.

`OadpDataProtectionApplication.yaml`:: If more than one `backupLocations` entries are defined in the `OadpDataProtectionApplication` CR, ensure that each location has a corresponding `OadpBackupStorageLocation` CR added for status tracking. Ensure that the name of each additional `OadpBackupStorageLocation` CR is overridden with the correct index as described in the example `OadpBackupStorageLocationStatus.yaml` file.

`your_S3_URL`:: Specifies the URL for your S3-compatible bucket.

`bucket` and `prefix`:: The `bucket` defines the bucket name that is created in S3 backend. The `prefix` defines the name of the subdirectory that will be automatically created in the `bucket`. The combination of `bucket` and `prefix` must be unique for each target cluster to avoid interference between them. To ensure a unique storage directory for each target cluster, you can use the {rh-rhacm-title} hub template function, for example, `prefix: {{hub .ManagedClusterName hub}}`.