diff --git a/environments/net-multiple-nics-vlans.j2.yaml b/environments/net-multiple-nics-vlans.j2.yaml new file mode 100644 index 0000000000..7ce7159c5d --- /dev/null +++ b/environments/net-multiple-nics-vlans.j2.yaml @@ -0,0 +1,13 @@ +# This template configures each role to use a separate NIC for +# each isolated network with tagged VLANs on each NIC. +# This template assumes use of network-isolation.yaml. +# +# FIXME: if/when we add functionality to heatclient to include heat +# environment files we should think about using it here to automatically +# include network-isolation.yaml. +# +resource_registry: +{%- for role in roles %} + # Network configuration assignments for the {{role.name}} + OS::TripleO::{{role.name}}::Net::SoftwareConfig: ../network/config/multiple-nics-vlans/{{role.deprecated_nic_config_name|default(role.name.lower() ~ ".yaml")}} +{%- endfor %} diff --git a/network/config/multiple-nics-vlans/README.md b/network/config/multiple-nics-vlans/README.md new file mode 100644 index 0000000000..208bb53bbd --- /dev/null +++ b/network/config/multiple-nics-vlans/README.md @@ -0,0 +1,46 @@ +This directory contains Heat templates to help configure +multiple NICs for each Overcloud role, where it is +assumed that each NIC is running a specific network +traffic type with tagged VLANs. + +Configuration +------------- + +To make use of these templates create a Heat environment that looks +something like this: + + resource\_registry: + OS::TripleO::BlockStorage::Net::SoftwareConfig: network/config/multiple-nics/cinder-storage.yaml + OS::TripleO::Compute::Net::SoftwareConfig: network/config/multiple-nics/compute.yaml + OS::TripleO::Controller::Net::SoftwareConfig: network/config/multiple-nics/controller.yaml + OS::TripleO::ObjectStorage::Net::SoftwareConfig: network/config/multiple-nics/swift-storage.yaml + OS::TripleO::CephStorage::Net::SoftwareConfig: network/config/multiple-nics/ceph-storage.yaml + +Or use this Heat environment file: + + environments/net-multiple-nics-vlans.yaml + +Configuration with System Management Network +-------------------------------------------- + +The Management network is enabled for backwards-compatibility, but +is not included in any roles by default. To enable the optional System +Management network, create a Heat environment that looks something like +this: + + resource\_registry: + OS::TripleO::Network::Management: ../network/management.yaml + OS::TripleO::Controller::Ports::ManagementPort: ../network/ports/management.yaml + OS::TripleO::Compute::Ports::ManagementPort: ../network/ports/management.yaml + OS::TripleO::CephStorage::Ports::ManagementPort: ../network/ports/management.yaml + OS::TripleO::ObjectStorage::Ports::ManagementPort: ../network/ports/management.yaml + OS::TripleO::BlockStorage::Ports::ManagementPort: ../network/ports/management.yaml + +Or use this Heat environment file: + + environments/network-management.yaml + +Or, add the network to the list of networks used by each role in the role +definition file (e.g. roles_data.yaml). Refer to installation documentation +for procedure to generate a role file for custom roles. + diff --git a/network/config/multiple-nics-vlans/compute-dvr.j2.yaml b/network/config/multiple-nics-vlans/compute-dvr.j2.yaml new file mode 100644 index 0000000000..72f6f4d811 --- /dev/null +++ b/network/config/multiple-nics-vlans/compute-dvr.j2.yaml @@ -0,0 +1,198 @@ +# FIXME: This legacy template should be converted to a composable role +heat_template_version: rocky +description: > + Software Config to drive os-net-config to configure multiple interfaces for the + compute role with external bridge for DVR. +parameters: + ControlPlaneIp: + default: '' + description: IP address/subnet on the ctlplane network + type: string + ControlPlaneSubnetCidr: + default: '' + description: > + The subnet CIDR of the control plane network. (The parameter is + automatically resolved from the ctlplane subnet's cidr attribute.) + type: string + ControlPlaneDefaultRoute: + default: '' + description: The default route of the control plane network. (The parameter + is automatically resolved from the ctlplane subnet's gateway_ip attribute.) + type: string + ControlPlaneStaticRoutes: + default: [] + description: > + Routes for the ctlplane network traffic. + JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}] + Unless the default is changed, the parameter is automatically resolved + from the subnet host_routes attribute. + type: json + ControlPlaneMtu: + default: 1500 + description: The maximum transmission unit (MTU) size(in bytes) that is + guaranteed to pass through the data path of the segments in the network. + (The parameter is automatically resolved from the ctlplane network's mtu attribute.) + type: number +{% for network in networks %} + {{network.name}}IpSubnet: + default: '' + description: IP address/subnet on the {{network.name_lower}} network + type: string + {{network.name}}NetworkVlanID: + default: {{network.vlan|default(1)}} + description: Vlan ID for the {{network.name_lower}} network traffic. + type: number + {{network.name}}Mtu: + default: {{network.mtu|default('1500')}} + description: The maximum transmission unit (MTU) size(in bytes) that is + guaranteed to pass through the data path of the segments in the + {{network.name}} network. + type: number + {{network.name}}InterfaceRoutes: + default: [] + description: > + Routes for the {{network.name_lower}} network traffic. + JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}] + Unless the default is changed, the parameter is automatically resolved + from the subnet host_routes attribute. + type: json +{%- endfor %} + # Uncomment when including environments/network-management.yaml and setting + # default route on the Management interface. Also comment out the default + # route on the Control Plane and add the Management network to the roles + # default_route_networks in roles data. + # ManagementInterfaceDefaultRoute: + # default: '' + # description: default route for the management network + # type: string + DnsServers: # Override this via parameter_defaults + default: [] + description: > + DNS servers to use for the Overcloud (2 max for some implementations). + If not set the nameservers configured in the ctlplane subnet's + dns_nameservers attribute will be used. + type: comma_delimited_list + DnsSearchDomains: # Override this via parameter_defaults + default: [] + description: A list of DNS search domains to be added (in order) to resolv.conf. + type: comma_delimited_list + +resources: + OsNetConfigImpl: + type: OS::Heat::SoftwareConfig + properties: + group: script + config: + str_replace: + template: + get_file: ../../scripts/run-os-net-config.sh + params: + $network_config: + network_config: + - type: interface + name: nic1 + mtu: + get_param: ControlPlaneMtu + use_dhcp: false + dns_servers: + get_param: DnsServers + domain: + get_param: DnsSearchDomains + addresses: + - ip_netmask: + list_join: + - / + - - get_param: ControlPlaneIp + - get_param: ControlPlaneSubnetCidr + routes: + list_concat_unique: + - get_param: ControlPlaneStaticRoutes + - - default: true + next_hop: + get_param: ControlPlaneDefaultRoute + - type: interface + name: nic2 + mtu: + get_param: StorageMtu + use_dhcp: false + - type: vlan + device: nic2 + mtu: + get_param: StorageMtu + vlan_id: + get_param: StorageNetworkVlanID + addresses: + - ip_netmask: + get_param: StorageIpSubnet + routes: + get_param: StorageInterfaceRoutes + - type: interface + name: nic4 + mtu: + get_param: InternalApiMtu + use_dhcp: false + - type: vlan + device: nic4 + mtu: + get_param: InternalApiMtu + vlan_id: + get_param: InternalApiNetworkVlanID + addresses: + - ip_netmask: + get_param: InternalApiIpSubnet + routes: + get_param: InternalApiInterfaceRoutes + - type: ovs_bridge + name: br-tenant + mtu: + get_param: TenantMtu + use_dhcp: false + addresses: + - ip_netmask: + get_param: TenantIpSubnet + routes: + get_param: TenantInterfaceRoutes + members: + - type: interface + name: nic5 + mtu: + get_param: TenantMtu + use_dhcp: false + primary: true + # External bridge for DVR (no IP address required) + - type: ovs_bridge + name: bridge_name + mtu: + get_param: ExternalMtu + dns_servers: + get_param: DnsServers + use_dhcp: false + members: + - type: interface + name: nic6 + mtu: + get_param: ExternalMtu + primary: true + # Uncomment when including environments/network-management.yaml + # If setting default route on the Management interface, comment + # out the default route on the Control Plane. + #- type: interface + # name: nic7 + # mtu: + # get_param: ManagementMtu + # use_dhcp: false + # addresses: + # - ip_netmask: + # get_param: ManagementIpSubnet + # routes: + # list_concat_unique: + # - get_param: ManagementInterfaceRoutes + # - - default: true + # next_hop: + # get_param: ManagementInterfaceDefaultRoute +outputs: + OS::stack_id: + description: The OsNetConfigImpl resource. + value: + get_resource: OsNetConfigImpl + diff --git a/network/config/multiple-nics-vlans/role.role.j2.yaml b/network/config/multiple-nics-vlans/role.role.j2.yaml new file mode 100644 index 0000000000..a7efa8b01b --- /dev/null +++ b/network/config/multiple-nics-vlans/role.role.j2.yaml @@ -0,0 +1,231 @@ +{#- Convert net map or net list to internal list of networks #} +{#- NOTE(hjensas): For backward compatibility support role data with both #} +{#- networks map (new schema) and network list (old schema). #} +{%- if role.networks is mapping %} +{%- set _role_networks = [] %} +{%- for key, val in role.networks.items() %} +{%- set _ = _role_networks.append(key) %} +{%- endfor %} +{%- else %} +{%- set _role_networks = role.networks %} +{%- endif %} +heat_template_version: rocky +description: > + Software Config to drive os-net-config to configure multiple interfaces for the {{role.name}} role. +parameters: + ControlPlaneIp: + default: '' + description: IP address/subnet on the ctlplane network + type: string + ControlPlaneSubnetCidr: + default: '' + description: > + The subnet CIDR of the control plane network. (The parameter is + automatically resolved from the ctlplane subnet's cidr attribute.) + type: string + ControlPlaneDefaultRoute: + default: '' + description: The default route of the control plane network. (The parameter + is automatically resolved from the ctlplane subnet's gateway_ip attribute.) + type: string + ControlPlaneStaticRoutes: + default: [] + description: > + Routes for the ctlplane network traffic. + JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}] + Unless the default is changed, the parameter is automatically resolved + from the subnet host_routes attribute. + type: json + ControlPlaneMtu: + default: 1500 + description: The maximum transmission unit (MTU) size(in bytes) that is + guaranteed to pass through the data path of the segments in the network. + (The parameter is automatically resolved from the ctlplane network's mtu attribute.) + type: number +{% for network in networks if network.enabled|default(true) and network.name in role.networks %} + {{network.name}}IpSubnet: + default: '' + description: IP address/subnet on the {{network.name_lower}} network + type: string +{%- if network.vlan %} + {{network.name}}NetworkVlanID: + default: {{network.vlan|default(1)}} + description: Vlan ID for the {{network.name_lower}} network traffic. + type: number +{%- endif %} + {{network.name}}Mtu: + default: {{network.mtu|default('1500')}} + description: The maximum transmission unit (MTU) size(in bytes) that is + guaranteed to pass through the data path of the segments in the + {{network.name}} network. + type: number +{%- if network.name in role.default_route_networks %} + {{network.name}}InterfaceDefaultRoute: + default: '' + description: default route for the {{network.name_lower}} network + type: string +{%- endif %} + {{network.name}}InterfaceRoutes: + default: [] + description: > + Routes for the {{network.name_lower}} network traffic. + JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}] + Unless the default is changed, the parameter is automatically resolved + from the subnet host_routes attribute. + type: json +{%- endfor %} +{% for network in networks if network.name == "External" and 'external_bridge' in role.tags and not network.name in role.networks %} + {{network.name}}Mtu: + default: {{network.mtu|default('1500')}} + description: The maximum transmission unit (MTU) size(in bytes) that is + guaranteed to pass through the data path of the segments in the + {{network.name}} network. + type: number +{% endfor %} + DnsServers: # Override this via parameter_defaults + default: [] + description: > + DNS servers to use for the Overcloud (2 max for some implementations). + If not set the nameservers configured in the ctlplane subnet's + dns_nameservers attribute will be used. + type: comma_delimited_list + DnsSearchDomains: # Override this via parameter_defaults + default: [] + description: A list of DNS search domains to be added (in order) to resolv.conf. + type: comma_delimited_list +{%- if role.name == 'ComputeOvsDpdk' %} + NumDpdkInterfaceRxQueues: + description: Number of Rx Queues required for DPDK bond or DPDK ports + default: 1 + type: number +{%- endif %} +resources: + OsNetConfigImpl: + type: OS::Heat::SoftwareConfig + properties: + group: script + config: + str_replace: + template: + get_file: ../../scripts/run-os-net-config.sh + params: + $network_config: + network_config: + - type: interface + name: nic1 + mtu: + get_param: ControlPlaneMtu + use_dhcp: false + dns_servers: + get_param: DnsServers + domain: + get_param: DnsSearchDomains + addresses: + - ip_netmask: + list_join: + - / + - - get_param: ControlPlaneIp + - get_param: ControlPlaneSubnetCidr + routes: + list_concat_unique: + - get_param: ControlPlaneStaticRoutes +{%- if role.default_route_networks is not defined or 'ControlPlane' in role.default_route_networks %} + - - default: true + next_hop: + get_param: ControlPlaneDefaultRoute +{%- endif %} +{%- set nics_used = [1] %} +{%- for network in networks if network.enabled|default(true) and network.name not in role.networks_skip_config|default([]) %} +{%- if network.name not in ["External", "Tenant"] %} +{%- if network.name in _role_networks %} + - type: interface + name: nic{{loop.index + 1}} + mtu: + get_param: {{network.name}}Mtu + use_dhcp: false + - type: vlan + device: nic{{loop.index + 1}} + mtu: + get_param: {{network.name}}Mtu + vlan_id: + get_param: {{network.name}}NetworkVlanID + addresses: + - ip_netmask: + get_param: {{network.name}}IpSubnet + routes: + list_concat_unique: + - get_param: {{network.name}}InterfaceRoutes +{%- if network.name in role.default_route_networks %} + - - default: true + next_hop: + get_param: {{network.name}}InterfaceDefaultRoute +{%- endif %} +{%- endif %} +{#- We need bridge also for ComputeDVR and Computes with OVN #} +{%- elif network.name in role.networks or 'external_bridge' in role.tags %} + - type: ovs_bridge +{%- if network.name == "External" %} + name: bridge_name +{%- else %} + name: br-{{network.name_lower}} +{%- endif %} + mtu: + get_param: {{network.name}}Mtu + dns_servers: + get_param: DnsServers + use_dhcp: false + members: + - type: interface + name: nic{{loop.index + 1}} + mtu: + get_param: {{network.name}}Mtu + use_dhcp: false + primary: true +{%- if network.name in _role_networks %} + - type: vlan + mtu: + get_param: InternalApiMtu + vlan_id: + get_param: InternalApiNetworkVlanID + addresses: + - ip_netmask: + get_param: {{network.name}}IpSubnet + routes: + list_concat_unique: + - get_param: {{network.name}}InterfaceRoutes +{%- if network.name in role.default_route_networks %} + - - default: true + next_hop: + get_param: {{network.name}}InterfaceDefaultRoute +{%- endif %} +{%- endif %} +{%- endif %} +{#- This hack gets around Jinja scope limitations to update nics_used within loop. #} +{%- set _ = nics_used.append(loop.index) %} +{%- endfor %} +{%- if role.name == 'ComputeOvsDpdk' %} + # Used as a provider network with external DHCP + - type: ovs_user_bridge + name: br-dpdk0 + members: + - type: ovs_dpdk_bond + name: dpdkbond0 + rx_queue: + get_param: NumDpdkInterfaceRxQueues + members: + - type: ovs_dpdk_port + name: dpdk0 + members: + - type: interface + name: nic{{nics_used[-1] + 1}} + - type: ovs_dpdk_port + name: dpdk1 + members: + - type: interface + name: nic{{nics_used[-1] + 2}} +{%- endif %} +outputs: + OS::stack_id: + description: The OsNetConfigImpl resource. + value: + get_resource: OsNetConfigImpl