From 335757bf44c7ede72ab1dbd2fde802084734ac97 Mon Sep 17 00:00:00 2001 From: jez Date: Mon, 21 Mar 2022 23:27:54 -0400 Subject: [PATCH] Add: Initial code --- cloud_project/main.tf | 81 +++++ cloud_project/provider.tf | 0 iaas_inv_ansible/_OLD/example.inv.yml | 14 + iaas_inv_ansible/_OLD/inventory.tmpl | 6 + iaas_inv_ansible/_OLD/main.tf | 13 + iaas_inv_ansible/_OLD/tpl_example.tpl | 17 + iaas_inv_ansible/ansible_host/main.tf | 42 +++ iaas_inv_ansible/ansible_host/provider.tf | 9 + iaas_inv_ansible/main.tf | 34 ++ iaas_inv_ansible/provider.tf | 0 virt_cloudinit/main.tf | 89 +++++ virt_cloudinit/provider.tf | 8 + virt_flavor/main.tf | 93 ++++++ virt_flavor/provider.tf | 0 virt_images/main.tf | 54 +++ virt_images/provider.tf | 0 virt_instance/main.tf | 362 +++++++++++++++++++++ virt_instance/provider.tf | 12 + virt_instances/main.tf | 112 +++++++ virt_instances/provider.tf | 0 virt_namespace/main.tf | 147 +++++++++ virt_namespace/provider.tf | 0 virt_network/main.tf | 171 ++++++++++ virt_network/provider.tf | 12 + virt_network/templates/ferm_nat.tpl | 3 + virt_network/templates/ipvs_config.tpl | 8 + virt_networks/main.tf | 73 +++++ virt_networks/provider.tf | 0 virt_os/main.tf | 194 +++++++++++ virt_os/provider.tf | 0 virt_os/templates/cloud_debian_generic.yml | 57 ++++ virt_pools/main.tf | 55 ++++ virt_pools/provider.tf | 8 + virt_volume/main.tf | 262 +++++++++++++++ virt_volume/provider.tf | 10 + virt_volumes/main.tf | 74 +++++ virt_volumes/provider.tf | 0 37 files changed, 2020 insertions(+) create mode 100644 cloud_project/main.tf create mode 100644 cloud_project/provider.tf create mode 100644 iaas_inv_ansible/_OLD/example.inv.yml create mode 100644 iaas_inv_ansible/_OLD/inventory.tmpl create mode 100644 iaas_inv_ansible/_OLD/main.tf create mode 100644 iaas_inv_ansible/_OLD/tpl_example.tpl create mode 100644 iaas_inv_ansible/ansible_host/main.tf create mode 100644 iaas_inv_ansible/ansible_host/provider.tf create mode 100644 iaas_inv_ansible/main.tf create mode 100644 iaas_inv_ansible/provider.tf create mode 100644 virt_cloudinit/main.tf create mode 100644 virt_cloudinit/provider.tf create mode 100644 virt_flavor/main.tf create mode 100644 virt_flavor/provider.tf create mode 100644 virt_images/main.tf create mode 100644 virt_images/provider.tf create mode 100644 virt_instance/main.tf create mode 100644 virt_instance/provider.tf create mode 100644 virt_instances/main.tf create mode 100644 virt_instances/provider.tf create mode 100644 virt_namespace/main.tf create mode 100644 virt_namespace/provider.tf create mode 100644 virt_network/main.tf create mode 100644 virt_network/provider.tf create mode 100644 virt_network/templates/ferm_nat.tpl create mode 100644 virt_network/templates/ipvs_config.tpl create mode 100644 virt_networks/main.tf create mode 100644 virt_networks/provider.tf create mode 100644 virt_os/main.tf create mode 100644 virt_os/provider.tf create mode 100644 virt_os/templates/cloud_debian_generic.yml create mode 100644 virt_pools/main.tf create mode 100644 virt_pools/provider.tf create mode 100644 virt_volume/main.tf create mode 100644 virt_volume/provider.tf create mode 100644 virt_volumes/main.tf create mode 100644 virt_volumes/provider.tf diff --git a/cloud_project/main.tf b/cloud_project/main.tf new file mode 100644 index 0000000..07b567b --- /dev/null +++ b/cloud_project/main.tf @@ -0,0 +1,81 @@ + +# Variables +# ===================== + +variable "cloud" { + description = "Cloud informations" + type = any + default = {} +} + +variable "tenant" { + description = "Tenant informations" + type = any + default = {} +} + +variable "deploy" { + description = "Deployment options" + type = any + default = {} +} + +variable "stack" { + description = "Default stack" + type = any + default = {} +} + +variable "stacks" { + description = "Deployments configuration" + type = any + default = [] +} + + +# Resources +# ===================== + +locals { + + # Fetch stack name + stack_name = try( + var.deploy.stack, + "main" + ) + # Proceed to chained merges + stack = merge( + var.stack, + try( + var.stacks[local.stack_name], {} + ) + ) +} + +module "virt_namespace" { + source = "../virt_namespace" + + cloud = var.cloud + tenant = var.tenant + deploy = var.deploy + + stack = local.stack +} + +#module "iaas_inv_ansible" { +# source = "../iaas_inv_ansible" +# payload = var.config +#} + + + +# Output +# ===================== +output "namespace" { + value = module.virt_namespace +} +#output "iaas" { +# value = module.iaas_inv_ansible +#} + + diff --git a/cloud_project/provider.tf b/cloud_project/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/iaas_inv_ansible/_OLD/example.inv.yml b/iaas_inv_ansible/_OLD/example.inv.yml new file mode 100644 index 0000000..38b78d4 --- /dev/null +++ b/iaas_inv_ansible/_OLD/example.inv.yml @@ -0,0 +1,14 @@ +--- +terraform: + hosts: + mail.example.com: + children: + webservers: + hosts: + foo.example.com: + bar.example.com: + dbservers: + hosts: + one.example.com: + two.example.com: + three.example.com: diff --git a/iaas_inv_ansible/_OLD/inventory.tmpl b/iaas_inv_ansible/_OLD/inventory.tmpl new file mode 100644 index 0000000..1d7c6ab --- /dev/null +++ b/iaas_inv_ansible/_OLD/inventory.tmpl @@ -0,0 +1,6 @@ +${ ip_addrs } +%{ for addr in ip_addrs ~} +backend ${addr}:xx +%{ endfor ~} + + diff --git a/iaas_inv_ansible/_OLD/main.tf b/iaas_inv_ansible/_OLD/main.tf new file mode 100644 index 0000000..a6f3da7 --- /dev/null +++ b/iaas_inv_ansible/_OLD/main.tf @@ -0,0 +1,13 @@ +variable "payload" { + description = "Payload informations" + type = any + default = {} +} + +resource "local_file" "ansible_inventory" { + filename = "inventory.txt" + content = templatefile("${path.module}/inventory.tmpl", { ip_addrs = ["10.0.0.1", "10.0.0.2"] } + ) +} +# tutu = ["bli", "blaaah"] + #toto = "${var.payload}" diff --git a/iaas_inv_ansible/_OLD/tpl_example.tpl b/iaas_inv_ansible/_OLD/tpl_example.tpl new file mode 100644 index 0000000..bad3d4c --- /dev/null +++ b/iaas_inv_ansible/_OLD/tpl_example.tpl @@ -0,0 +1,17 @@ +[cfg] +%{ for index, group in ansible_group_cfg ~} +${ hostname_cfg[index] } ${ index == 0 ? "mongodb_primary=True" : "" } +%{ endfor ~} + +%{ for shard_index in number_of_shards ~} +[shard${shard_index}] +%{ for index, group in ansible_group_shards ~} +${ group == tostring(shard_index) && ansible_group_index[index] == "0" ? join(" ", [ hostname_shards[index], "mongodb_primary=True\n" ]) : "" ~} +${ group == tostring(shard_index) && ansible_group_index[index] != "0" ? join("", [ hostname_shards[index], "\n" ]) : "" ~} +%{ endfor ~} +%{ endfor ~} + +[mongos] +%{ for index, group in ansible_group_mongos ~} +${hostname_mongos[index]} +%{ endfor ~} diff --git a/iaas_inv_ansible/ansible_host/main.tf b/iaas_inv_ansible/ansible_host/main.tf new file mode 100644 index 0000000..28c2236 --- /dev/null +++ b/iaas_inv_ansible/ansible_host/main.tf @@ -0,0 +1,42 @@ + +#variable "hostname" { +# description = "hostname" +# type = any +# default = {} +#} +#variable "groups" { +# description = "groups" +# type = any +# default = {} +#} +#variable "vars" { +# description = "Variables" +# type = any +# default = {} +#} + +resource "ansible_host" "example2" { + inventory_hostname = "www.example.com" + groups = ["web"] + vars = { + foo = "bar" + } +} + + +resource "ansible_host" "example" { + inventory_hostname = "example.com" + groups = ["web"] + vars = { + ansible_user = "admin" + } +} + +resource "ansible_group" "web" { + inventory_group_name = "web" + children = ["foo", "bar", "baz"] + vars = { + foo = "bar" + bar = 2 + } +} diff --git a/iaas_inv_ansible/ansible_host/provider.tf b/iaas_inv_ansible/ansible_host/provider.tf new file mode 100644 index 0000000..45b51b8 --- /dev/null +++ b/iaas_inv_ansible/ansible_host/provider.tf @@ -0,0 +1,9 @@ + +terraform { + required_providers { + ansible = { + source = "nbering/ansible" + version = "1.0.4" + } + } +} diff --git a/iaas_inv_ansible/main.tf b/iaas_inv_ansible/main.tf new file mode 100644 index 0000000..17ca06a --- /dev/null +++ b/iaas_inv_ansible/main.tf @@ -0,0 +1,34 @@ + +variable "payload" { + description = "Instance description" + type = any + default = {} +} + + +resource "ansible_host" "example2" { + inventory_hostname = "www.example.com" + groups = ["web"] + vars = { + foo = "bar" + } +} + + +resource "ansible_host" "example" { + inventory_hostname = "example.com" + groups = ["web"] + vars = { + ansible_user = "admin" + } +} + +resource "ansible_group" "web" { + inventory_group_name = "web" + children = ["foo", "bar", "baz"] + vars = { + foo = "bar" + bar = 2 + } +} + diff --git a/iaas_inv_ansible/provider.tf b/iaas_inv_ansible/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_cloudinit/main.tf b/virt_cloudinit/main.tf new file mode 100644 index 0000000..60a7140 --- /dev/null +++ b/virt_cloudinit/main.tf @@ -0,0 +1,89 @@ + +# Variables +# ============ + +variable "name" { + type = string +} +variable "pool" { + type = string + default = "default" +} + +variable "userdata" { + type = string + default = "" +} + + +# Main +# ============ + +# Cloud init ISO +resource "libvirt_cloudinit_disk" "volume_cloudinit" { + name = var.name + pool = var.pool + user_data = var.userdata +} + +# Outputs +# ============ + +output "volume" { + value = libvirt_cloudinit_disk.volume_cloudinit +} + + + + + + +# ==================== DEPRECATED !!!! + + +# variable "baked_image" { +# type = bool +# default = true +# } +# +# variable "image_name" { +# type = string +# } +# +# variable "image_pool" { +# type = string +# } +# variable "image_dir" { +# type = string +# } +# variable "image_url" { +# type = string +# } + +# Deprecated by cloud_volume ! +# # Baked volume +# resource "libvirt_volume" "volume_system_baked" { +# name = "${var.prefix}system.qcow2" +# count = var.baked_image ? 1 : 0 +# pool = var.pool +# +# base_volume_name = var.image_name +# base_volume_pool = var.image_pool +# size = var.disk_size_gb * 1024 * 1024 * 1024 +# } +# +# # Copied volume +# resource "libvirt_volume" "volume_system_full" { +# name = "${var.prefix}system.qcow2" +# count = var.baked_image ? 0 : 1 +# pool = var.pool +# +# #source = var.baked_image ? "" : "${var.image_dir}/${var.image_name}" +# source = var.image_url +# } +# + + +#output "volume_os" { +# value = var.baked_image ? resource.libvirt_volume.volume_system_baked[0] : resource.libvirt_volume.volume_system_full[0] +#} diff --git a/virt_cloudinit/provider.tf b/virt_cloudinit/provider.tf new file mode 100644 index 0000000..7557e9b --- /dev/null +++ b/virt_cloudinit/provider.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + version = "0.6.14" + } + } +} diff --git a/virt_flavor/main.tf b/virt_flavor/main.tf new file mode 100644 index 0000000..bdea7e5 --- /dev/null +++ b/virt_flavor/main.tf @@ -0,0 +1,93 @@ + +# Flavors +# ======================== + +variable "flavor" { + description = "The flavor to use" + type = string + default = "small" +} + +# Default flavors +locals { + + + flavors = { + "default" = { + "cpu" = 2, + "ram" = 1024, + "disk" = 5 + }, + + "tiny" = { + "cpu" = 1, + "ram" = 512, + "disk" = 5 + }, + "tiny_ram" = { + "cpu" = 1, + "ram" = 1024, + "disk" = 10 + }, + "small" = { + "cpu" = 2, + "ram" = 2048, + "disk" = 10 + }, + "small_ram" = { + "cpu" = 2, + "ram" = 4096, + "disk" = 10 + }, + "medium" = { + "cpu" = 4, + "ram" = 4096, + "disk" = 10 + }, + "medium_ram" = { + "cpu" = 4, + "ram" = 6144, + "disk" = 10 + }, + "large" = { + "cpu" = 6, + "ram" = 6144, + "disk" = 20 + }, + "large_ram" = { + "cpu" = 6, + "ram" = 8192, + "disk" = 10 + }, + "huge" = { + "cpu" = 8, + "ram" = 8192, + "disk" = 10 + }, + "huge_ram" = { + "cpu" = 8, + "ram" = 12288, + "disk" = 10 + } + } +} + +locals { + flavor = local.flavors[var.flavor] + cpu = local.flavor.cpu + ram = local.flavor.ram + disk = local.flavor.disk +} +output "flavor" { + value = local.flavor +} +output "cpu" { + value = local.cpu +} +output "disk" { + value = local.disk +} +output "ram" { + value = local.ram +} + diff --git a/virt_flavor/provider.tf b/virt_flavor/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_images/main.tf b/virt_images/main.tf new file mode 100644 index 0000000..3aace0c --- /dev/null +++ b/virt_images/main.tf @@ -0,0 +1,54 @@ + +# Variables +# ===================== + +variable "images" { + description = "Images definitions" + type = any + default = {} +} + +variable "images_defaults" { + description = "Images default definitions" + type = map + default = { + pool = "default", + } +} + +# Resources +# ===================== + +locals { + images = flatten( + [for dist_name, dist_config in var.images: + { + name = dist_name + + format = try(dist_config.format, "") + file = try(dist_config.file, "${dist_name}.${dist_config.format}" , basename( dist_config.url )) + url = dist_config.url + + pool = try(dist_config.pool, var.images_defaults.pool, "default") + } + ] + ) +} + +module "volumes" { + source = "../virt_volumes" + volumes = local.images + volumes_defaults = var.images_defaults +} + + +# Outputs +# ===================== + +output "images" { + value = local.images +} + +output "volumes" { + value = module.volumes.volumes +} diff --git a/virt_images/provider.tf b/virt_images/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_instance/main.tf b/virt_instance/main.tf new file mode 100644 index 0000000..ec46b17 --- /dev/null +++ b/virt_instance/main.tf @@ -0,0 +1,362 @@ + + + +# See: +# https://github.com/sk4zuzu/vm-pool/blob/master/terraform/redhat/nodes/domain.tf + # SEE: https://github.com/SUSE/ha-sap-terraform-deployments/blob/master/libvirt/modules/hana_node/main.tf#L21 + +#variable "tenant_networks" { +# type = any +# default = {} +#} + + + + +# Variables +# ===================== + +variable "name" { + description = "Instance name" + type = string +} +variable "domain" { + description = "Instance domain" + type = string + default = "" +} +variable "number" { + description = "Number of instances" + type = number + default = 1 +} + +# +variable "prefix" { + description = "String to prefix each instances" + type = string + default = "" +} +variable "name_fqdn" { + description = "Define instance name with fqdn" + type = bool + default = false +} +variable "name_prefix" { + description = "Define instance name with project prefix" + type = bool + default = true +} +variable "instance_pool" { + description = "Volume pool for instance disks" + type = string + default = "default" +} +variable "images_pool" { + description = "Default image pool" + type = string + default = "default" +} +variable "disk_gb" { + description = "Size in gb of the root disk" + type = number + default = 2 +} + +# +variable "flavor" { + description = "Instance flavor" + type = string + default = "x-small" +} +variable "memory" { + description = "Instance memory" + type = string + default = "2048" +} +variable "vcpu" { + description = "Number of vcpu" + type = number + default = 2 +} + + + +variable "disks" { + description = "Ephemeral disks list" + type = list + default = [] +} +variable "volumes" { + description = "Persistant volume list" + type = list + default = [] +} +variable "networks" { + description = "Network list" + type = list + default = [] +} + +variable "wait_for_lease" { + description = "Wait for network ip assignment" + type = bool + default = false +} + +variable "metadata" { + description = "Metadata do add in state" + type = any + default = {} +} + + +# Cloud init +# ----------- + +variable "user" { + description = "Default user login" + type = string + default = "cloud" +} + +variable "authorized_key" { + description = "Default user authorized key" + type = string + default = "" +} + +# Note: This should only be used for debugging purpose +variable "password_hash" { + description = "Default user password hash (ie: $1$SaltSalt$GhE887kYCerthShgxern00)" + type = string + default = "" + # sensitive = true +} + + +# Cloud settings +# ===================== + +module "system_os" { + source = "../../modules/virt_os" + count = var.number + + os_name = "debian" + os_version = "10" + domain = var.domain + hostname = "${var.name}${count.index}" + user = var.user + password_hash = var.password_hash + authorized_key = var.authorized_key +} + +module "system_flavor" { + source = "../../modules/virt_flavor" + count = var.number + flavor = var.flavor +} + +# Volumes Configuration +# ===================== + +module "volume_cloudinit" { + source = "../virt_cloudinit" + count = var.number + + name = "inst_${var.prefix}${var.name}${count.index}_cloudinit.iso" + pool = var.instance_pool + userdata = module.system_os[count.index].template +} + +module "volume_os" { + source = "../virt_volume" + count = var.number + + format = "qcow2" + name = "inst_${var.prefix}${var.name}${count.index}" + + pool = var.instance_pool + size_gb = 42 + base_pool = var.images_pool + # TOFIX: Hardcoded refrence to debian + base_file = "debian_latest.qcow2" +} + +module "volumes_extra" { + source = "../virt_volumes" + count = var.number + + volumes = var.disks + volumes_defaults = { + prefix = "inst_${var.prefix}${var.name}${count.index}_" + pool = var.instance_pool + # TOFIX: Hardcoded variable + pool_dir = "/virt" + } +} + + +# Instance +# ===================== + +locals { + hostname = replace( var.name, "_", "-") + vmname = ( var.name_prefix ? + "${var.prefix}${local.hostname}": + "${local.hostname}" ) + domain = var.domain + + metadata = { + #cloud_init = one(module.system_os[*].template) + os_name = "debian" + os_version = "10" + domain = var.domain + user = var.user + #password_hash = var.password_hash + authorized_key = var.authorized_key + } +} + +resource "ansible_host" "ansible_def" { + + count = var.number + inventory_hostname = ( var.name_fqdn ? + "${local.hostname}${count.index}.${var.domain}" : + "${local.hostname}${count.index}" ) + + #groups = [ + # "role_${local.hostname}", + # var.prefix != "" ? "prj_${var.prefix}" : "" + # ] + vars = { + ansible_user = var.user + ansible_host = "${local.hostname}${count.index}.${var.domain}" + ansible_connection = "ssh" + + instances_count = var.number + instances_index = count.index + + instance_domain = var.domain + instance_hostname = "${local.hostname}${count.index}" + instance_name = "${local.hostname}" + + instance_provisionning_key = var.authorized_key + instance_provisionning_user = var.user + instance_flavor = var.flavor + + instance_metadata = jsonencode(merge(local.metadata, var.metadata)) + + # TOFIX: lol + instance_os_name = "debian" + instance_os_version = "10" + + instance_vm = ( var.name_fqdn ? + "${local.vmname}${count.index}.${var.domain}" : + "${local.vmname}${count.index}" ) + } +} + + +resource "libvirt_domain" "instdef" { + count = var.number + + autostart = true + name = ( var.name_fqdn ? + "${local.vmname}${count.index}.${var.domain}" : + "${local.vmname}${count.index}" ) + description = "${var.name}${count.index}.${var.domain}" + memory = var.memory + vcpu = var.vcpu + + metadata = jsonencode(merge(local.metadata, var.metadata)) + + # Root FS + # ------------------- + cloudinit = module.volume_cloudinit[count.index].volume.id + disk { + volume_id = module.volume_os[count.index].volume.id + } + + # Instance disks + dynamic "disk" { + for_each = module.volumes_extra[count.index].volumes + content { + volume_id = disk.value.volume.id + #volume_id = disk.value.info.id + #volume_id = coalesce(disk.value.volume.id) + #file = coalesce(disk.value.info.id) + } + } + + # Networking + # ------------------- + dynamic "network_interface" { + for_each = var.networks + content { + network_name = network_interface.value.name + mac = try(network_interface.value.mac, null) + addresses = try(network_interface.value.addresses, null) + #hostname = try(network_interface.value.hostname, var.name) + + wait_for_lease = try(network_interface.value.wait_for_lease, var.wait_for_lease ) + macvtap = try(network_interface.value.macvtap, null) + vepa = try(network_interface.value.vepa, null) + } + } + + # Other + # ------------------- + console { + type = "pty" + target_port = "0" + target_type = "serial" + } + + console { + type = "pty" + target_type = "virtio" + target_port = "1" + } + + graphics { + type = "spice" + listen_type = "address" + autoport = true + } + + cpu { + mode = "host-passthrough" + } + +} + + +# Outputs +# ===================== + +output "instance" { + value = try(resource.libvirt_domain.instdef, null) +} + + +# output "volume_cloudinit" { +# value = module.volume_cloudinit +# } +output "volume_os" { + value = module.volume_os +} +output "volumes_extra" { + value = module.volumes_extra +} + +# Tag infos +output "system_os" { + value = module.system_os +} +output "system_flavor" { + value = module.system_flavor +} + + + diff --git a/virt_instance/provider.tf b/virt_instance/provider.tf new file mode 100644 index 0000000..b882ae4 --- /dev/null +++ b/virt_instance/provider.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + version = "0.6.14" + } + ansible = { + source = "nbering/ansible" + version = "~>1.0.4" + } + } +} diff --git a/virt_instances/main.tf b/virt_instances/main.tf new file mode 100644 index 0000000..a7f681c --- /dev/null +++ b/virt_instances/main.tf @@ -0,0 +1,112 @@ + +# Variables +# ===================== + +variable "tenant" { + description = "Tenant informations" + type = any + default = { + prefix = "" + } +} + +variable "instances" { + description = "Instances definitions" + type = any + default = [] +} + +variable "instances_defaults" { + description = "Instances default definitions" + type = any + default = {} +} + +variable "networks" { + description = "Known networks to find domain" + type = any + default = {} +} + + +# Resources +# ===================== + +locals { + pre_default = { + network = "default" + domain = "no_domain22" + } + default_network = try(var.networks[var.instances_defaults.default_network], null) != null ? var.instances_defaults.default_network : local.pre_default.network + + networks = local.default_network != null ? [{ name = "${var.tenant.prefix}${local.default_network}" }] : [] + domain = try( var.networks[local.default_network].domain, local.pre_default.domain) + + # Recommended default flavor + default = { + number = 1 + instance_pool = "default" + disk_gb = 14 + flavor = "default" + memory = 1024 + vcpu = 1 + disks = [] + volumes = [] + name_fqdn = true + wait_for_lease = false + password_hash = "" + authorized_key = "" + user = "" + metadata = {} + + prefix = var.tenant.prefix + default_network = local.default_network + networks = local.networks + domain = local.domain + } + instances_defaults = merge(local.default, var.instances_defaults) +} + +module "virt_instances" { + source = "../../modules/virt_instance" + for_each = { for v in var.instances : v.name => merge(local.instances_defaults, v) } + + name = each.value.name + prefix = each.value.prefix + name_fqdn = each.value.name_fqdn + metadata = each.value.metadata + + domain = each.value.domain + number = each.value.number + instance_pool = each.value.instance_pool + images_pool = each.value.images_pool + disk_gb = each.value.disk_gb + flavor = each.value.flavor + memory = each.value.memory + vcpu = each.value.vcpu + disks = each.value.disks + volumes = each.value.volumes + networks = each.value.networks + wait_for_lease = each.value.wait_for_lease + + user = each.value.user + authorized_key = each.value.authorized_key + password_hash = each.value.password_hash + +} + + +# Outputs +# ===================== +output "instances" { + value = module.virt_instances +} + +# output "DEBUG" { +# value = { +# NORMAL = module.virt_instances +# INSTANCES = var.instances +# INSTANCES_defaults = var.instances_defaults +# } +# } + diff --git a/virt_instances/provider.tf b/virt_instances/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_namespace/main.tf b/virt_namespace/main.tf new file mode 100644 index 0000000..dedd641 --- /dev/null +++ b/virt_namespace/main.tf @@ -0,0 +1,147 @@ + +# Variables +# ===================== + +variable "cloud" { + description = "Cloud informations" + type = any + default = {} +} + +variable "tenant" { + description = "Tenant informations" + type = any + default = {} +} + +variable "deploy" { + description = "Deployments configuration" + type = map + default = {} +} + +variable "stack" { + description = "Deployment options" + type = any + default = {} +} + + +# Resources +# ===================== + +locals { + + def_deploy = { + stack = "main" + pools = false + volumes = false + networks = false + instances = false + images = false + } + base_stack = { + pool = {} + image = {} + volume = {} + network = {} + instance = {} + + pools = {} + images = {} + volumes = [] + networks = {} + instances = [] + } + + deploy = merge ( local.def_deploy, var.deploy ) + stack = { for k, v in local.base_stack: + k => try( + merge ( + local.base_stack[k], + var.cloud[k], + var.stack[k] + ), + var.stack[k], + var.cloud[k] + ,local.base_stack[k] + ) + } +} + + + +# Modules +# ===================== + +module "cloud_pools" { + source = "../virt_pools" + count = local.deploy.pools ? 1: 0 + + pools = local.stack.pools + pools_defaults = local.stack.pool +} + +module "cloud_images" { + source = "../virt_images" + count = local.deploy.images ? 1: 0 + depends_on = [module.cloud_pools] + + images = local.stack.images + images_defaults = local.stack.image +} + +module "cloud_volumes" { + source = "../virt_volumes" + count = local.deploy.volumes ? 1: 0 + depends_on = [module.cloud_pools] + + tenant = var.tenant + volumes = local.stack.volumes + volumes_defaults = local.stack.volume +} + +module "cloud_networks" { + source = "../virt_networks" + count = local.deploy.networks ? 1: 0 + + tenant = var.tenant + networks = local.stack.networks + networks_defaults = local.stack.network +} + +module "cloud_instances" { + source = "../virt_instances" + count = local.deploy.instances ? 1: 0 + depends_on = [module.cloud_networks, module.cloud_images, module.cloud_volumes] + + tenant = var.tenant + networks = local.stack.networks + instances = local.stack.instances + instances_defaults = local.stack.instance +} + + +# Output +# ===================== + +output "cloud_pools" { + value = module.cloud_pools +} + +output "cloud_images" { + value = module.cloud_images +} +output "cloud_volumes" { + value = module.cloud_volumes +} +output "cloud_networks" { + value = module.cloud_networks +} +output "cloud_instances" { + value = module.cloud_instances +} + +# output "DEBUG" { +# value = local.stack +# } diff --git a/virt_namespace/provider.tf b/virt_namespace/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_network/main.tf b/virt_network/main.tf new file mode 100644 index 0000000..3d5668b --- /dev/null +++ b/virt_network/main.tf @@ -0,0 +1,171 @@ + +# Variables +# ===================== + +variable "name" { + type = string + description = "Network name" +} + +variable "mode" { + description = "Network mode (route|nat)" + type = string + default = "nat" +} + +variable "bridge" { + description = "Network interface name (16 char max, virbr_)" + type = string +} + +variable "domain" { + description = "Network domain" + type = string + default = "local" +} + +variable "gw4" { + description = "Network address" + type = string + default = "192.168.0.1" +} + +variable "mask" { + description = "Netmask of the network" + type = number + default = 24 +} + + +# +variable "nat_enable" { + description = "Enable NAT from outside of libvirt" + type = bool + default = false +} + +variable "nat_driver" { + description = "Default NAT driver" + type = string + default = "ferm" +} + +variable "nat_device" { + description = "Device to forward unrouted traffic (ie: eth0)" + type = string + default = "enp1s0" +} + + +# +variable "vip" { + description = "List of vips" + type = list + default = [] +} + +variable "subnets" { + description = "List of subnets" + type = list + default = [] +} + + +# Resources +# ===================== + +resource "libvirt_network" "netdef" { + name = var.name + mode = var.mode + bridge = var.bridge + domain = var.domain + addresses = ["${var.gw4}/${var.mask}"] + autostart = true + + dns { + enabled = true + local_only = true + + hosts { + hostname = "gw" + ip = cidrhost("${var.gw4}/${var.mask}", 1) + } + + dynamic "hosts" { + for_each = var.vip + content { + hostname = try(hosts.value.hostname) + ip = try(hosts.value.ip) + } + } + } +} + + +# Tests +# ===================== + +# resource "consul_keys" "app" { +# count = var.nat_enable ? 1 : 0 +# +# depends_on = [libvirt_network.netdef] +# key { +# path = "tests/net/${var.bridge}/nat" +# value = "${var.nat_device} - ${ var.nat_enable }" +# delete = true +# } +# } + +# TMP DISABVLED, require ferm first resource "ssh_resource" "nat_config" { +# TMP DISABVLED, require ferm first count = var.nat_enable ? 1 : 0 +# TMP DISABVLED, require ferm first +# TMP DISABVLED, require ferm first host = "192.168.142.10" +# TMP DISABVLED, require ferm first user = "root" +# TMP DISABVLED, require ferm first agent = true +# TMP DISABVLED, require ferm first +# TMP DISABVLED, require ferm first depends_on = [libvirt_network.netdef] +# TMP DISABVLED, require ferm first +# TMP DISABVLED, require ferm first file { +# TMP DISABVLED, require ferm first content = templatefile("${path.module}/templates/ferm_nat.tpl", { +# TMP DISABVLED, require ferm first device = "${var.nat_device}" +# TMP DISABVLED, require ferm first driver = "${var.nat_driver}" +# TMP DISABVLED, require ferm first }) +# TMP DISABVLED, require ferm first destination = "/etc/libvirt/hooks/state/net/${var.bridge}_nat.ini" +# TMP DISABVLED, require ferm first permissions = "0644" +# TMP DISABVLED, require ferm first } +# TMP DISABVLED, require ferm first } + +# resource "ssh_resource" "ipvs_config" { +# count = var.nat_enable ? 1 : 0 +# +# host = "192.168.142.10" +# user = "root" +# agent = true +# +# depends_on = [libvirt_network.netdef] +# +# file { +# content = templatefile("${path.module}/templates/ipvs_config.tpl", { +# vips = var.vip +# }) +# destination = "/etc/libvirt/hooks/state/net/${var.bridge}_ipvs.ini" +# permissions = "0644" +# } +# } + + +# Output +# ===================== + +output "networks" { + value = resource.libvirt_network.netdef +} + +output "subnets" { + value = var.subnets +} + +output "vips" { + value = var.vip +} + diff --git a/virt_network/provider.tf b/virt_network/provider.tf new file mode 100644 index 0000000..77d6a51 --- /dev/null +++ b/virt_network/provider.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + libvirt = { + source = "registry.terraform.io/dmacvicar/libvirt" + version = "0.6.14" + } +# ssh = { +# source = "registry.terraform.io/loafoe/ssh" +# version = "0.4.0" +# } + } +} diff --git a/virt_network/templates/ferm_nat.tpl b/virt_network/templates/ferm_nat.tpl new file mode 100644 index 0000000..678f181 --- /dev/null +++ b/virt_network/templates/ferm_nat.tpl @@ -0,0 +1,3 @@ +[nat] +driver = ${ driver } +device = ${ device } diff --git a/virt_network/templates/ipvs_config.tpl b/virt_network/templates/ipvs_config.tpl new file mode 100644 index 0000000..10fd21e --- /dev/null +++ b/virt_network/templates/ipvs_config.tpl @@ -0,0 +1,8 @@ +[ipvs] +%{ for vip in vips } +%{ if can(vip.public_ip) && can(vip.public_port) } +-A -t ${vip.public_ip}:${vip.public_port} -s rr +-a -t ${vip.public_ip}:${vip.public_port} -r ${vip.ip}:${try(vip.internal_port, vip.public_port)} -m -w 1 +%{ endif } +%{ endfor } + diff --git a/virt_networks/main.tf b/virt_networks/main.tf new file mode 100644 index 0000000..630ece0 --- /dev/null +++ b/virt_networks/main.tf @@ -0,0 +1,73 @@ + +# Variables +# ===================== + +variable "tenant" { + description = "Tenant informations" + type = any + default = { + prefix = "" + } +} + +variable "networks" { + description = "Networks definitions" + type = any + default = {} +} + +variable "networks_defaults" { + description = "Network default definitions" + type = any + default = {} +} + + + +# Resources +# ===================== + +locals { + defaults = { + name_prefix = var.tenant.prefix + #interface_prefix = "vibr_${var.tenant.prefix}" + #interface_prefix = "vibr_" + interface_prefix = null + mode = "nat" + domain = "local" + gw4 = "192.168.100.1" + mask = "24" + + nat_enable = false + vip = [] + subnets = [] + } + networks_defaults = merge(local.defaults, var.networks_defaults) +} + +module "cloud_networks" { + source = "../../modules/virt_network" + for_each = { for k, v in var.networks : k => merge(local.networks_defaults, v) } + + name = "${each.value.name_prefix}${each.key}" + bridge = each.value.interface_prefix == null ? "" : substr("${each.value.interface_prefix}${each.key}", 0 , 15) + + mode = each.value.mode + domain = each.value.domain + gw4 = each.value.gw4 + mask = each.value.mask + + nat_enable = each.value.nat_enable + vip = each.value.vip + subnets = each.value.subnets +} + + +# Output +# ===================== + +output "networks" { + value = module.cloud_networks +} + + diff --git a/virt_networks/provider.tf b/virt_networks/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_os/main.tf b/virt_os/main.tf new file mode 100644 index 0000000..5d877ab --- /dev/null +++ b/virt_os/main.tf @@ -0,0 +1,194 @@ + +# Instance System +# ======================== + + +# Variables +variable "os_name" { + description = "The name of the operating system to create" + type = string + default = "ubuntu" +} + +variable "os_version" { + description = "The version of the operationg system to use" + type = string + default = "latest" +} + +# ======== + +variable "cloud_init" { + type = string + default = "" + description = "Override system cloud_init" +} +variable "cloud_init_vars" { + type = map + default = {} + description = "Override cloud init vars" +} +# ========== + +variable "domain" { + type = string + default = "nodomain" +} + +variable "hostname" { + type = string + default = "noname" +} + +variable "user" { + type = string + default = "cloud" +} + +variable "password_hash" { + type = string + default = "" +} + +variable "authorized_key" { + type = string + default = "" +} + + + +locals { + # Operating System + # ======================== + distro = { + "debian" = { + "latest" = { + "cloud_init" = "debian", + "url" = "https://cdimage.debian.org/cdimage/cloud/buster/20210208-542/debian-10-genericcloud-amd64-20210208-542.qcow2", + }, + "10" = { + "cloud_init" = "debian", + "url" = "https://cdimage.debian.org/cdimage/cloud/buster/20210208-542/debian-10-genericcloud-amd64-20210208-542.qcow2", + }, + "10-20210208-542" = { + "cloud_init" = "debian", + "url" = "https://cdimage.debian.org/cdimage/cloud/buster/20210208-542/debian-10-genericcloud-amd64-20210208-542.qcow2", + }, + }, +# "ubuntu" = { +# "latest" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/groovy/release/ubuntu-20.10-server-cloudimg-amd64-disk-kvm.img", +# }, +# "20.10" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/groovy/release/ubuntu-20.10-server-cloudimg-amd64-disk-kvm.img", +# }, +# "20.04" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img", +# }, +# "19.04" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/disco/release/ubuntu-19.04-server-cloudimg-amd64.img", +# }, +# "18.04" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img", +# }, +# "17.04" = { +# "cloud_init" = "debian", +# "url" = "http://cloud-images-archive.ubuntu.com/releases/zesty/release-20171208/ubuntu-17.04-server-cloudimg-amd64.img", +# }, +# "16.04" = { +# "cloud_init" = "debian", +# "url" = "https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img" +# }, +# }, +# "centos" = { +# "latest" = { +# "cloud_init" = "centos", +# "url" = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2", +# }, +# "8" = { +# "cloud_init" = "centos", +# "url" = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2", +# }, +# "8-stream" = { +# "cloud_init" = "centos", +# "url" = "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20201217.0.x86_64.qcow2", +# }, +# "7" = { +# "cloud_init" = "centos", +# "url" = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2009.qcow2", +# }, +# "6" = { +# "cloud_init" = "centos", +# "url" = "https://cloud.centos.org/centos/6/images/CentOS-6-x86_64-GenericCloud.qcow2" +# }, +# } + } + + + # Cloud Init + # ======================== + templates = { + "centos" = { + "template" = "${path.module}/templates/cloud_centos_generic.yml", + "vars" = {} + }, + "debian" = { + "template" = "${path.module}/templates/cloud_debian_generic.yml", + "vars" = { + "authorized_key" = "", + "authorized_keys" = [], + "commands" = [], + "packages" = [], + "allow_passwords" = true, + } + } + } + + template_default = { + "authorized_key" = var.authorized_key, + "password_hash" = var.password_hash, + "user" = var.user, + "domain" = var.domain, + "hostname" = var.hostname, + } + +} + + +locals { + os = local.distro[var.os_name][var.os_version] + + # Generate template + cloud_template = try(local.templates[var.cloud_init], local.templates[local.os.cloud_init]) + template_vars = merge(local.cloud_template.vars, local.template_default, var.cloud_init_vars) +} + + +output "distro" { + value = local.distro +} + + +output "os" { + value = local.os +} + +output "cloud_init" { + value = local.cloud_template +} +output "template_vars" { + value = local.template_vars +} + + +output "template" { + #value = data.template_file.user_data.rendered + value = templatefile("${local.cloud_template.template}", local.template_vars) +} + + diff --git a/virt_os/provider.tf b/virt_os/provider.tf new file mode 100644 index 0000000..e69de29 diff --git a/virt_os/templates/cloud_debian_generic.yml b/virt_os/templates/cloud_debian_generic.yml new file mode 100644 index 0000000..adb1177 --- /dev/null +++ b/virt_os/templates/cloud_debian_generic.yml @@ -0,0 +1,57 @@ +#cloud-config + +preserve_hostname: false +hostname: ${hostname} +fqdn: ${hostname}.${domain} +# prefer_fqdn_over_hostname: true +%{ if allow_passwords ~} +ssh_pwauth: true +%{ endif ~} + +groups: + - wheel +users: +- name: ${user} + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + groups: users, admin, sudo +%{ if allow_passwords ~} + passwd: "${password_hash}" +%{ endif ~} + lock_passwd: %{ if allow_passwords ~}false%{ else }true%{ endif } + ssh_authorized_keys: +%{ if authorized_key != "" ~} + - "${authorized_key}" +%{ endif ~} +%{ for key in authorized_keys ~} + - "${key}" +%{ endfor ~} + +packages: + - vim + - telnet + - bash-completion + - htop + - tree + - lvm2 +%{ for pkg in packages ~} + - ${pkg} +%{ endfor ~} + +bootcmd: + - echo "127.0.0.1 ${hostname}.${domain} ${hostname}" >> /etc/hosts + +runcmd: + - rm /etc/skel/.bashrc + - apt update + - apt install -y qemu-guest-agent ca-certificates + - systemctl enable qemu-guest-agent + - systemctl start qemu-guest-agent + - apt upgrade +%{ for cmd in commands ~} + - ${cmd} +%{ endfor ~} + - echo "$(date): Success" > /var/log/provisionned + +final_message: "The system is ready, after $UPTIME seconds" + diff --git a/virt_pools/main.tf b/virt_pools/main.tf new file mode 100644 index 0000000..c930d4f --- /dev/null +++ b/virt_pools/main.tf @@ -0,0 +1,55 @@ + +# Variables +# ===================== + +variable "tenant" { + description = "Tenant informations" + type = any + default = { + prefix = "" + } +} + +variable "pools" { + description = "Pools definitions" + type = any + default = {} +} + +variable "pools_defaults" { + description = "Pools default definitions" + type = any + default = {} +} + + +locals { + defaults = { + root_dir = "/virt" + } + pools_defaults = merge(local.defaults, var.pools_defaults) +} + + +# Resources +# ===================== + +resource "libvirt_pool" "pooldef" { + for_each = var.pools + + name = "${each.key}" + path = length( + regexall("^/", try( each.value.dir, "")) + ) > 0 ? "${each.value.dir}" : "${local.pools_defaults.root_dir}/${try( each.value.dir, each.key)}" + type = "dir" + +} + + +# Output +# ===================== + +output "pools" { + value = resource.libvirt_pool.pooldef +} + diff --git a/virt_pools/provider.tf b/virt_pools/provider.tf new file mode 100644 index 0000000..6e0ebe3 --- /dev/null +++ b/virt_pools/provider.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + version = "0.6.14" + } + } +} diff --git a/virt_volume/main.tf b/virt_volume/main.tf new file mode 100644 index 0000000..4e13583 --- /dev/null +++ b/virt_volume/main.tf @@ -0,0 +1,262 @@ + +# Variables +# ===================== +# +variable "name" { + type = string + description = "Determine the name of the volume" +} + +variable "persistant" { + type = bool + default = false + description = "Enable destroy protection on this volume" +} + + +# +variable "format" { + type = string + default = "qcow2" + description = "Determine the format of the image" +} + +variable "file" { + type = string + description = "Determine the filename of the volume" + default = "" +} + + +# +variable "pool" { + type = string + default = "default" + description = "Determine pool to create volume within" +} + +variable "pool_dir" { + type = string + default = "/virt" + description = "Default path for all pools" +} + +variable "size_gb" { + type = number + default = 0 + description = "Default size for the volume" +} + + +# +variable "url" { + type = string + default = "" + description = "Download url for volume" +} + +variable "base_pool" { + type = string + default = "default" + description = "Pool of the source image" +} +variable "base_file" { + type = string + description = "Name of the source image" + default = "" +} + + +# Variables +# ===================== + + + #agent=var.ssh_agent # "true" + #host=var.ssh_host # "wks1.office.barbu-it.net" + #user=var.ssh_user # "root" + #password=var.password + +variable "ssh_conn" { + description = "Default settings for ssh connexion" + type = any + default = { + agent = true, + #host = "localhost", + host = "wks1.office.barbu-it.net", + user = null, + password = null + } +} + + + +# Resources +# ===================== + +locals { + + # Guess things from URL + url_split = split(".", basename( var.url )) + url_ext = element(local.url_split, length(local.url_split ) -1 ) + url_file = "${var.name}.${local.url_ext}" + + # Guess things from name + name_file = "${var.name}.${var.format}" + + # Determine resource to use + is_baked = var.base_file != "" ? true : false + is_sourced = var.url != "" && ! local.is_baked ? true : false + is_created = ! local.is_baked && ! local.is_sourced ? true: false + + # Volume settings + vol_name = coalesce(var.file, local.is_sourced ? local.url_file : local.name_file) + size_gb = try(var.size_gb * 1024 * 1024 * 1024, null) + id = "${var.pool_dir}/${var.pool}/${local.vol_name}" + +} + + +# Sourced +resource "libvirt_volume" "voldef_ephemeral_sourced" { + count = local.is_sourced && ! var.persistant ? 1 : 0 + + name = local.vol_name + pool = var.pool + source = local.is_sourced ? var.url : null +} + +# Created +resource "libvirt_volume" "voldef_ephemeral_created" { + count = local.is_created && ! var.persistant ? 1 : 0 + + name = local.vol_name + pool = var.pool + source = local.is_sourced ? var.url : null + size = local.size_gb + format = var.format +} + +# Backed +resource "libvirt_volume" "voldef_ephemeral_baked" { + count = local.is_baked && ! var.persistant ? 1 : 0 + + name = local.vol_name + pool = var.pool + + size = local.is_baked ? try(local.size_gb, 1) : local.size_gb + base_volume_pool = local.is_baked ? var.base_pool : null + base_volume_name = local.is_baked ? var.base_file : null +} + +# Todo: Manage persistant volumes with: +# lifecycle { +# prevent_destroy = false +# } + +# # Created Persistant +# resource "libvirt_volume" "voldef_ephemeral_created" { +# +# name = local.vol_name +# pool = var.pool +# source = local.is_sourced ? var.url : null +# size = local.size_gb +# format = var.format +# } + + +resource "null_resource" "voldef_persistant_created" { + # We only support created volumes basically + count = var.persistant ? 1 : 0 + #count = local.is_created && var.persistant ? 1 : 0 + #count = 0 + + + # local ssh connection, make sure to pass variables 'user' andd 'password' on cli + # terraform apply -var user=$USER -var password=xxxxxxx + connection { + type="ssh" + # agent=var.ssh_agent # "true" + # host=var.ssh_host # "wks1.office.barbu-it.net" + # user=var.ssh_user # "root" + # password=var.password + + agent = var.ssh_conn.agent + host= var.ssh_conn.host + user = var.ssh_conn.user + password = var.ssh_conn.password + + #user=var.user + #password=var.password + + + } + + provisioner "remote-exec" { + inline = [ + "/opt/virt-scripts/bin/virt-vol.sh create ${local.vol_name} ${var.size_gb} ${var.pool} ${var.format}" + #"[[ ! -f '${/virt/cloud_safe/inst_storage0_data.qcow2}' ]] || \{ qemu-img create -f '${var.format}' ${local.id} '${local.size_gb}Gb; virsh pool-refresh '${var.pool}'; \}" + #"virsh vol-create-as --pool '${var.pool}' --name '${local.name_file}' --format '${var.format}' --prealloc-metadata --capacity '${local.size_gb * 100000000}'" + ] + } + + #provisioner "file" { + # destination = "/tmp/script.sh" + # content = templatefile( + # "${path.module}/script.sh.tpl", + # { + # "params": local.params + # "params_for_inline_command" : local.params_for_inline_command + # } + # ) + #} + +} + + + + +# Output +# ===================== + +output "volume" { + value = coalescelist( + resource.libvirt_volume.voldef_ephemeral_sourced, + resource.libvirt_volume.voldef_ephemeral_created, + resource.libvirt_volume.voldef_ephemeral_baked, + [ { id = local.id } ], + )[0] +} + +output "info" { + value = { + #id = local.id, + #id = coalescelist( + id = coalescelist( + resource.libvirt_volume.voldef_ephemeral_sourced, + resource.libvirt_volume.voldef_ephemeral_created, + resource.libvirt_volume.voldef_ephemeral_baked, + [ { id = local.id } ], + )[0].id + vol_name = local.vol_name, + is_baked = local.is_baked, + is_sourced = local.is_sourced, + is_created = local.is_created, + name_url = local.url_file, + name_file = local.name_file, + format = var.format, + file = var.file, + #out = [ + # resource.libvirt_volume.voldef_ephemeral_sourced, + # resource.libvirt_volume.voldef_ephemeral_baked, + # resource.libvirt_volume.voldef_ephemeral_created, + # resource.null_resource.voldef_persistant_created + #] + #volume_id = coalescelist( + # resource.libvirt_volume.voldef_ephemeral_sourced, + # resource.libvirt_volume.voldef_ephemeral_created, + # resource.libvirt_volume.voldef_ephemeral_baked, + # resource.null_resource.voldef_persistant_created, + # )[0].id + } +} + diff --git a/virt_volume/provider.tf b/virt_volume/provider.tf new file mode 100644 index 0000000..2da3751 --- /dev/null +++ b/virt_volume/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + libvirt = { + source = "registry.terraform.io/dmacvicar/libvirt" + version = "0.6.14" + } + } +} + + diff --git a/virt_volumes/main.tf b/virt_volumes/main.tf new file mode 100644 index 0000000..51379a0 --- /dev/null +++ b/virt_volumes/main.tf @@ -0,0 +1,74 @@ + +# Variables +# ============ + +variable "tenant" { + description = "Tenant informations" + type = map + default = { + prefix = "" + } +} + +variable "volumes" { + description = "List of volumes" + type = list(any) + default = [] +} + +variable "volumes_defaults" { + description = "Default settings for volumes" + type = map + default = {} +} + + +# Main +# ============ + + +locals { + defaults = { + prefix = var.tenant.prefix + pool = "default", + pool_dir = "/virt", + size_gb = 10, + format = "qcow2" + persistant = false + + base_pool = "default", + base_file = "", + + url = "" + file = "" + } + volumes_defaults = merge(local.defaults, var.volumes_defaults) +} + + +module "cloud_volume" { + source = "../virt_volume" + for_each = { for v in var.volumes: v.name => merge(local.volumes_defaults, v) } + + name = "${each.value.prefix}${each.value.name}" + pool = each.value.pool + size_gb = each.value.size_gb + format = each.value.format + persistant = each.value.persistant + + base_pool = each.value.base_pool + base_file = each.value.base_file + + url = each.value.url + file = each.value.file + +} + + +# Output +# ============ + +output "volumes" { + value = module.cloud_volume +} + diff --git a/virt_volumes/provider.tf b/virt_volumes/provider.tf new file mode 100644 index 0000000..e69de29