diff --git a/README.md b/README.md index 4d8ebf2..01a6b25 100644 --- a/README.md +++ b/README.md @@ -100,65 +100,6 @@ The "Import?" column refers to support for [importing existing openstack configu | Image elements | No | N/A | Considered out of scope | | Ratings | No | N/A | | -## Network config example -The following is an example config for how to use the new network support. A single -project is defined which contains a single subnet. - -Note that: -- Networks (and their subnets) and routers do not necessarily have to be associated -with a project. If they are this association can be made with the project's name -(if the project is controllled by this config) or by a project/tenant id from -OpenStack (if it is not). -- The names in OpenStack for networks, subnets and routers are not necessarily unique -across projects. Therefore these resources have a tofu resource name which must be -unique across projects, which can be used to refer to them for other resources. -It is suggested that a convention of using `$NAME:$PROJECT_NAME` is used. - - -``` -module "openstack" { - source = "github.com/stackhpc/tofu-openstack-config?ref=main" - projects = { - "demo-project" = { - compute_quota = { - } - network_quota = { - } - blockstorage_quota = { - } - } - } - - networks = { - "demo-network:demo-project" = { # unique tofu resource name - name = "demo-network" # openstack network name - project = "demo-project" - - subnets = { - "demo-subnet:demo-project" = { # unique tofu resource name - name = "demo-subnet" # openstack subnet name - cidr = "10.0.0.0/24" - } - } - } - } - - routers = { - "demo-router:demo-project" = { # unique tofu resource name - name = "demo-router" # openstack router name - project = "demo-project" - external_network = "demo-network:demo-project" # unique tofu resource name of network - external_fixed_ips = [{ - subnet = "demo-subnet:demo-project" # unique tofu resource name of subnet - }] - interfaces = [ - { subnet = "demo-subnet:demo-project" } # unique tofu resource name of subnet - ] - } - } - -} -``` ## Current Issues @@ -267,3 +208,38 @@ committed, it does not matter. - Changes to the `src/` files are picked up when running `tofu-os-cfg`. - Note that the `--output` argument can be used to determine where files are generated. + +## VAST Support + +Support for resources: +- `vastdata_vip_pool` +- `vastdata_tenant` + +To use the VAST resources, you'll need a `provider.tf` file in your `tofu/` dir containing +the required config: + +```shell +terraform { + required_providers { + vastdata = { + source = "vast-data/vastdata" + version = "2.1.1" + } + } +} + +provider "vastdata" { + username = #string + port = #number + password = var.vast_password #string + host = #string + skip_ssl_verify = true +} + +variable "vast_password" { + sensitive = true +} +``` + +Filling in the missing variables in the `provider "vastdata"` block. More infomation +on the vastdata provider config can be found in the [HashiCorp Terrafrom docs](https://registry.terraform.io/providers/vast-data/vastdata/latest/docs#example-usage). diff --git a/docs/flavors.md b/docs/flavors.md new file mode 100644 index 0000000..c0b1df9 --- /dev/null +++ b/docs/flavors.md @@ -0,0 +1,36 @@ +## Flavors + +To create a flavor, + +Example usage: + +```console +flavors = { + "test-flavour" = { + ram = 4096 + vcpus = 1 + disk = 50 + ephemeral = 0 + swap = 0 + rx_tx_factor = 1.0 + is_public = true + extra_specs = { + } + projects = [ + "client", "client-other-project" + ] + } +} +``` + +Argument reference: +- `ram` (Required) number. Value in megabytes. Changing this creates a new flavor. +- `vcpus` (Required) number. Changing this creates a new flavor. +- `disk` (Required) number. Value in GiB. Changing this creates a new flavor. +- `ephemral` (Optional) number. Changing this creates a new flavor. +- `swap` (Optional) number. The amount of disk space in megabytes to use. Changing this creates a new flavor. +- `rx_tx_factor` (Optional) number. Changing this creates a new flavor. +- `is_public` (Optional) bool, default true. If "projects" is non-empty this is ignored and set false. Changing this creates a new flavor. +- `flavor_id` (Optional) string. Changing this creates a new flavor access +- `extra_specs` (Optional) map of strings +- `projects` (Optional) list of strings. Project names to have access to the flavor. Changing this creates a new flavor access. diff --git a/docs/guide.md b/docs/guide.md new file mode 100644 index 0000000..329433f --- /dev/null +++ b/docs/guide.md @@ -0,0 +1,28 @@ +# Tofu OpenStack Config User Guide + +Tofu OpenStack Config allows you to manage your Openstack config using Terraform. +This guide will provide you with example templates for available resources. A full +list of variables available for each resource can be found in [variables.tf](https://github.com/stackhpc/tofu-openstack-config/blob/main/variables.tf), +with a description and type. + +It is recommended for easy readibility to separate your resources in `main.tf` +as follows: + +```console +module "openstack" { + source = + + projects = local.project-config + networks = local.network-config + ... +} +``` + +The config for each resource can then be written into separate files, suggested +format is `-config.tf`, for example: + +- project-config.tf +- network-config.tf +- router-config.tf + +For information on how local values work, see this [opentofu.org website](https://opentofu.org/docs/language/values/locals/). diff --git a/docs/guide.rst b/docs/guide.rst new file mode 100644 index 0000000..9c13936 --- /dev/null +++ b/docs/guide.rst @@ -0,0 +1,364 @@ +================================ +Tofu OpenStack Config User Guide +================================ + +Tofu OpenStack Config allows you to manage your OpenStack config using Terraform. +This guide will provide you with example templates for available resources. A full +list of variables available for each resource can be found in `variables.tf`_, +with a description and type. + +It is recommended for easy readibility to separate your resources in ``main.tf`` +as follows: + +.. code-block:: console + + module "openstack" { + source = + + projects = local.project-config + networks = local.network-config + ... + } + +The config for each resource can then be written into separate files, suggested +format is ``-config.tf``, for example: + +- project-config.tf +- network-config.tf +- router-config.tf + +Projects +--------- + +To create a project, add config to ``project-config.tf``. + +Template: + +.. code-block:: console + + locals { + project-config = { + ## start of template + "" = { + description = + computa_quota = { + cores = + instances = + ram = + .... + } + network_quota = { + networks = + ports = + rbac_policies = + .... + } + blockstorage_quota = { + volumes = + snapshots = + gigbytes = + .... + } + } + ## end of template + } + } + +Flavors +------- + +To create a flavor, add config to ``flavor-config.tf``. + +Template: + +.. code-block:: console + + locals { + flavor-config = { + ## start of template + = { + ram = + vcpus = + disk = + ... + projects = [ ... ] + } + ## end of template + } + } + +Networks +-------- + +To create a network, add config to ``network-config.tf``. + +Template: + +.. code-block:: console + + locals { + network-config = { + ## start of template + "" = { + name = "" + shared = + external = + admin_state_up = + project = "" + tenant_id = # does not need to be defined if project is defined + mtu = + port_security_enabled = + + segments = [{ + physical_network = + network_type = + segmentation_id = + }] + + subnets = { + # first subnet config + "" = { + name = "" + cidr = "" + ip_version = + gateway_ip = "" + enable_dhcp = + + allocation_pool = [{ + start = "" + end = "" + }] + } , # subnets need to be separated by a comma (,) + # second subnet config + "" = { + name = "" + region = + external_network = "" + # or + external_network_id = + project = "" + # or + tenant_id = + ... + + external_fixed_ips = [ + { subnet = "" }, # external_fixed_ips need to be separated by a comma (,) + { subnet_id = } + ... + ] + + interfaces = [ + { subnet = "" }, # interfaces need to be separated by a comma (,) + { subnet_id = } + ... + ] + } + ## end of template + } + } + +Users +----- + +To create a new user, add config to ``user-config.tf``. + +Template: + +.. code-block:: console + + locals { + user-config = { + ## start of template + "" = { + name = "" + default_project = "" + groups = [ + "", + "" + ... + ] + } + ## end of template + } + } + +For users to have access to projects - groups and roles need to be created then +users are assigned the corresponding groups that match their project:role needs. + +Groups +------ + +To create a group, add config to ``group-config.tf``. + +Template: + +.. code-block:: console + + locals { + group-config = { + admins = "" + ## start of template + = "" + ## end of template + } + } + + +Roles +----- + +To create a role, add config to ``role-config.tf``. + +Available roles can be seen by running ``openstack role list`` + +Template: + +.. code-block:: console + + locals { + role-config = [ + ## start of template + { + role = "member" + group = "" + project = "" + }, + { + role = "admin" + group = "" + project = "" + }, + ... + ## end of template + ] + } + +Images +------ + +To create an image, add config to ``image-config.tf``. + +Template: + +.. code-block:: console + + locals { + image-config = { + ## start of template + = { + container_format = + disk_format = + image_source_url = + ... + } + ## end of template + } + +Sharetypes +---------- + +To create a sharetype, add config to ``sharetype-config.tf``. + +Template: + +.. code-block:: console + + locals { + sharetype-config = { + ## start of template + = { + name = + description = + is_public = + + extra_specs = { + driver_handles_share_servers = + snapshot_support = + share_backend_name = + vippoolname = # see opentofu manila integration + } + } + ## end of template + } + } + + +Sharetypes Access +----------------- + +For projects to have access to the correct sharetypes, the ``sharetypes_access`` +resource is used. + +To create a sharetype access, add config to ``sharetype-access.tf``. + +Template: + +.. code-block:: console + + locals { + sharetype-access-config = { + ## start of templace + = { + share_type_id = + project = + # or + project_id = + } + ## end of template + } + } + +================================= +OpenTofu Vast Manila Integration +================================= + +To access the ``vippools`` resource from the `OpenTofu Vast Manila`_ module, +you need to provide the ``openstack`` module with the ``vast`` resources. +This can be done by including the following in your ``main.tf``: + +.. code-block:: console + + ##main.tf + module "openstack" { + source = "github.com/stackhpc/tofu-openstack-config?ref=main" + # this lines takes the vippools resources from the module "vast" into the openstack module + vippools = module.vast.vippools + ... + } + + module "vast" { + source = "github.com/stackhpc/opentofu-vast-manila?ref=main" + + vippools = + ... + } + +.. _OpenTofu Vast Manila: https://github.com/stackhpc/opentofu-vast-manila/ +.. _variables.tf: https://github.com/stackhpc/tofu-openstack-config/blob/main/variables.tf diff --git a/docs/identity.md b/docs/identity.md new file mode 100644 index 0000000..da57a3b --- /dev/null +++ b/docs/identity.md @@ -0,0 +1,76 @@ +## Users + +To create a new user, + +Example usage: + +```console +users = { + "" = { + name = "bob" + default_project = "client" + email = "bob@client.com" + description = "Bob from client" + groups = [ + "admin:client", + "member:client-other-project" + ] + } +} +``` + +Argument reference: +- `description` (Optional) string +- `email` (Optional) string +- `groups` (Optional) string +- `password` (Optional) string +- `default_project` (Optional) string. Project name. + +For users to have access to projects - groups and role assignments need to be created then +users are assigned the corresponding groups that match their `role:project` needs. + +## Groups + +To create a group, add config to `group-config.tf`. + +Template: + +```console +group-config = { + "admin:client" = "Admins of client project" + "member:client" = "Members of client project" + ... +} +``` + +Argument reference: +- `description` (Optional) string + +## Role assignment + +To create a role, + +Available roles can be seen by running `openstack role list` + +Example usage: + +```console + role_assignments = [ + { + role = "admin" + group = "admin:client" + project = "client" + }, + { + role = "member" + group = "member:client-other-project" + project = "client-other-project" + }, + ... + ] +``` + +Argument reference: +- `role` (Required) string. Role name, available roles found by running `openstack role list`. +- `group` (Required) string. Group name. +- `project` (Required) string. Project name. \ No newline at end of file diff --git a/docs/images.md b/docs/images.md new file mode 100644 index 0000000..6dde823 --- /dev/null +++ b/docs/images.md @@ -0,0 +1,29 @@ +## Images + +To create an image, + +Example usage: + +```console +images = { + "Ubuntu-24.04-20260323-noble-server-cloudimg-amd64" = { + image_source_url = "https://cloud-images.ubuntu.com/noble/20260323/noble-server-cloudimg-amd64.img" + container_format = "bare" + disk_format = "qcow2" + } +} +``` + +Argument reference: +- `container_format` (Required) string. Must be one of "bare", "ovf", "aki", "ari", "ami", "ova", "docker", "compressed". +- `disk_format` (Required) string. Must be one of "raw", "vhd", "vhdx", "vmdk", "vdi", "iso", "ploop", "qcow2", "aki", "ari", "ami". +- `image_cache_path` (Optional) string. +- `image_source_url` (Optional) string. +- `image_id` (Optional) string. +- `min_disk_gb` (Optional) number, default 0. +- `min_ram_mb` (Optional) number, default 0. +- `protected` (Optional) bool, default false. +- `hidden` (Optional) bool, default false. +- `web_download` (Optional) bool, default false. +- `properties` (Optional) list of strings. +- `visibility` (Optional) string. diff --git a/docs/networking.md b/docs/networking.md new file mode 100644 index 0000000..d51a81d --- /dev/null +++ b/docs/networking.md @@ -0,0 +1,139 @@ +## Networking config + +Note that: + +- Networks (and their subnets) and routers do not necessarily have to be associated with a project. If they are this association can be made with the project's name (if the project is controllled by this config) or by a project/tenant id from OpenStack (if it is not). +- The names in OpenStack for networks, subnets and routers are not necessarily unique across projects. Therefore these resources have a tofu resource name which must be unique across projects, which can be used to refer to them for other resources. It is suggested that a convention of using $NAME:$PROJECT_NAME is used. + + +## Networks + +To create a network, + +Example usage: + +```console +network = { + "client_net_data:client" = { + name = "client-net-data" + project = "client" + admin_state_up = true + external = false + mtu = 9000 + port_security_enabled = false + + segments = [{ + network_type = "vlan" + physical_network = "physnet1" + }] + + subnets = { + "client_subnet_data:client" = { + name = "client-subnet-data" + ip_version = 4 + no_gateway = true + + #project-nets + subnetpool_id = "..." + prefix_length = 24 + } + } + } +} +``` + +Argument reference: +- `name` (Required) string. +- `region` (Optional) string. Changing this creates a new network. +- `shared` (Optional) bool, default false. +- `external` (Optional) bool, default false. +- `admin_state_up` (Optional) bool, default false. +- `project` (Optional) string. Project name, overrides `tenant_id`. Changing this creates a new network. +- `tenant_id` (Optional) string. Openstack project id, overriden by `project`. Changing this creates a new network. +- `mtu` (Optional) number. +- `port_sercuirty_enabled` (Optional) bool, default false. +- `tags` (Optional) list. +- `segments` (Optional) list of objects, block supports: + - `physical_network` (Optional) string. + - `network_type` (Optonal) string. + - `segmentation_id` (Optional) string. +- `subnets` (Optional) list of maps, block supports: + - `key` (Required) string. + - `name` (Required) string. + - `region` (Optional) string. Changing this creates a new subnet. + - `cidr` (Optional) string. Can omit option if creating subnet from a subnet pool (using `subnetpool_id` ). + - `ip_version` (Optional) number, default 4. Changing this creates a new subnet. + - `gateway_ip` (Optional) string. + - `enable_dhcp` (Optional) bool, default true. + - `dns_nameserver` (Optional) list. + - `dns_publish_fixed_ips` (Optional) bool, default false. + - `service_type` (Optional) list + - `subnetpool_id` (Optional) string + - `prefix_length` (Optional) number + - `no_gateway` (Optional) bool + - `tags` (Optional) list + - `allocation_pool` (Optional) list, block supports: + - `start` (Required) string. + - `end` (Required) string. + + +## Routers + +To create a router, + +Example usage: + +```console +routers = { + "internal:admin" = { + name = "internal" + external_network = "internal-net:admin" # tofu resource name of network + project = "admin" + + external_fixed_ips = [ + { subnet = "internal-net:admin" } + ] + + interfaces = [ + { subnet = "internal-net:admin" } + ] + } +} +``` + +Arguments referenece: +- `name` (Required) string. Openstack router name. +- `region` (Optional) string. Changing this creates a new router. +- `external_network` (Optional) string. Tofu resource name of network. +- `external_network_id` (Optional) string. Openstack network id. +- `admin_state_up` (Optional) bool. +- `project` (Optional) string. Project name, overrides `tenant_id`. Changing this creates a new router. +- `tenant_id` (Optional) string. Openstack project id, overriden by `project`. Changing this creates a new router. +- `tags` (Optional) list. +- `external_fixed_ip` (Optional) list of maps, block supports: + - `subnet` (Optional) string. Tofu resource name of subnet. + - `subnet_id` (Optional) string. Openstack subnet id. + - `ip_address` (Optional) string. +- `interfaces` (Optional) list of maps, block supports: + - `region` (Optional) string. Changing this creates a new router interface. + - `subnet` (Optional) string. Tofu resource name of subnet, overrides `subnet_id`. Changing this creates a new router interface. + - `subnet_id` (Optional) string. Openstack subnet id, overriden by `subnet`. Changing this creates a new router interface. + - `port_id` (Optional) string. Openstack port id. Changing this creates a new router interface. + - `force_destroy` (Optional) bool, default false. + +## Network RBAC +To create a network RBAC (role based access control), + +Example usage: + +```console +network_rbac = { + +} +``` + +Argument reference: +- `network` (Required) string. Changing this creates a new routing entry. +- `projects` (Required) list of strings. Project names. +- `access` (Required) string. Valid values are either `access_as_external` or `access_as_shared`. + diff --git a/docs/projects.md b/docs/projects.md new file mode 100644 index 0000000..2d079c9 --- /dev/null +++ b/docs/projects.md @@ -0,0 +1,72 @@ +## Projects + +To create a project, add the config to `project-config.tf`. + +Example Usage: + +```console +projects = { + "client" = { + description = "client project" + compute_quota = { + key_pairs = 100 + ram = -1 + cores = -1 + instances = 10 + server_groups = 10 + server_group_members = 10 + } + + blockstorage_quota = { + volumes = 50 + snapshots = 10 + gigabytes = 100 + per_volume_gigabytes = 20 + backups = 10 + backup_gigabytes = 1000 + groups = 10 + } + + network_quota = { + floating_ips = 50 + network = 100 + port = 500 + rbac_policy = 10 + router = 10 + subnet = 100 + subnetpool = -1 + security_group_rule = 100 + security_group = 10 + } + } +} +``` + +Argument reference: +- `description` (Optional) string +- `compute_quota` (Required), block supports: + - `key_pairs` (Optional) number + - `ram` (Optional) number + - `cores` (Optional) number + - `instances` (Optional) number + - `server_groups` (Optional) number + - `server_group_members` (Optional) number +- `blockstorage_quota` (Required), block supports: + - `volumes` (Optional) number + - `snapshots` (Optional) number + - `gigabytes` (Optional) number + - `per_volume_gigabytes` (Optional) number + - `backups` (Optional) number + - `backup_gigabytes` (Optional) number + - `groups` (Optional) number + - `volume_type_quota` (Optional) map +- `network_quota` (Required), block supports: + - `floatingip` (Optional) number + - `network` (Optional) number + - `port` (Optional) number + - `rbac_policy` (Optional) number + - `router` (Optional) number + - `security_group` (Optional) number + - `security_group_rule` (Optional) number + - `subnet` (Optional) number + - `subnetpool` (Optional) number diff --git a/docs/shared_filesystem.md b/docs/shared_filesystem.md new file mode 100644 index 0000000..88ecc24 --- /dev/null +++ b/docs/shared_filesystem.md @@ -0,0 +1,69 @@ +> **WARNING:** +> +>The resources: +>- `openstack_sharedfilesystem_sharetype_v2` used for `sharetypes`. +>- `openstack_sharedfilesystem_sharetype_access_v2` used for `sharetypes_access`. +> +>Are currently in development in opentofu. Therefore, they require +>a custom provider to use. + + +## Sharetypes + +To create a sharetype, + +Example usage: + +```console +sharetypes = { + client_sharetype = { + name = "client-vast" + description = "client - data" + is_public = false + + extra_specs = { + driver_handles_share_servers = false + snapshot_support = true + share_backend_name = "VAST" + vippoolname = "client_manila" + } + } +} +``` + +Argument reference: +- `description` (Optional) string +- `is_public` (Optional) bool, default true +- `extra_specs` (Required), block supports: + - `driver_handles_share_servers` (Required) bool + - `snapshot_support` (Optional) bool + - `share_backend_name` (Required) string + - `vippoolname` (Required) string + +## Sharetypes Access + +For projects to have access to the correct sharetypes, the `sharetypes_access` +resource is used. + +To create a sharetype access, + +Example usage: + +```console +sharetypes-access = { + "client4_sharetype_access" = { + sharetype_name = "client4_sharetype" + project = "client" + } +} +``` + +Argument reference: +One is required: +- `sharetype_name` string +or +- `share_type_id` string +One is required: +- `project` string +or +- `project_id` string diff --git a/docs/vast.md b/docs/vast.md new file mode 100644 index 0000000..6e5049d --- /dev/null +++ b/docs/vast.md @@ -0,0 +1,88 @@ +## Vippools + +To create a vippool, + +Example usage: + +```console +vippools = { + "client_manila" = { + subnet_cidr = "24" + network = "client_net_data:client" + + vast_tenant = "client" + + vip_ranges = [{ + subnet = "client_subnet_data:client" + start = 200 + end = 249 + }] + } + +} +``` + +Arugment reference: +- `name` (Optional) string. +- `network` (Optional) string. Tofu resource network name. +- `vlan` (Optional) string +- `role` (Optional) string +- `subnet_cidr` (Optional) number +- `tenant_id` (Optional) string. Vast tenant id. Overriden by `vast_tenant`. +- `vast_tenant` (Optional) string. Vast tenant name. Overrides `tenant_id`. +- `vip_ranges` (Optional) list. Overriden by `ip_ranges`. Block supports: + - `subnet` (Required) number. Tofu resource name of subnet. + - `start` (Requied) number + - `end` (Required) number +- `ip_ranges` (Optional) list. Overrides `vip_ranges`. + + +## Vast Tenants + +To create a vast tenant, + +Example usage: + +```console +vast_tenants = { + "testclient" = { + allow_locked_users = true + allow_disabled_users = true + + client_ranges = [{ + subnet = "testclient_subnet_data:testclient" + start = 2 + end = 149 + }] + } +} +``` + +Argument reference: +- `allow_locked_users` (Optional) bool +- `allow_disabled_users` (Optional) bool +- `client_ranges` (Optional) list. Overriden by `client_ip_ranges`. Block supports: + - `subnet` (Required) string. Tofu resource name of subnet. + - `start` (Required) number + - `end` (Required) number +- `client_ip_ranges` (Optional) list. Overrides `client_ranges`. + +## Vast host + +To set the vast host set: + +```console +vast_host = string +``` + +By default `vast_host` is set to `10.3.2.10` . + +## Vast username + +To set the vast username set: + +```console +username = string +``` + +By default `username` is set to `openstack-manila` . \ No newline at end of file