From 740a8de4a202d0e973aa61fcda8434d9d4d839c9 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Mon, 22 Mar 2021 19:52:11 +0100 Subject: [PATCH] Adding Terraform basics --- configs/nginx/factory.conf | 17 +++ fabrica | 11 +- terraform/01-main.tfvars | 12 ++ terraform/02-dns-zones.tfvars | 22 ++++ terraform/03-networks.tfvars | 24 ++++ terraform/04-virtual-machines.tfvars | 45 +++++++ terraform/main.tf | 89 ++++++++++++++ terraform/modules/cadolesDNS/main.tf | 29 +++++ terraform/modules/cadolesDNS/outputs.tf | 0 terraform/modules/cadolesDNS/variables.tf | 23 ++++ terraform/modules/virtualMachine/main.tf | 115 ++++++++++++++++++ terraform/modules/virtualMachine/outputs.tf | 7 ++ terraform/modules/virtualMachine/variables.tf | 93 ++++++++++++++ terraform/modules/virtualMachine/versions.tf | 15 +++ terraform/templates/groups/standard.tpl | 4 + terraform/variables.tf | 82 +++++++++++++ terraform/version.tf | 11 ++ 17 files changed, 597 insertions(+), 2 deletions(-) create mode 100644 configs/nginx/factory.conf create mode 100644 terraform/01-main.tfvars create mode 100644 terraform/02-dns-zones.tfvars create mode 100644 terraform/03-networks.tfvars create mode 100644 terraform/04-virtual-machines.tfvars create mode 100644 terraform/main.tf create mode 100644 terraform/modules/cadolesDNS/main.tf create mode 100644 terraform/modules/cadolesDNS/outputs.tf create mode 100644 terraform/modules/cadolesDNS/variables.tf create mode 100644 terraform/modules/virtualMachine/main.tf create mode 100644 terraform/modules/virtualMachine/outputs.tf create mode 100644 terraform/modules/virtualMachine/variables.tf create mode 100644 terraform/modules/virtualMachine/versions.tf create mode 100644 terraform/templates/groups/standard.tpl create mode 100644 terraform/variables.tf create mode 100644 terraform/version.tf diff --git a/configs/nginx/factory.conf b/configs/nginx/factory.conf new file mode 100644 index 0000000..1670c92 --- /dev/null +++ b/configs/nginx/factory.conf @@ -0,0 +1,17 @@ +location /factory/ { + alias /srv/factory/images/; + autoindex on; + allow 192.168.10.0/24; + allow 192.168.5.0/24; + deny all; +} +location /factory/images/cadoles/ { + alias /srv/factory/images/cadoles/; + autoindex on; + allow 192.168.5.10; + allow 192.168.5.11; + allow 192.168.5.12; + allow 192.168.5.13; + allow 192.168.10.177/24; + deny all; +} diff --git a/fabrica b/fabrica index 71c0458..348d4c3 100755 --- a/fabrica +++ b/fabrica @@ -2,7 +2,6 @@ WORKDIR="./terraform" TERRA="terraform" -VAR_FILE="main.tfvars" PACKER_ROOT="./packer" # FIXME @@ -23,7 +22,15 @@ function trun() echo "--> Git pull needed !" return 1 fi - ${TERRA} ${1} -var-file ${VAR_FILE} + + VAR_FILES=$(ls *.tfvars) + OPTS="" + for fl in ${VAR_FILES} + do + OPTS="${OPTS} -var-file ${fl}" + done + + ${TERRA} ${1} ${OPTS} res=${?} cd - diff --git a/terraform/01-main.tfvars b/terraform/01-main.tfvars new file mode 100644 index 0000000..f371473 --- /dev/null +++ b/terraform/01-main.tfvars @@ -0,0 +1,12 @@ +one_endpoint = "https://myhapy.fabrica.local/RPC2" +one_user = "terra" +one_pass = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +one_vswitch = "vswitch" +one_prod_ds = "101" +image_builder_ip = "192.168.1.108" +dns_server = "192.168.5.53" +dns_domain = "fabrica.local." +cluster_id = 0 + +dns_key_name = "terraform.key." +dns_key_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" diff --git a/terraform/02-dns-zones.tfvars b/terraform/02-dns-zones.tfvars new file mode 100644 index 0000000..d508f45 --- /dev/null +++ b/terraform/02-dns-zones.tfvars @@ -0,0 +1,22 @@ +dns_zones = [ + { + domain = "cadoles.com", + a_records = { + hapy = [ "192.168.1.108" ], + amon = [ "192.168.1.1"] + }, + cname_records = { + hapy = "virt.cadoles.com." + } + }, + { + domain = "cadol.es", + a_records = { + hapy = [ "192.168.1.108" ], + amon = [ "192.168.1.1"] + }, + cname_records = { + hapy = "virt.cadol.es." + } + } +] \ No newline at end of file diff --git a/terraform/03-networks.tfvars b/terraform/03-networks.tfvars new file mode 100644 index 0000000..d7b9bc4 --- /dev/null +++ b/terraform/03-networks.tfvars @@ -0,0 +1,24 @@ +virtual_networks = { + internet = { + vlan_id = "4", + adress_range = { + ar_type = "IP4", + size = "10", + ip4 = "192.168.1.28" + }, + dns = "192.168.5.53", + gateway = "192.168.1.1", + clusters = [ "0" ] + }, + office = { + vlan_id = "10", + adress_range = { + ar_type = "IP4", + size = "30", + ip4 = "192.168.10.100" + }, + dns = "192.168.5.53", + gateway = "192.168.10.254", + clusters = [ "0" ] + } +} \ No newline at end of file diff --git a/terraform/04-virtual-machines.tfvars b/terraform/04-virtual-machines.tfvars new file mode 100644 index 0000000..fb70100 --- /dev/null +++ b/terraform/04-virtual-machines.tfvars @@ -0,0 +1,45 @@ +virtual_machines = { + amon = { + fqdn = "amon.fabrica.local", + domain = "fabrica.local", + create_dns_a_record = "no", + cpu = "0.4", + vcpu = "4", + memory = "4096", + network_interfaces = [ + { network_name = "internet", ip = "192.168.1.3" }, + { network_name = "office", ip = "192.168.10.254" } + ], + + labels = "Production, Amon, Infra, Backup, EOLE", + + disks = { + system = { + name = "prod-amon-static", + source = "http://localhost/fabrica/infra/production/amon.fabrica.local/system/amon.fabrica.local" + } + } + depends = [ "internet" ] + }, + scribe = { + fqdn = "scribe.fabrica.local", + domain = "fabrica.local", + create_dns_a_record = "no", + cpu = "0.4", + vcpu = "4", + memory = "4096", + network_interfaces = [ + { network_name = "office", ip = "192.168.10.200" } + ], + + labels = "Production, Scribe, Infra, Backup, EOLE", + + disks = { + system = { + name = "prod-scribe-static", + source = "http://localhost/fabrica/infra/production/scribe.fabrica.local/system/scribe.fabrica.local" + } + } + depends = [ "internet" ] + } +} \ No newline at end of file diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..f68b0fd --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,89 @@ +provider "opennebula" { + endpoint = var.one_endpoint + username = var.one_user + password = var.one_pass +} + +provider "dns" { + update { + server = var.dns_server + port = "53530" + key_name = var.dns_key_name + key_algorithm = var.dns_key_algo + key_secret = var.dns_key_secret + retries = 10 + timeout = 300 + } +} + + +// Production + +/* + * Virtual networks + */ +resource "opennebula_virtual_network" "vnet"{ + for_each = var.virtual_networks + name = each.key + vlan_id = each.value.vlan_id + permissions = "660" + bridge = var.one_vswitch + type = "ovswitch" + mtu = 1500 + ar { + ar_type = each.value.adress_range.ar_type + size = each.value.adress_range.size + ip4 = each.value.adress_range.ip4 + } + dns = each.value.dns + gateway = each.value.gateway + clusters = each.value.clusters +} + +/* + * VIRTUAL MACHINES + */ + +// Production +module "vms" { + source = "./modules/virtualMachine" + one_user = var.one_user + one_prod_ds = var.one_prod_ds + for_each = var.virtual_machines + + vm_shortname = each.key + vm_fqdn = each.value.fqdn + vm_domain = var.dns_domain + dns_a_record = each.value.create_dns_a_record + + cpu = each.value.cpu + vcpu = each.value.vcpu + ram = each.value.memory + + vnets = opennebula_virtual_network.vnet + network_interfaces = each.value.network_interfaces + + tag_labels = each.value.labels + + system_image_name = each.value.disks.system.name + data_image_name = "" + + system_image_source = each.value.disks.system.source + data_image_source = "" + + depends = [ + opennebula_virtual_network.vnet[each.value.depends[0]].id + ] +} + + + +/* Additionnal DNS Entry +module "ber_asso_fr" { + source = "./modules/cadolesDNS" + dns_domain = "cadoles.com." + dns_a_records = var.dns_a_records + dns_cname_records = var.dns_cname_records + depends = [ module.dns.virtual_machine_shortname ] +} +*/ diff --git a/terraform/modules/cadolesDNS/main.tf b/terraform/modules/cadolesDNS/main.tf new file mode 100644 index 0000000..be8ca7f --- /dev/null +++ b/terraform/modules/cadolesDNS/main.tf @@ -0,0 +1,29 @@ +// Dependencies management +resource "null_resource" "depends_on" { + triggers = { + depends_on = join("", var.depends) + } +} + + +resource "dns_a_record_set" "a_records" { + for_each = var.dns_a_records + + zone = var.dns_domain + name = each.key + ttl = 300 + + addresses = each.value + depends_on = [ null_resource.depends_on ] +} + +resource "dns_cname_record" "cname_records" { + for_each = var.dns_cname_records + + zone = var.dns_domain + name = each.key + cname = each.value + ttl = 300 + + depends_on = [ null_resource.depends_on ] +} diff --git a/terraform/modules/cadolesDNS/outputs.tf b/terraform/modules/cadolesDNS/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/terraform/modules/cadolesDNS/variables.tf b/terraform/modules/cadolesDNS/variables.tf new file mode 100644 index 0000000..9f9f51c --- /dev/null +++ b/terraform/modules/cadolesDNS/variables.tf @@ -0,0 +1,23 @@ +variable "dns_domain" { + description = "DNS Domain name (FQDN)" + type = string + default = "cadoles.com." +} + +variable "dns_a_records" { + description = "List of dns A records to create" + type = map + default = {} +} + +variable "dns_cname_records" { + description = "List of CNAME entires" + type = map + default = {} +} + +variable "depends" { + description = "List of output_variables for dependences management" + type = list + default = [] +} \ No newline at end of file diff --git a/terraform/modules/virtualMachine/main.tf b/terraform/modules/virtualMachine/main.tf new file mode 100644 index 0000000..7ec57c4 --- /dev/null +++ b/terraform/modules/virtualMachine/main.tf @@ -0,0 +1,115 @@ +// Dependencies management +resource "null_resource" "depends_on" { + triggers = { + depends_on = join("", var.depends) + } +} + +// OpenNebula disk image ! +resource "opennebula_image" "system" { + name = var.system_image_name + description = "System disk image" + datastore_id = var.one_prod_ds + //persistent = false + persistent = true + //lock = "MANAGE" + path = var.system_image_source + dev_prefix = "vd" + driver = "qcow2" + format = "qcow2" + permissions = "660" + group = "production" +} + +resource "opennebula_image" "data" { + name = var.data_image_name + description = "Data disk image" + datastore_id = var.one_prod_ds + persistent = true + //lock = "MANAGE" + path = var.data_image_source + dev_prefix = "vd" + driver = "qcow2" + format = "qcow2" + permissions = "660" + group = "production" + count = var.data_image_name != "" ? 1 : 0 +} + +// OpenNebula (VM) Template definition +resource "opennebula_template" "vm_template" { + name = var.vm_shortname + cpu = var.cpu + vcpu = var.vcpu + memory = var.ram + graphics { + keymap = "fr" + listen = "0.0.0.0" + type = "VNC" + } + context = { + DNS_HOSTNAME = "yes" + NETWORK = "YES" + SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]" + USERNAME = "root" + } + + disk { + image_id = opennebula_image.system.id + } + + dynamic "disk" { + for_each = opennebula_image.data + content { + image_id = disk.id + } + } + + //labels = var.tag_labels + + dynamic "nic" { + for_each = var.network_interfaces + + content { + network_id = var.vnets[nic.value.network_name].id + model = "virtio" + ip = nic.value.ip + } + } + permissions = "600" + group = "production" + depends_on = [ opennebula_image.system, + opennebula_image.data ] +} + +// OpenNebula Virtual Machine +resource "opennebula_virtual_machine" "vm" { + name = var.vm_fqdn + group = "production" + timeout = 10 + template_id = opennebula_template.vm_template.id + depends_on = [ opennebula_template.vm_template, + null_resource.depends_on ] +} + +resource "dns_a_record_set" "vm_dns_a_record" { + count = var.dns_a_record == "yes" ? 1 : 0 + + zone = var.vm_domain + name = var.vm_shortname + ttl = 300 + + addresses = [ var.network_interfaces[0].ip ] + depends_on = [ opennebula_virtual_machine.vm ] +} + +resource "dns_cname_record" "vm_dns_cname_record" { + for_each = var.dns_cname_record + + zone = var.vm_domain + name = each.value + cname = "${var.vm_fqdn}." + ttl = 300 + + depends_on = [ opennebula_virtual_machine.vm ] +} diff --git a/terraform/modules/virtualMachine/outputs.tf b/terraform/modules/virtualMachine/outputs.tf new file mode 100644 index 0000000..26c74dc --- /dev/null +++ b/terraform/modules/virtualMachine/outputs.tf @@ -0,0 +1,7 @@ +output "virtual_machine_shortname" { + value = opennebula_virtual_machine.vm.name +} + +output "network_interfaces" { + value = var.network_interfaces +} \ No newline at end of file diff --git a/terraform/modules/virtualMachine/variables.tf b/terraform/modules/virtualMachine/variables.tf new file mode 100644 index 0000000..5b84d3c --- /dev/null +++ b/terraform/modules/virtualMachine/variables.tf @@ -0,0 +1,93 @@ +variable "one_user" { + description = "OpenNebula user" + type = string +} + +variable "one_prod_ds" { + description = "ID du Datastore de production" + type = string +} + +variable "vm_fqdn" { + description = "Virtual Machine FQDN Name" + type = string +} + +variable "vm_shortname" { + description = "Virtual machine short name" + type = string +} + +variable "vm_domain" { + description = "Full qualified dns domain name" + type = string +} + +variable "system_image_name" { + description = "System image disk name" + type = string +} + +variable "system_image_source" { + description = "Virtual Machine system image source" + type = string +} + +variable "data_image_name" { + description = "Data image disk name" + type = string +} + +variable "data_image_source" { + description = "Virtual Machine data disk image source" + type = string +} + +variable "tag_labels" { + description = "Labels" + type = string +} + +variable "network_interfaces" { + description = "Network interfaces" + type = list +} + +variable "cpu" { + description = "VM CPU" + type = string +} + +variable "vcpu" { + description = "VM vCPU" + type = string +} + +variable "ram" { + description = "VM RAM" + type = string +} + +variable "depends" { + description = "List of output_variables for dependences management" + type = list + default = [] +} + +variable "dns_a_record" { + description = "Create a dns A record (yes/no)" + type = string + default = "no" +} + +variable "dns_cname_record" { + description = "List of CNAME for A entry" + type = map(string) + default = {} +} + +variable "vnets" { + description = "OpenNebula virtual network resource" + type = map + default = {} +} \ No newline at end of file diff --git a/terraform/modules/virtualMachine/versions.tf b/terraform/modules/virtualMachine/versions.tf new file mode 100644 index 0000000..a983d4a --- /dev/null +++ b/terraform/modules/virtualMachine/versions.tf @@ -0,0 +1,15 @@ +terraform { + required_providers { + dns = { + source = "hashicorp/dns" + } + null = { + source = "hashicorp/null" + } + opennebula = { + source = "OpenNebula/opennebula" + version = "0.3.0" + } + } + required_version = ">= 0.13" +} diff --git a/terraform/templates/groups/standard.tpl b/terraform/templates/groups/standard.tpl new file mode 100644 index 0000000..1f3b9a7 --- /dev/null +++ b/terraform/templates/groups/standard.tpl @@ -0,0 +1,4 @@ +SUNSTONE = [ + DEFAULT_VIEW = "${group_default_view}", + VIEWS = "group_views" +] \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..2cf3ece --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,82 @@ +/* + * Variables + */ + +variable "one_endpoint" { + description = "OpenNebula endpoint" + type = string +} + +variable "one_user" { + description = "OpenNebula user" + type = string +} + +variable "one_pass" { + description = "OpenNebula password" + type = string +} + +variable "one_vswitch" { + description = "OpenvSwitch bridge name" + type = string +} +variable "dns_server" { + description = "DNS Server IP" + type = string +} + +variable "cluster_id" { + description = "Cadoles ONE cluster ID" + type = string +} + +variable "one_prod_ds" { + description = "ID du Datastore de production" + type = string +} + +variable "dns_domain" { + description = "DNS Full qualified domain" + type = string +} + +variable "dns_key_name" { + description = "DDNS Key name" + type = string +} + +variable "dns_key_algo" { + description = "DDNS Key algorithm" + type = string + default = "hmac-sha256" +} + +variable "dns_key_secret" { + description = "DDNS Key secret" + type = string +} + +variable "dns_zones" { + description = "DNS Zone description" + type = list + default = [] +} + +variable "image_builder_ip" { + description = "Image builder IP" + type = string + default = "192.168.5.251" +} + +variable "virtual_networks" { + description = "OpenNebula virtual networks definition" + type = map + default = {} +} + +variable "virtual_machines" { + description = "OpenNebula virtual machines definition" + type = map + default = {} +} \ No newline at end of file diff --git a/terraform/version.tf b/terraform/version.tf new file mode 100644 index 0000000..67a5e3d --- /dev/null +++ b/terraform/version.tf @@ -0,0 +1,11 @@ +terraform { + required_providers { + dns = { + source = "hashicorp/dns" + } + opennebula = { + source = "opennebula/opennebula" + } + } + required_version = ">= 0.13" +} \ No newline at end of file