From b354fa75c23bee5b67908f1e345bc49963179999 Mon Sep 17 00:00:00 2001 From: Brendan Shephard Date: Thu, 7 Sep 2023 14:07:31 +1000 Subject: [PATCH] Remove NetworkConfig override handling This change removes the CRD level override for network config files. Instead, this allows us to use the Ansible variable directly to set any require network config customizations. Depends-On: openstack-k8s-operators/edpm-ansible#341 Depends-On: openstack-k8s-operators/ci-framework#560 Signed-off-by: Brendan Shephard --- ...nstack.org_openstackdataplanenodesets.yaml | 14 +- api/v1beta1/common.go | 32 ++-- api/v1beta1/zz_generated.deepcopy.go | 23 +-- ...nstack.org_openstackdataplanenodesets.yaml | 14 +- ...penstackdataplane_baremetal_with_ipam.yaml | 165 ++++++++++++++++++ ...ane_v1beta1_openstackdataplanenodeset.yaml | 33 ++++ ...1_openstackdataplanenodeset_baremetal.yaml | 35 +++- ...kdataplanenodeset_baremetal_with_ipam.yaml | 32 ++++ ...1beta1_openstackdataplanenodeset_ceph.yaml | 33 ++++ ...nstackdataplanenodeset_customnetworks.yaml | 34 +++- ...1_openstackdataplanenodeset_with_ipam.yaml | 33 ++++ docs/openstack_dataplanedeloyment.md | 14 +- docs/openstack_dataplanenodeset.md | 14 +- docs/openstack_dataplaneservice.md | 14 +- pkg/deployment/inventory.go | 20 --- pkg/util/ansible_execution.go | 10 -- .../01-assert.yaml | 46 ----- .../dataplane-extramounts/00-assert.yaml | 5 - .../dataplane-service-config/00-assert.yaml | 5 - .../00-assert.yaml | 5 - 20 files changed, 426 insertions(+), 155 deletions(-) create mode 100644 config/samples/dataplane_v1beta1_openstackdataplane_baremetal_with_ipam.yaml diff --git a/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml b/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml index 2f75215a3..118a78ba1 100644 --- a/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml +++ b/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml @@ -1021,11 +1021,10 @@ spec: type: array managementNetwork: type: string - networkConfig: - properties: - template: - type: string - type: object + networkAttachments: + items: + type: string + type: array networkData: properties: name: @@ -1826,11 +1825,6 @@ spec: type: string managementNetwork: type: string - networkConfig: - properties: - template: - type: string - type: object networkData: properties: name: diff --git a/api/v1beta1/common.go b/api/v1beta1/common.go index 49bf20f4d..0c9737bed 100644 --- a/api/v1beta1/common.go +++ b/api/v1beta1/common.go @@ -52,11 +52,6 @@ type NodeSection struct { // +kubebuilder:validation:Optional HostName string `json:"hostName,omitempty"` - // NetworkConfig - Network configuration details. Contains os-net-config - // related properties. - // +kubebuilder:validation:Optional - NetworkConfig NetworkConfigSection `json:"networkConfig"` - // Networks - Instance networks // +kubebuilder:validation:Optional Networks []infranetworkv1.IPSetNetwork `json:"networks,omitempty"` @@ -93,10 +88,10 @@ type NodeTemplate struct { // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"} AnsibleSSHPrivateKeySecret string `json:"ansibleSSHPrivateKeySecret"` - // NetworkConfig - Network configuration details. Contains os-net-config - // related properties. + // NetworkAttachments is a list of NetworkAttachment resource names to pass to the ansibleee resource + // which allows to connect the ansibleee runner to the given network // +kubebuilder:validation:Optional - NetworkConfig NetworkConfigSection `json:"networkConfig,omitempty"` + NetworkAttachments []string `json:"networkAttachments,omitempty"` // Networks - Instance networks // +kubebuilder:validation:Optional @@ -123,13 +118,24 @@ type NodeTemplate struct { NetworkData *corev1.SecretReference `json:"networkData,omitempty"` } -// NetworkConfigSection is a specification of the Network configuration details -type NetworkConfigSection struct { +// DeployStrategySection for fields controlling the deployment +type DeployStrategySection struct { + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + // Deploy boolean to trigger ansible execution + // +kubebuilder:default=true + Deploy bool `json:"deploy"` - // Template - Contains a Ansible j2 nic config template to use when applying node - // network configuration + // AnsibleTags for ansible execution // +kubebuilder:validation:Optional - Template string `json:"template,omitempty" yaml:"template,omitempty"` + AnsibleTags string `json:"ansibleTags,omitempty"` + + // AnsibleLimit for ansible execution + // +kubebuilder:validation:Optional + AnsibleLimit string `json:"ansibleLimit,omitempty"` + + // AnsibleSkipTags for ansible execution + // +kubebuilder:validation:Optional + AnsibleSkipTags string `json:"ansibleSkipTags,omitempty"` } // AnsibleEESpec is a specification of the ansible EE attributes diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 67ec54aa8..59c6e3624 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -100,31 +100,31 @@ func (in *AnsibleOpts) DeepCopy() *AnsibleOpts { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KubeService) DeepCopyInto(out *KubeService) { +func (in *DeployStrategySection) DeepCopyInto(out *DeployStrategySection) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeService. -func (in *KubeService) DeepCopy() *KubeService { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeployStrategySection. +func (in *DeployStrategySection) DeepCopy() *DeployStrategySection { if in == nil { return nil } - out := new(KubeService) + out := new(DeployStrategySection) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NetworkConfigSection) DeepCopyInto(out *NetworkConfigSection) { +func (in *KubeService) DeepCopyInto(out *KubeService) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfigSection. -func (in *NetworkConfigSection) DeepCopy() *NetworkConfigSection { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeService. +func (in *KubeService) DeepCopy() *KubeService { if in == nil { return nil } - out := new(NetworkConfigSection) + out := new(KubeService) in.DeepCopyInto(out) return out } @@ -132,7 +132,6 @@ func (in *NetworkConfigSection) DeepCopy() *NetworkConfigSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeSection) DeepCopyInto(out *NodeSection) { *out = *in - out.NetworkConfig = in.NetworkConfig if in.Networks != nil { in, out := &in.Networks, &out.Networks *out = make([]networkv1beta1.IPSetNetwork, len(*in)) @@ -173,7 +172,11 @@ func (in *NodeSection) DeepCopy() *NodeSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeTemplate) DeepCopyInto(out *NodeTemplate) { *out = *in - out.NetworkConfig = in.NetworkConfig + if in.NetworkAttachments != nil { + in, out := &in.NetworkAttachments, &out.NetworkAttachments + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Networks != nil { in, out := &in.Networks, &out.Networks *out = make([]networkv1beta1.IPSetNetwork, len(*in)) diff --git a/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml b/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml index 2f75215a3..118a78ba1 100644 --- a/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml +++ b/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml @@ -1021,11 +1021,10 @@ spec: type: array managementNetwork: type: string - networkConfig: - properties: - template: - type: string - type: object + networkAttachments: + items: + type: string + type: array networkData: properties: name: @@ -1826,11 +1825,6 @@ spec: type: string managementNetwork: type: string - networkConfig: - properties: - template: - type: string - type: object networkData: properties: name: diff --git a/config/samples/dataplane_v1beta1_openstackdataplane_baremetal_with_ipam.yaml b/config/samples/dataplane_v1beta1_openstackdataplane_baremetal_with_ipam.yaml new file mode 100644 index 000000000..4ffed463f --- /dev/null +++ b/config/samples/dataplane_v1beta1_openstackdataplane_baremetal_with_ipam.yaml @@ -0,0 +1,165 @@ +apiVersion: dataplane.openstack.org/v1beta1 +kind: OpenStackDataPlaneNodeSet +metadata: + name: openstack-edpm-ipam +spec: + env: + - name: ANSIBLE_FORCE_COLOR + value: "True" + - name: ANSIBLE_ENABLE_TASK_DEBUGGER + value: "True" + services: + - configure-network + - validate-network + - install-os + - configure-os + - run-os + - ovn + - libvirt + - nova + deployStrategy: + deploy: true + baremetalSetTemplate: + bmhNamespace: openstack + deploymentSSHSecret: dataplane-ansible-ssh-private-key-secret + bmhLabelSelector: + app: openstack + ctlplaneInterface: enp1s0 + dnsSearchDomains: + - osptest.openstack.org + cloudUserName: cloud-admin + nodeTemplate: + ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret + nodes: + edpm-compute-0: + hostName: edpm-compute-0 + ansible: + ansibleUser: root + ansibleHost: 192.168.122.100 + ansibleVars: + ctlplane_ip: 192.168.122.100 + internal_api_ip: 172.17.0.100 + storage_ip: 172.18.0.100 + tenant_ip: 172.19.0.100 + fqdn_internal_api: edpm-compute-0.example.com + networks: + - name: CtlPlane + subnetName: subnet1 + defaultRoute: true + fixedIP: 192.168.122.100 + - name: InternalApi + subnetName: subnet1 + - name: Storage + subnetName: subnet1 + - name: Tenant + subnetName: subnet1 + managementNetwork: ctlplane + ansible: + ansibleUser: root + ansiblePort: 22 + ansibleVars: + service_net_map: + nova_api_network: internal_api + nova_libvirt_network: internal_api + edpm_chrony_ntp_servers: + - clock.redhat.com + # edpm_network_config + # Default nic config template for a EDPM compute node + # These vars are edpm_network_config role vars + edpm_network_config_hide_sensitive_logs: false + edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} + # These vars are for the network config templates themselves and are + # considered EDPM network defaults. + neutron_physical_bridge_name: br-ex + neutron_public_interface_name: eth0 + ctlplane_mtu: 1500 + ctlplane_subnet_cidr: 24 + ctlplane_gateway_ip: 192.168.122.1 + ctlplane_host_routes: + - ip_netmask: 0.0.0.0/0 + next_hop: 192.168.122.1 + external_mtu: 1500 + external_vlan_id: 44 + external_cidr: '24' + external_host_routes: [] + internal_api_mtu: 1500 + internal_api_vlan_id: 20 + internal_api_cidr: '24' + internal_api_host_routes: [] + storage_mtu: 1500 + storage_vlan_id: 21 + storage_cidr: '24' + storage_host_routes: [] + tenant_mtu: 1500 + tenant_vlan_id: 22 + tenant_cidr: '24' + tenant_host_routes: [] + role_networks: + - InternalApi + - Storage + - Tenant + networks_lower: + External: external + InternalApi: internal_api + Storage: storage + Tenant: tenant + # edpm_nodes_validation + edpm_nodes_validation_validate_controllers_icmp: false + edpm_nodes_validation_validate_gateway_icmp: false + edpm_ovn_metadata_agent_DEFAULT_transport_url: rabbit://default_user@rabbitmq.openstack.svc:5672 + edpm_ovn_metadata_agent_metadata_agent_ovn_ovn_sb_connection: tcp:10.217.5.121:6642 + edpm_ovn_metadata_agent_metadata_agent_DEFAULT_nova_metadata_host: 127.0.0.1 + edpm_ovn_metadata_agent_metadata_agent_DEFAULT_metadata_proxy_shared_secret: 12345678 + edpm_ovn_metadata_agent_DEFAULT_bind_host: 127.0.0.1 + ctlplane_dns_nameservers: + - 192.168.122.1 + dns_search_domains: [] + edpm_ovn_dbs: + - 192.168.122.1 + registry_url: quay.io/podified-antelope-centos9 + image_tag: current-podified + edpm_ovn_controller_agent_image: "{{ registry_url }}/openstack-ovn-controller:{{ image_tag }}" + edpm_iscsid_image: "{{ registry_url }}/openstack-iscsid:{{ image_tag }}" + edpm_logrotate_crond_image: "{{ registry_url }}/openstack-cron:{{ image_tag }}" + edpm_nova_compute_container_image: "{{ registry_url }}/openstack-nova-compute:{{ image_tag }}" + edpm_nova_libvirt_container_image: "{{ registry_url }}/openstack-nova-libvirt:{{ image_tag }}" + edpm_ovn_metadata_agent_image: "{{ registry_url }}/openstack-neutron-metadata-agent-ovn:{{ image_tag }}" + gather_facts: false + enable_debug: false + # edpm firewall, change the allowed CIDR if needed + edpm_sshd_configure_firewall: true + edpm_sshd_allowed_ranges: ['192.168.122.0/24'] + # SELinux module + edpm_selinux_mode: enforcing diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml index 1ca35d397..74bb8574f 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml @@ -47,6 +47,39 @@ spec: # These vars are edpm_network_config role vars edpm_network_config_hide_sensitive_logs: false edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} + # These vars are for the network config templates themselves and are # considered EDPM network defaults. neutron_physical_bridge_name: br-ex diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal.yaml index cce7b85a5..ec5e5a28a 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal.yaml @@ -67,9 +67,40 @@ spec: # edpm_network_config # Default nic config template for a EDPM compute node # These vars are edpm_network_config role vars - edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 edpm_network_config_hide_sensitive_logs: false - + edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} # These vars are for the network config templates themselves and are # considered EDPM network defaults. neutron_physical_bridge_name: br-ex diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal_with_ipam.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal_with_ipam.yaml index 6d0538fc0..ae34ad1ef 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal_with_ipam.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_baremetal_with_ipam.yaml @@ -55,6 +55,38 @@ spec: # These vars are edpm_network_config role vars edpm_network_config_hide_sensitive_logs: false edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} # These vars are for the network config templates themselves and are # considered EDPM network defaults. neutron_physical_bridge_name: br-ex diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_ceph.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_ceph.yaml index d03970eca..0d861ebda 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_ceph.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_ceph.yaml @@ -57,6 +57,39 @@ spec: # Default nic config template for a EDPM compute node # These vars are edpm_network_config role vars edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} + edpm_network_config_hide_sensitive_logs: false # # These vars are for the network config templates themselves and are diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_customnetworks.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_customnetworks.yaml index 9e5ca079c..3bb4b12b0 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_customnetworks.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_customnetworks.yaml @@ -48,7 +48,39 @@ spec: # edpm_network_config # Default nic config template for a EDPM compute node # These vars are edpm_network_config role vars - edpm_network_config_template: /runner/network/nic-config-template + edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} edpm_network_config_hide_sensitive_logs: false edpm_network_config_update: false # diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_with_ipam.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_with_ipam.yaml index d01e4b5ba..67c53bc97 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset_with_ipam.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset_with_ipam.yaml @@ -66,6 +66,39 @@ spec: # edpm_network_config # Default nic config template for a EDPM compute node # These vars are edpm_network_config role vars + edpm_network_config_template: templates/single_nic_vlans/single_nic_vlans.j2 + edpm_network_config_override: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_networks %} + {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} + {%- endfor %} + {% set min_viable_mtu = mtu_list | max %} + network_config: + - type: ovs_bridge + name: {{ neutron_physical_bridge_name }} + mtu: {{ min_viable_mtu }} + use_dhcp: false + dns_servers: {{ ctlplane_dns_nameservers }} + domain: {{ dns_search_domains }} + addresses: + - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }} + routes: {{ ctlplane_host_routes }} + members: + - type: interface + name: nic1 + mtu: {{ min_viable_mtu }} + # force the MAC address of the bridge to this interface + primary: true + {% for network in role_networks %} + - type: vlan + mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} + vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} + addresses: + - ip_netmask: + {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} + routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} + {% endfor %} edpm_network_config_hide_sensitive_logs: false # These vars are for the network config templates themselves and are # considered EDPM network defaults. diff --git a/docs/openstack_dataplanedeloyment.md b/docs/openstack_dataplanedeloyment.md index afa34706a..0d2ab753f 100644 --- a/docs/openstack_dataplanedeloyment.md +++ b/docs/openstack_dataplanedeloyment.md @@ -7,7 +7,7 @@ * [AnsibleEESpec](#ansibleeespec) * [AnsibleOpts](#ansibleopts) -* [NetworkConfigSection](#networkconfigsection) +* [DeployStrategySection](#deploystrategysection) * [NodeSection](#nodesection) * [NodeTemplate](#nodetemplate) * [OpenStackDataPlaneDeploymentList](#openstackdataplanedeploymentlist) @@ -44,13 +44,16 @@ AnsibleOpts defines a logical grouping of Ansible related configuration options. [Back to Custom Resources](#custom-resources) -#### NetworkConfigSection +#### DeployStrategySection -NetworkConfigSection is a specification of the Network configuration details +DeployStrategySection for fields controlling the deployment | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | -| template | Template - Contains a Ansible j2 nic config template to use when applying node network configuration | string | false | +| deploy | Deploy boolean to trigger ansible execution | bool | true | +| ansibleTags | AnsibleTags for ansible execution | string | false | +| ansibleLimit | AnsibleLimit for ansible execution | string | false | +| ansibleSkipTags | AnsibleSkipTags for ansible execution | string | false | [Back to Custom Resources](#custom-resources) @@ -61,7 +64,6 @@ NodeSection defines the top level attributes inherited by nodes in the CR. | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | hostName | HostName - node name | string | false | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | true | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | @@ -78,7 +80,7 @@ NodeTemplate is a specification of the node attributes that override top level a | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | ansibleSSHPrivateKeySecret | AnsibleSSHPrivateKeySecret Name of a private SSH key secret containing private SSH key for connecting to node. The named secret must be of the form: Secret.data.ssh-privatekey: | string | true | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | false | +| networkAttachments | NetworkAttachments is a list of NetworkAttachment resource names to pass to the ansibleee resource which allows to connect the ansibleee runner to the given network | []string | false | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | diff --git a/docs/openstack_dataplanenodeset.md b/docs/openstack_dataplanenodeset.md index 8c05e6946..fe3ca947e 100644 --- a/docs/openstack_dataplanenodeset.md +++ b/docs/openstack_dataplanenodeset.md @@ -7,7 +7,7 @@ * [AnsibleEESpec](#ansibleeespec) * [AnsibleOpts](#ansibleopts) -* [NetworkConfigSection](#networkconfigsection) +* [DeployStrategySection](#deploystrategysection) * [NodeSection](#nodesection) * [NodeTemplate](#nodetemplate) * [OpenStackDataPlaneNodeSetList](#openstackdataplanenodesetlist) @@ -44,13 +44,16 @@ AnsibleOpts defines a logical grouping of Ansible related configuration options. [Back to Custom Resources](#custom-resources) -#### NetworkConfigSection +#### DeployStrategySection -NetworkConfigSection is a specification of the Network configuration details +DeployStrategySection for fields controlling the deployment | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | -| template | Template - Contains a Ansible j2 nic config template to use when applying node network configuration | string | false | +| deploy | Deploy boolean to trigger ansible execution | bool | true | +| ansibleTags | AnsibleTags for ansible execution | string | false | +| ansibleLimit | AnsibleLimit for ansible execution | string | false | +| ansibleSkipTags | AnsibleSkipTags for ansible execution | string | false | [Back to Custom Resources](#custom-resources) @@ -61,7 +64,6 @@ NodeSection defines the top level attributes inherited by nodes in the CR. | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | hostName | HostName - node name | string | false | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | true | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | @@ -78,7 +80,7 @@ NodeTemplate is a specification of the node attributes that override top level a | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | ansibleSSHPrivateKeySecret | AnsibleSSHPrivateKeySecret Name of a private SSH key secret containing private SSH key for connecting to node. The named secret must be of the form: Secret.data.ssh-privatekey: | string | true | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | false | +| networkAttachments | NetworkAttachments is a list of NetworkAttachment resource names to pass to the ansibleee resource which allows to connect the ansibleee runner to the given network | []string | false | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | diff --git a/docs/openstack_dataplaneservice.md b/docs/openstack_dataplaneservice.md index 92aa87241..2156d43b0 100644 --- a/docs/openstack_dataplaneservice.md +++ b/docs/openstack_dataplaneservice.md @@ -7,7 +7,7 @@ * [AnsibleEESpec](#ansibleeespec) * [AnsibleOpts](#ansibleopts) -* [NetworkConfigSection](#networkconfigsection) +* [DeployStrategySection](#deploystrategysection) * [NodeSection](#nodesection) * [NodeTemplate](#nodetemplate) * [KubeService](#kubeservice) @@ -45,13 +45,16 @@ AnsibleOpts defines a logical grouping of Ansible related configuration options. [Back to Custom Resources](#custom-resources) -#### NetworkConfigSection +#### DeployStrategySection -NetworkConfigSection is a specification of the Network configuration details +DeployStrategySection for fields controlling the deployment | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | -| template | Template - Contains a Ansible j2 nic config template to use when applying node network configuration | string | false | +| deploy | Deploy boolean to trigger ansible execution | bool | true | +| ansibleTags | AnsibleTags for ansible execution | string | false | +| ansibleLimit | AnsibleLimit for ansible execution | string | false | +| ansibleSkipTags | AnsibleSkipTags for ansible execution | string | false | [Back to Custom Resources](#custom-resources) @@ -62,7 +65,6 @@ NodeSection defines the top level attributes inherited by nodes in the CR. | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | hostName | HostName - node name | string | false | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | true | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | @@ -79,7 +81,7 @@ NodeTemplate is a specification of the node attributes that override top level a | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | ansibleSSHPrivateKeySecret | AnsibleSSHPrivateKeySecret Name of a private SSH key secret containing private SSH key for connecting to node. The named secret must be of the form: Secret.data.ssh-privatekey: | string | true | -| networkConfig | NetworkConfig - Network configuration details. Contains os-net-config related properties. | [NetworkConfigSection](#networkconfigsection) | false | +| networkAttachments | NetworkAttachments is a list of NetworkAttachment resource names to pass to the ansibleee resource which allows to connect the ansibleee runner to the given network | []string | false | | networks | Networks - Instance networks | []infranetworkv1.IPSetNetwork | false | | managementNetwork | ManagementNetwork - Name of network to use for management (SSH/Ansible) | string | false | | ansible | Ansible is the group of Ansible related configuration options. | [AnsibleOpts](#ansibleopts) | false | diff --git a/pkg/deployment/inventory.go b/pkg/deployment/inventory.go index fee15efbb..bdedecec9 100644 --- a/pkg/deployment/inventory.go +++ b/pkg/deployment/inventory.go @@ -93,11 +93,6 @@ func GenerateNodeSetInventory(ctx context.Context, helper *helper.Helper, host.Vars[entry+"_host_routes"] = res.Routes dnsSearchDomains = append(dnsSearchDomains, res.DNSDomain) } - networkConfig := getAnsibleNetworkConfig(instance, nodeName) - - if networkConfig.Template != "" { - host.Vars["edpm_network_config_template"] = NicConfigTemplateFile - } host.Vars["ansible_user"] = getAnsibleUser(instance, nodeName) host.Vars["ansible_port"] = getAnsiblePort(instance, nodeName) @@ -134,7 +129,6 @@ func GenerateNodeSetInventory(ctx context.Context, helper *helper.Helper, } secretData := map[string]string{ "inventory": string(invData), - "network": string(instance.Spec.NodeTemplate.NetworkConfig.Template), } secretName := fmt.Sprintf("dataplanenodeset-%s", instance.Name) template := []utils.Template{ @@ -215,14 +209,6 @@ func getAnsibleManagementNetwork( return instance.Spec.NodeTemplate.ManagementNetwork } -// getAnsibleNetworkConfig returns a JSON string value from the template unless it is set in the node -func getAnsibleNetworkConfig(instance *dataplanev1.OpenStackDataPlaneNodeSet, nodeName string) dataplanev1.NetworkConfigSection { - if instance.Spec.Nodes[nodeName].NetworkConfig.Template != "" { - return instance.Spec.Nodes[nodeName].NetworkConfig - } - return instance.Spec.NodeTemplate.NetworkConfig -} - // getAnsibleNetworks returns a JSON string mapping fixedIP and/or network name to their valules func getAnsibleNetworks(instance *dataplanev1.OpenStackDataPlaneNodeSet, nodeName string) []infranetworkv1.IPSetNetwork { if len(instance.Spec.Nodes[nodeName].Networks) > 0 { @@ -296,9 +282,6 @@ func resolveAnsibleVars(nodeTemplate *dataplanev1.NodeTemplate, host *ansible.Ho if nodeTemplate.ManagementNetwork != "" { ansibleVarsData["management_network"] = nodeTemplate.ManagementNetwork } - if nodeTemplate.NetworkConfig.Template != "" { - ansibleVarsData["edpm_network_config_template"] = NicConfigTemplateFile - } if len(nodeTemplate.Networks) > 0 { ansibleVarsData["networks"] = nodeTemplate.Networks } @@ -340,9 +323,6 @@ func resolveNodeAnsibleVars(node *dataplanev1.NodeSection, host *ansible.Host, g if node.ManagementNetwork != "" { ansibleVarsData["management_network"] = node.ManagementNetwork } - if node.NetworkConfig.Template != "" { - ansibleVarsData["edpm_network_config_template"] = NicConfigTemplateFile - } if len(node.Networks) > 0 { ansibleVarsData["networks"] = node.Networks } diff --git a/pkg/util/ansible_execution.go b/pkg/util/ansible_execution.go index f7fd0cbbc..213cae427 100644 --- a/pkg/util/ansible_execution.go +++ b/pkg/util/ansible_execution.go @@ -127,10 +127,6 @@ func AnsibleExecution( Key: "inventory", Path: "inventory", }, - { - Key: "network", - Path: "network", - }, }, }, }, @@ -140,17 +136,11 @@ func AnsibleExecution( MountPath: "/runner/inventory/hosts", SubPath: "inventory", } - networkConfigMount := corev1.VolumeMount{ - Name: "inventory", - MountPath: "/runner/network/nic-config-template", - SubPath: "network", - } ansibleEEMounts.Volumes = append(ansibleEEMounts.Volumes, sshKeyVolume) ansibleEEMounts.Volumes = append(ansibleEEMounts.Volumes, inventoryVolume) ansibleEEMounts.Mounts = append(ansibleEEMounts.Mounts, sshKeyMount) ansibleEEMounts.Mounts = append(ansibleEEMounts.Mounts, inventoryMount) - ansibleEEMounts.Mounts = append(ansibleEEMounts.Mounts, networkConfigMount) ansibleEE.Spec.ExtraMounts = append(aeeSpec.ExtraMounts, []storage.VolMounts{ansibleEEMounts}...) ansibleEE.Spec.Env = aeeSpec.Env diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml index 213b6b131..8fe5d465d 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml @@ -62,9 +62,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -77,8 +74,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -118,9 +113,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -133,8 +125,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -174,9 +164,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -189,8 +176,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -230,9 +215,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -245,8 +227,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -287,9 +267,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -302,8 +279,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -343,9 +318,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -358,8 +330,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -433,9 +403,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -448,8 +415,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -483,7 +448,6 @@ spec: backoffLimit: 6 debug: false envConfigMapName: openstack-aee-default-env - extraMounts: - mounts: - mountPath: /runner/env/ssh_key @@ -492,9 +456,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -507,8 +468,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee @@ -556,9 +515,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -571,8 +527,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee diff --git a/tests/kuttl/tests/dataplane-extramounts/00-assert.yaml b/tests/kuttl/tests/dataplane-extramounts/00-assert.yaml index e2fdb5f63..0d05a98e0 100644 --- a/tests/kuttl/tests/dataplane-extramounts/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-extramounts/00-assert.yaml @@ -49,9 +49,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -64,6 +61,4 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-extramounts diff --git a/tests/kuttl/tests/dataplane-service-config/00-assert.yaml b/tests/kuttl/tests/dataplane-service-config/00-assert.yaml index e376880fd..045e5dd66 100644 --- a/tests/kuttl/tests/dataplane-service-config/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-service-config/00-assert.yaml @@ -73,9 +73,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -88,8 +85,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-compute-no-nodes image: quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest name: openstackansibleee diff --git a/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml b/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml index 7c6418de0..b16d243ad 100644 --- a/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml @@ -53,9 +53,6 @@ spec: - mountPath: /runner/inventory/hosts name: inventory subPath: inventory - - mountPath: /runner/network/nic-config-template - name: inventory - subPath: network volumes: - name: ssh-key secret: @@ -68,8 +65,6 @@ spec: items: - key: inventory path: inventory - - key: network - path: network secretName: dataplanenodeset-edpm-no-nodes-custom-service image: example.com/repo/runner-image:latest name: openstackansibleee