From 8b0b09ffcee00c7a034440903cc7a7d21a442752 Mon Sep 17 00:00:00 2001 From: Roy Golan Date: Sun, 10 Nov 2024 17:23:30 +0200 Subject: [PATCH] Add migration-cluster-day-2 This work contains the ArgoCD application and the mtv-init web-service to initiate the MTV provider Signed-off-by: Roy Golan --- .../.github/workflows/lint.yaml | 14 ++ .../.github/workflows/release.yml | 31 +++ migration-cluster-day2/.gitignore | 25 +++ migration-cluster-day2/LICENSE | 201 ++++++++++++++++++ migration-cluster-day2/README.md | 67 ++++++ .../charts/migration-cluster-day2/.helmignore | 23 ++ .../charts/migration-cluster-day2/Chart.yaml | 24 +++ .../charts/migration-cluster-day2/README.md | 53 +++++ .../templates/NOTES.txt | 31 +++ .../templates/_helpers.tpl | 62 ++++++ .../templates/image-registry.yaml | 91 ++++++++ .../templates/lvm-storage-operator.yaml | 83 ++++++++ .../templates/mtv-init.yaml | 64 ++++++ .../templates/mtv-operator.yaml | 59 +++++ .../templates/nmstate-operator.yaml | 35 +++ .../templates/serviceaccount.yaml | 107 ++++++++++ .../templates/vddk.yaml | 161 ++++++++++++++ .../charts/migration-cluster-day2/values.yaml | 19 ++ migration-cluster-day2/manifest.yaml | 24 +++ migration-cluster-day2/mtv-init/Containerfile | 8 + migration-cluster-day2/mtv-init/Makefile | 2 + migration-cluster-day2/mtv-init/go.mod | 3 + migration-cluster-day2/mtv-init/index.html | 125 +++++++++++ migration-cluster-day2/mtv-init/main.go | 101 +++++++++ 24 files changed, 1413 insertions(+) create mode 100644 migration-cluster-day2/.github/workflows/lint.yaml create mode 100644 migration-cluster-day2/.github/workflows/release.yml create mode 100644 migration-cluster-day2/.gitignore create mode 100644 migration-cluster-day2/LICENSE create mode 100644 migration-cluster-day2/README.md create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/.helmignore create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/Chart.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/README.md create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/NOTES.txt create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/_helpers.tpl create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/image-registry.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/lvm-storage-operator.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-init.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-operator.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/nmstate-operator.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/serviceaccount.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/templates/vddk.yaml create mode 100644 migration-cluster-day2/charts/migration-cluster-day2/values.yaml create mode 100644 migration-cluster-day2/manifest.yaml create mode 100644 migration-cluster-day2/mtv-init/Containerfile create mode 100644 migration-cluster-day2/mtv-init/Makefile create mode 100644 migration-cluster-day2/mtv-init/go.mod create mode 100644 migration-cluster-day2/mtv-init/index.html create mode 100644 migration-cluster-day2/mtv-init/main.go diff --git a/migration-cluster-day2/.github/workflows/lint.yaml b/migration-cluster-day2/.github/workflows/lint.yaml new file mode 100644 index 00000000..34625d47 --- /dev/null +++ b/migration-cluster-day2/.github/workflows/lint.yaml @@ -0,0 +1,14 @@ +name: Helm lint +on: + workflow_dispatch: + pull_request: + branches: + - main +jobs: + helmlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Orchestartor Helm Lint + run: | + helm lint charts/migration-cluster-day2 diff --git a/migration-cluster-day2/.github/workflows/release.yml b/migration-cluster-day2/.github/workflows/release.yml new file mode 100644 index 00000000..1a0fba99 --- /dev/null +++ b/migration-cluster-day2/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: Release Chart + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - "charts/**" + +jobs: + release: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + diff --git a/migration-cluster-day2/.gitignore b/migration-cluster-day2/.gitignore new file mode 100644 index 00000000..6f72f892 --- /dev/null +++ b/migration-cluster-day2/.gitignore @@ -0,0 +1,25 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env diff --git a/migration-cluster-day2/LICENSE b/migration-cluster-day2/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/migration-cluster-day2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/migration-cluster-day2/README.md b/migration-cluster-day2/README.md new file mode 100644 index 00000000..ea1e7d9b --- /dev/null +++ b/migration-cluster-day2/README.md @@ -0,0 +1,67 @@ +# migration-cluster-day-2 + +The Day-2 configuration of a cluster for migration is setup using an ArgoCD application. +See the installation instruction in charts/migration-cluster-day-2/README.md + +This repo maintains 2 components: +- the ArgoCD helm application in charts/migration-cluster-day-2 +- the mtv-init application + +> [!Note] +> 2 things that must be set for the argo application to deploy properly: +> 1. an annotation on resources which need their CRD by prior waves. For example +> the LVMCluster have this: +> ``` +> annotations: +> argocd.argoproj.io/sync-wave: "2" +> argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +> ``` +> +> This makes sure the wave is after the operator is deployed so the CRD is there +> and that the CRD is okay to be missing in the dry run check +> +> 2. Every target namespace we create needs this label so ArgoCD will have permissions to create resources there: +> ``` +> labels: +> argocd.argoproj.io/managed-by: openshift-gitops +> ``` + +# Architecture +> [!Note] +> Needs an update + + +```mermaid +architecture-beta + + group srcDC[VSPhere] + group agent(cloud)[Agent VM] in srcDC + service agentd(server)[Agent] in agent + + + group amservice(cloud)[Assisted Migration Service] + service amserviced(server)[AMService] in amservice + service db1(database)[Database] in amservice + + group targetcluster[Target Cluster] + + group mta(server)[MTA] in targetcluster + service mtaAPI[migration CRD] in mta +``` + + +```mermaid +architecture-beta + + MA[mtv-init Service] + MA --> MB[HTTP API: /, /upload, /vmware, /vmware/done] + + MB --> MC[vddk-task Job] + MC --> MD[Download vddk.tar.gz] + MC --> ME[Trigger vddk build config
to build image] + + ME --> MF[vddk build config] + + MC --> MG[Update MTV Operator Resource
with vddk Image URL] + MG --> MH[mtv-operator Resource] +``` diff --git a/migration-cluster-day2/charts/migration-cluster-day2/.helmignore b/migration-cluster-day2/charts/migration-cluster-day2/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/migration-cluster-day2/charts/migration-cluster-day2/Chart.yaml b/migration-cluster-day2/charts/migration-cluster-day2/Chart.yaml new file mode 100644 index 00000000..77b1c921 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: migration-cluster-day2 +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.14 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/migration-cluster-day2/charts/migration-cluster-day2/README.md b/migration-cluster-day2/charts/migration-cluster-day2/README.md new file mode 100644 index 00000000..3f8fa5d3 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/README.md @@ -0,0 +1,53 @@ +# Migration Cluster Day2 + +This repository is meant to provide the means for Day-2 operations on a target cluster for VM migrations. +It should be used in this milestone only. Next milestone we would like to push most of this functionality into MTV. + +Some or all the items here may end up as an integral part of MTV, and for the time being we will make all efforts +to automate and smooth the experience to the maximum we can. + +## Prerequisites +- Installed cluster + - 3 node baremetals that can run virtualization + - each node has extra disk or more for storage +- Operators + - OpenShift Virtualization + - OpenShift GitOps +- `oc` client installed + +## Install the ArgoCD application + +After ArgoCD (OpenShift GitOps) is ready, apply this manifest that will create the applications which will +be responsible for the Day-2: + +```console +oc create -f https://raw.githubusercontent.com/rgolangh/migration-cluster-day2/refs/heads/main/manifest.yaml +``` + +> [!Note] +> The argo application is referencing the HEAD of the main branch of the helm chart, and not a version, +> because it is quicker and easier to publish changes. when things get stable enough we will shall move to versions. + +Initialize the MTV provider + +Navigate to the mtv-init application route +```console +oc get route -n default mtv-init -o jsonpath={.status.ingress[0].host} +``` + +Fill in the details of form: +- vddk image: go and download the vddk.tar.gz from broadcom site. The link is part of the form +- vcenter username: use the admin username, or a user which is the most credentials you can get +- vcenter password +- vcenter url: the url of vcenter, no need to add /sdk in the end + +When the form is submitted, follow the job in the default namespace that creates the vddk image and updates the existing +vmware-credentials + +Check the vmware provider status, if it is ready we can start migrating VMs + + + + + + diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/NOTES.txt b/migration-cluster-day2/charts/migration-cluster-day2/templates/NOTES.txt new file mode 100644 index 00000000..ff62b00c --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/NOTES.txt @@ -0,0 +1,31 @@ +======================================================================= +🚀 Thank you for installing {{ .Chart.Name }}! + +To verify the status of each operator, use the following commands: + +- MTV operator + oc get forkliftcontroller -n {{ .Values.mtvOperator.subscription.namespace }} + +- MTV Init + A helper service to help configure MTV for vmware providers + + oc get deployment mtv-init -n {{ .Values.mtvOperator.subscription.namespace }} + oc get route mtv-init -n {{ .Values.mtvOperator.subscription.namespace }} + +- NMState operator + A Red Hat operator to declare and define L2 networks on the cluster + TODO + +- LVM Storage operator + A Red Hat operator to dynamically provide storage for pods/VMs using LVM + + oc get lvmcluster -n openshift-storage + +- (future) NHC operator + Node Health Check - a Red Hat opeartor to fence and remediate workloads + TODO + +- (future) SNR opeartor + Self Node Remediation - a Red Hat operator that implements the remediation contract - works with NHC + TODO +======================================================================= diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/_helpers.tpl b/migration-cluster-day2/charts/migration-cluster-day2/templates/_helpers.tpl new file mode 100644 index 00000000..065a8eac --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "migration-cluster-day2.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "migration-cluster-day2.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "migration-cluster-day2.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "migration-cluster-day2.labels" -}} +helm.sh/chart: {{ include "migration-cluster-day2.chart" . }} +{{ include "migration-cluster-day2.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "migration-cluster-day2.selectorLabels" -}} +app.kubernetes.io/name: {{ include "migration-cluster-day2.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "migration-cluster-day2.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "migration-cluster-day2.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/image-registry.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/image-registry.yaml new file mode 100644 index 00000000..b11bb758 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/image-registry.yaml @@ -0,0 +1,91 @@ +--- +# Cluster Role for the installer +apiVersion: v1 +kind: ServiceAccount +metadata: + name: migration-cluster-day2-installer + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: migration-cluster-day2-installer + annotations: + argocd.argoproj.io/sync-wave: "1" +rules: + - apiGroups: ["imageregistry.operator.openshift.io"] + resources: ["configs"] + verbs: ["create","get", "update", "patch", "list", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: migration-cluster-day2-installer-binding + annotations: + argocd.argoproj.io/sync-wave: "1" +subjects: + - kind: ServiceAccount + name: migration-cluster-day2-installer + namespace: {{ .Values.mtvOperator.subscription.namespace }} +roleRef: + kind: ClusterRole + name: migration-cluster-day2-installer + apiGroup: rbac.authorization.k8s.io +--- + +--- +# pvc for the image registry for RWO - used with LVM storage backend +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: image-registry-storage + namespace: openshift-image-registry + labels: {{ include "migration-cluster-day2.labels" . | nindent 4 }} + annotations: + argocd.argoproj.io/sync-wave: "5" +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + # we require the image registry for building the vddk image, we don't need more than + # 50Gi at the moment + storage: 40Gi + + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: image-registry-config + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "2" +spec: + parallelism: 1 + completions: 1 + activeDeadlineSeconds: 604800 + backoffLimit: 6 + template: + metadata: + name: image-registry-tasks + spec: + serviceAccountName: migration-cluster-day2-installer + containers: + - name: image-registry-tasks + image: registry.access.redhat.com/ubi9/ubi-minimal + command: ["/bin/bash", "-c"] + args: + - | + set -o errexit + set -x + + curl -O downloads.openshift-console.svc.cluster.local/amd64/linux/oc.tar + microdnf install -y tar + tar -xvf oc.tar && chmod +x oc + + ./oc patch configs.imageregistry.operator.openshift.io/cluster --type=merge -p '{"spec":{"rolloutStrategy":"Recreate", "replicas": 1, "managementState": "Managed", "storage":{"pvc":{"claim":"image-registry-storage"}}}}' + restartPolicy: OnFailure +# diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/lvm-storage-operator.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/lvm-storage-operator.yaml new file mode 100644 index 00000000..8640a2a3 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/lvm-storage-operator.yaml @@ -0,0 +1,83 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.lvmsOperator.subscription.namespace }} + # prevent the namespace deletion because in some sceneraious the namespace + # is not removed and stays in terminating state. + annotations: + argocd.argoproj.io/sync-wave: "-1" + labels: + argocd.argoproj.io/managed-by: openshift-gitops +--- +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: lvm-storage-operator-group + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + labels: {{ include "migration-cluster-day2.labels" . | nindent 4 }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + targetNamespaces: + - {{ .Values.lvmsOperator.subscription.namespace }} +--- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: lvm-storage-operator + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + labels: {{ include "migration-cluster-day2.labels" . | nindent 4 }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + channel: {{ .Values.lvmsOperator.subscription.channel }} + installPlanApproval: Automatic + name: lvms-operator + source: redhat-operators + sourceNamespace: openshift-marketplace +--- + +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + annotations: + description: Provides RWO and RWOP Filesystem & Block volumes + argocd.argoproj.io/sync-wave: "1" + storageclass.kubernetes.io/is-default-class: "true" + labels: + owned-by.topolvm.io/group: lvm.topolvm.io + owned-by.topolvm.io/kind: LVMCluster + {{ include "migration-cluster-day2.labels" . | nindent 4 }} + name: lvms-vg1-1 +parameters: + csi.storage.k8s.io/fstype: xfs + topolvm.io/device-class: vg1 +provisioner: topolvm.io +reclaimPolicy: Delete +volumeBindingMode: WaitForFirstConsumer + +--- +apiVersion: lvm.topolvm.io/v1alpha1 +kind: LVMCluster +metadata: + annotations: + argocd.argoproj.io/sync-wave: "2" + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + finalizers: + - lvmcluster.topolvm.io + generation: 1 + name: lvmcluster + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + labels: {{ include "migration-cluster-day2.labels" . | nindent 4 }} +spec: + storage: + deviceClasses: + - fstype: xfs + name: vg1 + thinPoolConfig: + chunkSizeCalculationPolicy: Static + name: thin-pool-1 + overprovisionRatio: 10 + sizePercent: 90 diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-init.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-init.yaml new file mode 100644 index 00000000..91157bf4 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-init.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: mtv-init + name: mtv-init + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + replicas: 1 + selector: + matchLabels: + app: mtv-init + template: + metadata: + creationTimestamp: null + labels: + app: mtv-init + spec: + containers: + - image: quay.io/rgolangh/mtv-init + name: mtv-init + ports: + - containerPort: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: mtv-init + name: mtv-init + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + ports: + - name: 80-8080 + port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: mtv-init + type: ClusterIP +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: mtv-init + namespace: {{ .Values.mtvOperator.subscription.namespace }} + labels: + app: mtv-init + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + tls: + termination: edge + port: + targetPort: 8080 + to: + kind: "Service" + name: mtv-init + weight: null + diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-operator.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-operator.yaml new file mode 100644 index 00000000..4f8f89e7 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/mtv-operator.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.mtvOperator.subscription.namespace }} + # prevent the namespace deletion because in some sceneraious the namespace + # is not removed and stays in terminating state. + annotations: + argocd.argoproj.io/sync-wave: "-1" + labels: + argocd.argoproj.io/managed-by: openshift-gitops +--- +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: migration + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + targetNamespaces: + - {{ .Values.mtvOperator.subscription.namespace }} +--- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: mtv-operator + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + channel: {{ .Values.mtvOperator.subscription.channel }} + installPlanApproval: Automatic + name: mtv-operator + source: redhat-operators + sourceNamespace: openshift-marketplace +--- +apiVersion: forklift.konveyor.io/v1beta1 +kind: ForkliftController +metadata: + name: forklift-controller + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "2" + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + feature_ui_plugin: "true" + feature_validation: "true" + feature_volume_populator: "true" +--- +apiVersion: v1 +kind: Secret +metadata: + name: vmware-credentials + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "2" +--- + diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/nmstate-operator.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/nmstate-operator.yaml new file mode 100644 index 00000000..ef322e5d --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/nmstate-operator.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.nmstateOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "-1" + labels: + argocd.argoproj.io/managed-by: openshift-gitops +--- +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: nmstate-operator-group + namespace: {{ .Values.nmstateOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + targetNamespaces: + - {{ .Values.nmstateOperator.subscription.namespace }} +--- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: nmstate-operator + namespace: {{ .Values.nmstateOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + channel: {{ .Values.nmstateOperator.subscription.channel }} + installPlanApproval: Automatic + name: kubernetes-nmstate-operator + source: redhat-operators + sourceNamespace: openshift-marketplace +--- diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/serviceaccount.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/serviceaccount.yaml new file mode 100644 index 00000000..87601538 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/serviceaccount.yaml @@ -0,0 +1,107 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: migration-cluster-day2-installer + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + securitycontextconstraints.security.openshift.io: anyuid + argocd.argoproj.io/sync-wave: "1" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: migration-cluster-day2-installer + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +rules: + - apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: + - anyuid + verbs: ["use"] + - apiGroups: ["forklift.konveyor.io"] + resources: ["providers"] + verbs: ["get", "update", "patch", "list", "delete"] + + - apiGroups: ["operators.coreos.com"] + resources: ["clusterserviceversions"] + verbs: ["get", "update", "patch", "list", "delete"] + + - apiGroups: ["lvm.topolvm.io"] + resources: ["lvmclusters"] + verbs: ["get", "update", "patch", "list", "delete"] + + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: migration-cluster-day2-installer-binding + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +subjects: + - kind: ServiceAccount + name: migration-cluster-day2-installer + namespace: {{ .Values.mtvOperator.subscription.namespace }} +roleRef: + kind: Role + name: migration-cluster-day2-installer + apiGroup: rbac.authorization.k8s.io +--- + +--- +# LVM Storage SA +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: migration-cluster-day2-installer + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + annotations: + securitycontextconstraints.security.openshift.io: anyuid + argocd.argoproj.io/sync-wave: "1" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: migration-cluster-day2-installer + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +rules: + - apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: + - anyuid + verbs: ["use"] + + - apiGroups: ["operators.coreos.com"] + resources: ["clusterserviceversions"] + verbs: ["get", "update", "patch", "list", "delete"] + + - apiGroups: ["lvm.topolvm.io"] + resources: ["lvmclusters"] + verbs: ["get", "update", "patch", "list", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: migration-cluster-day2-installer-binding + namespace: {{ .Values.lvmsOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +subjects: + - kind: ServiceAccount + name: migration-cluster-day2-installer + namespace: {{ .Values.lvmsOperator.subscription.namespace }} +roleRef: + kind: Role + name: migration-cluster-day2-installer + apiGroup: rbac.authorization.k8s.io +--- + diff --git a/migration-cluster-day2/charts/migration-cluster-day2/templates/vddk.yaml b/migration-cluster-day2/charts/migration-cluster-day2/templates/vddk.yaml new file mode 100644 index 00000000..d0d9e124 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/templates/vddk.yaml @@ -0,0 +1,161 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: mtv-initiator + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + securitycontextconstraints.security.openshift.io: anyuid + argocd.argoproj.io/sync-wave: "1" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: mtv-initiator + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +rules: + - apiGroups: ["build.openshift.io"] + resources: ["builds", "buildconfigs", "buildconfigs/instantiate"] + verbs: ["create", "get", "list", "watch", "update"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["create", "get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets", "configmaps"] + verbs: ["get", "update", "patch", "list"] + - apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: + - anyuid + verbs: ["use"] + - apiGroups: ["forklift.konveyor.io"] + resources: ["providers"] + verbs: ["create", "get", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: mtv-initiator-binding + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +subjects: + - kind: ServiceAccount + name: mtv-initiator + namespace: {{ .Values.mtvOperator.subscription.namespace }} +roleRef: + kind: Role + name: mtv-initiator + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: build.openshift.io/v1 +kind: BuildConfig +metadata: + name: vddk + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + strategy: + dockerStrategy: {} + output: + to: + kind: ImageStreamTag + name: "vddk:latest" + source: + dockerfile: | + FROM registry.access.redhat.com/ubi9/ubi-minimal + ADD http://mtv-init.{{ .Values.mtvOperator.subscription.namespace }}/vmware/vddk.tar.gz /vddk.tar.gz + RUN microdnf install -y tar gzip file + RUN tar -zxvf /vddk.tar.gz + ENTRYPOINT ["cp", "-r", "/vmware-vix-disklib-distrib", "/opt"] +--- +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + name: vddk + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "1" +spec: + lookupPolicy: + local: true + tags: + - importPolicy: + importMode: Legacy + name: latest + referencePolicy: + type: Source +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: mtv-deps + namespace: {{ .Values.mtvOperator.subscription.namespace }} + annotations: + argocd.argoproj.io/sync-wave: "50" +spec: + parallelism: 1 + completions: 1 + activeDeadlineSeconds: 604800 + backoffLimit: 6 + template: + metadata: + name: vddk-tasks + annotations: + openshift.io/required-scc: "anyuid" + spec: + serviceAccountName: mtv-initiator + # securityContext: + # runAsUser: 0 + containers: + - name: vddk-tasks + image: registry.access.redhat.com/ubi9/ubi-minimal + # securityContext: + # runAsUser: 0 + command: ["/bin/bash", "-c"] + args: + - | + + set -o errexit + set -x + + echo ⌛ Waiting for the user to complete the survey at https://mtv-init-{{ .Values.mtvOperator.subscription.namespace }}.apps.clusterName.clusterDomeain + until $(curl --fail --silent mtv-init.{{ .Values.mtvOperator.subscription.namespace }}/vmware/done); do + sleep 5 + done + + curl -O downloads.openshift-console.svc.cluster.local/amd64/linux/oc.tar + microdnf install -y tar + tar -xvf oc.tar && chmod +x oc + + # start the build of vddk + ./oc start-build vddk + + # update the vmware-credentials secret + source <(curl -o - mtv-init.{{ .Values.mtvOperator.subscription.namespace }}/vmware/env) + ./oc set data secret/vmware-credentials user="$username" password="$password" insecureSkipVerify="true" + # update url in vsphere provider + + ./oc create -f - << EOF + apiVersion: forklift.konveyor.io/v1beta1 + kind: Provider + metadata: + labels: + app: mtv + name: vmware-provider + namespace: openshift-mtv + spec: + type: vsphere + url: "$url" + secret: + name: vmware-credentials + namespace: openshift-mtv + settings: + vddkInitImage: image-registry.openshift-image-registry.svc:5000/openshift-mtv/vddk:latest + EOF + + restartPolicy: OnFailure +#... diff --git a/migration-cluster-day2/charts/migration-cluster-day2/values.yaml b/migration-cluster-day2/charts/migration-cluster-day2/values.yaml new file mode 100644 index 00000000..837eed78 --- /dev/null +++ b/migration-cluster-day2/charts/migration-cluster-day2/values.yaml @@ -0,0 +1,19 @@ +mtvOperator: + subscription: + namespace: openshift-mtv + channel: release-v2.7 # the recent z version is 2.6.7 + installPlanApproval: Automatic # whether the update should be installed automatically + source: redhat-operators # name of the catalog source +nmstateOperator: + subscription: + namespace: openshift-nmstate + channel: stable + installPlanApproval: Automatic # whether the update should be installed automatically + source: redhat-operators # name of the catalog source +lvmsOperator: + subscription: + namespace: openshift-storage + channel: stable-4.16 + installPlanApproval: Automatic # whether the update should be installed automatically + source: redhat-operators # name of the catalog source + diff --git a/migration-cluster-day2/manifest.yaml b/migration-cluster-day2/manifest.yaml new file mode 100644 index 00000000..39b64671 --- /dev/null +++ b/migration-cluster-day2/manifest.yaml @@ -0,0 +1,24 @@ +--- +# The ArgoCD application that points to the chart code in this repo. +# Reminder: ArgoCD uses the helm format only for variable substitution, and +# applies the manifests with its own order and control, wihich is far better. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: mig + namespace: openshift-gitops +spec: + destination: + namespace: default + server: https://kubernetes.default.svc + project: default + source: + path: migration-cluster-day2/charts/migration-cluster-day2 + repoURL: https://github.com/kubev2v/migration-planner + targetRevision: main + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - Validate=false diff --git a/migration-cluster-day2/mtv-init/Containerfile b/migration-cluster-day2/mtv-init/Containerfile new file mode 100644 index 00000000..25fd2f22 --- /dev/null +++ b/migration-cluster-day2/mtv-init/Containerfile @@ -0,0 +1,8 @@ +FROM registry.access.redhat.com/ubi9/ubi-minimal as builder +RUN microdnf install -y go-toolset jq +COPY . . +RUN go build -o /usr/local/bin/migration-helper + +FROM registry.access.redhat.com/ubi9/ubi-micro +COPY --from=builder /usr/local/bin/migration-helper /usr/local/bin/migration-helper +ENTRYPOINT migration-helper diff --git a/migration-cluster-day2/mtv-init/Makefile b/migration-cluster-day2/mtv-init/Makefile new file mode 100644 index 00000000..63a622fa --- /dev/null +++ b/migration-cluster-day2/mtv-init/Makefile @@ -0,0 +1,2 @@ +build-image: + podman build . -t quay.io/rgolangh/mtv-init diff --git a/migration-cluster-day2/mtv-init/go.mod b/migration-cluster-day2/mtv-init/go.mod new file mode 100644 index 00000000..3c75bd7b --- /dev/null +++ b/migration-cluster-day2/mtv-init/go.mod @@ -0,0 +1,3 @@ +module kubev2v/migration-planner/init-service + +go 1.21 diff --git a/migration-cluster-day2/mtv-init/index.html b/migration-cluster-day2/mtv-init/index.html new file mode 100644 index 00000000..3e703152 --- /dev/null +++ b/migration-cluster-day2/mtv-init/index.html @@ -0,0 +1,125 @@ + + + + + + + + + + + + +
+ + + + +
+ +
+
+
+

Create Source Provider

+
+
+ + + + Download the vddk file from VMWare + TODO - If the vddk image already exists in the internal registry then propose to skip or totally hide this section. +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + + +
+ +
+
+
+
+
+ + + diff --git a/migration-cluster-day2/mtv-init/main.go b/migration-cluster-day2/mtv-init/main.go new file mode 100644 index 00000000..ddd27fd6 --- /dev/null +++ b/migration-cluster-day2/mtv-init/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "errors" + _ "embed" + "fmt" + "html/template" + "io" + "net/http" + "os" + "path" + "strings" +) + +const savePath = "/tmp/vmware" + +func main() { + http.HandleFunc("/", bootstrapHandler) + http.HandleFunc("/migrations/bootstrap", bootstrapHandler) + http.HandleFunc("/upload", uploadHandler) + err := os.Mkdir(savePath, os.ModePerm) + if err != nil && !errors.Is(err, os.ErrExist){ + panic(err) + } + http.Handle("/vmware/", http.StripPrefix("/vmware/",http.FileServer(http.Dir(savePath)))) + fmt.Println("Starting server on :8080...") + http.ListenAndServe(":8080", nil) +} + +func bootstrapHandler(w http.ResponseWriter, r *http.Request) { + tmpl, err := template.New("form").Parse(indexhtml) + if err != nil { + http.Error(w, "Unable to load form", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "text/html") + tmpl.Execute(w, nil) +} + +func uploadHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + return + } + + // Parse the multipart form + err := r.ParseMultipartForm(10 << 20) // Max file size 10 MB + if err != nil { + http.Error(w, "Error parsing form", http.StatusInternalServerError) + return + } + + // Retrieve file and other form data + file, _, err := r.FormFile("vddk") + if err != nil { + http.Error(w, "Error retrieving file", http.StatusInternalServerError) + return + } + defer file.Close() + + target, err := os.Create(path.Join(savePath,"vddk.tar.gz")) + if err != nil { + http.Error(w, "Error creating destination file", http.StatusInternalServerError) + return + } + defer target.Close() + + _, err = io.Copy(target, file) + if err != nil { + http.Error(w, "Error writing destination file", http.StatusInternalServerError) + return + } + + envFile, err := os.Create(path.Join(savePath,"env")) + if err != nil { + http.Error(w, "Error creating destination file", http.StatusInternalServerError) + return + } + defer envFile.Close() + + j := fmt.Sprintf("url=%s\nusername=%s\npassword=%s\n", + r.FormValue("url"), + r.FormValue("username"), + r.FormValue("password")) + _, err = io.Copy(envFile, strings.NewReader(j)) + if err != nil { + http.Error(w, "Error writing destination env file", http.StatusInternalServerError) + return + } + + err = os.WriteFile(path.Join(savePath, "done"), nil, os.ModePerm) + if err != nil { + http.Error(w, "Error writing done file", http.StatusInternalServerError) + return + } + // For now, just return a simple confirmatio + fmt.Fprintf(w, "vddk.tar.gz and vmware credentials recieved and avaiable under /vmware\n") +} + +//go:embed index.html +var indexhtml string