From 6a3fc83246aa59eb531a59915307f34ea1c271c3 Mon Sep 17 00:00:00 2001 From: grodionov Date: Tue, 3 Feb 2026 14:13:51 +0300 Subject: [PATCH] =?UTF-8?q?doc:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BF=D0=BE=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8E=20=D0=B2=D0=BC=20?= =?UTF-8?q?=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20tf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simpleVm/.gitignore | 36 +++++++++ simpleVm/README.md | 120 ++++++++++++++++++++++++++++++ simpleVm/local.tf | 39 ++++++++++ simpleVm/provider.tf | 37 +++++++++ simpleVm/templates/cloudinit.yaml | 22 ++++++ simpleVm/terraform.tfvars | 39 ++++++++++ simpleVm/tools.tf | 5 ++ simpleVm/vapp.tf | 19 +++++ simpleVm/var.tf | 42 +++++++++++ simpleVm/vm.tf | 84 +++++++++++++++++++++ simpleVm/vm/.gitignore | 36 +++++++++ simpleVm/vm/README.md | 120 ++++++++++++++++++++++++++++++ simpleVm/vm/local.tf | 39 ++++++++++ simpleVm/vm/provider.tf | 37 +++++++++ simpleVm/vm/terraform.tfvars | 39 ++++++++++ simpleVm/vm/tools.tf | 5 ++ simpleVm/vm/vapp.tf | 19 +++++ simpleVm/vm/var.tf | 42 +++++++++++ simpleVm/vm/vm.tf | 84 +++++++++++++++++++++ 19 files changed, 864 insertions(+) create mode 100644 simpleVm/.gitignore create mode 100644 simpleVm/README.md create mode 100644 simpleVm/local.tf create mode 100644 simpleVm/provider.tf create mode 100644 simpleVm/templates/cloudinit.yaml create mode 100644 simpleVm/terraform.tfvars create mode 100644 simpleVm/tools.tf create mode 100644 simpleVm/vapp.tf create mode 100644 simpleVm/var.tf create mode 100644 simpleVm/vm.tf create mode 100644 simpleVm/vm/.gitignore create mode 100644 simpleVm/vm/README.md create mode 100644 simpleVm/vm/local.tf create mode 100644 simpleVm/vm/provider.tf create mode 100644 simpleVm/vm/terraform.tfvars create mode 100644 simpleVm/vm/tools.tf create mode 100644 simpleVm/vm/vapp.tf create mode 100644 simpleVm/vm/var.tf create mode 100644 simpleVm/vm/vm.tf diff --git a/simpleVm/.gitignore b/simpleVm/.gitignore new file mode 100644 index 0000000..bcd4e3c --- /dev/null +++ b/simpleVm/.gitignore @@ -0,0 +1,36 @@ +# ---> Terraform +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +# *.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl \ No newline at end of file diff --git a/simpleVm/README.md b/simpleVm/README.md new file mode 100644 index 0000000..410ffd8 --- /dev/null +++ b/simpleVm/README.md @@ -0,0 +1,120 @@ +# Развёртывание ВМ в VMware Cloud Director через tf + +Используется **OpenTofu** (`tofu`). Конфигурация создаёт виртуальные машины в vCD: можно задать несколько ВМ, размеры CPU/RAM/дисков и сеть. + +--- + +## Быстрый старт + +1. **Установите OpenTofu** ([opentofu.org](https://opentofu.org)). + +2. **Задайте переменные окружения** (доступ к vCD): + ```bash + export TF_VAR_vmware_username="ваш_пользователь_vCD" + export TF_VAR_vmware_password="ваш_пароль_vCD" + ``` + Пароль администратора ВМ можно не задавать — тогда он сгенерируется автоматически (см. `tools.tf`). Чтобы задать свой: `export TF_VAR_admin_password="ваш_пароль"`. + +3. **Отредактируйте `terraform.tfvars`** — укажите нужный vDC, имя vApp, параметры ВМ (см. раздел «Конфигурация» ниже). + +4. **Разверните инфраструктуру:** + ```bash + tofu init + tofu plan + tofu apply + ``` + +--- + +## Конфигурация + +### Переменные окружения + +Обязательные для доступа к vCD: + +- `TF_VAR_vmware_username` — пользователь VMware Cloud Director +- `TF_VAR_vmware_password` — пароль VMware Cloud Director + +Опционально: `TF_VAR_admin_password` — пароль администратора на ВМ (если не задан, генерируется автоматически). + +``` +vcds = { + "vdcconfiguration1" = { + url = "https://ngcloud.ru/api" + org = "dev" + vdc = "dev" + network_routed = "dev-mgmt-network" + servers = { + "vappname01" = { + "vmname01" = { + cpu = "4" + memory = "4096" + osDisk = "16384" + dataDisk = { + "1" = "30720" + "2" = "15360" + } + network = { + mode = "auto" + ip = "" + } + catalog_name = "dev" + template_name = "RockyLinux_9-16G-customize" + } + } + } + } +} +``` +Переменная задаётся в `terraform.tfvars`; схема — в [var.tf](var.tf), использование — [provider.tf](provider.tf), [vapp.tf](vapp.tf), [vm.tf](vm.tf), [local.tf](local.tf). + +*** Ключ vcds — произвольное имя контура (можно несколько vDC в одной конфигурации) *** +``` +vcds = { + "test" = { + ... + } +} +``` + +*** Настройка vDC *** +``` + url = URL API Cloud Director (https://<хост>/api) + org = имя организации + vdc = имя vDC + network_routed = имя routed-сети, куда подключаются ВМ +``` + +*** Настройка vApp (ключи внутри servers — имена vApp) *** +``` + servers = { + "testservers" = { ... } # первый vApp + "testvapp2" = { ... } # второй vApp + } +``` + +*** Настройка сервера (параметры ВМ) *** +``` +"testservers" = { + "test01" = { + cpu = кол-во ядер CPU + memory = объём RAM (МБ) + osDisk = размер системного диска (МБ) + dataDisk = { # ключ — unit, значение — размер в МБ + "1" = "30720" + "2" = "15360" + } + network = { # mode "auto" (IP из пула) или "manual" (указать ip) + mode = "auto" + ip = "" + } + network = mode "auto" (IP из пула) или "manual" (указать ip) + mode = "auto" + ip = "" + catalog_name = каталог с шаблоном + template_name = имя шаблона образа + # опционально (cloud-init): + init_username = "deploy" + ssh_authorized_keys = ["ssh-ed25519 AAAA..."] + } +``` diff --git a/simpleVm/local.tf b/simpleVm/local.tf new file mode 100644 index 0000000..a586f73 --- /dev/null +++ b/simpleVm/local.tf @@ -0,0 +1,39 @@ +locals { + ####################### + admin_password = var.admin_password != "" ? var.admin_password : random_password.admin_pass.result + ####################### + # Получаем объект с ключами в виде имен серверов и содержимым всего, + # что мы хотим видеть при передаче из vars + servers = merge([ + for vcd_key, vcd_config in var.vcds : + merge([ + for server_group, servers in vcd_config.servers : + { + for server_name, server_config in servers : + "${server_name}.${server_group}" => { + vcd_key = vcd_key + server_group = server_group + server_name = server_name + config = server_config + network_routed = vcd_config.network_routed + role = server_group + } + } + ]...) + ]...) + + # Получаем объект с ключами в виде сервера-uidдиска, + # и содержимым в виде его сайзинга + disks = merge([ + for serverName, serverConfig in local.servers: + { + for diskUid, diskSize in serverConfig.config.dataDisk: + "${serverName}-${diskUid}" => { + vcd_key = serverConfig.vcd_key + vm_name = serverName + unit_num = diskUid + disk_size = diskSize + } + } + ]...) +} \ No newline at end of file diff --git a/simpleVm/provider.tf b/simpleVm/provider.tf new file mode 100644 index 0000000..9cb905a --- /dev/null +++ b/simpleVm/provider.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + vcd = { + source = "vmware/vcd" + version = "3.14.1" + } + random = { + source = "hashicorp/random" + version = "3.5.1" + } + local = { + source = "hashicorp/local" + version = "2.5.1" + } + } +} + +# Почему такая конфигурация не будет работать +# https://github.com/hashicorp/terraform/issues/24476 +# +# Но решили тут +# https://github.com/opentofu/opentofu/issues/2123 + +provider "vcd" { + alias = "al" + for_each = var.vcds + + user = var.vmware_username + password = var.vmware_password + + org = each.value.org + vdc = each.value.vdc + url = each.value.url + + max_retry_timeout = "10" + allow_unverified_ssl = "true" +} \ No newline at end of file diff --git a/simpleVm/templates/cloudinit.yaml b/simpleVm/templates/cloudinit.yaml new file mode 100644 index 0000000..9c469e6 --- /dev/null +++ b/simpleVm/templates/cloudinit.yaml @@ -0,0 +1,22 @@ +#cloud-config +hostname: ${hostname} +package_update: true +package_upgrade: false +packages: + - curl + - git + - jq + +users: + - name: ${username} + sudo: "ALL=(ALL) NOPASSWD:ALL" + groups: "sudo" + shell: /bin/bash + ssh_authorized_keys: +%{ if length(ssh_authorized_keys) > 0 ~} +%{ for key in ssh_authorized_keys ~} + - ${key} +%{ endfor ~} +%{ else ~} + [] +%{ endif ~} diff --git a/simpleVm/terraform.tfvars b/simpleVm/terraform.tfvars new file mode 100644 index 0000000..c4a43ca --- /dev/null +++ b/simpleVm/terraform.tfvars @@ -0,0 +1,39 @@ +####################################################### +# Импортируемые переменные из TF_VAR +# vmware_username = "" +# vmware_password = "" + + +####################################################### + +vcds = { + "test" = { + url = "https://sandbox.nubes.ru/api" + org = "dev" + vdc = "dev" + network_routed = "dev-mgmt-network" + servers = { + "testservers" = { + "test01" = { + cpu = "1" + memory = "1024" + osDisk = "35000" + dataDisk = { + "1" = "10000" + "2" = "5480" + } + network = { + mode = "auto" + ip = "" + } + catalog_name = "dev" + template_name = "Ubuntu_24-20G" + init_username = "deploy" + ssh_authorized_keys = [ + "ssh-ed25519 *********" + ] + } + } + } + } +} \ No newline at end of file diff --git a/simpleVm/tools.tf b/simpleVm/tools.tf new file mode 100644 index 0000000..34a9a2f --- /dev/null +++ b/simpleVm/tools.tf @@ -0,0 +1,5 @@ +# Генерируем пароль для админского пользователя +resource "random_password" "admin_pass" { + length = 20 + special = false +} \ No newline at end of file diff --git a/simpleVm/vapp.tf b/simpleVm/vapp.tf new file mode 100644 index 0000000..2c19c4b --- /dev/null +++ b/simpleVm/vapp.tf @@ -0,0 +1,19 @@ +resource "vcd_vapp" "vapp" { + for_each = var.vcds + + provider = vcd.al[each.key] + + name = each.key + power_on = false +} + + +resource "vcd_vapp_org_network" "routed_network" { + for_each = vcd_vapp.vapp + + provider = vcd.al[each.key] + + vapp_name = each.value.name + org_network_name = var.vcds[each.key].network_routed + reboot_vapp_on_removal = true +} diff --git a/simpleVm/var.tf b/simpleVm/var.tf new file mode 100644 index 0000000..f756b1e --- /dev/null +++ b/simpleVm/var.tf @@ -0,0 +1,42 @@ +#################################################### +variable "vmware_username" { + type = string + default = "" +} +variable "vmware_password" { + type = string + default = "" +} + +#################################################### +# Пароль от ВМ (если пустой — подставляется сгенерированный из tools.tf) +variable "admin_password" { + type = string + default = "" +} + +#################################################### +variable "vcds" { + type = map(object({ + url = string + org = string + vdc = string + network_routed = string + servers = map(map(object({ + cpu = string + memory = string + osDisk = string + catalog_name = string + template_name = string + dataDisk = map(string) + network = object({ + mode = string + ip = string + }) + # cloud-init: пользователь и SSH-ключи (опционально) + init_username = optional(string, "deploy") + ssh_authorized_keys = optional(list(string), []) + }))) + })) +} +#################################################### diff --git a/simpleVm/vm.tf b/simpleVm/vm.tf new file mode 100644 index 0000000..e62d919 --- /dev/null +++ b/simpleVm/vm.tf @@ -0,0 +1,84 @@ +resource "vcd_vapp_vm" "vm" { + for_each = local.servers + + provider = vcd.al[each.value.vcd_key] + + vapp_name = vcd_vapp.vapp[each.value.vcd_key].name + name = each.key + computer_name = each.key + catalog_name = each.value.config["catalog_name"] + template_name = each.value.config["template_name"] + memory = each.value.config["memory"] + cpus = each.value.config["cpu"] + + network { + type = "org" + name = each.value.network_routed + ip_allocation_mode = lookup(each.value.config["network"], "mode", "auto") == "manual" ? "MANUAL" : "POOL" + is_primary = true + + # Устанавливаем IP, только если режим "manual" + ip = lookup(each.value.config["network"], "mode", "auto") == "manual" ? lookup(each.value.config["network"], "ip", null) : null + } + + override_template_disk { + bus_type = "paravirtual" + size_in_mb = each.value.config["osDisk"] + bus_number = 0 + unit_number = 0 + } + + customization { + enabled = true + #force = var.forceRecustomization || !contains(var.servers, var.servers[count.index]) + #force = var.forceRecustomization + force = false + allow_local_admin_password = true + auto_generate_password = false + admin_password = local.admin_password + } + + set_extra_config { + key = "disk.EnableUUID" + value = "TRUE" + } + + guest_properties = { + "user-data" = base64encode(templatefile("${path.module}/templates/cloudinit.yaml", { + hostname = each.key + username = each.value.config["init_username"] + ssh_authorized_keys = each.value.config["ssh_authorized_keys"] + })) + } + + # Игноирование изменений дисков (PVC - Named Disks) + lifecycle { + ignore_changes = [ + disk, # Игнорирует изменения всех дисков + ] + } + + depends_on = [ + vcd_vapp_org_network.routed_network + ] +} + +resource "vcd_vm_internal_disk" "vmdisk" { + for_each = local.disks + + provider = vcd.al[each.value.vcd_key] + + vapp_name = vcd_vapp.vapp[each.value.vcd_key].name + vm_name = each.value.vm_name + + bus_type = "paravirtual" + bus_number = 0 + unit_number = each.value.unit_num + size_in_mb = each.value.disk_size + + allow_vm_reboot = true + + depends_on = [ + vcd_vapp_vm.vm + ] +} diff --git a/simpleVm/vm/.gitignore b/simpleVm/vm/.gitignore new file mode 100644 index 0000000..bcd4e3c --- /dev/null +++ b/simpleVm/vm/.gitignore @@ -0,0 +1,36 @@ +# ---> Terraform +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +# *.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl \ No newline at end of file diff --git a/simpleVm/vm/README.md b/simpleVm/vm/README.md new file mode 100644 index 0000000..410ffd8 --- /dev/null +++ b/simpleVm/vm/README.md @@ -0,0 +1,120 @@ +# Развёртывание ВМ в VMware Cloud Director через tf + +Используется **OpenTofu** (`tofu`). Конфигурация создаёт виртуальные машины в vCD: можно задать несколько ВМ, размеры CPU/RAM/дисков и сеть. + +--- + +## Быстрый старт + +1. **Установите OpenTofu** ([opentofu.org](https://opentofu.org)). + +2. **Задайте переменные окружения** (доступ к vCD): + ```bash + export TF_VAR_vmware_username="ваш_пользователь_vCD" + export TF_VAR_vmware_password="ваш_пароль_vCD" + ``` + Пароль администратора ВМ можно не задавать — тогда он сгенерируется автоматически (см. `tools.tf`). Чтобы задать свой: `export TF_VAR_admin_password="ваш_пароль"`. + +3. **Отредактируйте `terraform.tfvars`** — укажите нужный vDC, имя vApp, параметры ВМ (см. раздел «Конфигурация» ниже). + +4. **Разверните инфраструктуру:** + ```bash + tofu init + tofu plan + tofu apply + ``` + +--- + +## Конфигурация + +### Переменные окружения + +Обязательные для доступа к vCD: + +- `TF_VAR_vmware_username` — пользователь VMware Cloud Director +- `TF_VAR_vmware_password` — пароль VMware Cloud Director + +Опционально: `TF_VAR_admin_password` — пароль администратора на ВМ (если не задан, генерируется автоматически). + +``` +vcds = { + "vdcconfiguration1" = { + url = "https://ngcloud.ru/api" + org = "dev" + vdc = "dev" + network_routed = "dev-mgmt-network" + servers = { + "vappname01" = { + "vmname01" = { + cpu = "4" + memory = "4096" + osDisk = "16384" + dataDisk = { + "1" = "30720" + "2" = "15360" + } + network = { + mode = "auto" + ip = "" + } + catalog_name = "dev" + template_name = "RockyLinux_9-16G-customize" + } + } + } + } +} +``` +Переменная задаётся в `terraform.tfvars`; схема — в [var.tf](var.tf), использование — [provider.tf](provider.tf), [vapp.tf](vapp.tf), [vm.tf](vm.tf), [local.tf](local.tf). + +*** Ключ vcds — произвольное имя контура (можно несколько vDC в одной конфигурации) *** +``` +vcds = { + "test" = { + ... + } +} +``` + +*** Настройка vDC *** +``` + url = URL API Cloud Director (https://<хост>/api) + org = имя организации + vdc = имя vDC + network_routed = имя routed-сети, куда подключаются ВМ +``` + +*** Настройка vApp (ключи внутри servers — имена vApp) *** +``` + servers = { + "testservers" = { ... } # первый vApp + "testvapp2" = { ... } # второй vApp + } +``` + +*** Настройка сервера (параметры ВМ) *** +``` +"testservers" = { + "test01" = { + cpu = кол-во ядер CPU + memory = объём RAM (МБ) + osDisk = размер системного диска (МБ) + dataDisk = { # ключ — unit, значение — размер в МБ + "1" = "30720" + "2" = "15360" + } + network = { # mode "auto" (IP из пула) или "manual" (указать ip) + mode = "auto" + ip = "" + } + network = mode "auto" (IP из пула) или "manual" (указать ip) + mode = "auto" + ip = "" + catalog_name = каталог с шаблоном + template_name = имя шаблона образа + # опционально (cloud-init): + init_username = "deploy" + ssh_authorized_keys = ["ssh-ed25519 AAAA..."] + } +``` diff --git a/simpleVm/vm/local.tf b/simpleVm/vm/local.tf new file mode 100644 index 0000000..a586f73 --- /dev/null +++ b/simpleVm/vm/local.tf @@ -0,0 +1,39 @@ +locals { + ####################### + admin_password = var.admin_password != "" ? var.admin_password : random_password.admin_pass.result + ####################### + # Получаем объект с ключами в виде имен серверов и содержимым всего, + # что мы хотим видеть при передаче из vars + servers = merge([ + for vcd_key, vcd_config in var.vcds : + merge([ + for server_group, servers in vcd_config.servers : + { + for server_name, server_config in servers : + "${server_name}.${server_group}" => { + vcd_key = vcd_key + server_group = server_group + server_name = server_name + config = server_config + network_routed = vcd_config.network_routed + role = server_group + } + } + ]...) + ]...) + + # Получаем объект с ключами в виде сервера-uidдиска, + # и содержимым в виде его сайзинга + disks = merge([ + for serverName, serverConfig in local.servers: + { + for diskUid, diskSize in serverConfig.config.dataDisk: + "${serverName}-${diskUid}" => { + vcd_key = serverConfig.vcd_key + vm_name = serverName + unit_num = diskUid + disk_size = diskSize + } + } + ]...) +} \ No newline at end of file diff --git a/simpleVm/vm/provider.tf b/simpleVm/vm/provider.tf new file mode 100644 index 0000000..9cb905a --- /dev/null +++ b/simpleVm/vm/provider.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + vcd = { + source = "vmware/vcd" + version = "3.14.1" + } + random = { + source = "hashicorp/random" + version = "3.5.1" + } + local = { + source = "hashicorp/local" + version = "2.5.1" + } + } +} + +# Почему такая конфигурация не будет работать +# https://github.com/hashicorp/terraform/issues/24476 +# +# Но решили тут +# https://github.com/opentofu/opentofu/issues/2123 + +provider "vcd" { + alias = "al" + for_each = var.vcds + + user = var.vmware_username + password = var.vmware_password + + org = each.value.org + vdc = each.value.vdc + url = each.value.url + + max_retry_timeout = "10" + allow_unverified_ssl = "true" +} \ No newline at end of file diff --git a/simpleVm/vm/terraform.tfvars b/simpleVm/vm/terraform.tfvars new file mode 100644 index 0000000..c4a43ca --- /dev/null +++ b/simpleVm/vm/terraform.tfvars @@ -0,0 +1,39 @@ +####################################################### +# Импортируемые переменные из TF_VAR +# vmware_username = "" +# vmware_password = "" + + +####################################################### + +vcds = { + "test" = { + url = "https://sandbox.nubes.ru/api" + org = "dev" + vdc = "dev" + network_routed = "dev-mgmt-network" + servers = { + "testservers" = { + "test01" = { + cpu = "1" + memory = "1024" + osDisk = "35000" + dataDisk = { + "1" = "10000" + "2" = "5480" + } + network = { + mode = "auto" + ip = "" + } + catalog_name = "dev" + template_name = "Ubuntu_24-20G" + init_username = "deploy" + ssh_authorized_keys = [ + "ssh-ed25519 *********" + ] + } + } + } + } +} \ No newline at end of file diff --git a/simpleVm/vm/tools.tf b/simpleVm/vm/tools.tf new file mode 100644 index 0000000..34a9a2f --- /dev/null +++ b/simpleVm/vm/tools.tf @@ -0,0 +1,5 @@ +# Генерируем пароль для админского пользователя +resource "random_password" "admin_pass" { + length = 20 + special = false +} \ No newline at end of file diff --git a/simpleVm/vm/vapp.tf b/simpleVm/vm/vapp.tf new file mode 100644 index 0000000..2c19c4b --- /dev/null +++ b/simpleVm/vm/vapp.tf @@ -0,0 +1,19 @@ +resource "vcd_vapp" "vapp" { + for_each = var.vcds + + provider = vcd.al[each.key] + + name = each.key + power_on = false +} + + +resource "vcd_vapp_org_network" "routed_network" { + for_each = vcd_vapp.vapp + + provider = vcd.al[each.key] + + vapp_name = each.value.name + org_network_name = var.vcds[each.key].network_routed + reboot_vapp_on_removal = true +} diff --git a/simpleVm/vm/var.tf b/simpleVm/vm/var.tf new file mode 100644 index 0000000..f756b1e --- /dev/null +++ b/simpleVm/vm/var.tf @@ -0,0 +1,42 @@ +#################################################### +variable "vmware_username" { + type = string + default = "" +} +variable "vmware_password" { + type = string + default = "" +} + +#################################################### +# Пароль от ВМ (если пустой — подставляется сгенерированный из tools.tf) +variable "admin_password" { + type = string + default = "" +} + +#################################################### +variable "vcds" { + type = map(object({ + url = string + org = string + vdc = string + network_routed = string + servers = map(map(object({ + cpu = string + memory = string + osDisk = string + catalog_name = string + template_name = string + dataDisk = map(string) + network = object({ + mode = string + ip = string + }) + # cloud-init: пользователь и SSH-ключи (опционально) + init_username = optional(string, "deploy") + ssh_authorized_keys = optional(list(string), []) + }))) + })) +} +#################################################### diff --git a/simpleVm/vm/vm.tf b/simpleVm/vm/vm.tf new file mode 100644 index 0000000..e62d919 --- /dev/null +++ b/simpleVm/vm/vm.tf @@ -0,0 +1,84 @@ +resource "vcd_vapp_vm" "vm" { + for_each = local.servers + + provider = vcd.al[each.value.vcd_key] + + vapp_name = vcd_vapp.vapp[each.value.vcd_key].name + name = each.key + computer_name = each.key + catalog_name = each.value.config["catalog_name"] + template_name = each.value.config["template_name"] + memory = each.value.config["memory"] + cpus = each.value.config["cpu"] + + network { + type = "org" + name = each.value.network_routed + ip_allocation_mode = lookup(each.value.config["network"], "mode", "auto") == "manual" ? "MANUAL" : "POOL" + is_primary = true + + # Устанавливаем IP, только если режим "manual" + ip = lookup(each.value.config["network"], "mode", "auto") == "manual" ? lookup(each.value.config["network"], "ip", null) : null + } + + override_template_disk { + bus_type = "paravirtual" + size_in_mb = each.value.config["osDisk"] + bus_number = 0 + unit_number = 0 + } + + customization { + enabled = true + #force = var.forceRecustomization || !contains(var.servers, var.servers[count.index]) + #force = var.forceRecustomization + force = false + allow_local_admin_password = true + auto_generate_password = false + admin_password = local.admin_password + } + + set_extra_config { + key = "disk.EnableUUID" + value = "TRUE" + } + + guest_properties = { + "user-data" = base64encode(templatefile("${path.module}/templates/cloudinit.yaml", { + hostname = each.key + username = each.value.config["init_username"] + ssh_authorized_keys = each.value.config["ssh_authorized_keys"] + })) + } + + # Игноирование изменений дисков (PVC - Named Disks) + lifecycle { + ignore_changes = [ + disk, # Игнорирует изменения всех дисков + ] + } + + depends_on = [ + vcd_vapp_org_network.routed_network + ] +} + +resource "vcd_vm_internal_disk" "vmdisk" { + for_each = local.disks + + provider = vcd.al[each.value.vcd_key] + + vapp_name = vcd_vapp.vapp[each.value.vcd_key].name + vm_name = each.value.vm_name + + bus_type = "paravirtual" + bus_number = 0 + unit_number = each.value.unit_num + size_in_mb = each.value.disk_size + + allow_vm_reboot = true + + depends_on = [ + vcd_vapp_vm.vm + ] +}