From 2b118f08ac25cb1763be5d503587ef655633ce7b Mon Sep 17 00:00:00 2001 From: Javier Diaz <jdiaz@mirantis.com> Date: Thu, 22 Sep 2022 14:07:41 -0500 Subject: [PATCH 1/2] Configure ARM formula --- formulas/arm/configure.sls | 384 +++++++++++++++++- formulas/arm/files/10-iommu.cfg | 1 + formulas/arm/files/arp_protect.py | 236 +++++++++++ formulas/arm/files/ceph-nova.xml | 6 + formulas/arm/files/ceph-volumes.xml | 6 + formulas/arm/files/config | 1 + formulas/arm/files/hosts | 3 + formulas/arm/files/kvm.conf | 1 + formulas/arm/files/linuxbridge_agent.ini | 17 + formulas/arm/files/neutron.conf | 45 ++ .../arm/files/neutron_ovn_metadata_agent.ini | 23 ++ formulas/arm/files/neutron_sudoers | 5 + formulas/arm/files/nova.conf | 184 +++++++++ formulas/arm/files/openvswitch_agent.ini | 22 + formulas/arm/install.sls | 62 ++- formulas/common/base.sls | 4 + 16 files changed, 997 insertions(+), 3 deletions(-) create mode 100644 formulas/arm/files/10-iommu.cfg create mode 100644 formulas/arm/files/arp_protect.py create mode 100644 formulas/arm/files/ceph-nova.xml create mode 100644 formulas/arm/files/ceph-volumes.xml create mode 100644 formulas/arm/files/config create mode 100644 formulas/arm/files/hosts create mode 100644 formulas/arm/files/kvm.conf create mode 100644 formulas/arm/files/linuxbridge_agent.ini create mode 100644 formulas/arm/files/neutron.conf create mode 100644 formulas/arm/files/neutron_ovn_metadata_agent.ini create mode 100644 formulas/arm/files/neutron_sudoers create mode 100644 formulas/arm/files/nova.conf create mode 100644 formulas/arm/files/openvswitch_agent.ini diff --git a/formulas/arm/configure.sls b/formulas/arm/configure.sls index 30c7d581..32fef4c5 100644 --- a/formulas/arm/configure.sls +++ b/formulas/arm/configure.sls @@ -1,2 +1,384 @@ +## Copyright 2018 Augusta University +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. + include: - - /formulas/compute/configure + - /formulas/{{ grains['role'] }}/install + - /formulas/common/ceph/configure + +{% set type = opts.id.split('-')[0] %} +{% set role = salt['pillar.get']('hosts:'+type+':role', type) %} + +{% import 'formulas/common/macros/constructor.sls' as constructor with context %} + +### Calculate public interface - this is referenced a few times +### Potential to make 'interface calculator' macro +{% if salt['pillar.get']('hosts:'+grains['type']+':networks:public:bridge', False) == True %} + {% set public_interface = 'public_br' %} +{% elif salt['pillar.get']('hosts:'+grains['type']+':networks:public:interfaces') | length > 1 %} + {% set public_interface = 'public_bond' %} +{% else %} + {% set public_interface = pillar['hosts'][grains['type']]['networks']['public']['interfaces'][0] %} +{% endif %} + +{% set nova_uuid = pillar['ceph']['nova-uuid'] %} +{% set volumes_uuid = pillar['ceph']['volumes-uuid'] %} + + +#/etc/frr/daemons: +# file.managed: +# - source: salt://formulas/common/frr/files/daemons + + +conf-files: + file.managed: + - template: jinja + - defaults: + nova_uuid: {{ nova_uuid }} + volumes_uuid: {{ volumes_uuid }} + transport_url: {{ constructor.rabbitmq_url_constructor() }} + www_authenticate_uri: {{ constructor.endpoint_url_constructor(project='keystone', service='keystone', endpoint='public') }} +{% if salt['pillar.get']('hosts:barbican:enabled', 'False') == True %} + barbican_endpoint: {{ constructor.endpoint_url_constructor(project='barbican', service='barbican', endpoint='internal') }} +{% endif %} + auth_url: {{ constructor.endpoint_url_constructor(project='keystone', service='keystone', endpoint='internal') }} + memcached_servers: {{ constructor.memcached_url_constructor() }} + nova_password: {{ pillar['nova']['nova_service_password'] }} + my_ip: {{ salt['network.ipaddrs'](cidr=pillar['networking']['subnets']['management'])[0] }} + api_servers: {{ constructor.endpoint_url_constructor(project='glance', service='glance', endpoint='internal') }} + neutron_password: {{ pillar['neutron']['neutron_service_password'] }} + placement_password: {{ pillar['placement']['placement_service_password'] }} + rbd_secret_uuid: {{ pillar['ceph']['nova-uuid'] }} + token_ttl: {{ pillar['nova']['token_ttl'] }} + console_domain: {{ pillar['haproxy']['console_domain'] }} + dashboard_domain: {{ pillar['haproxy']['dashboard_domain'] }} + initial_cpu_allocation_ratio : {{ pillar['hosts'][grains['type']]['initial_cpu_allocation_ratio'] | default(1.0) }} + initial_ram_allocation_ratio : {{ pillar['hosts'][grains['type']]['initial_ram_allocation_ratio'] | default(1.5) }} + initial_disk_allocation_ratio : {{ pillar['hosts'][grains['type']]['initial_disk_allocation_ratio'] | default(1.0) }} + {% if grains['os_family'] == 'Debian' %} + lock_path: /var/lock/neutron + {% elif grains['os_family'] == 'RedHat' %} + lock_path: /var/lib/neutron/tmp + {% endif %} + - names: + - /etc/modprobe.d/kvm.conf: + - source: salt://formulas/compute/files/kvm.conf +# - /etc/frr/daemons: +# - source: salt://formulas/common/frr/files/daemons + - /etc/ceph/ceph-nova.xml: + - source: salt://formulas/compute/files/ceph-nova.xml + - /etc/ceph/ceph-volumes.xml: + - source: salt://formulas/compute/files/ceph-volumes.xml + - /etc/nova/nova.conf: + - source: salt://formulas/compute/files/nova.conf + - /etc/sudoers.d/neutron_sudoers: + - source: salt://formulas/compute/files/neutron_sudoers + - /etc/neutron/neutron.conf: + - source: salt://formulas/compute/files/neutron.conf + + +compute_hosts: + file.managed: + - template: jinja + - defaults: + compute_hosts: {{ constructor.host_file_constructor(role='compute')|yaml_encode }} + - names: + - /etc/hosts: + - source: salt://formulas/compute/files/hosts + +ceph_keyrings: + file.managed: + - names: + - /etc/ceph/ceph.client.compute.keyring: + - contents_pillar: ceph:ceph-client-compute-keyring + - /etc/ceph/client.compute.key: + - contents_pillar: ceph:ceph-client-compute-key + - /etc/ceph/client.volumes.key: + - contents_pillar: ceph:ceph-client-volumes-key + - mode: "0640" + - user: root + - group: nova + +libvirt_secrets: + file.managed: + - makedirs: True + - template: jinja + - defaults: + nova_uuid: {{ nova_uuid }} + volumes_uuid: {{ volumes_uuid }} + - names: + - /etc/libvirt/secrets/{{ nova_uuid }}.base64: + - contents_pillar: ceph:ceph-client-compute-key + - /etc/libvirt/secrets/{{ volumes_uuid }}.base64: + - contents_pillar: ceph:ceph-client-volumes-key + - /etc/libvirt/secrets/{{ nova_uuid }}.xml: + - source: salt://formulas/compute/files/ceph-nova.xml + - /etc/libvirt/secrets/{{ volumes_uuid }}.xml: + - source: salt://formulas/compute/files/ceph-volumes.xml + - mode: "0600" + - user: root + - group: root + +/root/.ssh/config: + file.managed: + - user: root + - group: root + - mode: '0400' + - source: salt://formulas/compute/files/config + +{% for key in pillar['nova_live_migration_auth_key'] %} +{{ key }}: + ssh_auth.present: + - user: root + - enc: {{ pillar['nova_live_migration_auth_key'][ key ]['encoding'] }} +{% endfor %} + +/root/.ssh/id_rsa: + file.managed: + - contents_pillar: nova_private_key + - user: root + - group: root + - mode: '0600' + - replace: False + +{% if grains['os_family'] == 'RedHat' %} +spice-html5: + git.latest: + - name: https://github.com/freedesktop/spice-html5.git + - target: /usr/share/spice-html5 +{% endif %} + +nova_compute_service: + service.running: +{% if grains['os_family'] == 'Debian' %} + - name: nova-compute +{% elif grains['os_family'] == 'RedHat' %} + - name: openstack-nova-compute +{% endif %} + - enable: true + - watch: + - file: /etc/nova/nova.conf + +{% set neutron_backend = pillar['neutron']['backend'] %} +{% if neutron_backend != "networking-ovn" %} +/etc/neutron/plugins/ml2/{{ neutron_backend }}_agent.ini: + file.managed: + - source: salt://formulas/compute/files/{{ neutron_backend }}_agent.ini + - template: jinja + - defaults: + local_ip: {{ salt['network.ip_addrs'](cidr=pillar['networking']['subnets']['private'])[0] }} + public_interface: {{ public_interface }} + {% if neutron_backend == "openvswitch" %} + extensions: qos + bridge_mappings: public_br + vxlan_udp_port: 4789 + l2_population: True + arp_responder: True + enable_distributed_routing: False + drop_flows_on_start: False + explicitly_egress_direct: True + +create_bridge: + openvswitch_bridge.present: + - name: public_br + +create_port: + openvswitch_port.present: + - name: {{ public_interface }} + - bridge: public_br + {% endif %} + {% if grains['os_family'] == 'RedHat' %} + {% if (salt['grains.get']('selinux:enabled', False) == True) and (salt['grains.get']('selinux:enforced', 'Permissive') == 'Enforcing') %} +## this used to be a default but was changed to a boolean here: +## https://github.com/redhat-openstack/openstack-selinux/commit/9cfdb0f0aa681d57ca52948f632ce679d9e1f465 +os_neutron_dac_override: + selinux.boolean: + - value: on + - persist: True + - watch_in: + - service: neutron_{{ neutron_backend }}_agent_service + {% endif %} + {% endif %} + +neutron_{{ neutron_backend }}_agent_service: + service.running: + - name: neutron-{{ neutron_backend }}-agent + - enable: true + - watch: + - file: conf-files + - file: /etc/neutron/plugins/ml2/{{ neutron_backend }}_agent.ini + +{% elif neutron_backend == "networking-ovn" %} +neutron-ovn-metadata-agent.ini: + file.managed: + - source: salt://formulas/compute/files/neutron_ovn_metadata_agent.ini + - name: /etc/neutron/neutron_ovn_metadata_agent.ini + - template: jinja + - defaults: + nova_metadata_host: {{ pillar['endpoints']['public'] }} + metadata_proxy_shared_secret: {{ pillar['neutron']['metadata_proxy_shared_secret'] }} + ovn_sb_connection: {{ constructor.ovn_sb_connection_constructor() }} + +openvswitch_service: + service.running: + {% if grains['os_family'] == 'Debian' %} + - name: openvswitch-switch + {% elif grains['os_family'] == 'RedHat' %} + - name: openvswitch + {% endif %} + - enable: true + - watch: + - file: conf-files + - file: neutron-ovn-metadata-agent.ini + +set-ovn-remote: + cmd.run: + - name: ovs-vsctl set open . external-ids:ovn-remote={{ constructor.ovn_sb_connection_constructor() }} + - require: + - service: openvswitch_service + - unless: + - ovs-vsctl get open . external-ids:ovn-remote | grep -q "{{ constructor.ovn_sb_connection_constructor() }}" + +set_encap: + cmd.run: + - name: ovs-vsctl set open . external-ids:ovn-encap-type=geneve + - require: + - service: openvswitch_service + - unless: + - ovs-vsctl get open . external-ids:ovn-encap-type | grep -q "geneve" + +set_encap_ip: + cmd.run: + - name: ovs-vsctl set open . external-ids:ovn-encap-ip={{ salt['network.ip_addrs'](cidr=pillar['networking']['subnets']['private'])[0] }} + - require: + - service: openvswitch_service + - cmd: set_encap + - unless: + - ovs-vsctl get open . external-ids:ovn-encap-ip | grep -q "{{ salt['network.ip_addrs'](cidr=pillar['networking']['subnets']['private'])[0] }}" + +make_bridge: + cmd.run: + - name: ovs-vsctl --may-exist add-br br-provider -- set bridge br-provider protocols=OpenFlow13 + - require: + - service: openvswitch_service + - cmd: set_encap + - cmd: set_encap_ip + - unless: + - ovs-vsctl br-exists br-provider + +map_bridge: + cmd.run: + - name: ovs-vsctl set open . external-ids:ovn-bridge-mappings=provider:br-provider + - require: + - service: openvswitch_service + - cmd: set_encap + - cmd: set_encap_ip + - cmd: make_bridge + - unless: + - ovs-vsctl get open . external-ids:ovn-bridge-mappings | grep -q "provider:br-provider" + +ovs-vsctl set open . external_ids:ovn-remote-probe-interval=180000 : + cmd.run: + - require: + - service: openvswitch_service + - retry: + attempts: 3 + interval: 10 + splay: 5 + - unless: + - ovs-vsctl get open . external-ids:ovn-remote-probe-interval | grep -q "180000" + +ovs-vsctl set open . external_ids:ovn-openflow-probe-interval=180 : + cmd.run: + - require: + - service: openvswitch_service + - retry: + attempts: 3 + interval: 10 + splay: 5 + - unless: + - ovs-vsctl get open . external-ids:ovn-openflow-probe-interval | grep -q "180" + +ovsdb_listen: + cmd.run: + - name: ovs-vsctl set-manager ptcp:6640:127.0.0.1 + - unless: + - ovs-vsctl get-manager | grep -q "ptcp:6640:127.0.0.1" + +enable_bridge: + cmd.run: + - name: ovs-vsctl --may-exist add-port br-provider {{ public_interface }} + - require: + - service: openvswitch_service + - cmd: set_encap + - cmd: set_encap_ip + - cmd: make_bridge + - cmd: map_bridge + - unless: + - ovs-vsctl port-to-br {{ public_interface }} | grep -q "br-provider" + +ovn_controller_service: + service.running: + {% if grains['os_family'] == 'Debian' %} + - name: ovn-host + {% elif grains['os_family'] == 'RedHat' %} + - name: ovn-controller + {% endif %} + - enable: true + - require: + - service: openvswitch_service + - cmd: set_encap + - cmd: set_encap_ip + +ovn_metadata_service: + service.running: + - name: neutron-ovn-metadata-agent + - enable: True + - watch: + - file: neutron-ovn-metadata-agent.ini + - require: + - cmd: ovsdb_listen +{% endif %} + +libvirtd_service: + service.running: + - name: libvirtd + - enable: True + - watch: + - file: /etc/libvirt/secrets/{{ nova_uuid }}.xml + - file: /etc/libvirt/secrets/{{ volumes_uuid }}.xml + - file: /etc/libvirt/secrets/{{ nova_uuid }}.base64 + - file: /etc/libvirt/secrets/{{ volumes_uuid }}.base64 + - require: + - file: libvirt_secrets + +/etc/default/grub.d/10-iommu.cfg: + file.managed: + - user: root + - group: root + - mode: '0644' + - template: jinja + - source: salt://formulas/compute/files/10-iommu.cfg + - defaults: + kernel_param: {{ pillar['hosts'][grains['type']]['kernel_param'][0] }} + +update-grub: + cmd.run: + - onchanges: + - file: /etc/default/grub.d/10-iommu.cfg + +system.reboot: + module.run: + - onchanges: + - file: /etc/default/grub.d/10-iommu.cfg + diff --git a/formulas/arm/files/10-iommu.cfg b/formulas/arm/files/10-iommu.cfg new file mode 100644 index 00000000..28265c04 --- /dev/null +++ b/formulas/arm/files/10-iommu.cfg @@ -0,0 +1 @@ +GRUB_CMDLINE_LINUX_DEFAULT="{{ kernel_param }}" \ No newline at end of file diff --git a/formulas/arm/files/arp_protect.py b/formulas/arm/files/arp_protect.py new file mode 100644 index 00000000..6ed3f7ed --- /dev/null +++ b/formulas/arm/files/arp_protect.py @@ -0,0 +1,236 @@ +# Copyright (c) 2015 Mirantis, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import netaddr +from neutron_lib.utils import net +from oslo_concurrency import lockutils +from oslo_log import log as logging +import tenacity + +from neutron.agent.linux import ip_lib + +LOG = logging.getLogger(__name__) +SPOOF_CHAIN_PREFIX = 'neutronARP-' +MAC_CHAIN_PREFIX = 'neutronMAC-' + + +def setup_arp_spoofing_protection(vif, port_details): + if not port_details.get('port_security_enabled', True): + # clear any previous entries related to this port + delete_arp_spoofing_protection([vif]) + LOG.info("Skipping ARP spoofing rules for port '%s' because " + "it has port security disabled", vif) + return + if net.is_port_trusted(port_details): + # clear any previous entries related to this port + delete_arp_spoofing_protection([vif]) + LOG.debug("Skipping ARP spoofing rules for network owned port " + "'%s'.", vif) + return + _setup_arp_spoofing_protection(vif, port_details) + + +@lockutils.synchronized('ebtables') +def _setup_arp_spoofing_protection(vif, port_details): + current_rules = ebtables(['-L']).splitlines() + _install_mac_spoofing_protection(vif, port_details, current_rules) + # collect all of the addresses and cidrs that belong to the port + addresses = {f['ip_address'] for f in port_details['fixed_ips']} + if port_details.get('allowed_address_pairs'): + addresses |= {p['ip_address'] + for p in port_details['allowed_address_pairs']} + + addresses = {ip for ip in addresses + if netaddr.IPNetwork(ip).version == 4} + if any(netaddr.IPNetwork(ip).prefixlen == 0 for ip in addresses): + # don't try to install protection because a /0 prefix allows any + # address anyway and the ARP_SPA can only match on /1 or more. + return + + _install_arp_spoofing_protection(vif, addresses, current_rules) + + +def chain_name(vif): + # start each chain with a common identifier for cleanup to find + return '%s%s' % (SPOOF_CHAIN_PREFIX, vif) + + +@lockutils.synchronized('ebtables') +def delete_arp_spoofing_protection(vifs): + current_rules = ebtables(['-L']).splitlines() + _delete_arp_spoofing_protection(vifs, current_rules, table='nat', + chain='PREROUTING') + + # TODO(haleyb) this can go away in "R" cycle, it's here to cleanup + # old chains in the filter table + current_rules = ebtables(['-L'], table='filter').splitlines() + _delete_arp_spoofing_protection(vifs, current_rules, table='filter', + chain='FORWARD') + + +def _delete_arp_spoofing_protection(vifs, current_rules, table, chain): + # delete the jump rule and then delete the whole chain + jumps = [vif for vif in vifs if vif_jump_present(vif, current_rules)] + for vif in jumps: + ebtables(['-D', chain, '-i', vif, '-j', + chain_name(vif), '-p', 'ARP'], table=table) + for vif in vifs: + chain_delete(chain_name(vif), table, current_rules) + _delete_mac_spoofing_protection(vifs, current_rules, table=table, + chain=chain) + + +def _delete_unreferenced_arp_protection(current_vifs, table, chain): + # deletes all jump rules and chains that aren't in current_vifs but match + # the spoof prefix + current_rules = ebtables(['-L'], table=table).splitlines() + to_delete = [] + for line in current_rules: + # we're looking to find and turn the following: + # Bridge chain: SPOOF_CHAIN_PREFIXtap199, entries: 0, policy: DROP + # into 'tap199' + if line.startswith('Bridge chain: %s' % SPOOF_CHAIN_PREFIX): + devname = line.split(SPOOF_CHAIN_PREFIX, 1)[1].split(',')[0] + if devname not in current_vifs: + to_delete.append(devname) + LOG.info("Clearing orphaned ARP spoofing entries for devices %s", + to_delete) + _delete_arp_spoofing_protection(to_delete, current_rules, table=table, + chain=chain) + + +@lockutils.synchronized('ebtables') +def delete_unreferenced_arp_protection(current_vifs): + _delete_unreferenced_arp_protection(current_vifs, + table='nat', chain='PREROUTING') + + # TODO(haleyb) this can go away in "R" cycle, it's here to cleanup + # old chains in the filter table + _delete_unreferenced_arp_protection(current_vifs, + table='filter', chain='FORWARD') + + +@lockutils.synchronized('ebtables') +def install_arp_spoofing_protection(vif, addresses): + current_rules = ebtables(['-L']).splitlines() + _install_arp_spoofing_protection(vif, addresses, current_rules) + + +def _install_arp_spoofing_protection(vif, addresses, current_rules): + # make a VIF-specific ARP chain so we don't conflict with other rules + vif_chain = chain_name(vif) + if not chain_exists(vif_chain, current_rules): + ebtables(['-N', vif_chain, '-P', 'DROP']) + # flush the chain to clear previous accepts. this will cause dropped ARP + # packets until the allows are installed, but that's better than leaked + # spoofed packets and ARP can handle losses. + ebtables(['-F', vif_chain]) + for addr in sorted(addresses): + ebtables(['-A', vif_chain, '-p', 'ARP', '--arp-ip-src', addr, + '-j', 'ACCEPT']) + # check if jump rule already exists, if not, install it + if not vif_jump_present(vif, current_rules): + ebtables(['-A', 'PREROUTING', '-i', vif, '-j', + vif_chain, '-p', 'ARP']) + + +def chain_exists(chain, current_rules): + for rule in current_rules: + if rule.startswith('Bridge chain: %s' % chain): + return True + return False + + +def chain_delete(chain, table, current_rules): + # flush and delete chain if exists + if chain_exists(chain, current_rules): + ebtables(['-F', chain], table=table) + ebtables(['-X', chain], table=table) + + +def vif_jump_present(vif, current_rules): + searches = (('-i %s' % vif), ('-j %s' % chain_name(vif)), ('-p ARP')) + for line in current_rules: + if all(s in line for s in searches): + return True + return False + + +def _install_mac_spoofing_protection(vif, port_details, current_rules): + mac_addresses = {port_details['mac_address']} + if port_details.get('allowed_address_pairs'): + mac_addresses |= {p['mac_address'] + for p in port_details['allowed_address_pairs']} + mac_addresses = list(mac_addresses) + vif_chain = _mac_chain_name(vif) + # mac filter chain for each vif which has a default deny + if not chain_exists(vif_chain, current_rules): + ebtables(['-N', vif_chain, '-P', 'DROP']) + # check if jump rule already exists, if not, install it + if not _mac_vif_jump_present(vif, current_rules): + ebtables(['-A', 'PREROUTING', '-i', vif, '-j', vif_chain]) + # we can't just feed all allowed macs at once because we can exceed + # the maximum argument size. limit to 500 per rule. + for chunk in (mac_addresses[i:i + 500] + for i in range(0, len(mac_addresses), 500)): + new_rule = ['-A', vif_chain, '-i', vif, + '--among-src', ','.join(sorted(chunk)), '-j', 'RETURN'] + ebtables(new_rule) + _delete_vif_mac_rules(vif, current_rules) + + +def _mac_vif_jump_present(vif, current_rules): + searches = (('-i %s' % vif), ('-j %s' % _mac_chain_name(vif))) + for line in current_rules: + if all(s in line for s in searches): + return True + return False + + +def _mac_chain_name(vif): + return '%s%s' % (MAC_CHAIN_PREFIX, vif) + + +def _delete_vif_mac_rules(vif, current_rules): + chain = _mac_chain_name(vif) + for rule in current_rules: + if '-i %s' % vif in rule and '--among-src' in rule: + ebtables(['-D', chain] + rule.split()) + + +def _delete_mac_spoofing_protection(vifs, current_rules, table, chain): + # delete the jump rule and then delete the whole chain + jumps = [vif for vif in vifs + if _mac_vif_jump_present(vif, current_rules)] + for vif in jumps: + ebtables(['-D', chain, '-i', vif, '-j', + _mac_chain_name(vif)], table=table) + for vif in vifs: + chain_delete(_mac_chain_name(vif), table, current_rules) + + +# Used to scope ebtables commands in testing +NAMESPACE = None + + +@tenacity.retry( + wait=tenacity.wait_exponential(multiplier=0.02), + retry=tenacity.retry_if_exception(lambda e: e.returncode == 255), + reraise=True +) +def ebtables(comm, table='nat'): + execute = ip_lib.IPWrapper(NAMESPACE).netns.execute + return execute(['ebtables', '-t', table, '--concurrent'] + comm, + run_as_root=True) diff --git a/formulas/arm/files/ceph-nova.xml b/formulas/arm/files/ceph-nova.xml new file mode 100644 index 00000000..78d9fa87 --- /dev/null +++ b/formulas/arm/files/ceph-nova.xml @@ -0,0 +1,6 @@ +<secret ephemeral="no" private="no"> +<uuid>{{ nova_uuid }}</uuid> +<usage type="ceph"> +<name>client.compute secret</name> +</usage> +</secret> diff --git a/formulas/arm/files/ceph-volumes.xml b/formulas/arm/files/ceph-volumes.xml new file mode 100644 index 00000000..e4da0afc --- /dev/null +++ b/formulas/arm/files/ceph-volumes.xml @@ -0,0 +1,6 @@ +<secret ephemeral="no" private="no"> +<uuid>{{ volumes_uuid }}</uuid> +<usage type="ceph"> +<name>client.volumes secret</name> +</usage> +</secret> diff --git a/formulas/arm/files/config b/formulas/arm/files/config new file mode 100644 index 00000000..b34c69cb --- /dev/null +++ b/formulas/arm/files/config @@ -0,0 +1 @@ +StrictHostKeyChecking no \ No newline at end of file diff --git a/formulas/arm/files/hosts b/formulas/arm/files/hosts new file mode 100644 index 00000000..7a742350 --- /dev/null +++ b/formulas/arm/files/hosts @@ -0,0 +1,3 @@ +127.0.0.1 localhost + +{{ compute_hosts }} \ No newline at end of file diff --git a/formulas/arm/files/kvm.conf b/formulas/arm/files/kvm.conf new file mode 100644 index 00000000..3d7921fa --- /dev/null +++ b/formulas/arm/files/kvm.conf @@ -0,0 +1 @@ +options kvm ignore_msrs=1 \ No newline at end of file diff --git a/formulas/arm/files/linuxbridge_agent.ini b/formulas/arm/files/linuxbridge_agent.ini new file mode 100644 index 00000000..f3948192 --- /dev/null +++ b/formulas/arm/files/linuxbridge_agent.ini @@ -0,0 +1,17 @@ +[DEFAULT] + +[agent] + +[linux_bridge] +physical_interface_mappings = provider:{{ public_interface }} + +[network_log] + +[securitygroup] +enable_security_group = True +firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver + +[vxlan] +enable_vxlan = True +local_ip = {{ local_ip }} +l2_population = True diff --git a/formulas/arm/files/neutron.conf b/formulas/arm/files/neutron.conf new file mode 100644 index 00000000..e3c7b15a --- /dev/null +++ b/formulas/arm/files/neutron.conf @@ -0,0 +1,45 @@ +[DEFAULT] +core_plugin = ml2 +transport_url = {{ transport_url }} +auth_strategy = keystone +use_syslog = False +rpc_conn_pool_size = 300 +executor_thread_pool_size = 2048 +rpc_response_timeout = 3600 +rpc_workers = 5 +report_interval = 120 + +[agent] +root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf +root_helper_daemon = sudo /usr/bin/neutron-rootwrap-daemon /etc/neutron/rootwrap.conf + +[cors] +[cors.subdomain] +[database] + +[keystone_authtoken] +www_authenticate_uri = {{ www_authenticate_uri }} +auth_url = {{ auth_url }} +memcached_servers = {{ memcached_servers }} +auth_type = password +project_domain_name = Default +user_domain_name = Default +project_name = service +username = neutron +password = {{ neutron_password }} +service_token_roles = admin +service_token_roles_required = True + +[matchmaker_redis] +[nova] +[oslo_concurrency] +lock_path = {{ lock_path }} + +[oslo_messaging_amqp] +[oslo_messaging_notifications] +[oslo_messaging_rabbit] +[oslo_messaging_zmq] +[oslo_policy] +[qos] +[quotas] +[ssl] diff --git a/formulas/arm/files/neutron_ovn_metadata_agent.ini b/formulas/arm/files/neutron_ovn_metadata_agent.ini new file mode 100644 index 00000000..277576b1 --- /dev/null +++ b/formulas/arm/files/neutron_ovn_metadata_agent.ini @@ -0,0 +1,23 @@ +[DEFAULT] +nova_metadata_host = {{ nova_metadata_host }} +metadata_proxy_shared_secret = {{ metadata_proxy_shared_secret }} +nova_metadata_protocol = https +use_syslog = False +### Added this per https://bugs.launchpad.net/neutron/+bug/1893656 +### and great feedback from redhat +metadata_workers = 2 + +[AGENT] +root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf +root_helper_daemon = sudo /usr/bin/neutron-rootwrap-daemon /etc/neutron/rootwrap.conf + +[cache] + +[ovs] +ovsdb_connection = tcp:127.0.0.1:6640 + +[ovn] +ovn_sb_connection = {{ ovn_sb_connection }} + +[privsep] +helper_command = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf privsep-helper --config-file /etc/neutron/neutron_ovn_metadata_agent.ini diff --git a/formulas/arm/files/neutron_sudoers b/formulas/arm/files/neutron_sudoers new file mode 100644 index 00000000..0abb34bc --- /dev/null +++ b/formulas/arm/files/neutron_sudoers @@ -0,0 +1,5 @@ +Defaults:neutron !requiretty +Defaults use_pty +Defaults logfile="/var/log/sudo.log" + +neutron ALL = (root) NOPASSWD: /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf *,/usr/bin/neutron-rootwrap-daemon /etc/neutron/rootwrap.conf diff --git a/formulas/arm/files/nova.conf b/formulas/arm/files/nova.conf new file mode 100644 index 00000000..910e9aa1 --- /dev/null +++ b/formulas/arm/files/nova.conf @@ -0,0 +1,184 @@ +[DEFAULT] +lock_path = /var/lock/nova +state_path = /var/lib/nova +use_neutron = True +firewall_driver = nova.virt.firewall.NoopFirewallDriver +my_ip = {{ my_ip }} +transport_url = {{ transport_url }} +vnc_enabled = false +web=/usr/share/spice-html5 +block_device_allocate_retries_interval = 10 +block_device_allocate_retries = 120 +resume_guests_state_on_host_boot = True +use_syslog = False +reserved_host_memory_mb=8196 +timeout_nbd = 60 +heal_instance_info_cache_interval = 600 +vif_plugging_timeout = 600 +rpc_response_timeout = 3600 + + +# Weighting Options + +initial_cpu_allocation_ratio = {{ initial_cpu_allocation_ratio }} +initial_ram_allocation_ratio = {{ initial_ram_allocation_ratio }} +initial_disk_allocation_ratio = {{ initial_disk_allocation_ratio }} + +[api] +auth_strategy = keystone + +[api_database] + +{% if salt['pillar.get']('hosts:barbican:enabled', 'False') == True %} +[barbican] +barbican_endpoint = {{ barbican_endpoint }} +auth_endpoint = {{ auth_url }} +barbican_endpoint_type = internal +{% endif %} + +[cache] +enabled = True +memcache_servers = {{ memcached_servers }} +backend = oslo_cache.memcache_pool + +[cells] +enable=False + +[cinder] + +[compute] +consecutive_build_service_disable_threshold = 0 + +[conductor] +[console] +[consoleauth] +[cors] +[crypto] +[database] +[ephemeral_storage_encryption] +[filter_scheduler] +enabled_filters=AggregateMultiTenancyIsolation,AggregateImagePropertiesIsolation,AggregateInstanceExtraSpecsFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter +[glance] +api_servers = {{ api_servers }} + +[guestfs] +[healthcheck] +[hyperv] +[image_file_url] +[ironic] +[key_manager] +[keystone] + +[keystone_authtoken] +www_authenticate_uri = {{ www_authenticate_uri }} +auth_url = {{ auth_url }} +memcached_servers = {{ memcached_servers }} +auth_type = password +project_domain_name = Default +user_domain_name = Default +project_name = service +username = nova +password = {{ nova_password }} +service_token_roles = admin +service_token_roles_required = True + +[libvirt] +use_virtio_for_bridges = True +images_rbd_pool = vms +images_type = rbd +rbd_secret_uuid = {{ rbd_secret_uuid }} +rbd_user = compute +disk_cachemodes="network=writeback" +live_migration_retry_count = 10 +max_concurrent_live_migrations = 10 +live_migration_bandwidth = 0 +live_migration_uri = qemu+ssh://%s/system?no_verify=1 + +[matchmaker_redis] +[metrics] +[mks] + +[neutron] +auth_url = {{ auth_url }} +auth_type = password +project_domain_name = Default +user_domain_name = Default +project_name = service +region_name = RegionOne +username = neutron +password = {{ neutron_password }} + +[notifications] +[osapi_v21] + +[oslo_concurrency] +lock_path = /var/lib/nova/tmp + +[oslo_messaging_amqp] +connection_retry_interval_max = 60 +default_reply_timeout = 60 +default_send_timeout = 60 +default_notify_timeout = 60 + +[oslo_messaging_kafka] +[oslo_messaging_notifications] +[oslo_messaging_rabbit] +[oslo_messaging_zmq] +[oslo_middleware] +[oslo_policy] +enforce_new_defaults=False +enforce_scope=False + +[pci] +{% if pillar['gpu']['backend'] == "pci-passthrough" %} +alias = { "vendor_id":"10de", "product_id":"1db6", "device_type":"type-PCI", "name":"TeslaV100" } +passthrough_whitelist = { "vendor_id": "10de", "product_id": "1db6" } + +{% endif %} +[placement] +os_region_name = RegionOne +auth_url = {{ auth_url }} +auth_type = password +project_domain_name = Default +user_domain_name = Default +project_name = service +username = placement +password = {{ placement_password }} + +[quota] +[rdp] +[remote_debug] +[scheduler] +[serial_console] +enabled = True +port_range = 10000:20000 +base_url = wss://{{ dashboard_domain }}:6083/ +proxyclient_address = $my_ip +[service_user] + +[spice] +enabled = True +agent_enabled = True +html5proxy_base_url = https://{{ console_domain }}/spice_auto.html +server_proxyclient_address = $my_ip +server_listen = 0.0.0.0 + +[upgrade_levels] +[vault] +[vendordata_dynamic_auth] +[vmware] + +[vnc] +enabled = False +novncproxy_base_url = https://{{ console_domain }}/vnc_auto.html +server_listen = 0.0.0.0 +server_proxyclient_address = $my_ip + +[workarounds] +### related to https://bugs.launchpad.net/nova/+bug/1946729 +### config guide https://docs.openstack.org/nova/latest/configuration/config.html#:~:text=wait_for_vif_plugged_event_during_hard_reboot +wait_for_vif_plugged_event_during_hard_reboot = normal + +[wsgi] +[xenserver] +[xvp] diff --git a/formulas/arm/files/openvswitch_agent.ini b/formulas/arm/files/openvswitch_agent.ini new file mode 100644 index 00000000..155d5c69 --- /dev/null +++ b/formulas/arm/files/openvswitch_agent.ini @@ -0,0 +1,22 @@ +[DEFAULT] + +[agent] +tunnel_types = vxlan +vxlan_udp_port = {{ vxlan_udp_port }} +l2_population = {{ l2_population }} +arp_responder = {{ arp_responder }} +enable_distributed_routing = {{ enable_distributed_routing }} +drop_flows_on_start = {{ drop_flows_on_start }} +extensions = {{ extensions }} +explicitly_egress_direct = {{ explicitly_egress_direct }} + +[ovs] +local_ip = {{ local_ip }} +bridge_mappings = provider:{{ bridge_mappings }} +of_connect_timeout = 300 +of_request_timeout = 300 + +[securitygroup] +firewall_driver = openvswitch +enable_security_group = True +enable_ipset = true diff --git a/formulas/arm/install.sls b/formulas/arm/install.sls index bca65e1c..13594baf 100644 --- a/formulas/arm/install.sls +++ b/formulas/arm/install.sls @@ -1,4 +1,4 @@ -## Copyright 2021 United States Army Cyber School +## Copyright 2018 Augusta University ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. @@ -13,4 +13,62 @@ ## limitations under the License. include: - - /formulas/compute/install + - /formulas/common/base + - /formulas/common/networking + - /formulas/common/install + - /formulas/common/openstack/repo + - /formulas/common/ceph/repo + - /formulas/common/frr/repo + +{% if grains['os_family'] == 'Debian' %} +compute_packages: + pkg.installed: + - pkgs: + - nova-compute + - python3-tornado + - ceph-common + - spice-html5 + - python3-rbd + - python3-rados +# - frr +# - frr-pythontools + - python3-etcd3gw + - qemu-system + - nvme-cli + {% if pillar['neutron']['backend'] == "linuxbridge" %} + - neutron-linuxbridge-agent + {% elif pillar['neutron']['backend'] == "openvswitch" %} + - neutron-openvswitch-agent + {% elif pillar['neutron']['backend'] == "networking-ovn" %} + - ovn-host + - neutron-ovn-metadata-agent + - haproxy + {% endif %} + +{% elif grains['os_family'] == 'RedHat' %} +compute_packages: + pkg.installed: + - pkgs: + - openstack-nova-compute + - python3-tornado + - ceph-common + - python3-rbd + - python3-rados + - conntrack-tools + - frr + - frr-pythontools + - qemu-system-arm + - qemu-system-mips + - nvme-cli + {% if pillar['neutron']['backend'] == "linuxbridge" %} + - openstack-neutron-linuxbridge + {% elif pillar['neutron']['backend'] == "openvswitch" %} + - openstack-openvswitch-agent + {% elif pillar['neutron']['backend'] == "networking-ovn" %} + - rdo-ovn-host + - openstack-neutron-ovn-metadata-agent + - openstack-neutron-common + - haproxy + {% endif %} + +{% endif %} diff --git a/formulas/common/base.sls b/formulas/common/base.sls index b0745c67..d4a5d5db 100644 --- a/formulas/common/base.sls +++ b/formulas/common/base.sls @@ -191,6 +191,8 @@ cpufrequtils.service: - file: /etc/default/cpufrequtils {% endif %} +{% if role != 'arm' %} + /etc/udev/rules.d/60-netdev.rules: file.managed: - user: root @@ -198,6 +200,8 @@ cpufrequtils.service: - mode: '0600' - source: salt://formulas/common/kernel/files/60-netdev.rules +{% endif %} + # The LDAP server is not controlled under this project. Pointing to the source so if it ever changes this will still work /usr/local/share/ca-certificates/ipa.cybbh.space/ldap_ca.crt: file.managed: -- GitLab From 98dcd14087055e4f8933ab4cccdbf1c9b496eeeb Mon Sep 17 00:00:00 2001 From: Javier Diaz <jdiaz@mirantis.com> Date: Thu, 22 Sep 2022 14:10:01 -0500 Subject: [PATCH 2/2] Edit file locations --- formulas/arm/configure.sls | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/formulas/arm/configure.sls b/formulas/arm/configure.sls index 32fef4c5..d0309c24 100644 --- a/formulas/arm/configure.sls +++ b/formulas/arm/configure.sls @@ -72,19 +72,19 @@ conf-files: {% endif %} - names: - /etc/modprobe.d/kvm.conf: - - source: salt://formulas/compute/files/kvm.conf + - source: salt://formulas/arm/files/kvm.conf # - /etc/frr/daemons: # - source: salt://formulas/common/frr/files/daemons - /etc/ceph/ceph-nova.xml: - - source: salt://formulas/compute/files/ceph-nova.xml + - source: salt://formulas/arm/files/ceph-nova.xml - /etc/ceph/ceph-volumes.xml: - - source: salt://formulas/compute/files/ceph-volumes.xml + - source: salt://formulas/arm/files/ceph-volumes.xml - /etc/nova/nova.conf: - - source: salt://formulas/compute/files/nova.conf + - source: salt://formulas/arm/files/nova.conf - /etc/sudoers.d/neutron_sudoers: - - source: salt://formulas/compute/files/neutron_sudoers + - source: salt://formulas/arm/files/neutron_sudoers - /etc/neutron/neutron.conf: - - source: salt://formulas/compute/files/neutron.conf + - source: salt://formulas/arm/files/neutron.conf compute_hosts: @@ -94,7 +94,7 @@ compute_hosts: compute_hosts: {{ constructor.host_file_constructor(role='compute')|yaml_encode }} - names: - /etc/hosts: - - source: salt://formulas/compute/files/hosts + - source: salt://formulas/arm/files/hosts ceph_keyrings: file.managed: @@ -122,9 +122,9 @@ libvirt_secrets: - /etc/libvirt/secrets/{{ volumes_uuid }}.base64: - contents_pillar: ceph:ceph-client-volumes-key - /etc/libvirt/secrets/{{ nova_uuid }}.xml: - - source: salt://formulas/compute/files/ceph-nova.xml + - source: salt://formulas/arm/files/ceph-nova.xml - /etc/libvirt/secrets/{{ volumes_uuid }}.xml: - - source: salt://formulas/compute/files/ceph-volumes.xml + - source: salt://formulas/arm/files/ceph-volumes.xml - mode: "0600" - user: root - group: root @@ -134,7 +134,7 @@ libvirt_secrets: - user: root - group: root - mode: '0400' - - source: salt://formulas/compute/files/config + - source: salt://formulas/arm/files/config {% for key in pillar['nova_live_migration_auth_key'] %} {{ key }}: @@ -173,7 +173,7 @@ nova_compute_service: {% if neutron_backend != "networking-ovn" %} /etc/neutron/plugins/ml2/{{ neutron_backend }}_agent.ini: file.managed: - - source: salt://formulas/compute/files/{{ neutron_backend }}_agent.ini + - source: salt://formulas/arm/files/{{ neutron_backend }}_agent.ini - template: jinja - defaults: local_ip: {{ salt['network.ip_addrs'](cidr=pillar['networking']['subnets']['private'])[0] }} @@ -221,7 +221,7 @@ neutron_{{ neutron_backend }}_agent_service: {% elif neutron_backend == "networking-ovn" %} neutron-ovn-metadata-agent.ini: file.managed: - - source: salt://formulas/compute/files/neutron_ovn_metadata_agent.ini + - source: salt://formulas/arm/files/neutron_ovn_metadata_agent.ini - name: /etc/neutron/neutron_ovn_metadata_agent.ini - template: jinja - defaults: @@ -368,7 +368,7 @@ libvirtd_service: - group: root - mode: '0644' - template: jinja - - source: salt://formulas/compute/files/10-iommu.cfg + - source: salt://formulas/arm/files/10-iommu.cfg - defaults: kernel_param: {{ pillar['hosts'][grains['type']]['kernel_param'][0] }} -- GitLab