Initial commit 64/664/1
authorRalf Mueller <ralf.1.mueller@nokia.com>
Fri, 22 Mar 2019 09:17:29 +0000 (11:17 +0200)
committerRalf Mueller <ralf.1.mueller@nokia.com>
Thu, 9 May 2019 10:19:17 +0000 (13:19 +0300)
Change-Id: I9e0537fff4c113b39c1d4180a4ec5c15068a775c
Signed-off-by: Ralf Mueller <ralf.1.mueller@nokia.com>
373 files changed:
.gitreview [new file with mode: 0644]
LICENSE [new file with mode: 0644]
READ.ME [new file with mode: 0644]
conflicts-with-openstack-ansible/galera-install.yml [new file with mode: 0644]
conflicts-with-openstack-ansible/hosts_config.yml [new file with mode: 0644]
conflicts-with-openstack-ansible/os-ironic-install.yml [new file with mode: 0644]
conflicts-with-openstack-ansible/os-keystone-install.yml [new file with mode: 0644]
conflicts-with-openstack-ansible/rabbitmq-install.yml [new file with mode: 0644]
conflicts-with-openstack-ansible/rsyslog-install.yml [new file with mode: 0644]
dev_tools/startlan.sh [new file with mode: 0755]
infra-ansible.spec [new file with mode: 0644]
playbooks/access-management.yml [new file with mode: 0644]
playbooks/accounts.yml [new file with mode: 0644]
playbooks/adminuserfile.yml [new file with mode: 0644]
playbooks/allocate-cpu-cores.yml [new file with mode: 0644]
playbooks/ansibleldconfig.yml [new file with mode: 0644]
playbooks/ansiblesync.yml [new file with mode: 0644]
playbooks/associate_pools_for_application.yml [new file with mode: 0644]
playbooks/bare_lvm_backend.yml [new file with mode: 0644]
playbooks/baremetal-install.yml [new file with mode: 0644]
playbooks/baremetal-interface-config-post.yml [new file with mode: 0644]
playbooks/baremetal-interface-config.yml [new file with mode: 0644]
playbooks/baremetal-rm-nfs-mnt.yaml [new file with mode: 0644]
playbooks/baremetal-rm-nfs-server.yaml [new file with mode: 0644]
playbooks/baremetal-setup-nfs-mnt.yaml [new file with mode: 0644]
playbooks/baremetal-setup-nfs-server.yaml [new file with mode: 0644]
playbooks/ceph-deploy.yml [new file with mode: 0644]
playbooks/ceph-post-cleanup.yml [new file with mode: 0644]
playbooks/certificate_update.yml [new file with mode: 0644]
playbooks/cleanup-disk.yml [new file with mode: 0644]
playbooks/cmserverconfig.yml [new file with mode: 0644]
playbooks/collect_disk_jsons_together.yml [new file with mode: 0644]
playbooks/core-handling.yml [new file with mode: 0644]
playbooks/create-bash-command-auth-conf.yml [new file with mode: 0644]
playbooks/create_osd_disk_configuration.yml [new file with mode: 0644]
playbooks/dbwatchdog.yml [new file with mode: 0644]
playbooks/destroy_data_and_partitions.yml [new file with mode: 0644]
playbooks/disable-old-node-rsyslog.yml [new file with mode: 0644]
playbooks/distribute_disk_config.yml [new file with mode: 0644]
playbooks/distributed-state-server-etcd-plugin.yml [new file with mode: 0644]
playbooks/distributed-state-server-file-plugin.yml [new file with mode: 0644]
playbooks/distributed-state-server.yml [new file with mode: 0644]
playbooks/enablecmagent.yml [new file with mode: 0644]
playbooks/etcdansible.yml [new file with mode: 0644]
playbooks/glance-lvm.yml [new file with mode: 0644]
playbooks/hostcli.yml [new file with mode: 0644]
playbooks/initial_poweroff_hosts.yml [new file with mode: 0644]
playbooks/ipv6-config.yml [new file with mode: 0644]
playbooks/kernel-core-handling.yml [new file with mode: 0644]
playbooks/make_instance_disk_partitions.yml [new file with mode: 0644]
playbooks/make_osd_disk_metadata.yml [new file with mode: 0644]
playbooks/manage_chroot_user.yml [new file with mode: 0644]
playbooks/manage_linux_user.yml [new file with mode: 0644]
playbooks/monitoring.yml [new file with mode: 0644]
playbooks/motd.yml [new file with mode: 0644]
playbooks/oom.yml [new file with mode: 0644]
playbooks/openssh_server_conf_hardening.yml [new file with mode: 0644]
playbooks/openstack-ansible-log-dir.yml [new file with mode: 0644]
playbooks/operation_system_hardening.yml [new file with mode: 0644]
playbooks/osd_disk_configuration.j2 [new file with mode: 0644]
playbooks/osd_disk_metadata.j2 [new file with mode: 0644]
playbooks/partfs_rootdisk.yml [new file with mode: 0644]
playbooks/partfs_rootdisk_inst_cont.yml [new file with mode: 0644]
playbooks/performance-kernel-cmdline-set.yml [new file with mode: 0644]
playbooks/performance_nodes.yaml [new file with mode: 0644]
playbooks/prepare_cow_backend.yml [new file with mode: 0644]
playbooks/prepare_lvm_backend.yml [new file with mode: 0644]
playbooks/redisconfig.yml [new file with mode: 0644]
playbooks/redissync.yml [new file with mode: 0644]
playbooks/remove_volume_groups.yml [new file with mode: 0644]
playbooks/removevips.yml [new file with mode: 0644]
playbooks/reset_failed_ceph_disk_services.yml [new file with mode: 0644]
playbooks/restful.yml [new file with mode: 0644]
playbooks/root-openstack-admin-credentials.yml [new file with mode: 0644]
playbooks/rpm-database.yml [new file with mode: 0644]
playbooks/secretsextend.yml [new file with mode: 0644]
playbooks/service-profiles.yml [new file with mode: 0644]
playbooks/set_keyring_owners.yml [new file with mode: 0644]
playbooks/setup_aaa.yml [new file with mode: 0644]
playbooks/setup_audit.yml [new file with mode: 0644]
playbooks/setup_in_host_traffic_filtering.yml [new file with mode: 0644]
playbooks/single_node_partitions.yml [new file with mode: 0755]
playbooks/single_node_storage.yml [new file with mode: 0644]
playbooks/single_node_volume_groups.yml [new file with mode: 0755]
playbooks/site.yml [new file with mode: 0644]
playbooks/sriov_nodes.yaml [new file with mode: 0644]
playbooks/sriovdp_config.yaml [new file with mode: 0644]
playbooks/synchonize_ssh_keys.yml [new file with mode: 0644]
playbooks/systemd_services.yml [new file with mode: 0644]
playbooks/userskeyssync.yml [new file with mode: 0644]
roles/access-management/defaults/main.yaml [new file with mode: 0644]
roles/access-management/tasks/basic.yaml [new file with mode: 0644]
roles/access-management/tasks/dbfiller.yaml [new file with mode: 0644]
roles/access-management/tasks/fill_sqls.yaml [new file with mode: 0644]
roles/access-management/tasks/main.yaml [new file with mode: 0644]
roles/access-management/tasks/mysqldb.yaml [new file with mode: 0644]
roles/access-management/tasks/openrc_cloud.yaml [new file with mode: 0644]
roles/access-management/templates/am.backend.conf.j2 [new file with mode: 0644]
roles/access-management/templates/am.plugin.conf.j2 [new file with mode: 0644]
roles/access-management/templates/am_pri_key.pem [new file with mode: 0644]
roles/access-management/templates/custom_rc.j2 [new file with mode: 0644]
roles/access-management/templates/db_am_values.json.j2 [new file with mode: 0644]
roles/access-management/templates/db_service_values.json.j2 [new file with mode: 0644]
roles/access-management/templates/dbfiller.py.j2 [new file with mode: 0644]
roles/access-management/templates/keystone_users_patch.sh.j2 [new file with mode: 0644]
roles/account-hardenning/tasks/main.yml [new file with mode: 0644]
roles/allocate_cpu_cores/defaults/main.yml [new file with mode: 0644]
roles/allocate_cpu_cores/filter_plugins/helpers.py [new file with mode: 0644]
roles/allocate_cpu_cores/library/get_cpu_topology.py [new file with mode: 0644]
roles/allocate_cpu_cores/tasks/main.yml [new file with mode: 0644]
roles/allocate_cpu_cores/tasks/make_cpu_sets.yaml [new file with mode: 0644]
roles/allocate_cpu_cores/templates/ncir_cpu_allocation.fact.j2 [new file with mode: 0644]
roles/ansibleldconfig/README.rst [new file with mode: 0644]
roles/ansibleldconfig/handlers/main.yml [new file with mode: 0644]
roles/ansibleldconfig/tasks/ldconfig.yml [new file with mode: 0644]
roles/ansibleldconfig/tasks/main.yml [new file with mode: 0644]
roles/ansiblesync/handlers/main.yml [new file with mode: 0644]
roles/ansiblesync/tasks/main.yml [new file with mode: 0644]
roles/audit/defaults/main.yaml [new file with mode: 0644]
roles/audit/tasks/main.yaml [new file with mode: 0644]
roles/audit/templates/10-base-config.rules.j2 [new file with mode: 0644]
roles/audit/templates/11-loginuid.rules.j2 [new file with mode: 0644]
roles/audit/templates/12-filter-users.rules.j2 [new file with mode: 0644]
roles/audit/templates/30-stig.rules.j2 [new file with mode: 0644]
roles/audit/templates/31-privileged-gen.rules.j2 [new file with mode: 0644]
roles/audit/templates/32-power-abuse.rules.j2 [new file with mode: 0644]
roles/audit/templates/33-avoid-flood.rules.j2 [new file with mode: 0644]
roles/audit/templates/34-failed-actions.rules.j2 [new file with mode: 0644]
roles/audit/templates/35-umount.rules.j2 [new file with mode: 0644]
roles/audit/templates/36-resource-management.rules.j2 [new file with mode: 0644]
roles/audit/templates/37-linux-capabilities.rules.j2 [new file with mode: 0644]
roles/audit/templates/41-containers.rules.j2 [new file with mode: 0644]
roles/audit/templates/42-injection.rules.j2 [new file with mode: 0644]
roles/audit/templates/43-module-load.rules.j2 [new file with mode: 0644]
roles/audit/templates/44-certificates.rules.j2 [new file with mode: 0644]
roles/audit/templates/50-file-changes.rules.j2 [new file with mode: 0644]
roles/audit/templates/51-messaging.rules.j2 [new file with mode: 0644]
roles/audit/templates/52-sandbox.rules.j2 [new file with mode: 0644]
roles/audit/templates/53-kernel-parameters.rules.j2 [new file with mode: 0644]
roles/audit/templates/99-finalize.rules.j2 [new file with mode: 0644]
roles/baremetal_interface_config/README.rst [new file with mode: 0644]
roles/baremetal_interface_config/defaults/main.yml [new file with mode: 0644]
roles/baremetal_interface_config/tasks/main.yml [new file with mode: 0644]
roles/baremetal_interface_config/templates/os_net_config.j2 [new file with mode: 0644]
roles/baremetal_provision/defaults/main.yml [new file with mode: 0644]
roles/baremetal_provision/files/guest-img-nginx.service [new file with mode: 0644]
roles/baremetal_provision/files/tmux_setup/log.inc [new file with mode: 0755]
roles/baremetal_provision/files/tmux_setup/tmux.conf [new file with mode: 0644]
roles/baremetal_provision/files/tmux_setup/tmux.inc [new file with mode: 0644]
roles/baremetal_provision/files/virtualbmc.conf [new file with mode: 0644]
roles/baremetal_provision/library/README.rst [new file with mode: 0644]
roles/baremetal_provision/library/os_node_power_check.py [new file with mode: 0644]
roles/baremetal_provision/library/os_node_provision_check.py [new file with mode: 0644]
roles/baremetal_provision/tasks/convert_qcow_raw.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/ironic_nodes_create.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/ironic_nodes_deploy.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/main.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/setup_http.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/start_console_logging.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/stop_console_logging.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/teardown_http.yml [new file with mode: 0644]
roles/baremetal_provision/tasks/vbmc_port_setup.yml [new file with mode: 0644]
roles/baremetal_provision/templates/baremetal_nodes.j2 [new file with mode: 0644]
roles/baremetal_provision/templates/guest-img-nginx.conf.j2 [new file with mode: 0644]
roles/baremetal_provision/templates/guest-img-nginx.service [new file with mode: 0644]
roles/baremetal_provision/templates/meta_data.json.j2 [new file with mode: 0644]
roles/baremetal_provision/templates/nginx.conf [new file with mode: 0644]
roles/baremetal_provision/templates/user_data.j2 [new file with mode: 0644]
roles/bootstrap-host/defaults/main.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/check-requirements.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/create_sudo_user.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/install_packages.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/main.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_aio_config.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_ceph.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_data_disk.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_loopback_cinder.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_loopback_nova.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_loopback_swap.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_loopback_swift.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_networking.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_os_net_config.yml [new file with mode: 0644]
roles/bootstrap-host/tasks/prepare_ssh_keys.yml [new file with mode: 0644]
roles/bootstrap-host/templates/apt-sources.list.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/osa_interfaces.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/osa_interfaces_multinode.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_alias.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_default.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_ethernet.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_ifdown-post.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_ifup-post.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/redhat_interface_vlan.cfg.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/user_variables.aio.yml.j2 [new file with mode: 0644]
roles/bootstrap-host/templates/user_variables.ceph.yml.j2 [new file with mode: 0644]
roles/bootstrap-host/vars/redhat.yml [new file with mode: 0644]
roles/bootstrap-host/vars/ubuntu.yml [new file with mode: 0644]
roles/change_kernel_cmdline/README.rst [new file with mode: 0644]
roles/change_kernel_cmdline/defaults/main.yml [new file with mode: 0644]
roles/change_kernel_cmdline/filter_plugins/change_kernel_cmdline_helpers.py [new file with mode: 0644]
roles/change_kernel_cmdline/tasks/main.yml [new file with mode: 0644]
roles/cleanup_disks/defaults/main.yml [new file with mode: 0644]
roles/cleanup_disks/tasks/destroy_data_and_partitions.yml [new file with mode: 0644]
roles/cleanup_disks/tasks/main.yml [new file with mode: 0644]
roles/cleanup_disks/tasks/remove_volume_groups.yml [new file with mode: 0644]
roles/cmserver-config/README.rst [new file with mode: 0644]
roles/cmserver-config/defaults/main.yml [new file with mode: 0644]
roles/cmserver-config/handlers/main.yml [new file with mode: 0644]
roles/cmserver-config/tasks/generate_cmserver_config.yml [new file with mode: 0644]
roles/cmserver-config/tasks/main.yml [new file with mode: 0644]
roles/cmserver-config/templates/config.ini.j2 [new file with mode: 0644]
roles/core-handling-config/files/01-enable-cores.conf [new file with mode: 0644]
roles/core-handling-config/files/02-only-backtrace.conf [new file with mode: 0644]
roles/core-handling-config/tasks/main.yml [new file with mode: 0644]
roles/dbwatchdog/README.rst [new file with mode: 0644]
roles/dbwatchdog/handlers/main.yml [new file with mode: 0644]
roles/dbwatchdog/tasks/generate_config.yml [new file with mode: 0644]
roles/dbwatchdog/tasks/main.yml [new file with mode: 0644]
roles/dbwatchdog/templates/config.ini.j2 [new file with mode: 0644]
roles/dbwatchdog/templates/mariadb.service.j2 [new file with mode: 0644]
roles/disable-default-rsyslog/README.rst [new file with mode: 0644]
roles/disable-default-rsyslog/tasks/disable_rsyslog.yml [new file with mode: 0644]
roles/disable-default-rsyslog/tasks/main.yml [new file with mode: 0644]
roles/distributed-state-server-etcd-plugin/README.rst [new file with mode: 0644]
roles/distributed-state-server-etcd-plugin/handlers/main.yml [new file with mode: 0644]
roles/distributed-state-server-etcd-plugin/tasks/generate_config.yml [new file with mode: 0644]
roles/distributed-state-server-etcd-plugin/tasks/main.yml [new file with mode: 0644]
roles/distributed-state-server-etcd-plugin/templates/config.ini.j2 [new file with mode: 0644]
roles/distributed-state-server-file-plugin/README.rst [new file with mode: 0644]
roles/distributed-state-server-file-plugin/handlers/main.yml [new file with mode: 0644]
roles/distributed-state-server-file-plugin/tasks/generate_config.yml [new file with mode: 0644]
roles/distributed-state-server-file-plugin/tasks/main.yml [new file with mode: 0644]
roles/distributed-state-server-file-plugin/templates/config.ini.j2 [new file with mode: 0644]
roles/distributed-state-server/README.rst [new file with mode: 0644]
roles/distributed-state-server/handlers/main.yml [new file with mode: 0644]
roles/distributed-state-server/tasks/enable-dss-server.yml [new file with mode: 0644]
roles/distributed-state-server/tasks/generate_config.yml [new file with mode: 0644]
roles/distributed-state-server/tasks/main.yml [new file with mode: 0644]
roles/distributed-state-server/templates/config.ini.j2 [new file with mode: 0644]
roles/distributed-state-server/templates/dss-server.service.j2 [new file with mode: 0644]
roles/etcdansible/README.rst [new file with mode: 0644]
roles/etcdansible/handlers/main.yml [new file with mode: 0644]
roles/etcdansible/tasks/configure_etcd.yml [new file with mode: 0644]
roles/etcdansible/tasks/enable_etcd.yml [new file with mode: 0644]
roles/etcdansible/tasks/handle_reinitialized_etcd.yml [new file with mode: 0644]
roles/etcdansible/tasks/main.yml [new file with mode: 0644]
roles/etcdansible/templates/etcd.conf.j2 [new file with mode: 0644]
roles/hostcli/handlers/main.yml [new file with mode: 0644]
roles/hostcli/tasks/generate_bash_auto_complete.yml [new file with mode: 0644]
roles/hostcli/tasks/main.yml [new file with mode: 0644]
roles/in_host_traffic_filtering_controller/defaults/main.yml [new file with mode: 0644]
roles/in_host_traffic_filtering_controller/handlers/main.yml [new file with mode: 0644]
roles/in_host_traffic_filtering_controller/tasks/main.yml [new file with mode: 0644]
roles/in_host_traffic_filtering_controller/templates/ip6tables.j2 [new file with mode: 0644]
roles/in_host_traffic_filtering_controller/templates/iptables.j2 [new file with mode: 0644]
roles/initial_poweroff_hosts/README.rst [new file with mode: 0644]
roles/initial_poweroff_hosts/defaults/main.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/handlers/main.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/library/xml_parse_macs.py [new file with mode: 0644]
roles/initial_poweroff_hosts/tasks/mac_matcher.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/tasks/main.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/tasks/poweroff_real_nodes.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/tasks/poweroff_virtual_node.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/tasks/poweroff_virtual_nodes.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/vars/redhat-7.yml [new file with mode: 0644]
roles/initial_poweroff_hosts/vars/ubuntu-16.04.yml [new file with mode: 0644]
roles/kernel-core-handling-config/handlers/main.yml [new file with mode: 0644]
roles/kernel-core-handling-config/tasks/main.yml [new file with mode: 0644]
roles/logging/README.rst [new file with mode: 0644]
roles/logging/handlers/main.yml [new file with mode: 0644]
roles/logging/tasks/generate_log_forwarding_config.yml [new file with mode: 0644]
roles/logging/tasks/main.yml [new file with mode: 0644]
roles/logging/tasks/restart_centralized_instance.yml [new file with mode: 0644]
roles/logging/templates/logforwarding.j2 [new file with mode: 0644]
roles/manage_linux_user/tasks/main.yml [new file with mode: 0644]
roles/manage_user/tasks/main.yml [new file with mode: 0644]
roles/monitoring/README.rst [new file with mode: 0644]
roles/monitoring/defaults/main.yaml [new file with mode: 0644]
roles/monitoring/handlers/main.yml [new file with mode: 0644]
roles/monitoring/tasks/generate_active_standby_controller_file.yml [new file with mode: 0644]
roles/monitoring/tasks/generate_config.yml [new file with mode: 0644]
roles/monitoring/tasks/generate_rediscontroller_systemd_unit_file.yml [new file with mode: 0644]
roles/monitoring/tasks/generate_redismonitor_systemd_unit_file.yml [new file with mode: 0644]
roles/monitoring/tasks/main.yml [new file with mode: 0644]
roles/monitoring/tasks/start_services.yml [new file with mode: 0644]
roles/monitoring/tasks/update_hosts.yml [new file with mode: 0644]
roles/monitoring/templates/active-standby-controller.service.j2 [new file with mode: 0644]
roles/monitoring/templates/keepalivedmonitor.conf.j2 [new file with mode: 0644]
roles/monitoring/templates/keepalivedmonitor.service.j2 [new file with mode: 0644]
roles/monitoring/templates/keepalivedmonitoragent.service.j2 [new file with mode: 0644]
roles/monitoring/templates/rediscontroller.service.j2 [new file with mode: 0644]
roles/monitoring/templates/redismonitor.service.j2 [new file with mode: 0644]
roles/motd/README.rst [new file with mode: 0644]
roles/motd/handlers/main.yml [new file with mode: 0644]
roles/motd/tasks/generate_motd_config.yml [new file with mode: 0644]
roles/motd/tasks/main.yml [new file with mode: 0644]
roles/motd/templates/motd.j2 [new file with mode: 0644]
roles/oom-config/tasks/main.yml [new file with mode: 0644]
roles/ops-hardening/tasks/main.yaml [new file with mode: 0644]
roles/partfs_rootdisk/defaults/main.yml [new file with mode: 0644]
roles/partfs_rootdisk/handlers/main.yml [new file with mode: 0644]
roles/partfs_rootdisk/scripts/old_vol_rm.sh [new file with mode: 0755]
roles/partfs_rootdisk/scripts/vol_mgmt.sh [new file with mode: 0755]
roles/partfs_rootdisk/tasks/main.yml [new file with mode: 0644]
roles/partfs_rootdisk/tasks/remove_old_instance_vg.yml [new file with mode: 0644]
roles/partfs_rootdisk/tasks/root_disk_volume_groups.yml [new file with mode: 0644]
roles/partfs_rootdisk/templates/localstorage.j2 [new file with mode: 0644]
roles/partfs_rootdisk/vars/redhat-7.yml [new file with mode: 0644]
roles/partfs_rootdisk/vars/ubuntu-16.04.yml [new file with mode: 0644]
roles/performance_nodes/defaults/main.yml [new file with mode: 0644]
roles/performance_nodes/files/configure_ovsdpdk.py [new file with mode: 0644]
roles/performance_nodes/tasks/main.yaml [new file with mode: 0644]
roles/performance_nodes/tasks/ovsdpdk.yaml [new file with mode: 0644]
roles/performance_nodes/tasks/services.yaml [new file with mode: 0644]
roles/performance_nodes_post/defaults/main.yml [new file with mode: 0644]
roles/performance_nodes_post/tasks/main.yaml [new file with mode: 0644]
roles/performance_nodes_post/tasks/nova.yaml [new file with mode: 0644]
roles/performance_nodes_post/tasks/ovsdpdk_post.yaml [new file with mode: 0644]
roles/redisconfigure/README.rst [new file with mode: 0644]
roles/redisconfigure/handlers/main.yml [new file with mode: 0644]
roles/redisconfigure/tasks/generate_redis_config.yml [new file with mode: 0644]
roles/redisconfigure/tasks/main.yml [new file with mode: 0644]
roles/redisconfigure/templates/redis.conf.j2 [new file with mode: 0644]
roles/removevips/handlers/main.yml [new file with mode: 0644]
roles/removevips/tasks/main.yml [new file with mode: 0644]
roles/rpmdatabase/defaults/main.yml [new file with mode: 0644]
roles/rpmdatabase/handlers/main.yml [new file with mode: 0644]
roles/rpmdatabase/tasks/check_rpm_database.yml [new file with mode: 0644]
roles/rpmdatabase/tasks/main.yml [new file with mode: 0644]
roles/secretsextend/README.rst [new file with mode: 0644]
roles/secretsextend/handlers/main.yml [new file with mode: 0644]
roles/secretsextend/tasks/main.yml [new file with mode: 0644]
roles/secretsextend/tasks/secrets_extend.yml [new file with mode: 0644]
roles/service-profiles/README.rst [new file with mode: 0644]
roles/service-profiles/handlers/main.yml [new file with mode: 0644]
roles/service-profiles/tasks/generate_config.yml [new file with mode: 0644]
roles/service-profiles/tasks/main.yml [new file with mode: 0644]
roles/service-profiles/templates/config.ini.j2 [new file with mode: 0644]
roles/sriov_nodes/files/configure_vf_count.sh [new file with mode: 0644]
roles/sriov_nodes/tasks/main.yaml [new file with mode: 0644]
roles/sriov_nodes/tasks/sriov.yaml [new file with mode: 0644]
roles/sriov_nodes/templates/sriov.conf.j2 [new file with mode: 0644]
roles/sriovdp_config/defaults/main.yaml [new file with mode: 0644]
roles/sriovdp_config/tasks/main.yaml [new file with mode: 0644]
roles/sriovdp_config/templates/sriovdp_config.yaml.j2 [new file with mode: 0644]
roles/ssh_conf_hardening/library/ssh_conf.py [new file with mode: 0644]
roles/ssh_conf_hardening/tasks/main.yaml [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/README.rst [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/tasks/create-added-configuration.yml [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/tasks/disable-systemd-audit-log-reading.yml [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/tasks/main.yml [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/tasks/take-added-configuration-into-use.yml [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/templates/added-password-configuration.j2 [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/templates/added-system-configuration.j2 [new file with mode: 0644]
roles/take-pam-tty-audit-into-use/templates/updated-audisp-syslog.configuration.j2 [new file with mode: 0644]
roles/update_cert/tasks/main.yml [new file with mode: 0644]
roles/userskeyssync/README.rst [new file with mode: 0644]
roles/userskeyssync/handlers/main.yml [new file with mode: 0644]
roles/userskeyssync/tasks/main.yml [new file with mode: 0644]
roles/userskeyssync/tasks/sync_users_keys.yml [new file with mode: 0644]
roles/yarf/defaults/main.yml [new file with mode: 0644]
roles/yarf/handlers/main.yml [new file with mode: 0644]
roles/yarf/tasks/generate_config_and_reload_haproxy.yml [new file with mode: 0644]
roles/yarf/tasks/generate_restful_config.yml [new file with mode: 0644]
roles/yarf/tasks/main.yml [new file with mode: 0644]
roles/yarf/tasks/restful_service_setup.yml [new file with mode: 0644]
roles/yarf/templates/restful_config.j2 [new file with mode: 0644]
roles/yarf/templates/restful_ha_proxy.j2 [new file with mode: 0644]
secrets/aaa-secrets.yaml [new file with mode: 0644]
secrets/redis-secrets.yaml [new file with mode: 0644]
systemd/finalize-bootstrap.service [new file with mode: 0644]
systemd/finalize-bootstrap.sh [new file with mode: 0644]
systemd/sriov.service [new file with mode: 0644]
systemd/sriov.sh [new file with mode: 0644]

diff --git a/.gitreview b/.gitreview
new file mode 100644 (file)
index 0000000..3254cdd
--- /dev/null
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.att-akraino.org
+port=29418
+project=rec/infra-ansible
+defaultremote=origin
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/READ.ME b/READ.ME
new file mode 100644 (file)
index 0000000..7aae236
--- /dev/null
+++ b/READ.ME
@@ -0,0 +1,4 @@
+infra-playbooks
+---------------
+
+This is part of akraino-lite rec blueprint.
diff --git a/conflicts-with-openstack-ansible/galera-install.yml b/conflicts-with-openstack-ansible/galera-install.yml
new file mode 100644 (file)
index 0000000..d339343
--- /dev/null
@@ -0,0 +1,84 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+# cmframework.requires: initial_poweroff_hosts.yml, memcached-install.yml
+
+- name: Galera container config
+  hosts: galera_all
+  gather_facts: "{{ osa_gather_facts | default(True) }}"
+  serial: 1
+  tasks:
+    - include: common-tasks/os-log-dir-setup.yml
+      vars:
+        log_dirs:
+          - src: "/openstack/log/{{ inventory_hostname }}-mysql_logs"
+            dest: "/var/log/mysql_logs"
+      when: reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+    - include: "common-tasks/os-{{ container_tech | default('lxc') }}-container-setup.yml"
+      vars:
+        list_of_bind_mounts: "{{ galera_container_bind_mounts }}"
+        extra_container_config_no_restart:
+          - "lxc.start.order=10"
+      when: reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+    - include: common-tasks/unbound-clients.yml
+      static: no
+      when:
+        - hostvars['localhost']['resolvconf_enabled'] | bool
+        - reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - galera
+
+- name: Install galera server
+  hosts: galera_all
+  gather_facts: "{{ osa_gather_facts | default(True) }}"
+  serial: 1
+  roles:
+    - role: "galera_server"
+      when: reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+    - role: "rsyslog_client"
+      rsyslog_client_log_rotate_file: galera_log_rotate
+      rsyslog_client_log_dir: "/var/log/mysql_logs"
+      rsyslog_client_log_files:
+        - /var/log/mysql.log
+        - /var/log/mysql.err
+      rsyslog_client_config_name: "99-galera-rsyslog-client.conf"
+      tags:
+        - rsyslog
+      when: reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes) 
+    - role: "system_crontab_coordination"
+      tags:
+        - crontab
+      when: reinitialized_nodes is not defined or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+  vars:
+    galera_server_id: "{{ inventory_hostname | string_2_int }}"
+    galera_wsrep_node_name: "{{ container_name }}"
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - galera
+
+- name: Verify Galera cluster count.
+  hosts: baremetal-infra_hosts
+  tasks:
+    - set_fact:
+        given_cluster_count: "{{ groups['galera_all'] | count }}"
+
+    - name: Check the mysql cluster count
+      shell: mysql -e 'show status like "%wsrep_cluster_%";' | awk -F "wsrep_cluster_size" {'print $2'} |tr -d " \t\n\r"
+      register: cluster_count
+      until: cluster_count|success
+      failed_when: cluster_count.stdout != given_cluster_count
+  tags:
+    - galera
+
diff --git a/conflicts-with-openstack-ansible/hosts_config.yml b/conflicts-with-openstack-ansible/hosts_config.yml
new file mode 100644 (file)
index 0000000..9e6970f
--- /dev/null
@@ -0,0 +1,33 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+# cmframework.requires: baremetal-interface-config.yml
+
+- name: Setup /etc/hosts file
+  hosts: lxc_hosts
+  tasks:
+    - name: Fix /etc/hosts
+      lineinfile:
+        dest: /etc/hosts
+        state: present
+        line: "{{ hostvars[item]['ansible_host'] }} {{ hostvars[item]['ansible_hostname'] }} {{ hostvars[item]['ansible_hostname'].split('.')[0] }}"
+      with_items: "{{ groups['all'] }}"
+      when:
+        - item != 'localhost'
+    - name: Ensure localhost /etc/hosts entry is correct
+      lineinfile:
+        dest: /etc/hosts
+        state: present
+        line: '127.0.0.1 localhost'
+        regexp: '^127.0.0.1'
diff --git a/conflicts-with-openstack-ansible/os-ironic-install.yml b/conflicts-with-openstack-ansible/os-ironic-install.yml
new file mode 100644 (file)
index 0000000..c174c70
--- /dev/null
@@ -0,0 +1,65 @@
+#cmframework.requires: haproxy-install.yml, rabbitmq-install.yml, os-keystone-install.yml
+---
+# Copyright 2016, Rackspace, Inc.
+#
+# 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.
+# cmframework.requires: memcached-install.yml,galera-install.yml,rabbitmq-install.yml,rsyslog-install.yml,os-keystone-install.yml,os-glance-install.yml,os-nova-install.yml,os-neutron-install.yml,os-swift-install.yml
+
+- name: Installation and setup of Ironic
+  hosts: baremetal_management_nodes
+  gather_facts: "{{ osa_gather_facts | default(True) }}"
+  pre_tasks:
+    - include: "common-tasks/os-{{ container_tech | default('lxc') }}-container-setup.yml"
+    - include: common-tasks/rabbitmq-vhost-user.yml
+      static: no
+      vars:
+        user: "{{ ironic_rabbitmq_userid }}"
+        password: "{{ ironic_rabbitmq_password }}"
+        vhost: "{{ ironic_rabbitmq_vhost }}"
+        _rabbitmq_host_group: "{{ ironic_rabbitmq_host_group }}"
+      when:
+        - inventory_hostname == groups['ironic_all'][0]
+        - groups[ironic_rabbitmq_host_group] | length > 0
+    - include: common-tasks/mysql-db-user.yml
+      static: no
+      vars:
+        user_name: "{{ ironic_galera_user }}"
+        password: "{{ ironic_container_mysql_password }}"
+        login_host: "{{ ironic_galera_address }}"
+        db_name: "{{ ironic_galera_database }}"
+      when: inventory_hostname == groups['ironic_all'][0]
+    - include: common-tasks/unbound-clients.yml
+      static: no
+      when:
+        - hostvars['localhost']['resolvconf_enabled'] | bool
+  roles:
+    - role: "os_ironic"
+    - role: "openstack_openrc"
+      tags:
+        - openrc
+    - role: "rsyslog_client"
+      rsyslog_client_log_rotate_file: ironic_log_rotate
+      rsyslog_client_log_dir: "/var/log/ironic"
+      rsyslog_client_config_name: "99-ironic-rsyslog-client.conf"
+      tags:
+        - rsyslog
+    - role: "system_crontab_coordination"
+      tags:
+        - crontab
+  vars:
+    ironic_galera_user: ironic
+    ironic_galera_database: ironic
+    ironic_galera_address: "{{ galera_address }}"
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - ironic
diff --git a/conflicts-with-openstack-ansible/os-keystone-install.yml b/conflicts-with-openstack-ansible/os-keystone-install.yml
new file mode 100644 (file)
index 0000000..4bd9967
--- /dev/null
@@ -0,0 +1,205 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+# cmframework.requires: memcached-install.yml,galera-install.yml,rabbitmq-install.yml,rsyslog-install.yml
+
+- name: Prepare MQ/DB services
+  hosts: keystone_all
+  gather_facts: no
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - keystone
+  tasks:
+
+    - name: Configure rabbitmq vhost/user
+      include: common-tasks/rabbitmq-vhost-user.yml
+      vars:
+        user: "{{ keystone_rabbitmq_userid }}"
+        password: "{{ keystone_rabbitmq_password }}"
+        vhost: "{{ keystone_rabbitmq_vhost }}"
+        _rabbitmq_host_group: "{{ keystone_rabbitmq_host_group }}"
+      when:
+        - "groups[keystone_rabbitmq_host_group] | length > 0"
+      run_once: yes
+
+    - name: Configure rabbitmq vhost/user (telemetry)
+      include: common-tasks/rabbitmq-vhost-user.yml
+      vars:
+        user: "{{ keystone_rabbitmq_telemetry_userid }}"
+        password: "{{ keystone_rabbitmq_telemetry_password }}"
+        vhost: "{{ keystone_rabbitmq_telemetry_vhost }}"
+        _rabbitmq_host_group: "{{ keystone_rabbitmq_telemetry_host_group }}"
+      when:
+        - "keystone_ceilometer_enabled | bool"
+        - "groups[keystone_rabbitmq_telemetry_host_group] is defined"
+        - "groups[keystone_rabbitmq_telemetry_host_group] | length > 0"
+        - "groups[keystone_rabbitmq_telemetry_host_group] != groups[keystone_rabbitmq_host_group]"
+      run_once: yes
+
+    - name: Configure MySQL user
+      include: common-tasks/mysql-db-user.yml
+      vars:
+        user_name: "{{ keystone_galera_user }}"
+        password: "{{ keystone_container_mysql_password }}"
+        login_host: "{{ keystone_galera_address }}"
+        db_name: "{{ keystone_galera_database }}"
+      run_once: yes
+
+
+
+- name: Installation and setup of Keystone
+  hosts: keystone_all
+  serial: "{{ keystone_serial | default(['1', '100%']) }}"
+  gather_facts: "{{ osa_gather_facts | default(True) }}"
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - keystone
+  pre_tasks:
+
+    # In order to ensure that any container, software or
+    # config file changes which causes a container/service
+    # restart do not cause an unexpected outage, we drain
+    # the load balancer back end for this container.
+    - include: common-tasks/haproxy-endpoint-manage.yml
+      vars:
+        haproxy_backend: "{{ item }}"
+        haproxy_state: disabled
+      when: "groups['keystone_all'] | length > 1"
+      with_items:
+        - "keystone_service-back"
+        - "keystone_admin-back"
+
+    - name: Configure container
+      include: "common-tasks/os-{{ container_tech | default('lxc') }}-container-setup.yml"
+      vars:
+        extra_container_config_no_restart:
+          - "lxc.start.order=19"
+
+    - name: Configure log directories (on metal)
+      include: common-tasks/os-log-dir-setup.yml
+      vars:
+        log_dirs:
+          - src: "/openstack/log/{{ inventory_hostname }}-keystone"
+            dest: "/var/log/keystone"
+
+    - include: common-tasks/unbound-clients.yml
+      static: no
+      when:
+        - hostvars['localhost']['resolvconf_enabled'] | bool
+
+    # todo(cloudnull): this task is being run only if/when keystone is installed on a physical host.
+    #  This is not being run within a container because it is an unsupported action due to this
+    #  issue: (https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/1279041)
+    #  This issue was resolved however we'll need to eval it in the next LTS release.
+    #  Related OSA Bug: https://launchpad.net/bugs/1426371
+    - name: Add keystone reserved port to physical host
+      sysctl:
+        name: "{{ item.key }}"
+        value: "{{ item.value }}"
+        sysctl_set: "{{ item.set|default('yes') }}"
+        state: "{{ item.state|default('present') }}"
+        reload: "{{ item.reload|default('yes') }}"
+      with_items:
+        - { key: "net.ipv4.ip_local_reserved_ports", value: "{{ keystone_admin_port }}"}
+      when: is_metal | bool
+
+  roles:
+    - role: "os_keystone"
+      when: (reinitialized_nodes is not defined and scaled_out_nodes is not defined) or ((reinitialized_nodes is defined) and ((reinitialized_nodes | intersect(groups['keystone_all'])) | length > 0)) or (scaled_out_nodes is defined and hostname in scaled_out_nodes)
+    - role: "openstack_openrc"
+      tags:
+        - openrc
+    - role: "rsyslog_client"
+      rsyslog_client_log_rotate_file: keystone_log_rotate
+      rsyslog_client_log_dir: "/var/log/keystone"
+      rsyslog_client_config_name: "99-keystone-rsyslog-client.conf"
+      tags:
+        - rsyslog
+    - role: "system_crontab_coordination"
+      tags:
+        - crontab
+
+  post_tasks:
+    # Now that container changes are done, we can set
+    # the load balancer back end for this container
+    # to available again.
+    - include: common-tasks/haproxy-endpoint-manage.yml
+      vars:
+        haproxy_backend: "{{ item }}"
+        haproxy_state: enabled
+      when: "groups['keystone_all'] | length > 1"
+      with_items:
+        - "keystone_service-back"
+        - "keystone_admin-back"
+
+# These facts are set against the deployment host to ensure that
+# they are fast to access. This is done in preference to setting
+# them against each target as the hostvars extraction will take
+# a long time if executed against a large inventory.
+- name: Finalise data migrations if required
+  hosts: keystone_all
+  gather_facts: no
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - keystone
+  tasks:
+    - name: refresh local facts
+      setup:
+        filter: ansible_local
+        gather_subset: "!all"
+
+    # This variable contains the values of the local fact set for the keystone
+    # venv tag for all hosts in the 'keystone_all' host group.
+    - name: Gather software version list
+      set_fact:
+        keystone_all_software_versions: "{{ (groups['keystone_all'] | map('extract', hostvars, ['ansible_local', 'openstack_ansible', 'keystone', 'venv_tag'])) | list }}"
+      delegate_to: localhost
+      run_once: yes
+
+    # This variable outputs a boolean value which is True when
+    # keystone_all_software_versions contains a list of defined
+    # values. If they are not defined, it means that not all
+    # hosts have their software deployed yet.
+    - name: Set software deployed fact
+      set_fact:
+        keystone_all_software_deployed: "{{ (keystone_all_software_versions | select('defined')) | list == keystone_all_software_versions }}"
+      delegate_to: localhost
+      run_once: yes
+
+    # This variable outputs a boolean when all the values in
+    # keystone_all_software_versions are the same and the software
+    - name: Set software updated fact
+      set_fact:
+        keystone_all_software_updated: "{{ ((keystone_all_software_versions | unique) | length == 1) and (keystone_all_software_deployed | bool) }}"
+      delegate_to: localhost
+      run_once: yes
+
+    - name: Perform a Keystone DB sync contract
+      command: "{{ keystone_bin }}/keystone-manage db_sync --contract"
+      become: yes
+      become_user: "{{ keystone_system_user_name }}"
+      when:
+        - "keystone_all_software_updated | bool"
+        - "ansible_local['openstack_ansible']['keystone']['need_db_contract'] | bool"
+      register: dbsync_contract
+      run_once: yes
+
+    - name: Disable the need for any further db sync
+      ini_file:
+        dest: "/etc/ansible/facts.d/openstack_ansible.fact"
+        section: keystone
+        option: "need_db_contract"
+        value: False
+      when:
+        - "dbsync_contract | succeeded"
diff --git a/conflicts-with-openstack-ansible/rabbitmq-install.yml b/conflicts-with-openstack-ansible/rabbitmq-install.yml
new file mode 100644 (file)
index 0000000..a38f205
--- /dev/null
@@ -0,0 +1,76 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+# cmframework.requires: memcached-install.yml,galera-install.yml,rabbitmq-remove-reinitialized.yml
+
+- name: Create and configure rabbitmq container
+  hosts: "{{ rabbitmq_host_group | default('rabbitmq_all') }}"
+  serial: 1
+  gather_facts: "{{ osa_gather_facts | default(True) }}"
+  pre_tasks:
+    - include: "common-tasks/os-{{ container_tech | default('lxc') }}-container-setup.yml"
+      static:
+      vars:
+        extra_container_config_no_restart:
+          - "lxc.start.order=19"
+    - include: common-tasks/unbound-clients.yml
+      static: no
+      when:
+        - hostvars['localhost']['resolvconf_enabled'] | bool
+  roles:
+    - role: "system_crontab_coordination"
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - rabbitmq
+
+# The cluster must be stopped when doing major/minor upgrades
+# http://www.rabbitmq.com/clustering.html#upgrading
+- name: Stop RabbitMQ nodes that are not the upgrader
+  hosts: "{{ rabbitmq_host_group | default('rabbitmq_all') }}[1:]"
+  tasks:
+    - name: "Stop RabbitMQ"
+      service:
+        name: "rabbitmq-server"
+        state: "stopped"
+      when: rabbitmq_upgrade | default(false) | bool
+
+- name: Install rabbitmq server
+  hosts: "{{ rabbitmq_host_group | default('rabbitmq_all') }}"
+  serial: 20%
+  roles:
+    - role: "rabbitmq_server"
+    - role: "rsyslog_client"
+      rsyslog_client_log_rotate_file: rabbitmq_log_rotate
+      rsyslog_client_log_dir: "/var/log/rabbitmq"
+      rsyslog_client_config_name: "99-rabbitmq-rsyslog-client.conf"
+      tags:
+        - rsyslog
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - rabbitmq
+
+- name: Ensure rabbitmq user for monitoring GUI
+  hosts: "{{ rabbitmq_host_group | default('rabbitmq_all') }}[0]"
+  tasks:
+    - name: Create rabbitmq user for monitoring GUI
+      rabbitmq_user:
+         user: "{{ rabbitmq_monitoring_userid|default('monitoring') }}"
+         password: "{{ rabbitmq_monitoring_password }}"
+         tags: "monitoring"
+         state: "present"
+      when: rabbitmq_monitoring_password is defined
+  environment: "{{ deployment_environment_variables | default({}) }}"
+  tags:
+    - rabbitmq-config
+    - rabbitmq
diff --git a/conflicts-with-openstack-ansible/rsyslog-install.yml b/conflicts-with-openstack-ansible/rsyslog-install.yml
new file mode 100644 (file)
index 0000000..aa33266
--- /dev/null
@@ -0,0 +1,20 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+# cmframework.requires: memcached-install.yml,galera-install.yml,rabbitmq-install.yml
+
+- name: Install rsyslog
+  hosts: rsyslog
+  tags:
+    - rsyslog
diff --git a/dev_tools/startlan.sh b/dev_tools/startlan.sh
new file mode 100755 (executable)
index 0000000..ced88a4
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Copyright 2019 Nokia
+
+# 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.
+
+if [ $# -le 3 ];
+then
+       echo $0 '<ip> <gw>'
+       exit 1
+fi
+
+ip l set dev ens3f0 up
+ip l add link ens3f0 name vlan40 type vlan id 40
+ip a add $1/24 dev vlan40
+ip l s vlan40 up
+ip route add default dev vlan40 via $2
diff --git a/infra-ansible.spec b/infra-ansible.spec
new file mode 100644 (file)
index 0000000..42c045e
--- /dev/null
@@ -0,0 +1,159 @@
+# Copyright 2019 Nokia
+#
+# 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.
+#
+
+Name:           infra-ansible
+Version:        %{_version}
+Release:        1%{?dist}
+Summary:        Contains ansible playbook and roles for Akraino rec blueprint
+License:        %{_platform_licence}
+Source0:        %{name}-%{version}.tar.gz
+Vendor:         %{_platform_vendor}
+
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildArch:      noarch
+
+%description
+This RPM contains Contains ansible playbook and roles for Akraino rec blueprint
+
+%prep
+%autosetup
+
+%install
+mkdir -p %{buildroot}/root/dev_tools
+cp dev_tools/* %{buildroot}/root/dev_tools
+
+mkdir -p %{buildroot}%{_playbooks_path}
+cp playbooks/* %{buildroot}%{_playbooks_path}
+
+# mkdir -p %{buildroot}%{_inventory_path}
+# cp -rf inventory/* %{buildroot}%{_inventory_path}
+
+mkdir -p %{buildroot}%{_roles_path}
+cp -rf roles/* %{buildroot}%{_roles_path}
+
+mkdir -p %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/removevips.yml                              %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/monitoring.yml                              %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/redissync.yml                               %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/ansiblesync.yml                             %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/redisconfig.yml                             %{buildroot}/%{_finalize_path}
+ln -sf %{_playbooks_path}/cmserverconfig.yml                          %{buildroot}/%{_finalize_path}
+
+mkdir -p %{buildroot}/%{_secrets_path}
+cp secrets/* %{buildroot}/%{_secrets_path}
+
+# Create links for the bootstrapping phase
+mkdir -p %{buildroot}/%{_bootstrapping_path}
+ln -sf %{_playbooks_path}/initial_poweroff_hosts.yml         %{buildroot}/%{_bootstrapping_path}
+ln -sf %{_playbooks_path}/partfs_rootdisk_inst_cont.yml      %{buildroot}/%{_bootstrapping_path}
+ln -sf %{_playbooks_path}/ntp-config.yml                     %{buildroot}/%{_bootstrapping_path}
+
+# Create links for the provisioning phase
+mkdir -p %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/baremetal-install.yml              %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/partfs_rootdisk.yml                %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/allocate-cpu-cores.yml             %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/sriov_nodes.yaml                   %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/sriovdp_config.yaml                %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/performance-kernel-cmdline-set.yml %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/performance_nodes.yaml             %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/baremetal-interface-config.yml     %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/ntp-config.yml                     %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/rpm-database.yml                   %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/single_node_storage.yml            %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/ceph-deploy.yml                    %{buildroot}/%{_provisioning_path}
+ln -sf %{_playbooks_path}/baremetal-interface-config.yml     %{buildroot}/%{_provisioning_path}
+
+# Create links for the postconfig phase
+mkdir -p %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/synchonize_ssh_keys.yml                     %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/distributed-state-server-file-plugin.yml    %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/distributed-state-server-etcd-plugin.yml    %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/distributed-state-server.yml                %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/etcdansible.yml                             %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/core-handling.yml                           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/dbwatchdog.yml                              %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/access-management.yml                       %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/accounts.yml                                %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/adminuserfile.yml                           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/ansibleldconfig.yml                         %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/bare_lvm_backend.yml                        %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/baremetal-interface-config-post.yml         %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/certificate_update.yml                      %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/core-handling.yml                           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/create-bash-command-auth-conf.yml           %{buildroot}/%{_postconfig_path}
+# keepalive ln -sf %{_playbooks_path}/dbwatchdog.yml                              %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/disable-old-node-rsyslog.yml                %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/enablecmagent.yml                           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/haproxy-install.yml                         %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/ipv6-config.yml                             %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/kernel-core-handling.yml                    %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/motd.yml                                    %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/hostcli.yml                                 %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/oom.yml                                     %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/openssh_server_conf_hardening.yml           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/openstack-ansible-log-dir.yml               %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/operation_system_hardening.yml              %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/restful.yml                                 %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/root-openstack-admin-credentials.yml        %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/service-profiles.yml                        %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/setup_audit.yml                             %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/setup_in_host_traffic_filtering.yml         %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/synchonize_ssh_keys.yml                     %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/systemd_services.yml                        %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/userskeyssync.yml                           %{buildroot}/%{_postconfig_path}
+ln -sf %{_playbooks_path}/baremetal-interface-config-post.yml         %{buildroot}/%{_postconfig_path}
+
+ln -sf %{_roles_path}/baremetal_interface_config/templates/os_net_config.j2 %{buildroot}%{_roles_path}/bootstrap-host/templates/os_net_config.j2
+ln -sf /opt/config-encoder-macros %{buildroot}%{_roles_path}/access-management/templates/encoder
+
+mkdir -p %{buildroot}/usr/lib/systemd/system/
+cp systemd/finalize-bootstrap.service %{buildroot}/usr/lib/systemd/system/
+cp systemd/sriov.service %{buildroot}/usr/lib/systemd/system
+
+mkdir -p %{buildroot}/opt/ansible-change_kernel_cmdline/
+cp systemd/finalize-bootstrap.sh %{buildroot}/opt/ansible-change_kernel_cmdline/
+
+mkdir -p %{buildroot}/opt/sriov
+cp systemd/sriov.sh %{buildroot}/opt/sriov
+
+%files
+%defattr(0644,root,root,0755)
+/root/dev_tools
+%{_playbooks_path}/*
+# %{_inventory_path}/*
+%{_roles_path}/*
+%{_bootstrapping_path}/*
+%{_provisioning_path}/*
+%{_postconfig_path}/*
+%{_finalize_path}/*
+%{_secrets_path}/*
+%attr(0755,root,root) /usr/lib/systemd/system/*
+%attr(0755,root,root) /opt/ansible-change_kernel_cmdline/finalize-bootstrap.sh
+%attr(0755,root,root) /opt/sriov/sriov.sh
+
+%post
+for role in /usr/share/ceph-ansible/roles/*; do
+  ln -sf $role /etc/ansible/roles/
+done
+systemctl enable sriov
+
+%preun
+
+%postun
+
+%clean
+rm -rf ${buildroot}
diff --git a/playbooks/access-management.yml b/playbooks/access-management.yml
new file mode 100644 (file)
index 0000000..92d3aca
--- /dev/null
@@ -0,0 +1,21 @@
+#cmframework.requires: os-keystone-install.yml,restful.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# AM setup
+- hosts: [ management ]
+  roles:
+    - "access-management"
diff --git a/playbooks/accounts.yml b/playbooks/accounts.yml
new file mode 100644 (file)
index 0000000..c1b924c
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: provisioning_done.yml
+- name: Remove unused accounts
+  hosts: all:!localhost
+  roles:
+      - account-hardenning
+
diff --git a/playbooks/adminuserfile.yml b/playbooks/adminuserfile.yml
new file mode 100644 (file)
index 0000000..ef3fba4
--- /dev/null
@@ -0,0 +1,28 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create admin user name file to all hosts
+  hosts: all:!localhost
+  gather_facts: "{{ gather_facts | default(True) }}"
+  tasks:
+    - name: Create admin user name file
+      copy:
+        content: "{{ users['admin_user_name'] }}"
+        dest: /etc/admin_user
+        mode: 0600
+        owner: root
+        group: root
diff --git a/playbooks/allocate-cpu-cores.yml b/playbooks/allocate-cpu-cores.yml
new file mode 100644 (file)
index 0000000..7ee11db
--- /dev/null
@@ -0,0 +1,24 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: baremetal-install.yml
+
+- name: Allocate CPU cores for various purposes.
+  hosts: all:!localhost:!vnf-nodes
+  gather_facts: "{{ gather_facts | default(True) }}"
+  max_fail_percentage: 20
+  roles:
+    - role: "allocate_cpu_cores"
diff --git a/playbooks/ansibleldconfig.yml b/playbooks/ansibleldconfig.yml
new file mode 100644 (file)
index 0000000..f723560
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Run ldconfig
+  hosts: all:!localhost
+  roles:
+      - ansibleldconfig
diff --git a/playbooks/ansiblesync.yml b/playbooks/ansiblesync.yml
new file mode 100644 (file)
index 0000000..4b69519
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: os-horizon-install.yml, provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync ansible files
+  hosts: [ management ]
+  roles:
+      - ansiblesync
diff --git a/playbooks/associate_pools_for_application.yml b/playbooks/associate_pools_for_application.yml
new file mode 100644 (file)
index 0000000..aca4698
--- /dev/null
@@ -0,0 +1,35 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Associate the rbd application pools
+  # TODO: in the scope of the Hybrid storage feature this role needs to be executed also for the CaaS installation controllers. so, in the scope of that feature we will need to change this to "baremetal-infra-hosts"
+  hosts: baremetal-infra_hosts
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+    - name: get the pool names
+      command: "rados lspools ls"
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      register: pools
+
+    - name: associate the pools for rbd application
+      command: "ceph osd pool application enable {{ item }} rbd --yes-i-really-mean-it"
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      with_items: "{{ pools.stdout_lines }}"
diff --git a/playbooks/bare_lvm_backend.yml b/playbooks/bare_lvm_backend.yml
new file mode 100644 (file)
index 0000000..b829843
--- /dev/null
@@ -0,0 +1,71 @@
+# cmframework.requires:os-nova-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: baremetal-nodes
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  roles:
+  - role: cleanup_disks
+    vars:
+      disks: "{{ bare_lvm.disks }}"
+      creates_file: "/etc/storage/bare_lvm_disks_cleaned"
+    when: bare_lvm is defined
+  post_tasks:
+  - name: create /etc/storage/bare_lvm_disks_cleaned
+    command: "touch /etc/storage/bare_lvm_disks_cleaned"
+    args:
+      creates: /etc/storage/bare_lvm_disks_cleaned
+    when: bare_lvm is defined
+
+- name: Create bare LVM backend
+  hosts: baremetal-nodes
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+
+  tasks:
+  - name: initialize storage percentage
+    set_fact:
+      bare_lvm_storage_percent: "{{ 100 - instance_lv_percentage|default(0) }}"
+    when:
+      - bare_lvm is defined
+
+  - include_tasks: make_instance_disk_partitions.yml
+    vars:
+      instance_disks: "{{ bare_lvm.disks }}"
+      partition_number: "1"
+    when:
+      - bare_lvm is defined
+
+  - include_tasks: prepare_lvm_backend.yml
+    vars:
+      instance_physical_volumes: "{{ bare_lvm.physical_volumes }}"
+      lv_percentage: "{{ bare_lvm_storage_percent }}"
+      vgname: 'nova'
+      lvname: '{{ bare_lvm.name }}'
+      filesystem: 'xfs'
+      mountdir: '{{ bare_lvm.mount_dir }}'
+      mountpoint: '{{ bare_lvm.mount_dir }}'
+      mountoptions: '{{ bare_lvm.mount_options }}'
+      owner: root
+      group: root
+    when:
+      - bare_lvm is defined
diff --git a/playbooks/baremetal-install.yml b/playbooks/baremetal-install.yml
new file mode 100644 (file)
index 0000000..26279d0
--- /dev/null
@@ -0,0 +1,76 @@
+# cmframework.requires: enable_provisioning_in_iptables.yml,hasdisablerecovery.yml,remove_node_from_barematel.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+- name:  Make sure to remove leftover NFS mount points on other controllers where Ironic conductor is running
+  hosts: ironic_conductor
+  gather_facts: False
+  tasks:
+    - include: baremetal-rm-nfs-mnt.yaml
+      when:
+        - installation_phase != "provisioning-started"
+        - hosts|count > 1
+        - reinitialized_nodes is not defined or (inventory_hostname not in reinitialized_nodes)
+
+
+- name: Make sure nfs server is toren down before we start
+  hosts: baremetal-infra_hosts
+  tasks:
+    - include: baremetal-rm-nfs-server.yaml
+      when:
+        - hosts|count > 1
+        - reinitialized_nodes is not defined or (inventory_hostname not in reinitialized_nodes)
+
+- name: NFS server setup
+  hosts: baremetal-infra_hosts
+  tasks:
+    - include: baremetal-setup-nfs-server.yaml
+      when: hosts|count > 1
+
+- name:  Setup NFS mount points on other controllers where Ironic conductor is running
+  hosts: ironic_conductor
+  gather_facts: False
+  tasks:
+    - include: baremetal-setup-nfs-mnt.yaml
+      when:
+        - installation_phase != "provisioning-started"
+        - hosts|count > 1
+        - reinitialized_nodes is not defined or (inventory_hostname not in reinitialized_nodes)
+
+- name: Install baremetal nodes for this cloud infra
+  hosts: baremetal-infra_hosts
+  gather_facts: "{{ gather_facts | default(True) }}"
+  max_fail_percentage: 20
+  roles:
+    - role: baremetal_provision
+      when: hosts|count > 1
+
+- name:  Tear down NFS mount points on other controllers where Ironic conductor is running
+  hosts: ironic_conductor
+  gather_facts: False
+  tasks:
+    - include: baremetal-rm-nfs-mnt.yaml
+      when:
+        - installation_phase != "provisioning-started"
+        - hosts|count > 1
+
+- name: NFS server tear down
+  hosts: baremetal-infra_hosts
+  tasks:
+    - include: baremetal-rm-nfs-server.yaml
+      when:
+        - hosts|count > 1
diff --git a/playbooks/baremetal-interface-config-post.yml b/playbooks/baremetal-interface-config-post.yml
new file mode 100644 (file)
index 0000000..71c60f4
--- /dev/null
@@ -0,0 +1,106 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: performance_nodes_post.yaml,provisioning_done.yml
+
+- name: Interface configuration postconfig
+  hosts: baremetal-nodes:!localhost
+  gather_facts: "{{ gather_facts | default(True) }}"
+  tasks:
+  - name: Run os-net-config command
+    command: "os-net-config --detailed-exit-codes -v -c /etc/os-net-config/config.json"
+    register: os_net_config_result
+    failed_when: not (os_net_config_result.rc == 0 or os_net_config_result.rc == 2)
+    changed_when: os_net_config_result.rc == 2
+
+  - debug: var=os_net_config_result.stderr_lines
+    when: os_net_config_result.rc == 2
+
+  - name: Get os-net-config
+    slurp:
+      src: /etc/os-net-config/config.json
+    register: os_net_config_b64
+
+  - name: Set os_net_config
+    set_fact:
+      os_net_config: "{{ os_net_config_b64['content'] | b64decode | from_json }}"
+
+  - name: Get interface names
+    set_fact:
+      phy_ifaces: "{{ os_net_config | json_query('network_config[*].name') }}"
+
+  - name: Make sure bridges are up
+    command: "ifup {{item}}"
+    with_items: "{{phy_ifaces}}"
+    ignore_errors: "yes"
+
+  - name: Updating the facts due to net changes
+    setup:
+
+  - name: Check if SR-IOV is configured
+    stat:
+      path: /etc/sriov/sriov.conf
+    register: sriov_result
+
+  - name: Enable sriov.service
+    systemd:
+      name: sriov
+      daemon_reload: "yes"
+      enabled: "yes"
+    when: sriov_result.stat.exists == True
+
+  - name: Start sriov.service
+    systemd:
+      name: sriov
+      state: started
+    when: sriov_result.stat.exists == True and hostname != installation_controller
+
+  - name: Check if OVS offload SR-IOV is configured
+    shell: grep "SRIOV_INTERFACES_OFFLOADED" /etc/sriov/sriov.conf | cut -d = -f2 | sed -e 's/^"//' -e 's/"$//'
+    register: offload_result
+    when: sriov_result.stat.exists == True
+
+  - name: Enable ovsoffloadsriov.service
+    systemd:
+      name: ovsoffloadsriov
+      daemon_reload: "yes"
+      enabled: "yes"
+    when:
+      - sriov_result.stat.exists == True
+      - offload_result.stdout != ""
+
+  - name: Start offload.service
+    systemd:
+      name: ovsoffloadsriov
+      state: started
+    when:
+      - sriov_result.stat.exists == True
+      - offload_result.stdout != "" and hostname != installation_controller
+
+- name: Restart nova compute if sr-iov configured except on CAAS nodes
+  hosts: base:!vnf-nodes
+  gather_facts: "{{ gather_facts | default(True) }}"
+  tasks:
+  - name: Check if nova-compute service is enabled here
+    shell: "systemctl list-unit-files | grep enabled | grep -w nova-compute | wc -l"
+    register: novacomputeresult
+
+  - name: Restart nova compute
+    systemd:
+      name: nova-compute
+      state: restarted
+    when: sriov_result.stat.exists == True and hostname != installation_controller and novacomputeresult.stdout|int > 0
+
diff --git a/playbooks/baremetal-interface-config.yml b/playbooks/baremetal-interface-config.yml
new file mode 100644 (file)
index 0000000..bd3a6d7
--- /dev/null
@@ -0,0 +1,24 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: performance_nodes.yaml
+- name: Install baremetal nodes for this cloud infra
+  hosts: baremetal-nodes:!localhost
+  gather_facts: "{{ gather_facts | default(True) }}"
+  max_fail_percentage: 20
+  roles:
+    - role: "baremetal_interface_config"
+      when: (reinitialized_nodes is not defined and scaled_out_nodes is not defined) or (reinitialized_nodes is defined and inventory_hostname in reinitialized_nodes) or (scaled_out_nodes is defined and inventory_hostname in scaled_out_nodes)
diff --git a/playbooks/baremetal-rm-nfs-mnt.yaml b/playbooks/baremetal-rm-nfs-mnt.yaml
new file mode 100644 (file)
index 0000000..5ad7f78
--- /dev/null
@@ -0,0 +1,36 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- set_fact:
+    initiator_host: "{{ lookup('file', '/etc/hostname') }}"
+
+- name: Clear fstab entries for nfs mount
+  mount:
+    path: "/remote_image_share_root/"
+    src: "{{hostvars[initiator_host]['networking']['infra_external']['ip']}}:/remote_image_share_root/"
+    fstype: nfs
+    state: absent
+  when:
+    - inventory_hostname != initiator_host
+
+- name: Unmount the nfs server /remote_image_share_root/ on local server
+  mount:
+    path: "/remote_image_share_root/"
+    src: "{{hostvars[initiator_host]['networking']['infra_external']['ip']}}:/remote_image_share_root/"
+    fstype: nfs
+    state: unmounted
+  when:
+    - inventory_hostname != initiator_host
diff --git a/playbooks/baremetal-rm-nfs-server.yaml b/playbooks/baremetal-rm-nfs-server.yaml
new file mode 100644 (file)
index 0000000..ed62dce
--- /dev/null
@@ -0,0 +1,29 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Remove all entries in /etc/exports
+  copy:
+    content: ""
+    dest: /etc/exports
+    force: yes
+
+- name: Run exportfs command to reload enties
+  command: "exportfs -r"
+
+- name: stop nfs-server
+  systemd:
+    name: "nfs-server"
+    state: stopped
diff --git a/playbooks/baremetal-setup-nfs-mnt.yaml b/playbooks/baremetal-setup-nfs-mnt.yaml
new file mode 100644 (file)
index 0000000..8f9b9cf
--- /dev/null
@@ -0,0 +1,38 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- set_fact:
+    initiator_host: "{{ lookup('file', '/etc/hostname') }}"
+
+- name: Create /remote_image_share_root/ directory for virtmedia driver
+  file:
+    path: "/remote_image_share_root/"
+    state: directory
+    mode: u=rwx,g=rwx,o=rx
+    owner: "ironic"
+    group: "ironic"
+  when:
+    - inventory_hostname != initiator_host
+
+- name: Mount the nfs server /remote_image_share_root/ on local server
+  mount:
+    path: "/remote_image_share_root/"
+    src: "{{hostvars[initiator_host]['networking']['infra_external']['ip']}}:/remote_image_share_root/"
+    fstype: nfs
+    opts: ro
+    state: mounted
+  when:
+    - inventory_hostname != initiator_host
diff --git a/playbooks/baremetal-setup-nfs-server.yaml b/playbooks/baremetal-setup-nfs-server.yaml
new file mode 100644 (file)
index 0000000..076caf8
--- /dev/null
@@ -0,0 +1,55 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create /remote_image_share_root/ directory for virtmedia driver
+  file:
+    path: "/remote_image_share_root/"
+    state: directory
+    mode: u=rwx,g=rwx,o=rx
+    owner: "ironic"
+    group: "ironic"
+
+- name: Create entry in /etc/exports for other controllers /remote_image_share_root/
+  lineinfile:
+      dest: "/etc/exports"
+      # Use infra_external subnet for now. When we have infra_hwmgmt support add logic to make choice later.
+      line: "/remote_image_share_root/ {{hostvars[item.key]['networking']['infra_external']['ip']}}(rw,sync,no_root_squash,no_subtree_check)"
+      create: yes
+  with_dict: "{{hosts}}"
+  when:
+    - '"controller" in item.value["service_profiles"]'
+    - hostvars[item.key] != inventory_hostname
+    - installation_phase != "provisioning-started"
+  loop_control:
+    label: "{{ item.key }}"
+
+- name: Create access entries for BMC ports of all nodes in /etc/exports from /remote_image_share_root/
+  lineinfile:
+      dest: "/etc/exports"
+      line: "/remote_image_share_root/ {{item.value['hwmgmt']['address']}}(ro,sync,no_root_squash,no_subtree_check)"
+      create: yes
+  with_dict: "{{hosts}}"
+  loop_control:
+    label: "{{ item.key }}"
+
+- name: Enable nfs-server
+  systemd:
+    name: "nfs-server"
+    state: started
+    enabled: yes
+
+- name: Run exportfs command
+  command: "exportfs -a"
diff --git a/playbooks/ceph-deploy.yml b/playbooks/ceph-deploy.yml
new file mode 100644 (file)
index 0000000..84d9010
--- /dev/null
@@ -0,0 +1,47 @@
+# cmframework.requires:baremetal-install.yml,baremetal-interface-config.yml,performance-kernel-cmdline-set.yml,ntp-config.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: storage
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+  - debug:
+      msg: "Deploying ceph if configured"
+    when: (ceph_configured | default(False))
+
+- include: cleanup-disk.yml
+  when: (ceph_configured | default(False))
+
+- include: site.yml
+  when: (ceph_configured | default(False))
+
+- include: ceph-post-cleanup.yml
+  when: (ceph_configured | default(False))
+
+- include: set_keyring_owners.yml
+  when: (ceph_configured | default(False))
+
+- include: associate_pools_for_application.yml
+  when: (ceph_configured | default(False))
+
+- include: reset_failed_ceph_disk_services.yml
+  when: (ceph_configured | default(False))
+
+- include: make_osd_disk_metadata.yml
+  when: (ceph_configured | default(False))
diff --git a/playbooks/ceph-post-cleanup.yml b/playbooks/ceph-post-cleanup.yml
new file mode 100644 (file)
index 0000000..855a02f
--- /dev/null
@@ -0,0 +1,60 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: baremetal-infra_hosts
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+    - name: allow to delete pool
+      command: ceph tell mon.* injectargs '--mon-allow-pool-delete=true'
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      when:
+        - ceph_configured | default(False)
+
+    - name: list all pools
+      command: rados lspools
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      register: ceph_pools
+      when:
+       - ceph_configured | default(False)
+
+    - name: delete all pools
+      command: ceph osd pool delete {{ item }} {{ item }} --yes-i-really-really-mean-it
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      with_items: "{{ ceph_pools.stdout_lines }}"
+      ignore_errors: yes
+      when:
+        - ceph_configured | default(False)
+
+    - name: disable to delete pool
+      command: ceph tell mon.* injectargs '--mon-allow-pool-delete=false'
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      when:
+        - ceph_configured | default(False)
+
+    - name: create openstack pools
+      command: "ceph osd pool create {{ item.name }} {{ item.pg_num }} {{ item.rule_name }}"
+      args:
+        creates: /etc/storage/osd_disk_metadata.json
+      with_items: "{{ openstack_pools | unique }}"
+      when:
+        - ceph_configured | default(False)
diff --git a/playbooks/certificate_update.yml b/playbooks/certificate_update.yml
new file mode 100644 (file)
index 0000000..efa98f7
--- /dev/null
@@ -0,0 +1,22 @@
+#cmframework.requires: haproxy-install.yml
+# Controller setup
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: management
+  sudo: yes
+  roles:
+    - role: "update_cert"
diff --git a/playbooks/cleanup-disk.yml b/playbooks/cleanup-disk.yml
new file mode 100644 (file)
index 0000000..c5b6b00
--- /dev/null
@@ -0,0 +1,45 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: storage
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+    disks: "{{ devices }}"
+  tasks:
+  - include: remove_volume_groups.yml
+    when: devices is defined
+
+  - include: destroy_data_and_partitions.yml
+    when: devices is defined
+
+- hosts: compute
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+    disks: "{{ instance_disks }}"
+  tasks:
+  - include: remove_volume_groups.yml
+    when:
+    - instance_disks is defined
+
+  - include: destroy_data_and_partitions.yml
+    when:
+    - instance_disks is defined
diff --git a/playbooks/cmserverconfig.yml b/playbooks/cmserverconfig.yml
new file mode 100644 (file)
index 0000000..725fb84
--- /dev/null
@@ -0,0 +1,22 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure cmserver
+  hosts: [ management ]
+  roles:
+      - cmserver-config
+
diff --git a/playbooks/collect_disk_jsons_together.yml b/playbooks/collect_disk_jsons_together.yml
new file mode 100644 (file)
index 0000000..e6c5375
--- /dev/null
@@ -0,0 +1,35 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: collect all disks jsons together
+  hosts: base
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+  - name: initialize list variables
+    set_fact:
+      all_disk_config: {}
+
+  - name: Load variables from the json file
+    include_vars:
+      file: "/etc/storage/{{ item }}-disks.json"
+      name: "all_disk_config"
+    with_items: "{{ osds }}"
+
+  - name: dump disk_config variable
+    action: template src=osd_disk_metadata.j2 dest=/etc/storage/osd_disk_metadata.json  mode=644
diff --git a/playbooks/core-handling.yml b/playbooks/core-handling.yml
new file mode 100644 (file)
index 0000000..8fbf37d
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: provisioning_done.yml
+- name: Configure core file handling
+  hosts: all:!localhost
+  roles:
+      - core-handling-config
+
diff --git a/playbooks/create-bash-command-auth-conf.yml b/playbooks/create-bash-command-auth-conf.yml
new file mode 100644 (file)
index 0000000..bc47ff4
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure bash command logging
+  hosts: all:!localhost
+  roles:
+      - take-pam-tty-audit-into-use
diff --git a/playbooks/create_osd_disk_configuration.yml b/playbooks/create_osd_disk_configuration.yml
new file mode 100644 (file)
index 0000000..db8a96a
--- /dev/null
@@ -0,0 +1,71 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: create osd disk configuration
+  hosts: osds
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+
+  - name: get the ceph osd ids
+    shell: lsblk -r | grep ceph- | cut -d '-' -f2
+    register: ceph_osd_ids
+
+  - name: get the devices
+    shell: for part in $(lsblk -r | grep  ceph- | awk -F[^A-Za-z][0-9*] '{print $1}');do find -L /sys/block -maxdepth 2 -name $part|cut -d'/' -f4;done
+    register: osd_devices
+
+  - name: get the by-path disks
+    shell: file /dev/disk/by-path/* | grep -w {{ item }} | head -n 1 | awk '{print $1}' | sed 's/.$//'
+    with_items: "{{ osd_devices.stdout_lines }}"
+    register: by_path_tmp
+
+  - name: get the disk size
+    shell: lsblk -r | grep -w {{ item }} | awk '{print $4}'
+    with_items: "{{ osd_devices.stdout_lines }}"
+    register: disk_size_tmp
+
+  - name: initialize list variables
+    set_fact:
+      by_path: []
+      disk_size: []
+      disk_config: []
+      disk_config1: {}
+
+  - name: set by_path variable
+    set_fact:
+      by_path: "{{ by_path }} + {{ item.stdout_lines }} "
+    with_items: "{{ by_path_tmp.results }}"
+
+  - name: set disk_size variable
+    set_fact:
+      disk_size: "{{ disk_size }} + {{ item.stdout_lines }} "
+    with_items: "{{ disk_size_tmp.results }}"
+
+  - name: populate disk_config
+    set_fact:
+      disk_config: "{{ disk_config +  [ {'osd_id': item.0, 'device': item.1, 'by-path': item.2,  'size': item.3, 'service_name': 'ceph-osd-disk-' + item.4 | string, 'systemd': 'ceph-osd@' + item.0 | string + '.service'} ] }}"
+    with_together:
+      - "{{ ceph_osd_ids.stdout_lines }}"
+      - "{{ osd_devices.stdout_lines }}"
+      - "{{ by_path }}"
+      - "{{ disk_size }}"
+      - "{{ by_path_disks['osd_disks_ids'] }}"
+
+  - name: dump disk_config variable
+    action: template src=osd_disk_configuration.j2 dest=/tmp/{{ hostname }}-disks.json  mode=644
diff --git a/playbooks/dbwatchdog.yml b/playbooks/dbwatchdog.yml
new file mode 100644 (file)
index 0000000..04bf73a
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: distributed-state-server.yml,galera-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure db watchdog
+  hosts: management:!vnf-nodes
+  roles:
+      - dbwatchdog
diff --git a/playbooks/destroy_data_and_partitions.yml b/playbooks/destroy_data_and_partitions.yml
new file mode 100644 (file)
index 0000000..89c5f26
--- /dev/null
@@ -0,0 +1,33 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: wipe off filesystems from disks
+  shell: "[ -b {{ item }} ] | /usr/sbin/wipefs --all --force {{ item }} || /usr/sbin/wipefs --all --force {{ item }}"
+  args:
+    creates: /etc/storage/osd_disk_metadata.json
+  with_items: "{{ disks }}"
+
+- name: destroy data from disks
+  shell: "[ -b {{ item }} ] | dd if=/dev/zero of={{ item }} count=200 bs=1M"
+  args:
+    creates: /etc/storage/osd_disk_metadata.json
+  with_items: "{{ disks }}"
+
+- name: destroy partitions from disks
+  shell: "[ -b {{ item }} ] | /usr/sbin/sgdisk --zap-all --clear --mbrtogpt -- {{ item }} || /usr/sbin/sgdisk --zap-all --clear --mbrtogpt -- {{ item }}"
+  args:
+    creates: /etc/storage/osd_disk_metadata.json
+  with_items: "{{ disks }}"
diff --git a/playbooks/disable-old-node-rsyslog.yml b/playbooks/disable-old-node-rsyslog.yml
new file mode 100644 (file)
index 0000000..23695dd
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Disable default node rsyslog service
+  hosts: all:!localhost
+  roles:
+      - disable-default-rsyslog
diff --git a/playbooks/distribute_disk_config.yml b/playbooks/distribute_disk_config.yml
new file mode 100644 (file)
index 0000000..dc78252
--- /dev/null
@@ -0,0 +1,47 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: distribute disk config pull
+  hosts: osds
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+
+    - fetch:
+        src: /tmp/{{ item }}-disks.json
+        dest: /tmp/
+        flat: yes
+        fail_on_missing: no
+      with_items: "{{ osds }}"
+
+- name: distribute disk config push
+  hosts: base
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+    - file:
+        path: /etc/storage/
+        mode: 0555
+        state: directory
+
+    - copy:
+        src: /tmp/{{ item }}-disks.json
+        dest: /etc/storage/
+      with_items: "{{ osds }}"
diff --git a/playbooks/distributed-state-server-etcd-plugin.yml b/playbooks/distributed-state-server-etcd-plugin.yml
new file mode 100644 (file)
index 0000000..eef1cd3
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure distributed state server etcd plugin
+  hosts: [ management ]
+  roles:
+      - distributed-state-server-etcd-plugin
diff --git a/playbooks/distributed-state-server-file-plugin.yml b/playbooks/distributed-state-server-file-plugin.yml
new file mode 100644 (file)
index 0000000..a9f9fe0
--- /dev/null
@@ -0,0 +1,20 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure distributed state server file plugin
+  hosts: [ management ]
+  roles:
+      - distributed-state-server-file-plugin
diff --git a/playbooks/distributed-state-server.yml b/playbooks/distributed-state-server.yml
new file mode 100644 (file)
index 0000000..37cd2bb
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: distributed-state-server-etcd-plugin.yml,distributed-state-server-file-plugin.yml,etcdansible.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure distributed state server
+  hosts: [ management ]
+  roles:
+      - distributed-state-server
diff --git a/playbooks/enablecmagent.yml b/playbooks/enablecmagent.yml
new file mode 100644 (file)
index 0000000..c4ac94d
--- /dev/null
@@ -0,0 +1,39 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Enable cmagent
+  hosts: all:!localhost
+  gather_facts: "{{ gather_facts | default(True) }}"
+  tasks:
+    - name: Enable cmagent service
+      systemd:
+          name: cmagent
+          enabled: yes
+          masked: no
+          daemon_reload: yes
+
+- name: Disable cmagent on single controller
+  hosts: [ management ]
+  gather_facts: "{{ gather_facts | default(True) }}"
+  tasks:
+    - name: Disable cmagent service
+      systemd:
+          name: cmagent
+          enabled: no
+          masked: no
+          daemon_reload: yes
+      when: groups['management']|count == 1
diff --git a/playbooks/etcdansible.yml b/playbooks/etcdansible.yml
new file mode 100644 (file)
index 0000000..3a2bf5e
--- /dev/null
@@ -0,0 +1,24 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure etcd
+  hosts: management:!vnf-nodes
+  vars:
+      management_nodes: "{{ groups['management'] }}"
+  roles:
+      - role: etcdansible
+        when: management_nodes|count > 1
diff --git a/playbooks/glance-lvm.yml b/playbooks/glance-lvm.yml
new file mode 100644 (file)
index 0000000..b2e55e8
--- /dev/null
@@ -0,0 +1,48 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: management
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+
+  vars:
+    vg_name: nova
+    lv_name: glance
+    lv_percentage: 10
+    lv_fstype: ext4
+    lv_dev: /dev/{{ vg_name }}/{{ lv_name }}
+    lv_mnt_point: /var/lib/glance
+
+  tasks:
+  - name: Create {{ lv_name }} logical volume to {{ lv_percentage }}% of {{ vg_name }} VG
+    lvol:
+      vg: "{{ vg_name }}"
+      lv: "{{ lv_name }}"
+      size: "{{ lv_percentage  }}%VG"
+
+  - name: Make {{ lv_fstype }} fileystem on {{ lv_name }} logical volume
+    filesystem:
+      fstype: "{{ lv_fstype }}"
+      dev: "{{ lv_dev }}"
+
+  - name: Mount {{ lv_dev }} to {{ lv_mnt_point }}
+    mount:
+      path: "{{ lv_mnt_point }}"
+      src: "{{ lv_dev }}"
+      fstype: "{{ lv_fstype }}"
+      state: mounted
diff --git a/playbooks/hostcli.yml b/playbooks/hostcli.yml
new file mode 100644 (file)
index 0000000..c387d18
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate hostcli bash auto complete
+  hosts: all:!localhost
+  roles:
+      - hostcli
diff --git a/playbooks/initial_poweroff_hosts.yml b/playbooks/initial_poweroff_hosts.yml
new file mode 100644 (file)
index 0000000..0394a28
--- /dev/null
@@ -0,0 +1,23 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+- name: Power-off all the hosts provided in user_config.yml before starting deployemt.
+  hosts: baremetal-infra_hosts
+  gather_facts: "{{ gather_facts | default(True) }}"
+  max_fail_percentage: 20
+  roles:
+    - role: "initial_poweroff_hosts"
diff --git a/playbooks/ipv6-config.yml b/playbooks/ipv6-config.yml
new file mode 100644 (file)
index 0000000..4c044e1
--- /dev/null
@@ -0,0 +1,31 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: haproxy-install.yml
+- name: IPv6 Configuration
+  hosts: haproxy
+  tasks:
+    - name: Make haproxy bindable on non local ipv6 addresses
+      sysctl:
+        name: net.ipv6.ip_nonlocal_bind
+        value: 1
+        sysctl_set: yes
+        state: present
+      when: haproxy_bind_on_non_local | bool
+      notify:
+        - Restart haproxy
+  tags:
+    - ipv6_config
+  handlers:
+    - include: /etc/ansible/roles/haproxy_server/handlers/main.yml 
\ No newline at end of file
diff --git a/playbooks/kernel-core-handling.yml b/playbooks/kernel-core-handling.yml
new file mode 100644 (file)
index 0000000..89c507c
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: provisioning_done.yml
+- name: Configure core file handling
+  hosts: all:!localhost
+  roles:
+      - kernel-core-handling-config
+
diff --git a/playbooks/make_instance_disk_partitions.yml b/playbooks/make_instance_disk_partitions.yml
new file mode 100644 (file)
index 0000000..b7dbde2
--- /dev/null
@@ -0,0 +1,30 @@
+---
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: make partition table
+  parted: device={{ item }} number={{ partition_number }} label=gpt state=present
+  with_items: "{{ instance_disks }}"
+
+- name: Inform the OS of partition table changes
+  shell: "/sbin/partprobe {{ item }}"
+  args:
+    creates: /etc/storage/nova-instances
+  with_items: "{{ instance_disks }}"
+
+- name: set Linux LVM type to partition 1
+  shell: "[ -b {{ item }} ] | parted {{ item }} set 1 lvm on"
+  args:
+    creates: /etc/storage/nova-instances
+  with_items: "{{ instance_disks }}"
diff --git a/playbooks/make_osd_disk_metadata.yml b/playbooks/make_osd_disk_metadata.yml
new file mode 100644 (file)
index 0000000..98457db
--- /dev/null
@@ -0,0 +1,21 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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_playbook: create_osd_disk_configuration.yml
+
+- import_playbook: distribute_disk_config.yml
+
+- import_playbook: collect_disk_jsons_together.yml
diff --git a/playbooks/manage_chroot_user.yml b/playbooks/manage_chroot_user.yml
new file mode 100644 (file)
index 0000000..3cf1518
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# Controller setup
+---
+- hosts: management
+  sudo: yes
+  roles:
+    - "manage_user"
diff --git a/playbooks/manage_linux_user.yml b/playbooks/manage_linux_user.yml
new file mode 100644 (file)
index 0000000..7f55d90
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# Controller setup
+---
+- hosts: [base]
+  sudo: yes
+  roles:
+    - "manage_linux_user"
diff --git a/playbooks/monitoring.yml b/playbooks/monitoring.yml
new file mode 100644 (file)
index 0000000..48e6df6
--- /dev/null
@@ -0,0 +1,24 @@
+#cmframework.requires: removevips.yml,redisconfig.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure keepalived monitor
+  hosts: [ management ]
+  become: yes
+  become_method: sudo
+  become_user: root
+  roles:
+      - monitoring
diff --git a/playbooks/motd.yml b/playbooks/motd.yml
new file mode 100644 (file)
index 0000000..f151d89
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure MOTD
+  hosts: all:!localhost
+  roles:
+      - motd
diff --git a/playbooks/oom.yml b/playbooks/oom.yml
new file mode 100644 (file)
index 0000000..60387d6
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: provisioning_done.yml
+- name: Configure ouf-of-memory killer
+  hosts: base:!vnf-nodes!caas_worker
+  roles:
+      - oom-config
+
diff --git a/playbooks/openssh_server_conf_hardening.yml b/playbooks/openssh_server_conf_hardening.yml
new file mode 100644 (file)
index 0000000..52c4553
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+# Controller setup
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: [ base ]
+  roles:
+    - "ssh_conf_hardening"
diff --git a/playbooks/openstack-ansible-log-dir.yml b/playbooks/openstack-ansible-log-dir.yml
new file mode 100644 (file)
index 0000000..978cd2a
--- /dev/null
@@ -0,0 +1,30 @@
+# cmframework.requires: baremetal-interface-config.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create openstack-ansible log directory
+  hosts: management:!vnf-nodes
+  tasks:
+    - name: Create log directories
+      file:
+        path: "{{ item }}"
+        state: directory
+        mode: 0744
+        owner: "{{ users['admin_user_name'] }}"
+        group: "{{ users['admin_user_name'] }}"
+      with_items:
+        - /openstack/log
+        - /openstack/log/ansible-logging
diff --git a/playbooks/operation_system_hardening.yml b/playbooks/operation_system_hardening.yml
new file mode 100644 (file)
index 0000000..da63e71
--- /dev/null
@@ -0,0 +1,22 @@
+# cmframework.requires: provisioning_done.yml
+# Controller setup
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: [base]
+  sudo: yes
+  roles:
+    - "ops-hardening"
diff --git a/playbooks/osd_disk_configuration.j2 b/playbooks/osd_disk_configuration.j2
new file mode 100644 (file)
index 0000000..357f5bc
--- /dev/null
@@ -0,0 +1 @@
+{ {{ hostname | to_nice_json }}: {{ disk_config | to_nice_json }} }
diff --git a/playbooks/osd_disk_metadata.j2 b/playbooks/osd_disk_metadata.j2
new file mode 100644 (file)
index 0000000..25867ac
--- /dev/null
@@ -0,0 +1 @@
+{{ all_disk_config | to_nice_json }}
diff --git a/playbooks/partfs_rootdisk.yml b/playbooks/partfs_rootdisk.yml
new file mode 100644 (file)
index 0000000..5bd2e38
--- /dev/null
@@ -0,0 +1,41 @@
+# cmframework.requires: baremetal-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure Root disk partitions
+  hosts: baremetal-nodes:!localhost
+  pre_tasks:
+   - name: set generic partfs_valid_nodes variable
+     set_fact:
+      partfs_valid_nodes: "{{groups['baremetal-nodes']}}"
+
+   - name: check for reinitialize or scaleout
+     set_fact:
+      partfs_valid_nodes: "{{ scaled_out_nodes|default(reinitialized_nodes) }}"
+     when: scaled_out_nodes is defined or reinitialized_nodes is defined
+
+   - debug:
+      msg: "===> partfs_valid_nodes {{ partfs_valid_nodes }}"
+
+  roles:
+      - role: partfs_rootdisk
+        when: inventory_hostname != installation_controller and reinitialized_nodes is not defined and scaled_out_nodes is not defined
+
+      - role: partfs_rootdisk
+        when: (reinitialized_nodes is defined or scaled_out_nodes is defined) and inventory_hostname in partfs_valid_nodes
+  vars:
+    first_part_number: 1
+    delete_partition: 2
diff --git a/playbooks/partfs_rootdisk_inst_cont.yml b/playbooks/partfs_rootdisk_inst_cont.yml
new file mode 100644 (file)
index 0000000..fa023e4
--- /dev/null
@@ -0,0 +1,23 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure Root disk partitions
+  hosts: baremetal-infra_hosts
+  roles:
+      - role: partfs_rootdisk
+  vars:
+    first_part_number: 1
+    delete_partition: 2
diff --git a/playbooks/performance-kernel-cmdline-set.yml b/playbooks/performance-kernel-cmdline-set.yml
new file mode 100644 (file)
index 0000000..31f795c
--- /dev/null
@@ -0,0 +1,24 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: partfs_rootdisk.yml,allocate-cpu-cores.yml,sriov_nodes.yaml
+
+- name: Set the kernel command line options for nodes.
+  hosts: base
+  gather_facts: "{{ gather_facts | default(True) }}"
+  max_fail_percentage: 20
+  roles:
+    - role: "change_kernel_cmdline"
diff --git a/playbooks/performance_nodes.yaml b/playbooks/performance_nodes.yaml
new file mode 100644 (file)
index 0000000..77ea692
--- /dev/null
@@ -0,0 +1,22 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: performance-kernel-cmdline-set.yml
+
+- name: Performance node configuration
+  hosts: performance_profiles:&openstack_nodes
+  roles:
+      - performance_nodes
diff --git a/playbooks/prepare_cow_backend.yml b/playbooks/prepare_cow_backend.yml
new file mode 100644 (file)
index 0000000..9c6a5b0
--- /dev/null
@@ -0,0 +1,29 @@
+---
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: make single logical volume name
+  lvol: vg={{ vgname }} lv={{ lvname }} size="{{ lv_percentage }}%VG"
+
+- name: make fileystem on device
+  filesystem: fstype={{ filesystem }} dev=/dev/{{ vgname }}/{{ lvname }}
+
+- name: create dir for instances path value
+  file: path={{ mountpoint }} state=directory
+
+- name: mounting new filesystem
+  mount: name={{ mountpoint }} src=/dev/mapper/{{ vgname }}-{{ lvname }} fstype={{ filesystem }} state=mounted opts={{ mountoptions | default(omit) }}
+
+- name: change dir owner and group
+  file: path={{ mountdir }} state=directory  owner={{ owner }}  group={{ group }}  recurse=yes
diff --git a/playbooks/prepare_lvm_backend.yml b/playbooks/prepare_lvm_backend.yml
new file mode 100644 (file)
index 0000000..32bb4ff
--- /dev/null
@@ -0,0 +1,22 @@
+---
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: make volume group
+  lvg: vg={{ vgname }} pvs={{ instance_physical_volumes }} state=present
+  when: single_controller_host is not defined
+
+- name: prepare cow backend
+  include_tasks: prepare_cow_backend.yml
+  when: instance_default_backend != "lvm"
diff --git a/playbooks/redisconfig.yml b/playbooks/redisconfig.yml
new file mode 100644 (file)
index 0000000..88ce65b
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: os-horizon-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure rediscontroller
+  hosts: [ management ]
+  roles:
+      - redisconfigure
diff --git a/playbooks/redissync.yml b/playbooks/redissync.yml
new file mode 100644 (file)
index 0000000..be88833
--- /dev/null
@@ -0,0 +1,40 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync redis db
+  hosts: [ management ]
+  gather_facts: false
+  tasks:
+    - name: Save the DB to disk
+      shell: "redis-cli -a {{ redis_password }} save"
+      when: hostname == installation_controller
+
+    - name: Copy the file to tmp
+      shell: cp /var/lib/redis/dump.rdb /tmp/
+      when: hostname == installation_controller
+
+    - name: Sync redis DB to other controllers
+      copy:
+        src: /tmp/dump.rdb
+        dest: /var/lib/redis/dump.rdb
+        owner: redis
+        group: redis
+        mode: 0644
+      when: hostname != installation_controller
+
+    - name: Remove the file from tmp
+      shell: rm /tmp/dump.rdb
+      when: hostname == installation_controller
diff --git a/playbooks/remove_volume_groups.yml b/playbooks/remove_volume_groups.yml
new file mode 100644 (file)
index 0000000..ffcced0
--- /dev/null
@@ -0,0 +1,27 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: get volume groups
+  shell: "vgs -o vg_name --noheadings | sed 's/ //g'"
+  args:
+    creates: /etc/storage/osd_disk_metadata.json
+  register: volumegroups
+
+- name:  remove volume groups
+  lvg: vg={{ item }} state=absent force=yes
+  ignore_errors: yes
+  with_items: "{{ volumegroups.stdout_lines }}"
+  when: volumegroups is defined
diff --git a/playbooks/removevips.yml b/playbooks/removevips.yml
new file mode 100644 (file)
index 0000000..8b493c9
--- /dev/null
@@ -0,0 +1,20 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Remove external and internal vips
+  hosts: [ management ]
+  roles:
+      - removevips
diff --git a/playbooks/reset_failed_ceph_disk_services.yml b/playbooks/reset_failed_ceph_disk_services.yml
new file mode 100644 (file)
index 0000000..66d930b
--- /dev/null
@@ -0,0 +1,36 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: reset failed ceph-disk services
+  hosts: osds
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+
+  - name: get the failed ceph-disk services
+    shell: sudo systemctl --failed | awk '/ceph-disk@dev/ {print $2}'
+    register: failed_ceph_disk_services
+
+  - name: failed ceph-disk services
+    debug: var=failed_ceph_disk_services.stdout_lines
+
+  - name: reset failed ceph-disk services
+    shell: systemctl reset-failed {{ item }}
+    with_items: "{{ failed_ceph_disk_services.stdout_lines }}"
+    when: failed_ceph_disk_services.stdout_lines
+
diff --git a/playbooks/restful.yml b/playbooks/restful.yml
new file mode 100644 (file)
index 0000000..44e707a
--- /dev/null
@@ -0,0 +1,22 @@
+#cmframework.requires: haproxy-install.yml, os-keystone-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure restfulframework
+  hosts: management:!vnf-nodes
+  roles:
+       - role: yarf
+
diff --git a/playbooks/root-openstack-admin-credentials.yml b/playbooks/root-openstack-admin-credentials.yml
new file mode 100644 (file)
index 0000000..cbb1613
--- /dev/null
@@ -0,0 +1,37 @@
+#cmframework.requires: os-keystone-install.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# Create openstack credentials for root
+
+- name: Setup root openstack credentials
+  hosts: base:!vnf-nodes
+  roles:
+    - role: "openstack_openrc"
+      vars:
+          ## Create openrc file
+          openrc_file_dest: "/root/openrc"
+          openrc_file_owner: "root"
+          openrc_file_group: "root"
+
+          ## Create clouds.yml file
+          openrc_openstack_client_config_dir_dest: "/root/.config/openstack"
+          openrc_openstack_client_config_dir_owner: "root"
+          openrc_openstack_client_config_dir_group: "root"
+          openrc_clouds_yml_file_dest: "/root/.config/openstack/clouds.yaml"
+          openrc_clouds_yml_file_owner: "root"
+          openrc_clouds_yml_file_group: "root"
+
diff --git a/playbooks/rpm-database.yml b/playbooks/rpm-database.yml
new file mode 100644 (file)
index 0000000..f89897e
--- /dev/null
@@ -0,0 +1,22 @@
+# cmframework.requires: baremetal-interface-config.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Verify rpm database integrity
+  hosts: all:!localhost
+  roles:
+       - rpmdatabase
+
diff --git a/playbooks/secretsextend.yml b/playbooks/secretsextend.yml
new file mode 100644 (file)
index 0000000..c735df6
--- /dev/null
@@ -0,0 +1,20 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync users keys
+  hosts: localhost
+  roles:
+      - secretsextend
diff --git a/playbooks/service-profiles.yml b/playbooks/service-profiles.yml
new file mode 100644 (file)
index 0000000..de65049
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create mapping of nodes to service profiles
+  hosts: [ base ]
+  roles:
+      - service-profiles
diff --git a/playbooks/set_keyring_owners.yml b/playbooks/set_keyring_owners.yml
new file mode 100644 (file)
index 0000000..66b7b85
--- /dev/null
@@ -0,0 +1,61 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Set keyrings owners for controller
+  hosts: controller
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+    cephkeys_access_group: "cephkeys"
+  tasks:
+  - name: Create cephkeys_access_group group
+    group:
+      name: "{{ cephkeys_access_group }}"
+    when: (ceph_configured | default(False))
+  - name: set keyrings owner
+    file:
+      path: "/etc/ceph/ceph.client.{{ item }}.keyring"
+      owner: "{{ item }}"
+      group: "{{ cephkeys_access_group }}"
+      mode: 0640
+    with_items:
+      - glance
+      - cinder
+    when: (ceph_configured | default(False))
+
+- name: Set keyrings owners for caas_master
+  hosts: caas_master
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+    cephkeys_access_group: "cephkeys"
+  tasks:
+  - name: Create cephkeys_access_group group
+    group:
+      name: "{{ cephkeys_access_group }}"
+    when: (ceph_configured | default(False))
+  - name: set keyrings owner
+    file:
+      path: "/etc/ceph/ceph.client.caas.keyring"
+      # TODO: Probably CaaS should have an own user
+      owner: "{{ users.admin_user_name }}"
+      group: "{{ cephkeys_access_group }}"
+      mode: 0640
+    when: (ceph_configured | default(False))
diff --git a/playbooks/setup_aaa.yml b/playbooks/setup_aaa.yml
new file mode 100644 (file)
index 0000000..b6d3dbb
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+#cmframework.requires: setup_collectd.yml,os-horizon-install.yml
+# AAA setup
+- hosts: [ management ]
+  roles:
+    - "aaa"
diff --git a/playbooks/setup_audit.yml b/playbooks/setup_audit.yml
new file mode 100644 (file)
index 0000000..33e4e41
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+#cmframework.requires: setup_collectd.yml
+# Audit setup
+- hosts: [ management ]
+  roles:
+    - "audit"
diff --git a/playbooks/setup_in_host_traffic_filtering.yml b/playbooks/setup_in_host_traffic_filtering.yml
new file mode 100644 (file)
index 0000000..ba4b103
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: provisioning_done.yml
+# Controller setup
+- hosts: [ management ]
+  roles:
+    - "in_host_traffic_filtering_controller"
diff --git a/playbooks/single_node_partitions.yml b/playbooks/single_node_partitions.yml
new file mode 100755 (executable)
index 0000000..fd317a5
--- /dev/null
@@ -0,0 +1,65 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: management
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  tasks:
+    # To avoid this warning in lvs -command: WARNING: Not using lvmetad because config setting use_lvmetad=0.
+  - name: patch use_lvmetad parameter in lvm.conf
+    lineinfile: path=/etc/ansible/roles/os_cinder/templates/lvm.conf.j2  regexp='^\s*use_lvmetad ='   line='    use_lvmetad = 1'
+
+  - name: instance disks disk layout
+    debug:
+      msg: "Controller instance devices: {{ instance_disks }}"
+    when: instance_disks is defined
+
+  - name: make partition table for nova in controller
+    parted: device={{ item }}  number=1  label=gpt  state=present
+    with_items: "{{ instance_disks }}"
+    when: instance_disks is defined
+
+  - name: Inform the OS of partition table changes
+    shell: "/sbin/partprobe {{ item }}"
+    with_items: "{{ instance_disks }}"
+    when: instance_disks is defined
+
+  - name: set Linux LVM type to partition
+    shell: "[ -b {{ item }} ] | parted {{ item }} set 1 lvm on"
+    with_items: "{{ instance_disks }}"
+    when: instance_disks is defined
+
+  - name: cinder disk layout
+    debug:
+      msg: "Controller cinder devices: {{ devices }}"
+    when: devices is defined
+
+  - name: make partition table for cinder in controller
+    parted: device={{ item }}  number=1  label=gpt  state=present
+    with_items: "{{ devices }}"
+    when: devices is defined
+
+  - name: Inform the OS of partition table changes
+    shell: "/sbin/partprobe {{ item }}"
+    with_items: "{{ devices }}"
+    when: devices is defined
+
+  - name: set Linux LVM type to partition
+    shell: "[ -b {{ item }} ] | parted {{ item }} set 1 lvm on"
+    with_items: "{{ devices }}"
+    when: devices is defined
diff --git a/playbooks/single_node_storage.yml b/playbooks/single_node_storage.yml
new file mode 100644 (file)
index 0000000..844c3e5
--- /dev/null
@@ -0,0 +1,47 @@
+# cmframework.requires:baremetal-install.yml,baremetal-interface-config.yml,performance-kernel-cmdline-set.yml,ntp-config.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: openstack_nodes
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  roles:
+    - role: cleanup_disks
+      vars:
+        disks: "{{ devices }}"
+      when:
+        - devices is defined
+        - one_controller_node_config | bool
+
+- include: single_node_partitions.yml
+  when:
+    - one_controller_node_config | bool
+    - lvm_configured | default(False)
+
+- include: single_node_volume_groups.yml
+  when:
+    - one_controller_node_config | bool
+    - lvm_configured | default(False)
+
+- include: glance-lvm.yml
+  vars:
+    all_disk_size_for_volume_group_vg: "1"
+  when:
+    - one_controller_node_config | bool
+    - lvm_configured | default(False)
+    - rootdisk_vg_percentage != all_disk_size_for_volume_group_vg
diff --git a/playbooks/single_node_volume_groups.yml b/playbooks/single_node_volume_groups.yml
new file mode 100755 (executable)
index 0000000..07f18be
--- /dev/null
@@ -0,0 +1,30 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- hosts: management
+  become: yes
+  become_method: sudo
+  become_user: root
+  gather_facts: no
+  vars:
+    vgnova: 'nova'
+    vgcinder: 'cinder-volumes'
+    all_disk_size_for_volume_group_vg: "1"
+  tasks:
+  - name:  make cinder volume group
+    lvg: vg={{ vgcinder }}  pvs={{ cinder_physical_volumes }}  state=present
+    when:
+     - cinder_physical_volumes is defined
diff --git a/playbooks/site.yml b/playbooks/site.yml
new file mode 100644 (file)
index 0000000..be2fc87
--- /dev/null
@@ -0,0 +1,168 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# Defines deployment design and assigns role to server groups
+
+- hosts:
+  - mons
+#  - agents
+  - osds
+#  - mdss
+#  - rgws
+#  - nfss
+#  - restapis
+#  - rbdmirrors
+#  - clients
+  - mgrs
+#  - iscsi-gws
+
+  gather_facts: false
+
+  tags:
+    - always
+
+  tasks:
+    # If we can't get python2 installed before any module is used we will fail
+    # so just try what we can to get it installed
+    - name: check for python2
+      stat:
+        path: /usr/bin/python
+      ignore_errors: yes
+      register: systempython2
+
+    - name: install python2 for debian based systems
+      raw: sudo apt-get -y install python-simplejson
+      ignore_errors: yes
+      when:
+        - systempython2.stat.exists is undefined or systempython2.stat.exists == false
+
+    - name: install python2 for fedora
+      raw: sudo dnf -y install python creates=/usr/bin/python
+      ignore_errors: yes
+      when:
+        - systempython2.stat.exists is undefined or systempython2.stat.exists == false
+
+    - name: gather and delegate facts
+      setup:
+      delegate_to: "{{ item }}"
+      delegate_facts: True
+      with_items: "{{ groups['all'] }}"
+
+    - name: install required packages for fedora > 23
+      raw: sudo dnf -y install python2-dnf libselinux-python ntp
+      when:
+        - ansible_distribution == 'Fedora'
+        - ansible_distribution_major_version|int >= 23
+
+- hosts: mons
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-mon
+
+- hosts: mgrs
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - { role: ceph-config, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+    - { role: ceph-mgr, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+
+- hosts: agents
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-agent
+
+- hosts: osds
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-osd
+
+- hosts: mdss
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-mds
+
+- hosts: rgws
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-rgw
+
+- hosts: nfss
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - { role: ceph-config, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+    - { role: ceph-nfs, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+
+- hosts: restapis
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-restapi
+
+- hosts: rbdmirrors
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-rbd-mirror
+
+- hosts: clients
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - ceph-config
+    - ceph-client
+
+- hosts: iscsi-gws
+  gather_facts: false
+  become: True
+  roles:
+    - ceph-defaults
+    - ceph-common
+    - { role: ceph-config, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+    - { role: ceph-iscsi-gw, when: "ceph_release_num.{{ ceph_release }} >= ceph_release_num.luminous" }
+
diff --git a/playbooks/sriov_nodes.yaml b/playbooks/sriov_nodes.yaml
new file mode 100644 (file)
index 0000000..4a041f1
--- /dev/null
@@ -0,0 +1,22 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: partfs_rootdisk.yml,baremetal-install.yml
+
+- name: SR-IOV node configuration
+  hosts: [ compute, caas_nodes ]
+  roles:
+      - sriov_nodes
diff --git a/playbooks/sriovdp_config.yaml b/playbooks/sriovdp_config.yaml
new file mode 100644 (file)
index 0000000..92cef4c
--- /dev/null
@@ -0,0 +1,22 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# cmframework.requires: baremetal-install.yml,sriov_nodes.yaml
+
+- name: SR-IOV Network Device Plugin config generator
+  hosts: [ caas_nodes ]
+  roles:
+  - sriovdp_config
diff --git a/playbooks/synchonize_ssh_keys.yml b/playbooks/synchonize_ssh_keys.yml
new file mode 100644 (file)
index 0000000..615cc4c
--- /dev/null
@@ -0,0 +1,52 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Synchronize controller ssh keys
+  hosts: management:!vnf-nodes
+  pre_tasks:
+    - name: set master_key_holder to installation_controller
+      set_fact:
+        master_key_holder: "{{ installation_controller }}"
+
+  tasks:
+    - name: Copy temporary key to slaves
+      shell: |
+        sudo -u "{{ users.admin_user_name }}" \
+            scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
+            "/home/{{ users.admin_user_name }}/.ssh/id_rsa" "{{ hostvars[item]['ansible_host'] }}":/tmp/tmp_rsa
+      when: hostname == master_key_holder
+      with_items: "{{ groups['management'] }}"
+
+    - name: Copy ssh keys from active haproxyvip or installation controller
+      shell: |
+        sudo -u "{{ users.admin_user_name }}" \
+            ssh -i /tmp/tmp_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
+                "{{ hostvars[master_key_holder]['ansible_host'] }}" \
+                sudo tar -cf - "{{ item }}" |sudo tar -C / -xf -
+
+      with_items:
+        - '/etc/ssh/ssh_host_ecdsa_key'
+        - '/etc/ssh/ssh_host_ecdsa_key.pub'
+        - '/etc/ssh/ssh_host_ed25519_key'
+        - '/etc/ssh/ssh_host_ed25519_key.pub'
+        - '/etc/ssh/ssh_host_rsa_key'
+        - '/etc/ssh/ssh_host_rsa_key.pub'
+      when: master_key_holder != inventory_hostname
+
+    - name: Clean temporary key
+      file:
+        path: /tmp/tmp_rsa
+        state: absent
diff --git a/playbooks/systemd_services.yml b/playbooks/systemd_services.yml
new file mode 100644 (file)
index 0000000..f3d1aa5
--- /dev/null
@@ -0,0 +1,24 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Disable systemd services
+  hosts: all:!localhost
+  tasks:
+    - name: Disable the services in the list
+      service: name={{ item }} enabled=no
+      with_items:
+        - postfix
diff --git a/playbooks/userskeyssync.yml b/playbooks/userskeyssync.yml
new file mode 100644 (file)
index 0000000..97984ae
--- /dev/null
@@ -0,0 +1,21 @@
+# cmframework.requires: provisioning_done.yml
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync users keys
+  hosts: all:!localhost
+  roles:
+      - userskeyssync
diff --git a/roles/access-management/defaults/main.yaml b/roles/access-management/defaults/main.yaml
new file mode 100644 (file)
index 0000000..a02a133
--- /dev/null
@@ -0,0 +1,69 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+---
+am_config:
+  Logging:
+    loglevel: DEBUG
+    logdir: /var/log/access_management
+  DB:
+    name: am_database
+    user: am_db_user
+    pwd: "{{ am_db_user_password }}"
+    addr: "{{ aaa_galera_address }}"
+    port: 3306
+  Keystone:
+    auth_uri: "{{ keystone_service_internalurl }}"
+  Api:
+    host: "{{ am_listening_host }}"
+    port: "{{ auth_server_service_port }}"
+
+am_backend_config:
+  Logging:
+    loglevel: "{{ am_config.Logging.loglevel }}"
+    logdir: "{{ am_config.Logging.logdir }}"
+  DB:
+    name: "{{ am_config.DB.name }}"
+    user: am_db_backend_user
+    pwd: "{{ am_db_user_backend_password }}"
+    addr: "{{ am_config.DB.addr }}"
+    port: "{{ am_config.DB.port }}"
+  Keystone:
+    auth_uri: "{{ am_config.Keystone.auth_uri }}"
+  Api:
+    host: "{{ am_config.Api.host }}"
+    port: "{{ am_config.Api.port }}"
+
+infrastructure_admin_user_name: "{{ users.initial_user_name }}"
+infrastructure_admin_password: "{{ users.initial_user_password }}"
+am_project_name: infrastructure
+am_project_domain: default
+am_admin_role_name: admin
+am_member_role_name: _member_
+openrc_region_name: RegionOne
+openrc_clouds_yml_interface: internal
+service_proto: http
+service_internaluri_proto: "{{ openstack_service_internaluri_proto | default(service_proto) }}"
+
+am_listening_host : localhost
+am_server_config_dir : /etc/access_management/
+am_plugin_config_file : am_config.ini
+am_plugin_config_path : "{{am_server_config_dir}}{{am_plugin_config_file}}"
+am_backend_config_file : am_backend_config.ini
+am_backend_config_path : "{{am_server_config_dir}}{{am_backend_config_file}}"
+am_server_temp_dir : "{{am_server_config_dir}}temp"
+am_server_values_dir : "{{am_server_config_dir}}values"
+am_cloud_yaml_path : "{{ am_server_temp_dir }}/cloud.yaml"
+policy_sudoer : /etc/sudoers.d/policy_sudoer
+lib_source_folder : /usr/lib/python2.7/site-packages
diff --git a/roles/access-management/tasks/basic.yaml b/roles/access-management/tasks/basic.yaml
new file mode 100644 (file)
index 0000000..5812418
--- /dev/null
@@ -0,0 +1,216 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Ensures AM Configuration dir exists
+  file:
+    dest: "{{ am_server_config_dir }}"
+    state: directory
+
+- name: Ensures AM temp dir exists
+  file:
+    dest: "{{ am_server_temp_dir }}"
+    state: directory
+  tags:
+    - am_dbfiller
+    - am_rc
+
+- name: Ensures AM values dir exists
+  file:
+    dest: "{{ am_server_values_dir }}"
+    state: directory
+  tags:
+    - am_dbfiller
+
+- name: AM backend log file creation and rights set
+  file:
+    path: "{{ am_config.Logging.logdir }}/am.log"
+    owner: access-manager
+    group: access-manager
+    mode: 0600
+    state: touch
+
+- name: Patch log file creation and rights set
+  file:
+    path: "{{ am_config.Logging.logdir }}/keystone_users_patch.log"
+    owner: access-manager
+    group: access-manager
+    mode: 0600
+    state: touch
+
+- name: Create AM Plugin Config
+  template:
+    src: am.plugin.conf.j2
+    dest: "{{ am_plugin_config_path }}"
+    owner: restapi
+    group: restapi
+    mode: 0400
+
+- name: Create AM Backend Config
+  template:
+    src: am.backend.conf.j2
+    dest: "{{ am_backend_config_path }}"
+    owner: access-manager
+    group: access-manager
+    mode: 0400
+
+- name: Ensure project for um_admin exists
+  run_once: true
+  keystone:
+    command: ensure_project
+    project_name: "{{ am_project_name }}"
+    domain_name: "{{ am_project_domain }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+
+- name: Ensure um_admin user
+  run_once: true
+  keystone:
+    command: "ensure_user"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    user_name: "{{ infrastructure_admin_user_name }}"
+    tenant_name: "{{ am_project_name }}"
+    password: "{{ infrastructure_admin_password }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: um_admin_uuid
+  until: um_admin_uuid|success
+  retries: 5
+  delay: 10
+
+- name: Ensure UM admin user added to admin role
+  run_once: true
+  keystone:
+    command: "ensure_user_role"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    user_name: "{{ infrastructure_admin_user_name }}"
+    tenant_name: "{{ am_project_name }}"
+    role_name: "{{ am_admin_role_name }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+
+- name: Ensure keystone admin user added to member role
+  run_once: true
+  keystone:
+    command: "ensure_user_role"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    user_name: "{{ keystone_admin_user_name }}"
+    tenant_name: "{{ am_project_name }}"
+    role_name: "{{ am_member_role_name }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+
+- name: Set default project for keystone admin user
+  run_once: true
+  command: openstack user set {{ keystone_admin_user_name }} --project {{ am_project_name }} --os-cloud default
+
+- name: Add the security_compliance section to keystone.conf
+  ini_file:
+    path: /etc/keystone/keystone.conf
+    section: security_compliance
+    option: "{{ item.option }}"
+    value: "{{ item.value }}"
+  with_items:
+    - { option: "lockout_failure_attempts", value: "{{ host_os.failed_login_attempts | default(5) }}" }
+    - { option: "lockout_duration", value: "{{ host_os.lockout_time | default(300) }}" }
+    - { option: "change_password_upon_first_use", value: "True" }
+    - { option: "password_expires_days", value: "90" }
+    - { option: "unique_last_password_count", value: "12" }
+    - { option: "minimum_password_age", value: "0" }
+    - { option: "password_regex", value: "^(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[][.,:;/(){}<>~\\!?@#$%^&*_=+-])[][a-zA-Z0-9.,:;/(){}<>~\\!?@#$%^&*_=+-]{8,255}$" }
+    - { option: "password_regex_description", value: "The password must have a minimum length of 8 characters (maximum is 255 characters). The allowed characters are lower case letters (a-z), upper case letters (A-Z), digits (0-9), and special characters (.,:;/(){}<>~\\!?@#$%^&*_=+-). The password must contain at least one upper case letter, one digit and one special character." }
+
+- name: Restart Keystone WSGI services
+  service:
+    name: "{{ item }}"
+    enabled: yes
+    state: "restarted"
+    daemon_reload: "{{ (ansible_service_mgr == 'systemd') | ternary('yes', omit) }}"
+  register: _start1
+  until: _start1 | success
+  retries: 5
+  delay: 3
+  with_items:
+    - keystone-wsgi-public
+    - keystone-wsgi-admin
+
+- name: Wait for Keystone WSGI services to restart
+  wait_for:
+    port: "{{ item }}"
+    host: "{{ extra_hosts_entries.haproxyvip }}"
+    timeout: 25
+    delay: 10
+  with_items:
+    - "{{ keystone_service_port }}"
+    - "{{ keystone_admin_port }}"
+  register: _wait_check1
+  until: _wait_check1 | success
+  retries: 5
+
+- name:  Wait for Keystone WSGI services to respond
+  shell: openstack user list --os-cloud default
+  register: result
+  until: result | success
+  delay: 2
+  retries: 5
+
+- name: Create OpenStack client configuration directory
+  file:
+    dest: "{{ openrc_openstack_client_config_dir_dest }}"
+    owner: "{{ openrc_openstack_client_config_dir_owner }}"
+    group: "{{ openrc_openstack_client_config_dir_group }}"
+    state: directory
+
+- name: Change authorization in YARF config
+  lineinfile:
+    path: "/etc/yarf/config.ini"
+    regexp: "auth_method=.*"
+    line: "auth_method=access_management.backend.am_auth.AMAuth"
+
+- name: Restart YARF service
+  service:
+    name: restapi
+    enabled: yes
+    state: "restarted"
+    daemon_reload: "{{ (ansible_service_mgr == 'systemd') | ternary('yes', omit) }}"
+  register: _start2
+  until: _start2 | success
+  retries: 5
+  delay: 3
+
+- name: Wait for YARF service to restart
+  wait_for:
+    port: "{{ restful_service_port }}"
+    host: "{{ extra_hosts_entries.haproxyvip }}"
+    timeout: 25
+    delay: 10
+  register: _wait_check2
+  until: _wait_check2 | success
+  retries: 5
diff --git a/roles/access-management/tasks/dbfiller.yaml b/roles/access-management/tasks/dbfiller.yaml
new file mode 100644 (file)
index 0000000..0f44608
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create AM values json file
+  template:
+    src: db_am_values.json.j2
+    dest: "{{ am_server_values_dir }}/db_am_values.json"
+
+- name: Create service values json file
+  template:
+    src: db_service_values.json.j2
+    dest: "{{ am_server_values_dir }}/db_service_values.json"
+
+- name: Copy private key to temp location
+  copy:
+    src: templates/am_pri_key.pem
+    dest: "{{ am_server_temp_dir }}"
+
+- name: Create DB filler python script
+  template:
+    src: dbfiller.py.j2
+    dest: "{{ am_server_temp_dir }}/dbfiller.py"
+
+- name: DB filler log file creation and rights set
+  file:
+    path: "{{ am_config.Logging.logdir }}/dbfiller.log"
+    owner: access-manager
+    group: access-manager
+    mode: 0660
+    state: touch
+
+- name: Run the DB filler python script
+  run_once: true
+  shell: "python {{ am_server_temp_dir }}/dbfiller.py >> {{ am_config.Logging.logdir }}/dbfiller.log"
diff --git a/roles/access-management/tasks/fill_sqls.yaml b/roles/access-management/tasks/fill_sqls.yaml
new file mode 100644 (file)
index 0000000..789fb5c
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Set fact for users
+  set_fact:
+    am_users:
+      - "{{ keystone_admin_user_name }}"
+  tags:
+    - am_dbfiller
+
+- name: Set fact for users 2
+  set_fact:
+    am_users:
+      - keystone
+      - ironic
+      - restful
+      - "{{ keystone_admin_user_name }}"
+  when: '"controller" in hosts[installation_controller]["service_profiles"]'
+  tags:
+    - am_dbfiller
+
+- name: Get UUID of users
+  run_once: true
+  keystone:
+    command: "get_user"
+    user_name: "{{ item }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+  with_items: "{{ am_users }}"
+  register: keystone_uuids
+  tags:
+    - am_dbfiller
+
+- name: Create bash script to set service user special password policy options
+  template:
+    src: keystone_users_patch.sh.j2
+    dest: "{{ am_server_temp_dir }}/keystone_users_patch.sh"
+    owner: root
+    group: root
+    mode: 0500
+
+- name: Run the bash script
+  run_once: true
+  shell: "{{ am_server_temp_dir }}/keystone_users_patch.sh >> {{ am_config.Logging.logdir }}/keystone_users_patch.log"
diff --git a/roles/access-management/tasks/main.yaml b/roles/access-management/tasks/main.yaml
new file mode 100644 (file)
index 0000000..f2a817b
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright 2019 Nokia
+
+# 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: basic.yaml
+  tags:
+      - am
+
+- include: openrc_cloud.yaml
+  tags:
+      - am
+      - am_rc
+
+- include: fill_sqls.yaml
+  tags:
+      - am
+
+- include: mysqldb.yaml
+  tags:
+      - am
+      - am_dbfiller
+
+- include: dbfiller.yaml
+  tags:
+      - am_dbfiller
+
+- name: Delete AM's install folders
+  file:
+    path: "{{ item }}"
+    state: absent
+  with_items:
+    - "{{ am_server_values_dir }}"
+    - "{{ am_server_temp_dir }}"
+  tags:
+    - am
+    - am_dbfiller
+    - am_rc
diff --git a/roles/access-management/tasks/mysqldb.yaml b/roles/access-management/tasks/mysqldb.yaml
new file mode 100644 (file)
index 0000000..557f0b5
--- /dev/null
@@ -0,0 +1,40 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create AMDB in mariadb
+  run_once: true
+  mysql_db:
+    login_host: "{{ am_config.DB.addr }}"
+    name: "{{ am_config.DB.name }}"
+    state: present
+
+- name: Create admin mysql user for AMDB and set rights
+  run_once: true
+  mysql_user:
+    login_host: "{{ am_config.DB.addr }}"
+    host: "%"
+    name: "{{ am_config.DB.user }}"
+    password: "{{ am_config.DB.pwd }}"
+    priv: "{{ am_config.DB.name }}.*:ALL"
+    state: present
+
+- name: Create reader mysql user for AMDB and set rights
+  run_once: true
+  mysql_user:
+    login_host: "{{ am_backend_config.DB.addr }}"
+    host: "%"
+    name: "{{ am_backend_config.DB.user }}"
+    password: "{{ am_backend_config.DB.pwd }}"
+    priv: "{{ am_backend_config.DB.name }}.*:SELECT"
+    state: present
diff --git a/roles/access-management/tasks/openrc_cloud.yaml b/roles/access-management/tasks/openrc_cloud.yaml
new file mode 100644 (file)
index 0000000..c8650a5
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Add Rest endpoint to openrc
+  lineinfile:
+    path: "{{ openrc_file_dest }}"
+    regexp: "^export OS_REST_URL=.*"
+    line: "export OS_REST_URL={{ service_internaluri_proto }}://{{ internal_lb_vip_address }}:{{ restful_service_port }}"
+
+- name: Create custom_rc file for cloudadmin
+  template:
+    src: custom_rc.j2
+    dest: "/home/{{ users['admin_user_name'] }}/custom_rc"
+
+- name: Create custom_rc file in skeleton
+  template:
+    src: custom_rc.j2
+    dest: "/etc/skel/custom_rc"
diff --git a/roles/access-management/templates/am.backend.conf.j2 b/roles/access-management/templates/am.backend.conf.j2
new file mode 100644 (file)
index 0000000..edec100
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# This file is managed by Ansible.
+# Do not edit this file manually.
+# Any changes will be automatically reverted.
+#
+
+{% from "templates/encoder/macros/ini_encode_macro.j2" import ini_encode with context -%}
+
+{{ ini_encode(am_backend_config) }}
diff --git a/roles/access-management/templates/am.plugin.conf.j2 b/roles/access-management/templates/am.plugin.conf.j2
new file mode 100644 (file)
index 0000000..bcdc1c5
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# This file is managed by Ansible.
+# Do not edit this file manually.
+# Any changes will be automatically reverted.
+#
+
+{% from "templates/encoder/macros/ini_encode_macro.j2" import ini_encode with context -%}
+
+{{ ini_encode(am_config) }}
diff --git a/roles/access-management/templates/am_pri_key.pem b/roles/access-management/templates/am_pri_key.pem
new file mode 100644 (file)
index 0000000..e4d5f38
--- /dev/null
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDNT8kjgs6LziCW84d4IA7iM7zXpakiakYOzZlSTrWebBakqqqy
+KcYk7UhqHALF2tQoETFWXpAB7dGNT6j7gyIfKSbYFa4v60IBRfoZ9veqlTwpZH5d
+uhfpKD2u8vbC5mzBZvxuIZSWoIZ3POCKY1dRw6e4fQtN38S6QYiNZFpxLQIDAQAB
+AoGBALnPa4nn6GY+tt/mpsPgv5eYm1/PXbL320+qYwhKk7Q8voFos/NqOxlQZiki
+EKBf24InjS9Nhac5RF1Pqu91TnqlZPiciscdmp/eD3YS6OIWZ/WBYGJTeyz9LnN2
+gZYeIpPu9mnc4gcIBxisybM1KrfTcFkDEFh99wZVFp+zhPFBAkEA8xE+rlFqe/r/
+uHbilfavARcwBZjT96wOGiYiCZS849+TLkhG22L+cxWjJyboI2IL1kbPgxzYVfAl
+ZiSpsuskqwJBANg8R9bO6MGoHQAnEws81bzYeZJ1O6M3tua/kSwAql7YYFnx/eTW
+w/x8fw6aEvVQlN5+5ZPkQfV+p3NVBWtAUYcCQQDhWparlU5NfiuCga6X7OrZ7v6V
+4dh8Iue8NKiQC3eJKarSWS5gjopsdp4aWYcV7vwcgPA5lg+4tXpnFgzDliEbAkB/
+iV5dxf/maL9iHanP0PvHvG5IAblBFVVdV9PJ/kJ+WmTJ6D71v+4sd0mBVUKlSffk
+GzhROCnnH+Kn1ZeyoGb1AkEAnw60XS/DBtdWN07Y846uwqLbiWSbIpdt/IL9RvVY
+5tQXv5YPi8s+0T8HOKq9tcUHlZUjktmo3fFVEztHAbtwug==
+-----END RSA PRIVATE KEY-----
diff --git a/roles/access-management/templates/custom_rc.j2 b/roles/access-management/templates/custom_rc.j2
new file mode 100644 (file)
index 0000000..cc49450
--- /dev/null
@@ -0,0 +1,36 @@
+# {{ ansible_managed }}
+export LC_ALL=C
+
+# COMMON CINDER ENVS
+export CINDER_ENDPOINT_TYPE={{ openrc_clouds_yml_interface }}
+
+# COMMON NOVA ENVS
+export NOVA_ENDPOINT_TYPE={{ openrc_clouds_yml_interface }}
+
+# COMMON OPENSTACK ENVS
+export OS_ENDPOINT_TYPE={{ openrc_clouds_yml_interface }}
+export OS_INTERFACE={{ openrc_clouds_yml_interface }}
+export OS_PROJECT_NAME={{ am_project_name }}
+export OS_TENANT_NAME={{ am_project_name }}
+echo "Please enter your OpenStack Username for project $OS_PROJECT_NAME: "
+read OS_USERNAME_INPUT
+export OS_USERNAME=$OS_USERNAME_INPUT
+echo "Please enter your OpenStack Password for project $OS_PROJECT_NAME as user $OS_USERNAME: "
+read -sr OS_PASSWORD_INPUT
+export OS_PASSWORD=$OS_PASSWORD_INPUT
+export OS_AUTH_URL={{ openrc_os_auth_url }}
+export OS_NO_CACHE=1
+export OS_USER_DOMAIN_NAME={{ openrc_os_domain_name }}
+export OS_PROJECT_DOMAIN_NAME={{ openrc_os_domain_name }}
+export OS_REGION_NAME={{ openrc_region_name }}
+export PS1='[\u@\h \W($OS_USERNAME_INPUT)]\$ '
+export OS_REST_URL={{ service_internaluri_proto }}://{{ internal_lb_vip_address }}:{{ restful_service_port }}
+
+# For openstackclient
+{% if openrc_os_auth_url.endswith('v2.0') %}
+export OS_IDENTITY_API_VERSION=2.0
+export OS_AUTH_VERSION=2
+{% else %}
+export OS_IDENTITY_API_VERSION=3
+export OS_AUTH_VERSION=3
+{% endif %}
diff --git a/roles/access-management/templates/db_am_values.json.j2 b/roles/access-management/templates/db_am_values.json.j2
new file mode 100644 (file)
index 0000000..36d44e7
--- /dev/null
@@ -0,0 +1,71 @@
+{
+ "users": [
+  ["{{ infrastructure_admin_user_name }}",""]
+ ],
+ "roles": [
+  ["infrastructure_admin","Infrastructure Administrator","False"],
+  ["openstack_admin","Openstack Administrator","False"],
+  ["heat_stack_owner","Heat Stack Owner","False"],
+  ["linux_user","Linux User","False"]
+ ],
+ "permissions": [
+  ["am/users","POST","Creating new user in keystone"],
+  ["am/users","DELETE","Deleting one or more existing users"],
+  ["am/users","GET","Listing existing users"],
+  ["am/users/ownpasswords","POST","Changing the current user password"],
+  ["am/users/passwords","POST","changing a users password"],
+  ["am/users/parameters","POST","Setting user parameters"],
+  ["am/users/details","GET","Displaying the details of a user"],
+  ["am/users/owndetails","GET","Displaying the user's own details"],
+  ["am/users/roles","POST","Adding role for a user"],
+  ["am/users/roles","DELETE","Removing role from a user"],
+  ["am/users/locks","POST","Enabling a locked account"],
+  ["am/users/locks","DELETE","Enabling a locked account"],
+  ["am/users/keys","POST","Adding/updating key for one chroot"],
+  ["am/users/keys","DELETE","Removing key for the existing chroot"],
+  ["am/roles","POST","Creating a new role"],
+  ["am/roles","PUT","Modifying an existing role"],
+  ["am/roles","DELETE","Deleting an existing role"],
+  ["am/roles","GET","Listing existing roles"],
+  ["am/roles/details","GET","Displaying the details of a role"],
+  ["am/roles/users","GET","Listing the users of a role"],
+  ["am/roles/permissions","POST","Adding a new permission for a role"],
+  ["am/roles/permissions","DELETE","Removing a permission from a role"],
+  ["am/permissions","GET","Listing all the permissions & endpoints"],
+  ["am/permissions/details","GET","Listing a single resource & operations"]
+ ],
+ "user_roles": [
+  ["{{ keystone_admin_user_name }}","basic_member"],
+  ["{{ infrastructure_admin_user_name }}","infrastructure_admin"],
+  ["{{ infrastructure_admin_user_name }}","basic_member"]
+ ],
+ "role_permissions": [
+  ["infrastructure_admin","am/users","POST"],
+  ["infrastructure_admin","am/users","DELETE"],
+  ["infrastructure_admin","am/users","GET"],
+  ["infrastructure_admin","am/users/ownpasswords","POST"],
+  ["infrastructure_admin","am/users/passwords","POST"],
+  ["infrastructure_admin","am/users/parameters","POST"],
+  ["infrastructure_admin","am/users/details","GET"],
+  ["infrastructure_admin","am/users/roles","POST"],
+  ["infrastructure_admin","am/users/roles","DELETE"],
+  ["infrastructure_admin","am/users/locks","POST"],
+  ["infrastructure_admin","am/users/locks","DELETE"],
+  ["infrastructure_admin","am/users/keys","POST"],
+  ["infrastructure_admin","am/users/keys","DELETE"],
+  ["infrastructure_admin","am/roles","POST"],
+  ["infrastructure_admin","am/roles","PUT"],
+  ["infrastructure_admin","am/roles","DELETE"],
+  ["infrastructure_admin","am/roles","GET"],
+  ["infrastructure_admin","am/roles/details","GET"],
+  ["infrastructure_admin","am/roles/users","GET"],
+  ["infrastructure_admin","am/roles/permissions","POST"],
+  ["infrastructure_admin","am/roles/permissions","DELETE"],
+  ["infrastructure_admin","am/permissions","GET"],
+  ["infrastructure_admin","am/permissions/details","GET"],
+  ["basic_member","am/users/ownpasswords","POST"],
+  ["basic_member","am/users/owndetails","GET"],
+  ["linux_user","am/users/keys","POST"],
+  ["linux_user","am/users/keys","DELETE"]
+ ]
+}
diff --git a/roles/access-management/templates/db_service_values.json.j2 b/roles/access-management/templates/db_service_values.json.j2
new file mode 100644 (file)
index 0000000..aab2616
--- /dev/null
@@ -0,0 +1,17 @@
+{
+ "users": [
+{% for i in keystone_uuids.results %}
+  ["{{ i.item }}",""],
+{% endfor %}
+  ["{{ infrastructure_admin_user_name }}",""]
+ ],
+ "roles": [
+  ["basic_member","Basic Member","False"]
+ ],
+ "permissions": [
+ ],
+ "user_roles": [
+ ],
+ "role_permissions": [
+ ]
+}
diff --git a/roles/access-management/templates/dbfiller.py.j2 b/roles/access-management/templates/dbfiller.py.j2
new file mode 100644 (file)
index 0000000..b70e893
--- /dev/null
@@ -0,0 +1,312 @@
+import ConfigParser
+
+import logging
+import os
+import sys
+import M2Crypto
+import time
+
+from keystoneauth1.identity import v3
+from keystoneauth1 import session
+from keystoneauth1.exceptions.http import Conflict
+from keystoneclient import utils
+from keystoneclient.v3 import client
+
+sys.path.append('{{ lib_source_folder }}')
+from access_management.db.amdb import AMDatabase
+from access_management.cryptohelper.decryptaaafiles import DecryptAAAFile
+
+
+def get_config():
+    config = ConfigParser.ConfigParser()
+    config.read("/{{ am_plugin_config_path }}")
+    config_dict = {s: dict(config.items(s)) for s in config.sections()}
+    return config_dict
+
+
+def set_logger():
+    logger = logging.getLogger("DBfiller")
+    shandler = logging.StreamHandler(sys.stdout)
+    shandler.setLevel(logging.DEBUG)
+    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+    shandler.setFormatter(formatter)
+    logger.addHandler(shandler)
+    logger.info("logger set")
+    return logger
+
+
+def close_logger_handlers(logger):
+    for handler in logger.handlers:
+        logger.removeHandler(handler)
+
+
+def read_files():
+    users = []
+    roles = []
+    permissions = []
+    user_roles = []
+    role_permissions = []
+    dir = "{{ am_server_values_dir }}"
+    for encrypted_file in os.listdir(dir):
+        if os.stat(os.path.join(dir, encrypted_file)).st_uid is not 0:
+            print "--- File: ", encrypted_file, "is not of root, skipping"
+            continue
+        try:
+            crypter = DecryptAAAFile("{{ am_server_temp_dir }}/am_pri_key.pem")
+            jsoned_content = crypter.decrypt_file(os.path.join(dir, encrypted_file))
+            for user in jsoned_content["users"]:
+                users.append(user)
+            for role in jsoned_content["roles"]:
+                roles.append(role)
+            for permission in jsoned_content["permissions"]:
+                permissions.append(permission)
+            for user_role in jsoned_content["user_roles"]:
+                user_roles.append(user_role)
+            for role_permission in jsoned_content["role_permissions"]:
+                role_permissions.append(role_permission)
+        except M2Crypto.RSA.RSAError as ex:
+            print "Failed to decrypt file: {}, {}".format(encrypted_file, str(ex))
+        except Exception as ex:
+            print "File {} failed with error: {}".format(encrypted_file, str(ex))
+    users = map(list, set(map(tuple, users)))
+    roles = map(list, set(map(tuple, roles)))
+    permissions = map(list, set(map(tuple, permissions)))
+    user_roles = map(list, set(map(tuple, user_roles)))
+    role_permissions = map(list, set(map(tuple, role_permissions)))
+    return {"users": users, "roles": roles, "permissions": permissions, "user_roles": user_roles, "role_permissions": role_permissions}
+
+
+def get_db_content(db):
+    db.create_tables()
+    users = db.get_user_table()
+    roles = db.get_role_table()
+    permissions = db.get_resource_table()
+    user_roles = db.get_user_role_table()
+    role_permissions = db.get_role_resource_table()
+    return {"users": users, "roles": roles, "permissions": permissions, "user_roles": user_roles, "role_permissions": role_permissions}
+
+
+def compare_contents(db_content, files_content):
+    update_needed = {"roles":[], "permissions":[]}
+    adding_needed = {"users":[], "roles":[], "permissions":[], "user_roles":[], "role_permissions":[]}
+    for file_user in files_content["users"]:
+        if check_user_value(file_user, db_content["users"]):
+            print "User " + file_user[0] + " is ok"
+        else:
+            print "User " + file_user[0] + " needs to be added"
+            adding_needed["users"].append(file_user)
+
+    for file_role in files_content["roles"]:
+        result = check_role_value(file_role, db_content["roles"])
+        if result == "update":
+            if file_role[2] == "True":
+                file_role[2] = 1
+            if file_role[2] == "False":
+                file_role[2] = 0
+            update_needed["roles"].append(file_role)
+        elif result == "add":
+            print "Role " + file_role[0] + " needs to be added"
+            if file_role[2] == "True":
+                file_role[2] = 1
+            if file_role[2] == "False":
+                file_role[2] = 0
+            adding_needed["roles"].append(file_role)
+            if file_role[2] == 1:
+                adding_needed["role_permissions"].append([file_role[0],"am/users/keys","POST"])
+                adding_needed["role_permissions"].append([file_role[0],"am/users/keys","DELETE"])
+                print "am/users/keys permissions also needs to be added for role " + file_role[0]
+        else:
+            print "Role " + file_role[0] + " is ok"
+
+    for file_permission in files_content["permissions"]:
+        result = check_permission_value(file_permission,db_content["permissions"])
+        if result == "update":
+            print "Permission " + file_permission[0] + ":" + file_permission[1] + " needs update due to changed description"
+            update_needed["permissions"].append(file_permission)
+        elif result == "add":
+            print "Permission " + file_permission[0] + ":" + file_permission[1] + " needs to be added"
+            adding_needed["permissions"].append(file_permission)
+        else:
+            print "Permission " + file_permission[0] + ":" + file_permission[1] + " is ok"
+
+    for file_user_role in files_content["user_roles"]:
+        if not check_user_role_value(file_user_role, db_content["user_roles"]):
+            adding_needed["user_roles"].append(file_user_role)
+
+    for file_role_permission in files_content["role_permissions"]:
+        if not check_role_permission_value(file_role_permission, db_content["role_permissions"]):
+            adding_needed["role_permissions"].append(file_role_permission)
+
+    return (update_needed, adding_needed)
+
+
+def check_user_value(file_content, db_content):
+    for db_user in db_content:
+        if file_content[0] == db_user["name"]:
+            return True
+    return False
+
+
+def check_permission_value(file_content, db_content):
+    for db_permission in db_content:
+        if file_content[0] == db_permission["path"] and file_content[1] == db_permission["op"]:
+            if file_content[2] == db_permission["desc"]:
+                return "ok"
+            else:
+                return "update"
+    return "add"
+
+
+def check_role_permission_value(file_content, db_content):
+    for db_role_permission in db_content:
+        if file_content[0] == db_role_permission["name"] and file_content[1] == db_role_permission["path"] and file_content[2] == db_role_permission["op"]:
+            print "Role_permission " + file_content[0] + ":" + file_content[1] + ":" + file_content[2] + " is ok"
+            return True
+    print "Role_permission " + file_content[0] + ":" + file_content[1] + ":" + file_content[2] + " needs to be added"
+    return False
+
+
+def check_user_role_value(file_content, db_content):
+    for db_user_role in db_content:
+        if file_content[0] == db_user_role["user_name"] and file_content[1] == db_user_role["role_name"]:
+            print "User_role " + file_content[0] + ":" + file_content[1] + " is ok"
+            return True
+    print "User_role " + file_content[0] + ":" + file_content[1] + " needs to be added"
+    return False
+
+
+def check_role_value(file_content, db_content):
+    for db_role in db_content:
+        if file_content[0] == db_role["name"]:
+            if file_content[1] != db_role["desc"]:
+                print "Role " + file_content[0] + " needs update due to changed description"
+                return "update"
+            if file_content[2] != str(db_role["is_chroot"]):
+                print "Role " + file_content[0] + " needs update due to changed is_chroot"
+                return "update"
+            return "ok"
+    return "add"
+
+
+def update_tables(db, update_needed):
+    try:
+        for row in update_needed["roles"]:
+            db.set_role_param(row[0],row[1],row[2])
+            print "Role {} updated".format(row[0])
+        for row in update_needed["permissions"]:
+            db.update_resource(row[0],row[1],row[2])
+            print "Permission {0}:{1} updated".format(row[0], row[1])
+    except Exception as ex:
+        print ex
+        return False
+    return True
+
+
+def add_into_tables(db, adding_needed, config):
+    try:
+        keystone = make_keystone_auth(config)
+        for row in adding_needed["users"]:
+            uuid = get_resource_id(keystone, "users", row[0])
+            create_db_user(db, uuid, row[0])
+        for row in adding_needed["roles"]:
+            try:
+                role_id = keystone.roles.create(row[0])
+                print "Role {} created in Keystone".format(row[0])
+            except Conflict as ex:
+                print "Role {} already in Keystone".format(row[0])
+            db.create_role(row[0],row[1],row[2])
+            print "Role {} created in DB".format(row[0])
+        for row in adding_needed["permissions"]:
+            db.create_resource(row[0],row[1],row[2])
+            print "Permission {} created in DB".format(row[0])
+        for row in adding_needed["user_roles"]:
+            try:
+                project_id = get_resource_id(keystone, "projects", "{{ am_project_name }}")
+                role_id = get_resource_id(keystone, "roles", row[1])
+                uuid = db.get_user_uuid(row[0])
+                if row[1] == "infrastructure_admin":
+                    admin_project_id = get_resource_id(keystone, "projects", "admin")
+                    admin_role_id = get_resource_id(keystone, "roles", "admin")
+                    heat_role_id = get_resource_id(keystone, "roles", "heat_stack_owner")
+                    keystone.roles.grant(admin_role_id, user=uuid, project=admin_project_id)
+                    keystone.roles.grant(heat_role_id, user=uuid, project=admin_project_id)
+                keystone.roles.grant(role_id, user=uuid, project=project_id)
+                print "Role {} added to user {} in Keystone".format(row[1], row[0])
+            except Conflict as ex:
+                print "Role {} already at user {} in Keystone".format(row[1], row[0])
+            db.add_user_role(uuid, row[1])
+            print "Role {0} added to user {1} in DB".format(row[1], row[0])
+        for row in adding_needed["role_permissions"]:
+            db.add_resource_to_role(row[0], row[1], row[2])
+            print "Permission {0}:{1} added to role {2} in DB".format(row[1], row[2], row[0])
+    except Exception as ex:
+        print ex
+        print type(ex)
+        return False
+    return True
+
+
+def create_db_user(db, uuid, name):
+    if name == "{{ infrastructure_admin_user_name }}" or name == "admin":
+        db.create_user(uuid, name)
+    else:
+        db.create_user(uuid, name, service=True)
+    print "User {} created in DB".format(name)
+
+
+def get_resource_id(keystone, resource_type, resource_name):
+    res_type = getattr(keystone,resource_type)
+    resource = utils.find_resource(res_type, resource_name)
+    return resource.id
+
+
+def make_keystone_auth(config):
+    auth = v3.Password(
+                       auth_url="{{ keystone_service_internalurl }}",
+                       username="{{ keystone_admin_user_name }}",
+                       password="{{ keystone_auth_admin_password }}",
+                       project_name="{{ keystone_admin_tenant_name }}",
+                       project_domain_id="{{ am_project_domain }}",
+                       user_domain_id="{{ am_project_domain }}")
+    sess = session.Session(auth=auth)
+    keystone = client.Client(session=sess)
+    print "+++ Keystone authentication OK"
+    return keystone
+
+
+def main():
+    config = get_config()
+    logger = set_logger()
+    logger.info("logger set")
+    db = AMDatabase(db_name=config["DB"]["name"], db_addr=config["DB"]["addr"],
+                     db_port=int(config["DB"]["port"]), db_user=config["DB"]["user"],
+                     db_pwd=config["DB"]["pwd"], logger=logger, management_mode=True)
+    db.connect()
+    thime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
+    print "*** Start time " + thime + " ***"
+    print "+++ Connection to database successful"
+    db_content = get_db_content(db)
+    print "+++ DB dump acquired"
+    files_content = read_files()
+    print "+++ Value files read"
+    update_needed, adding_needed = compare_contents(db_content, files_content)
+    print "+++ Comparation done"
+    result = update_tables(db, update_needed)
+    if result:
+        print "+++ Updating tables completed"
+    else:
+        print "--- Problem during updating tables"
+    result = add_into_tables(db, adding_needed, config)
+    if result:
+        print "+++ Adding to tables completed"
+    else:
+        print "--- Problem during table additions"
+    db.close()
+    print "+++ Aaand done"
+    thime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
+    print "*** End time " + thime + " ***"
+    close_logger_handlers(logger)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/roles/access-management/templates/keystone_users_patch.sh.j2 b/roles/access-management/templates/keystone_users_patch.sh.j2
new file mode 100644 (file)
index 0000000..1a14767
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+result=$(\
+curl -i \
+  -H "Content-Type: application/json" \
+  -d '
+{ "auth": {
+    "identity": {
+      "methods": ["password"],
+      "password": {
+        "user": {
+          "name": "{{ infrastructure_admin_user_name }}",
+          "domain": { "id": "{{ am_project_domain }}" },
+          "password": "{{ infrastructure_admin_password }}"
+        }
+      }
+    },
+    "scope": {
+      "project": {
+        "name": "{{ am_project_name }}",
+        "domain": { "id": "{{ am_project_domain }}" }
+      }
+    }
+  }
+}' \
+  -X POST "{{ keystone_service_internalurl }}/auth/tokens" |grep X-Subject-Token | cut -c 17-); echo $result
+
+{% for i in keystone_uuids.results %}
+curl -i \
+  -H "X-Auth-Token:${result::-1}" \
+  -H "Content-Type: application/json" \
+  -d '
+{
+    "user": {
+        "options": {
+            "ignore_change_password_upon_first_use": true,
+            "ignore_lockout_failure_attempts": true,
+            "ignore_password_expiry": true
+        }
+    }
+}' \
+  -X PATCH "{{ keystone_service_internalurl }}/users/{{ i.ansible_facts.keystone_facts.id }}";echo
+{% endfor %}
diff --git a/roles/account-hardenning/tasks/main.yml b/roles/account-hardenning/tasks/main.yml
new file mode 100644 (file)
index 0000000..6aba847
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Remove unused accounts
+  user:
+    name: "{{ item }}"
+    state: absent
+  with_list:
+    - bin
+    - daemon
+    - ftp
+    - games
+    - halt
+    - lp
+    - mail
+    - operator
+    - shutdown
+    - sync
diff --git a/roles/allocate_cpu_cores/defaults/main.yml b/roles/allocate_cpu_cores/defaults/main.yml
new file mode 100644 (file)
index 0000000..00d0741
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# Number of platform CPUs to allocate per service by default.
+ncir_default_platform_cpus:
+  default:
+    controller:
+      own: 1
+      shared: 1
+    storage:
+      own: 3
+      shared: 1
+    compute:
+      shared: 1
+    caas_master:
+      own: 2
+    caas_worker:
+      own: 1
+  single:
+    controller:
+      own: 1
+      shared: 1
+    compute:
+      shared: 1
+    caas_master:
+      own: 1
+    caas_worker:
+      own: 1
+  virtual:
+    controller:
+      shared: 2
+    storage:
+      shared: 2
+    compute:
+      shared: 1
+    caas_master:
+      shared: 2
+    caas_worker:
+      shared: 1
+
+caas_service_profiles:
+  - caas_master
+  - caas_worker
+
+allocation_fact_file: "/etc/ansible/facts.d/ncir_cpu_allocation.fact"
+
+cpu_set_mapping:
+  ovs_dpdk:
+    opt: ovs_dpdk_cpus
+  platform:
+    opt: platform_cpus
+  caas_exclusive:
+    opt: exclusive_pool_percentage
+  caas_shared:
+    opt: shared_pool_percentage
diff --git a/roles/allocate_cpu_cores/filter_plugins/helpers.py b/roles/allocate_cpu_cores/filter_plugins/helpers.py
new file mode 100644 (file)
index 0000000..64f08aa
--- /dev/null
@@ -0,0 +1,150 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 itertools
+import re
+
+from ansible.errors import AnsibleError
+
+
+def cpulist_to_set(cl):
+    r = set()
+    for e in cl.split(','):
+        if '-' in e:
+            p = e.split('-')
+        else:
+            p = [e, e]
+        r.update(map(str, range(int(p[0]), int(p[1]) + 1)))
+    return list(r)
+
+
+def set_to_cpulist(cs):
+    r = []
+    for k, g in itertools.groupby(enumerate(sorted(cs, key=int)), lambda (i, v): int(v) - i):
+        t = list(g)
+        if len(t) == 1:
+            r.append(str(t[0][1]))
+        else:
+            r.append('-'.join([str(t[0][1]), str(t[-1][1])]))
+    return ','.join(r)
+
+
+def _validate_node(topo, node, count):
+    if node not in topo:
+        raise AnsibleError("Unknown NUMA node '%s' (known nodes: %s)"
+                           % (node, ', '.join(topo.keys())))
+    if len(topo[node]) < count:
+        raise AnsibleError("Cannot allocate %d CPUs in NUMA node '%s' (%d CPUs available)"
+                           % (count, node, len(topo[node])))
+
+
+def cpu_topology_alloc(topo, req, where='head'):
+    r = set()
+    for node, count in req.iteritems():
+        _validate_node(topo, node, count)
+        if count == 0:
+            continue
+        if where == 'tail':
+            for i in topo[node][-count:]:
+                r.update(i)
+        else:
+            for i in topo[node][:count]:
+                r.update(i)
+    return sorted(r)
+
+
+def cpu_topology_trim(topo, req, where='head'):
+    for node, count in req.iteritems():
+        _validate_node(topo, node, count)
+        if count == 0:
+            continue
+        if where == 'tail':
+            topo[node] = topo[node][:-count]
+        else:
+            topo[node] = topo[node][count:]
+    return topo
+
+
+def _natural_sort(k):
+    return [int(x) if x.isdigit() else x for x in re.split(r'([0-9]+)', k)]
+
+
+def cpu_topology_defaults(topo, srv, req, is_virtual=False, is_single=False):
+    own = 0
+    shared = 0
+
+    if is_virtual:
+        req = req['virtual']
+    elif is_single:
+        req = req['single']
+    else:
+        req = req['default']
+
+    for s in srv:
+        if s not in req:
+            continue
+        if 'own' in req[s]:
+            own += req[s]['own']
+        if 'shared' in req[s]:
+            shared = max(shared, req[s]['shared'])
+
+    platform = own + shared
+    if platform == 0:
+        platform = 1
+
+    nodes = [{'node': n, 'count': len(topo[n])} for n in sorted(topo, key=_natural_sort)]
+
+    r = {}
+
+    while platform > 0:
+        prev = platform
+        for i in nodes:
+            if i['count'] <= 0:
+                continue
+            if i['node'] not in r:
+                r[i['node']] = 0
+            r[i['node']] += 1
+            i['count'] -= 1
+            platform -= 1
+            if platform <= 0:
+                break
+        if platform == prev:
+            break
+
+    return r
+
+
+def get_cpu_count_by_percent(topo, percent):
+    return {
+        n: int(_amount_with_minimum(len(topo[n]), float(percent)))
+        for n in sorted(topo, key=_natural_sort)}
+
+
+def _amount_with_minimum(whole, percent):
+    amount = (whole * percent) / 100.0
+    return amount if 0 < int(amount) else 1
+
+
+class FilterModule(object):
+    def filters(self):
+        return {
+            'cpulist_to_set': cpulist_to_set,
+            'set_to_cpulist': set_to_cpulist,
+            'cpu_topology_alloc': cpu_topology_alloc,
+            'cpu_topology_trim': cpu_topology_trim,
+            'cpu_topology_defaults': cpu_topology_defaults,
+            'get_cpu_count_by_percent': get_cpu_count_by_percent,
+        }
diff --git a/roles/allocate_cpu_cores/library/get_cpu_topology.py b/roles/allocate_cpu_cores/library/get_cpu_topology.py
new file mode 100644 (file)
index 0000000..bfec347
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 glob
+
+from ansible.module_utils.basic import *
+
+def mask2list(path):
+    r = set()
+
+    with open(path, 'r') as f:
+        masks = [int(x, 16) for x in f.read().split(',')]
+
+    masks.reverse()
+
+    i = 0
+    for m in masks:
+        for j in range(32):
+            if m & (1 << j):
+                r.add(i)
+            i += 1
+
+    return sorted(r)
+
+def get_node_cores(nodepath):
+    r = []
+    s = set()
+
+    for cpu in mask2list(nodepath + '/cpumap'):
+        if cpu not in s:
+            v = mask2list(nodepath + '/cpu%d/topology/thread_siblings' % cpu)
+            r.append(v)
+            s.update(v)
+
+    return r
+
+def main():
+    module = AnsibleModule(argument_spec = { 'var': { 'required': True, 'type': 'str' } })
+
+    pattern = '/sys/devices/system/node/node*'
+    r = {}
+
+    for nodepath in glob.glob(pattern):
+        nodeid = nodepath[len(pattern) - 1:]
+        r['numa' + nodeid] = get_node_cores(nodepath)
+
+    module.exit_json(changed = False, ansible_facts = { module.params['var']: r })
+
+if __name__ == '__main__':
+    main()
diff --git a/roles/allocate_cpu_cores/tasks/main.yml b/roles/allocate_cpu_cores/tasks/main.yml
new file mode 100644 (file)
index 0000000..cca66d8
--- /dev/null
@@ -0,0 +1,122 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+- name: Prepare.
+  set_fact:
+    ncir_cpu_remain: []
+    ncir_cpu_sets: {}
+
+- name: Get CPU topology.
+  get_cpu_topology:
+    var: ncir_cpu_topology
+- debug:
+    var: ncir_cpu_topology
+
+- name: Make default performance profile.
+  set_fact:
+    perf_profile: {
+      platform_cpus: "{{ ncir_cpu_topology | cpu_topology_defaults(hosts[hostname]['service_profiles'], ncir_default_platform_cpus, virtual_env, hosts | length < 2) }}"
+    }
+- debug:
+    var: perf_profile
+
+- name: Get performance profile.
+  set_fact:
+    perf_profile: "{{ perf_profile | combine(performance_profiles[hosts[hostname]['performance_profiles'][0]]) }}"
+  when: "'performance_profiles' in hosts[hostname]"
+- debug:
+    var: perf_profile
+
+- name: Make CPU sets.
+  include_tasks: make_cpu_sets.yaml
+  loop_control:
+    loop_var: cpu_set
+  with_items:
+      - { 'name': 'ovs_dpdk', 'opt': "{{ cpu_set_mapping['ovs_dpdk']['opt'] }}", 'where': 'tail' }
+      - { 'name': 'platform', 'opt': "{{ cpu_set_mapping['platform']['opt'] }}", 'where': 'head' }
+  when: "cpu_set.opt in perf_profile"
+
+- name: Initialize VM CPU share.
+  set_fact:
+    vm_share_percent: 100
+
+- name: Set collocated VM CPU set.
+  set_fact:
+    vm_share_percent: "{{ 100 - (perf_profile['caas_cpu_pool_share'] | default(100) | int) }}"
+  when:
+    - "'compute' in hosts[hostname]['service_profiles']"
+    - hosts[hostname]['service_profiles'] | intersect(caas_service_profiles)
+
+- name: Make VM CPU sets.
+  include_tasks: make_cpu_sets.yaml
+  loop_control:
+    loop_var: cpu_set
+  with_items:
+    - { 'name': 'vm', 'request': "{{ ncir_cpu_topology | get_cpu_count_by_percent(vm_share_percent) }}", 'where': 'tail' }
+  when:
+    - "'compute' in hosts[hostname]['service_profiles']"
+
+- name: Calculate CaaS CPU counts
+  set_fact:
+    perf_profile: "{{ perf_profile | combine({ item.key: ncir_cpu_topology | get_cpu_count_by_percent(item.value) }) }}"
+  with_dict: "{{ perf_profile['caas_cpu_pools'] | default({}) }}"
+  when: hosts[hostname]['service_profiles'] | intersect(caas_service_profiles)
+
+- name: Make CaaS CPU sets.
+  include_tasks: make_cpu_sets.yaml
+  loop_control:
+    loop_var: cpu_set
+  with_items:
+    - { 'name': 'caas_exclusive', 'opt': "{{ cpu_set_mapping['caas_exclusive']['opt'] }}", 'where': 'tail' }
+    - { 'name': 'caas_shared',    'opt': "{{ cpu_set_mapping['caas_shared']['opt'] }}",    'where': 'tail' }
+  when:
+    - "cpu_set.opt in perf_profile"
+    - hosts[hostname]['service_profiles'] | intersect(caas_service_profiles)
+
+- name: Make set of remaining CPUs.
+  set_fact:
+    ncir_cpu_remain: "{{ ncir_cpu_remain | union(item) }}"
+  with_items: "{{ ncir_cpu_topology.values() }}"
+- debug:
+    var: ncir_cpu_remain
+
+- name: Allocate remaining CPUs to platform.
+  set_fact:
+    ncir_cpu_sets: "{{ ncir_cpu_sets | combine({ 'platform': ncir_cpu_sets['platform'] | default([]) | union(ncir_cpu_remain) }) }}"
+    ncir_cpu_remain: []
+  when: "ncir_cpu_remain | length > 0"
+
+- debug:
+    var: ncir_cpu_sets
+
+- name: Make sure facts directory exists.
+  file:
+    path: "{{ allocation_fact_file | dirname }}"
+    state: directory
+    mode: 0755
+
+- name: Save CPU allocation.
+  template:
+    src: ncir_cpu_allocation.fact.j2
+    dest: "{{ allocation_fact_file }}"
+  register: cpu_allocation
+
+- name: Refresh facts.
+  setup:
+  when:
+    - cpu_allocation.changed
+    - not skip_facts_reload | default(False)
diff --git a/roles/allocate_cpu_cores/tasks/make_cpu_sets.yaml b/roles/allocate_cpu_cores/tasks/make_cpu_sets.yaml
new file mode 100644 (file)
index 0000000..4bb3816
--- /dev/null
@@ -0,0 +1,27 @@
+---
+# Copyright (C) 2019 Nokia
+
+- name: Set requested CPUs.
+  set_fact:
+    cpu_request: "{% if cpu_set.opt is defined %}{{ perf_profile[cpu_set.opt] }}{% else %}{{ cpu_set.request }}{% endif %}"
+
+- name: Allocate CPU set.
+  set_fact:
+    allocated_cpu_set: "{{ ncir_cpu_topology | cpu_topology_alloc(cpu_request, cpu_set.where) }}"
+
+- name: Append allocated CPU set.
+  set_fact:
+    combined_cpu_set: "{{ allocated_cpu_set | union(ncir_cpu_sets[cpu_set.name] | default([])) | sort }}"
+
+- name: Make CPU set.
+  set_fact:
+    ncir_cpu_sets: "{{ ncir_cpu_sets | combine({ cpu_set.name: combined_cpu_set }) }}"
+    ncir_cpu_topology: "{{ ncir_cpu_topology | cpu_topology_trim(cpu_request, cpu_set.where) }}"
+
+- name: Show created CPU sets.
+  debug:
+    var: ncir_cpu_sets
+
+- name: Show CPU topology after sets creation.
+  debug:
+    var: ncir_cpu_topology
diff --git a/roles/allocate_cpu_cores/templates/ncir_cpu_allocation.fact.j2 b/roles/allocate_cpu_cores/templates/ncir_cpu_allocation.fact.j2
new file mode 100644 (file)
index 0000000..ab31352
--- /dev/null
@@ -0,0 +1,9 @@
+{# Copyright (C) 2018 Nokia #}
+{
+{% for s in ncir_cpu_sets %}
+    "{{ s }}": {
+        "set" : {{ ncir_cpu_sets[s] | sort }},
+        "list": "{{ ncir_cpu_sets[s] | set_to_cpulist }}"
+    }{{ "," if not loop.last else "" }}
+{% endfor %}
+}
diff --git a/roles/ansibleldconfig/README.rst b/roles/ansibleldconfig/README.rst
new file mode 100644 (file)
index 0000000..d39231d
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for running ldconfig
diff --git a/roles/ansibleldconfig/handlers/main.yml b/roles/ansibleldconfig/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/ansibleldconfig/tasks/ldconfig.yml b/roles/ansibleldconfig/tasks/ldconfig.yml
new file mode 100644 (file)
index 0000000..883be2a
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Linux works different ways
+  shell: "sync"
+
+- name: Run ldconfig
+  command: /usr/sbin/ldconfig
diff --git a/roles/ansibleldconfig/tasks/main.yml b/roles/ansibleldconfig/tasks/main.yml
new file mode 100644 (file)
index 0000000..07f6663
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: ldconfig.yml
+  tags:
+      - ldconfig
diff --git a/roles/ansiblesync/handlers/main.yml b/roles/ansiblesync/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/ansiblesync/tasks/main.yml b/roles/ansiblesync/tasks/main.yml
new file mode 100644 (file)
index 0000000..7c0d4b9
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync ansible files the other controllers
+  synchronize:
+    src: "{{ item.src }}"
+    dest: "{{ item.dest }}"
+    compress: no
+    archive: yes
+    recursive: yes
+  when: hostname != installation_controller
+  with_items:
+    - { src: "/etc/openstack_deploy", dest: "/etc/" }
+    - { src: "/etc/ansible/ansible.cfg", dest: "/etc/ansible/ansible.cfg" }
+    - { src: "/etc/userconfig/", dest: "/etc/userconfig/" }
+  tags:
+      - sync_ansible_files
+
+- name: Sync virtual environment specific files to the other controllers
+  synchronize:
+    src: "{{ item.src }}"
+    dest: "{{ item.dest }}"
+    compress: no
+    archive: no
+    perms: yes
+  when:
+    - hostname != installation_controller
+    - virtual_env
+  with_items:
+    - { src: "/etc/userconfig/id_rsa", dest: "/root/.ssh/"}
+  tags:
+      - sync_ansible_files
+
+- name: Set permissions for id_rsa
+  file:
+    path: "/root/.ssh/id_rsa"
+    owner: root
+    group: root
+    mode: 0400
+  when:
+    - hostname != installation_controller
+    - virtual_env
diff --git a/roles/audit/defaults/main.yaml b/roles/audit/defaults/main.yaml
new file mode 100644 (file)
index 0000000..20ca177
--- /dev/null
@@ -0,0 +1,25 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+uid_min: 1000
+log_file_action: ROTATE
+disk_full_action: ROTATE
+space_left_size: 200
+space_left_action: ROTATE
+admin_space_left: 120
+admin_space_left_action: ROTATE
+flush: data
+disk_error_action: SYSLOG
\ No newline at end of file
diff --git a/roles/audit/tasks/main.yaml b/roles/audit/tasks/main.yaml
new file mode 100644 (file)
index 0000000..e4d42d4
--- /dev/null
@@ -0,0 +1,104 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Replace audit rules from template
+  template:
+    src: "{{ item.src }}"
+    dest: "{{ item.dest }}"
+    owner: root
+    group: root
+    mode: 0700
+  with_items:
+    - {src: '10-base-config.rules.j2', dest: '/etc/audit/rules.d/10-base-config.rules'}
+    - {src: '11-loginuid.rules.j2', dest: '/etc/audit/rules.d/11-loginuid.rules'}
+    - {src: '12-filter-users.rules.j2', dest: '/etc/audit/rules.d/12-filter-users.rules'}
+    - {src: '30-stig.rules.j2', dest: '/etc/audit/rules.d/30-stig.rules'}
+    - {src: '31-privileged-gen.rules.j2', dest: '/etc/audit/rules.d/31-privileged-gen.rules'}
+    - {src: '32-power-abuse.rules.j2', dest: '/etc/audit/rules.d/32-power-abuse.rules'}
+    - {src: '33-avoid-flood.rules.j2', dest: '/etc/audit/rules.d/33-avoid-flood.rules'}
+    - {src: '34-failed-actions.rules.j2', dest: '/etc/audit/rules.d/34-failed-actions.rules'}
+    - {src: '35-umount.rules.j2', dest: '/etc/audit/rules.d/35-umount.rules'}
+    - {src: '36-resource-management.rules.j2', dest: '/etc/audit/rules.d/36-resource-management.rules'}
+    - {src: '37-linux-capabilities.rules.j2', dest: '/etc/audit/rules.d/37-linux-capabilities.rules'}
+    - {src: '41-containers.rules.j2', dest: '/etc/audit/rules.d/41-containers.rules'}
+    - {src: '42-injection.rules.j2', dest: '/etc/audit/rules.d/42-injection.rules'}
+    - {src: '43-module-load.rules.j2', dest: '/etc/audit/rules.d/43-module-load.rules'}
+    - {src: '44-certificates.rules.j2', dest: '/etc/audit/rules.d/44-certificates.rules'}
+    - {src: '50-file-changes.rules.j2', dest: '/etc/audit/rules.d/50-file-changes.rules'}
+    - {src: '51-messaging.rules.j2', dest: '/etc/audit/rules.d/51-messaging.rules'}
+    - {src: '52-sandbox.rules.j2', dest: '/etc/audit/rules.d/52-sandbox.rules'}
+    - {src: '53-kernel-parameters.rules.j2', dest: '/etc/audit/rules.d/53-kernel-parameters.rules'}
+    - {src: '99-finalize.rules.j2', dest: '/etc/audit/rules.d/99-finalize.rules'}
+
+- name: Delete original audit rules
+  file:
+    state: absent
+    path: "/etc/audit/rules.d/audit.rules"
+
+- name: Ask the audit log disc size
+  shell: df -BM --output=size,target | grep audit | awk '{print $1}' | tr -d 'M'
+  register: disc_size
+
+- name: Set the num_logs variable default value's
+  set_fact:
+    num_logs: "{{  ((disc_size.stdout|int *0.8)/100)|int  }}"
+    log_file_size: 100
+
+- name: Setting the log_file_size if the audit disk size is huge.
+  when: num_logs|int > 999
+  set_fact:
+    num_logs: 999
+    log_file_size: "{{ ((disc_size.stdout|int *0.8)/999)|int  }}"
+
+- name: Change auditd config
+  lineinfile:
+    path: /etc/audit/auditd.conf
+    regexp: '{{ item.regexp }}'
+    line: '{{ item.line }}'
+  with_items:
+    - regexp: "^[ #]*num_logs"
+      line: "num_logs = {{ num_logs }}"
+    - regexp: "^[ #]*max_log_file "
+      line: "max_log_file = {{ log_file_size }}"
+    - regexp: "^[ #]*max_log_file_action"
+      line: "max_log_file_action = {{ log_file_action }}"
+    - regexp: "^[ #]*disk_full_action"
+      line: "disk_full_action = {{ disk_full_action }}"
+    - regexp: "^[ #]*space_left "
+      line: "space_left = {{ space_left_size }}"
+    - regexp: "^[ #]*space_left_action"
+      line: "space_left_action = {{ space_left_action }}"
+    - regexp: "^[ #]*admin_space_left_action"
+      line: "admin_space_left_action = {{ admin_space_left_action }}"
+    - regexp: "^[ #]*flush"
+      line: "flush = {{ flush }}"
+    - regexp: "^[ #]*disk_error_action"
+      line: "disk_error_action = {{ disk_error_action }}"
+    - regexp: "^[ #]*admin_space_left "
+      line: "admin_space_left = {{ admin_space_left }}"
+
+- name: Restart Auditd service
+  command: service auditd restart
+
+- name: "Add the pam_tally2.so module to the PAM sshd conf 1."
+  lineinfile:
+    path: /etc/pam.d/sshd
+    insertafter: '^auth[\s]*required[\s]*pam_sepermit.so'
+    line: 'auth       required     pam_tally2.so deny={{ host_os.failed_login_attempts | default(5) }} onerr=fail unlock_time={{ host_os.lockout_time | default(300) }}'
+
+- name: "Add the pam_tally2.so module to the PAM sshd conf 2."
+  lineinfile:
+    path: /etc/pam.d/sshd
+    insertafter: '^account[\s]*required[\s]*pam_nologin.so'
+    line: 'account    required     pam_tally2.so'
diff --git a/roles/audit/templates/10-base-config.rules.j2 b/roles/audit/templates/10-base-config.rules.j2
new file mode 100644 (file)
index 0000000..8172358
--- /dev/null
@@ -0,0 +1,15 @@
+## First rule - delete all
+-D
+
+## Increase the buffers to survive stress events.
+## Make this bigger for busy systems
+-b 132000
+
+## This determine how long to wait in burst of events
+#--backlog_wait_time 0
+
+## Set failure mode to syslog
+-f 1
+
+## Generate unlimited audit messages per second
+-r 0
diff --git a/roles/audit/templates/11-loginuid.rules.j2 b/roles/audit/templates/11-loginuid.rules.j2
new file mode 100644 (file)
index 0000000..b4cf8c6
--- /dev/null
@@ -0,0 +1,2 @@
+## Make the loginuid immutable. This prevents tampering with the auid.
+--loginuid-immutable
diff --git a/roles/audit/templates/12-filter-users.rules.j2 b/roles/audit/templates/12-filter-users.rules.j2
new file mode 100644 (file)
index 0000000..28d991a
--- /dev/null
@@ -0,0 +1,3 @@
+## No more rules checked if the user does not have a valid uid or it is a system user
+-a exit,never -F auid=4294967295
+-a exit,never -F auid!=0 -F auid<{{ uid_min }}
diff --git a/roles/audit/templates/30-stig.rules.j2 b/roles/audit/templates/30-stig.rules.j2
new file mode 100644 (file)
index 0000000..14cc06a
--- /dev/null
@@ -0,0 +1,144 @@
+## The purpose of these rules is to meet the stig auditing requirements
+## These rules depends on having 10-base-config.rules & 99-finalize.rules
+## installed.
+
+## NOTE:
+## 1) if this is being used on a 32 bit machine, comment out the b64 lines
+## 2) These rules assume that login under the root account is not allowed.
+## 3) It is also assumed that 1000 represents the first usable user account. To
+##  be sure, look at UID_MIN in /etc/login.defs.
+## IMS uses 500 as the first usable account
+## 4) If these rules generate too much spurious data for your tastes, limit the
+## the syscall file rules with a directory, like -F dir=/etc
+## 5) You can search for the results on the key fields in the rules
+##
+##
+## (GEN002880: CAT II) The IAO will ensure the auditing software can
+## record the following for each audit event: 
+##- Date and time of the event 
+##- Userid that initiated the event 
+##- Type of event 
+##- Success or failure of the event 
+##- For I&A events, the origin of the request (e.g., terminal ID) 
+##- For events that introduce an object into a user's address space, and
+## for object deletion events, the name of the object, and in MLS
+## systems, the object's security level.
+##
+## Things that could affect time
+-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
+-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change
+-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -k time-change
+-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -k time-change
+# Introduced in 2.6.39, commented out because it can make false positives
+#-a always,exit -F arch=b32 -S clock_adjtime -F key=time-change
+#-a always,exit -F arch=b64 -S clock_adjtime -F key=time-change
+-w /etc/localtime -p wa -k time-change
+
+## Things that affect identity
+-w /etc/group -p wa -k identity
+-w /etc/passwd -p wa -k identity
+-w /etc/gshadow -p wa -k identity
+-w /etc/shadow -p wa -k identity
+-w /etc/security/opasswd -p wa -k identity
+
+-a always,exit -F arch=b32 -S setuid -F key=32bit_setuid
+-a always,exit -F arch=b64 -S setuid -F key=64bit_setuid
+-a always,exit -F arch=b32 -S setgid -F key=32bit_setgid
+-a always,exit -F arch=b64 -S setgid -F key=64bit_setgid
+
+## Things that could affect system locale
+-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale
+-a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale
+-w /etc/issue -p wa -k system-locale
+-w /etc/issue.net -p wa -k system-locale
+-w /etc/hosts -p wa -k system-locale
+-w /etc/sysconfig/network -p wa -k system-locale
+-w /etc/sysconfig/network-scripts/ -p wa -k system-locale
+-a always,exit -F dir=/etc/NetworkManager/ -F perm=wa -F key=system-locale
+
+## Things that could affect MAC policy
+-a always,exit -F dir=/etc/selinux/ -F perm=wa -F key=MAC-policy
+-a always,exit -F dir=/usr/share/selinux/ -F perm=wa -F key=MAC-policy
+
+## (GEN002900: CAT III) The IAO will ensure audit files are retained at
+## least one year; systems containing SAMI will be retained for five years.
+##
+## Site action - no action in config files
+
+## (GEN002920: CAT III) The IAO will ensure audit files are backed up
+## no less than weekly onto a different system than the system being
+## audited or backup media. 
+##
+## Can be done with cron script
+
+## (GEN002700: CAT I) (Previously - G095) The SA will ensure audit data
+## files have permissions of 640, or more restrictive.
+##
+## Done automatically by auditd
+
+## (GEN002720-GEN002840: CAT II) (Previously - G100-G106) The SA will
+## configure the auditing system to audit the following events for all
+## users and root:
+##
+## - Logon (unsuccessful and successful) and logout (successful)
+##
+## Handled by pam, sshd, login, and gdm
+## Might also want to watch these files if needing extra information
+-w /var/log/tallylog -p wa -k logins
+-w /var/run/faillock/ -p wa -k logins
+-w /var/log/lastlog -p wa -k logins
+-w /var/log/faillog -p wa -k logins
+-w /etc/login.defs -p wa -k logins
+
+##- Process and session initiation (unsuccessful and successful)
+##
+## The session initiation is audited by pam without any rules needed.
+## Might also want to watch this file if needing extra information
+-w /var/run/utmp -p wa -k session
+-w /var/log/btmp -p wa -k session
+-w /var/log/wtmp -p wa -k session
+
+##- Discretionary access control permission modification (unsuccessful
+## and successful use of chown/chmod)
+-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -S chown -S fchown -S fchownat -S lchown -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -k perm_mod
+-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -S chown -S fchown -S fchownat -S lchown -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -k perm_mod
+
+##- Unauthorized access attempts to files (unsuccessful) 
+-a always,exit -F arch=b64 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F key=access 
+-a always,exit -F arch=b32 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F key=access
+-a always,exit -F arch=b64 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F key=access
+-a always,exit -F arch=b32 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F key=access
+
+##- Use of privileged commands (unsuccessful and successful)
+## use find /bin -type f -perm -04000 2>/dev/null and put all those files in a rule like this
+#-a always,exit -F path=/bin/ping -F perm=x -F key=privileged
+
+##- Use of print command (unsuccessful and successful) 
+
+##- Export to media (successful)
+## You have to mount media before using it. You must disable all automounting
+## so that its done manually in order to get the correct user requesting the
+## export
+-a always,exit -F arch=b64 -S mount -k mounts
+-a always,exit -F arch=b32 -S mount -k mounts
+
+##- System startup and shutdown (unsuccessful and successful)
+
+##- Files and programs deleted by the user (successful and unsuccessful)
+-a always,exit -F arch=b64 -S rmdir -S unlink -S unlinkat -S rename -S renameat -k delete
+-a always,exit -F arch=b32 -S rmdir -S unlink -S unlinkat -S rename -S renameat -k delete
+
+##- All system administration actions 
+##- All security personnel actions
+## 
+## Look for pam_tty_audit and add it to your login entry point's pam configs.
+## If that is not found, use sudo which should be patched to record its
+## commands to the audit system. Do not allow unrestricted root shells or
+## sudo cannot record the action.
+-w /etc/sudoers -p wa -k actions
+-w /etc/sudoers.d/ -p wa -k actions
+
+## (GEN002860: CAT II) (Previously - G674) The SA and/or IAO will
+##ensure old audit logs are closed and new audit logs are started daily.
+##
+## Site action. Can be assisted by a cron job
diff --git a/roles/audit/templates/31-privileged-gen.rules.j2 b/roles/audit/templates/31-privileged-gen.rules.j2
new file mode 100644 (file)
index 0000000..7433add
--- /dev/null
@@ -0,0 +1,31 @@
+## Generated privilaged rules
+-a always,exit -F path=/usr/bin/chage -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/gpasswd -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/newgrp -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/mount -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/su -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/sudo -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/umount -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/at -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/chfn -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/chsh -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/passwd -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/pkexec -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/crontab -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/fusermount -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/pam_timestamp_check -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/unix_chkpwd -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/mount.nfs -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/usernetctl -F perm=x -k privileged
+-a always,exit -F path=/usr/bin/userhelper -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/semanage -F perm=x -k privileged-priv_change 
+-a always,exit -F path=/usr/sbin/setsebool -F perm=x -k privileged-priv_change
+-a always,exit -F path=/usr/bin/chcon -F perm=x -k privileged-priv_change
+-a always,exit -F path=/usr/sbin/restorecon -F perm=x -k privileged-priv_change
+-a always,exit -F path=/usr/bin/sudoedit -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/postdrop -F perm=x -k privileged
+-a always,exit -F path=/usr/sbin/postqueue -F perm=x -k privileged
+-a always,exit -F path=/usr/libexec/qemu-bridge-helper -F perm=x -k privileged
+-a always,exit -F path=/usr/libexec/dbus-1/dbus-daemon-launch-helper -F perm=x -k privileged
+-a always,exit -F path=/usr/lib/polkit-1/polkit-agent-helper-1 -F perm=x -k privileged
+-a always,exit -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -k privileged
diff --git a/roles/audit/templates/32-power-abuse.rules.j2 b/roles/audit/templates/32-power-abuse.rules.j2
new file mode 100644 (file)
index 0000000..9e02835
--- /dev/null
@@ -0,0 +1,3 @@
+## The purpose of this rule is to detect when an admin may be abusing power
+## by looking in user's home dir.
+-a always,exit -F dir=/home -F uid=0 -C auid!=obj_uid -F key=admin-abuse
diff --git a/roles/audit/templates/33-avoid-flood.rules.j2 b/roles/audit/templates/33-avoid-flood.rules.j2
new file mode 100644 (file)
index 0000000..ae87739
--- /dev/null
@@ -0,0 +1,4 @@
+## The purpose of this rule is to exclude reports that flooding normally the audit
+-a never,exit -F arch=b32 -S setsockopt
+-a never,exit -F arch=b64 -S setsockopt
+-a always,exclude -F msgtype=netfilter_cfg
diff --git a/roles/audit/templates/34-failed-actions.rules.j2 b/roles/audit/templates/34-failed-actions.rules.j2
new file mode 100644 (file)
index 0000000..e478a80
--- /dev/null
@@ -0,0 +1,5 @@
+## failed actions
+-a always,exit -F arch=b64 -S all -F exit=-EPERM -F key=access_denied
+-a always,exit -F arch=b64 -S all -F exit=-EACCES -F key=access_denied
+-a always,exit -F arch=b32 -S all -F exit=-EPERM -F key=access_denied
+-a always,exit -F arch=b32 -S all -F exit=-EACCES -F key=access_denied
diff --git a/roles/audit/templates/35-umount.rules.j2 b/roles/audit/templates/35-umount.rules.j2
new file mode 100644 (file)
index 0000000..74e46cf
--- /dev/null
@@ -0,0 +1,4 @@
+## umount
+-a always,exit -F arch=b32 -S umount -F key=32bit_umount
+-a always,exit -F arch=b32 -S umount2 -F key=32bit_umount2
+-a always,exit -F arch=b64 -S umount2 -F key=64bit_umount2
diff --git a/roles/audit/templates/36-resource-management.rules.j2 b/roles/audit/templates/36-resource-management.rules.j2
new file mode 100644 (file)
index 0000000..787324c
--- /dev/null
@@ -0,0 +1,11 @@
+## resource management
+-a always,exit -F arch=b32 -S modify_ldt -F key=32bit_modify_ldt
+-a always,exit -F arch=b64 -S modify_ldt -F key=64bit_modify_ldt
+-a always,exit -F arch=b32 -S move_pages -F key=32bit_move_pages
+-a always,exit -F arch=b64 -S move_pages -F key=64bit_move_pages
+-a always,exit -F arch=b32 -S set_mempolicy -F key=32bit_set_mempolicy
+-a always,exit -F arch=b64 -S set_mempolicy -F key=64bit_set_mempolicy
+-a always,exit -F arch=b32 -S swapoff -F key=32bit_swapoff
+-a always,exit -F arch=b64 -S swapoff -F key=64bit_swapoff
+-a always,exit -F arch=b32 -S reboot -F key=32bit_reboot
+-a always,exit -F arch=b64 -S reboot -F key=64bit_reboot
diff --git a/roles/audit/templates/37-linux-capabilities.rules.j2 b/roles/audit/templates/37-linux-capabilities.rules.j2
new file mode 100644 (file)
index 0000000..818deeb
--- /dev/null
@@ -0,0 +1,3 @@
+## linux capabilities
+-a always,exit -F arch=b32 -S capset -F key=32bit_capset
+-a always,exit -F arch=b64 -S capset -F key=64bit_capset
diff --git a/roles/audit/templates/41-containers.rules.j2 b/roles/audit/templates/41-containers.rules.j2
new file mode 100644 (file)
index 0000000..4b3f18b
--- /dev/null
@@ -0,0 +1,20 @@
+## Optional - log container creation 
+## Use these rules if you want to log container events
+## watch for container creation
+-a always,exit -F arch=b32 -S clone -F a0&0x7C020000 -F key=container-create
+-a always,exit -F arch=b64 -S clone -F a0&0x7C020000 -F key=container-create
+-w /etc/docker -p wa -k docker
+-w /etc/sysconfig/docker-registries -p wa -k docker
+-w /etc/sysconfig/docker-storage -p wa -k docker
+-w /etc/sysconfig/docker-proxy -p wa -k docker
+-w /usr/bin/docker -k docker
+-w /usr/lib/systemd/system/docker.service -p wa -k docker
+-w /var/run/docker.sock -p wa -k docker
+-w /usr/lib/systemd/system/kubelet.service -p wa -k kubelet
+-w /etc/kubernetes/ -p wa -k kubelet
+-w /var/log/audit/kube_apiserver/ -k container-audit
+#-w /var/lib/docker/manifests -p wa -k docker
+
+## watch for containers that may change their configuration
+-a always,exit -F arch=b32 -S unshare,setns -F key=container-config
+-a always,exit -F arch=b64 -S unshare,setns -F key=container-config
diff --git a/roles/audit/templates/42-injection.rules.j2 b/roles/audit/templates/42-injection.rules.j2
new file mode 100644 (file)
index 0000000..ca2b423
--- /dev/null
@@ -0,0 +1,32 @@
+## These rules watch for code injection by the ptrace facility.
+## This could indicate someone trying to do something bad or
+## just debugging
+
+#-a always,exit -F arch=b32 -S ptrace -F key=tracing
+#-a always,exit -F arch=b64 -S ptrace -F key=tracing
+-a always,exit -F arch=b32 -S ptrace -F a0=0x4 -F key=code-injection
+-a always,exit -F arch=b64 -S ptrace -F a0=0x4 -F key=code-injection
+-a always,exit -F arch=b32 -S ptrace -F a0=0x5 -F key=data-injection
+-a always,exit -F arch=b64 -S ptrace -F a0=0x5 -F key=data-injection
+-a always,exit -F arch=b32 -S ptrace -F a0=0x6 -F key=register-injection
+-a always,exit -F arch=b64 -S ptrace -F a0=0x6 -F key=register-injection
+-a always,exit -F arch=b64 -S ptrace -F key=64bit_ptrace
+-a always,exit -F arch=b32 -S ptrace -F key=32bit_ptrace
+-a always,exit -F arch=b32 -S tgkill -F key=32bit_tgkill
+-a always,exit -F arch=b64 -S tgkill -F key=64bit_tgkill
+-a always,exit -F arch=b32 -S tkill -F key=32bit_tkill
+-a always,exit -F arch=b64 -S tkill -F key=64bit_tkill
+-a always,exit -F arch=b32 -S kill -F key=32bit_kill
+-a always,exit -F arch=b64 -S kill -F key=64bit_kill
+-a always,exit -F arch=b32 -S prlimit64 -F key=32bit_prlimit64
+-a always,exit -F arch=b64 -S prlimit64 -F key=64bit_prlimit64
+-a always,exit -F arch=b32 -S unshare -F key=32bit_unshare
+-a always,exit -F arch=b64 -S unshare -F key=64bit_unshare
+-a always,exit -F arch=b32 -S set_thread_area -F key=32bit_set_thread_area
+-a always,exit -F arch=b64 -S set_thread_area -F key=64bit_set_thread_area
+-a always,exit -F arch=b32 -S sched_setattr -F key=32bit_sched_setattr
+-a always,exit -F arch=b64 -S sched_setattr -F key=64bit_sched_setattr
+-a always,exit -F arch=b32 -S pivot_root -F key=32bit_pivot_root
+-a always,exit -F arch=b64 -S pivot_root -F key=64bit_pivot_root
+-a always,exit -F arch=b32 -S setns -F key=32bit_setns
+-a always,exit -F arch=b64 -S setns -F key=64bit_setns
diff --git a/roles/audit/templates/43-module-load.rules.j2 b/roles/audit/templates/43-module-load.rules.j2
new file mode 100644 (file)
index 0000000..8c266f5
--- /dev/null
@@ -0,0 +1,6 @@
+## These rules watch for kernel module insertion
+-w /usr/sbin/insmod -p x -k modules
+-w /usr/sbin/rmmod -p x -k modules
+-w /usr/sbin/modprobe -p x -k modules
+-a always,exit -F arch=b64 -S init_module -S delete_module -S create_module -S finit_module -S kexec_file_load -S kexec_load -k modules
+-a always,exit -F arch=b32 -S init_module -S delete_module -S create_module -S finit_module -k modules
diff --git a/roles/audit/templates/44-certificates.rules.j2 b/roles/audit/templates/44-certificates.rules.j2
new file mode 100644 (file)
index 0000000..97e2fad
--- /dev/null
@@ -0,0 +1,3 @@
+## Check certificates
+-a always,exit -F arch=b32 -S add_key -F key=32bit_add_key
+-a always,exit -F arch=b64 -S add_key -F key=64bit_add_key
diff --git a/roles/audit/templates/50-file-changes.rules.j2 b/roles/audit/templates/50-file-changes.rules.j2
new file mode 100644 (file)
index 0000000..af0ca75
--- /dev/null
@@ -0,0 +1,22 @@
+## file changes
+-w /boot/ -p rwxa -k dir_boot
+-w /opt/ -p aw -k dir_opt
+-w /etc/ -p rwa -k dir_etc
+-w /usr/bin -p aw -k usr-bin
+-w /usr/sbin -p aw -k usr-sbin
+-w /usr/libexec -p aw -k usr-libexex
+-w /usr/local -p rwxa -k usr-local
+-w /mnt/symptomreport/ -p awr -k symptomreport
+-w /usr/lib -p aw -k usr-lib
+-w /usr/lib64 -p aw -k usr-lib64
+-w /var/log/audit/ -k audit-logs
+-w /var/log/sudo.log -p wa -k actions
+-a always,exit -F arch=b64 -S epoll_wait_old -F key=64bit_epoll_wait_old
+-a always,exit -F arch=b32 -S inotify_add_watch -F key=32bit_inotify_add_watch
+-a always,exit -F arch=b64 -S inotify_add_watch -F key=64bit_inotify_add_watch
+-a always,exit -F arch=b32 -S inotify_init -F key=32bit_inotify_init
+-a always,exit -F arch=b64 -S inotify_init -F key=64bit_inotify_init
+-a always,exit -F arch=b32 -S inotify_init1 -F key=32bit_inotify_init1
+-a always,exit -F arch=b64 -S inotify_init1 -F key=64bit_inotify_init1
+-a always,exit -F arch=b32 -S inotify_rm_watch -F key=32bit_inotify_rm_watch
+-a always,exit -F arch=b64 -S inotify_rm_watch -F key=64bit_inotify_rm_watch
diff --git a/roles/audit/templates/51-messaging.rules.j2 b/roles/audit/templates/51-messaging.rules.j2
new file mode 100644 (file)
index 0000000..a58491e
--- /dev/null
@@ -0,0 +1,9 @@
+## messaging and messaging queues
+-a always,exit -F arch=b32 -S mq_open -F key=32bit_mq_open
+-a always,exit -F arch=b64 -S mq_open -F key=64bit_mq_open
+-a always,exit -F arch=b32 -S mq_unlink -F key=32bit_mq_unlink
+-a always,exit -F arch=b64 -S mq_unlink -F key=64bit_mq_unlink
+-a always,exit -F arch=b32 -S bpf -F key=32bit_bpf
+-a always,exit -F arch=b64 -S bpf -F key=64bit_bpf
+-a always,exit -F arch=b32 -S vmsplice -F key=32bit_vmsplice
+-a always,exit -F arch=b64 -S vmsplice -F key=64bit_vmsplice
diff --git a/roles/audit/templates/52-sandbox.rules.j2 b/roles/audit/templates/52-sandbox.rules.j2
new file mode 100644 (file)
index 0000000..54e05d6
--- /dev/null
@@ -0,0 +1,3 @@
+## sandbox
+-a always,exit -F arch=b32 -S seccomp -F key=32bit_seccomp
+-a always,exit -F arch=b64 -S seccomp -F key=64bit_seccomp
diff --git a/roles/audit/templates/53-kernel-parameters.rules.j2 b/roles/audit/templates/53-kernel-parameters.rules.j2
new file mode 100644 (file)
index 0000000..ee1c4fc
--- /dev/null
@@ -0,0 +1,3 @@
+## reading kernel parameters
+-a always,exit -F arch=b32 -S _sysctl -F key=32bit__sysctl
+-a always,exit -F arch=b64 -S _sysctl -F key=64bit__sysctl
diff --git a/roles/audit/templates/99-finalize.rules.j2 b/roles/audit/templates/99-finalize.rules.j2
new file mode 100644 (file)
index 0000000..bc0fd92
--- /dev/null
@@ -0,0 +1,4 @@
+## Make the configuration immutable - reboot is required to change audit rules
+#-e 2
+## Temporarily the value is set to 1 until the upgrade issue will be solved.
+-e 1
diff --git a/roles/baremetal_interface_config/README.rst b/roles/baremetal_interface_config/README.rst
new file mode 100644 (file)
index 0000000..0822467
--- /dev/null
@@ -0,0 +1 @@
+Contains ansible role modules to run os-net-config, and configure network interfaces on target nodes.
diff --git a/roles/baremetal_interface_config/defaults/main.yml b/roles/baremetal_interface_config/defaults/main.yml
new file mode 100644 (file)
index 0000000..43da92f
--- /dev/null
@@ -0,0 +1,18 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+debug: True
+provider_network_type: []
diff --git a/roles/baremetal_interface_config/tasks/main.yml b/roles/baremetal_interface_config/tasks/main.yml
new file mode 100644 (file)
index 0000000..099c943
--- /dev/null
@@ -0,0 +1,73 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Setup hostname
+  hostname:
+    name: "{{ physical_host }}"
+
+- name: Updating the facts due to hostname change
+  setup:
+
+- set_fact:
+    host_network_profile_name: "{{hosts[ansible_hostname]['network_profiles']}}"
+
+- set_fact:
+    provider_network_type: "{{network_profiles[host_network_profile_name[0]]['provider_network_interfaces']|json_query('*.type')}}"
+  when: "'provider_network_interfaces' in network_profiles[host_network_profile_name[0]]"
+
+- set_fact:
+    os_net_config_options: "--detailed-exit-codes -v -c /etc/os-net-config/config.json"
+  when:
+    - hostname != installation_controller
+
+- set_fact:
+    os_net_config_options: "--no-activate --detailed-exit-codes -v -c /etc/os-net-config/config.json"
+  when:
+    - hostname == installation_controller
+    - "'ovs-dpdk' in provider_network_type"
+
+- set_fact:
+    os_net_config_options: "--detailed-exit-codes -v -c /etc/os-net-config/config.json"
+  when:
+    - hostname == installation_controller
+    - "'ovs-dpdk' not in provider_network_type"
+
+- name: Enable network service
+  service:
+    name: 'network.service'
+    enabled: "yes"
+
+- name: Create /etc/os-net-config/config.json file
+  vars:
+    config_phase: "{{ lookup('env','CONFIG_PHASE') }}"
+  template:
+    src: "os_net_config.j2"
+    dest: "/etc/os-net-config/config.json"
+    owner: "root"
+    mode: "0440"
+
+- name: Run os-net-config command
+  command: "os-net-config {{ os_net_config_options }}"
+  register: os_net_config_result
+  failed_when: not (os_net_config_result.rc == 0 or os_net_config_result.rc == 2)
+  changed_when: os_net_config_result.rc == 2
+
+- debug: var=os_net_config_result.stderr_lines
+  when: os_net_config_result.rc == 2
+
+- name: Updating the facts due to net changes
+  setup:
+  when: os_net_config_result.rc != 0
diff --git a/roles/baremetal_interface_config/templates/os_net_config.j2 b/roles/baremetal_interface_config/templates/os_net_config.j2
new file mode 100644 (file)
index 0000000..11c0d74
--- /dev/null
@@ -0,0 +1,511 @@
+{#
+This file is written with conditional check and for loop based indentation.
+It improved code readability. The output json is not pretty. Run cat <output.json> | python -m json.tool
+for pretty printing the same.
+#}
+
+{%- set CLOUD_TENANT = 'cloud_tenant' %}
+{%- set VXLAN_HDR_LEN = 50 %}
+
+{#- initialize some variables -#}
+{%- set host_networking = hostvars[ansible_hostname]['networking'] %}
+{%- if 'mtu' in host_networking %}
+    {%- set default_mtu = host_networking['mtu'] %}
+{%- else %}
+    {%- set default_mtu = 1500 %}
+{%- endif %}
+{%- set sriov_mtu = 9000 %}
+{%- set max_mtu = 9000 %}
+{%- set host_network_profiles_list = hosts[ansible_hostname]['network_profiles'] %}
+{%- set host_network_profile_value = hostvars[ansible_hostname]['network_profiles'][host_network_profiles_list[0]] %}
+{%- set host_interface_net_mapping = host_network_profile_value['interface_net_mapping'] %}
+{%- if 'bonding_interfaces' in host_network_profile_value %}
+    {%- set host_bonding_interfaces = host_network_profile_value['bonding_interfaces'] %}
+{%- else %}
+    {%- set host_bonding_interfaces = {} %}
+{%- endif %}
+{%- set single_nic_setup = False %}
+{%- if 'provider_network_interfaces' in host_network_profile_value %}
+    {%- set host_provider_network_interfaces = host_network_profile_value['provider_network_interfaces'] %}
+    {%- set dpdk_in_use = ((host_provider_network_interfaces.itervalues()|first).type == 'ovs-dpdk') %}
+
+    {%- if host_interface_net_mapping|length == 1 and host_provider_network_interfaces|length == 1 %}
+        {%- if host_interface_net_mapping.keys()[0] == host_provider_network_interfaces.keys()[0] %}
+            {%- set single_nic_setup = True %}
+            {%- if CLOUD_TENANT in host_networking.keys() %}
+                {%- set mtu = default_mtu %}
+                {%- if 'mtu' in host_networking[CLOUD_TENANT] %}
+                    {%- set mtu = host_networking[CLOUD_TENANT]['mtu'] %}
+                {%- endif %}
+                {%- set mtu = mtu + VXLAN_HDR_LEN %}
+                {%- if mtu > max_mtu %}
+                    {%- set max_mtu = mtu %}
+                {%- endif %}
+            {%- endif %}
+        {%-endif %}
+    {%-endif %}
+
+    {#- make a list of ixgbe devices, needed in ovs-dpdk configuration -#}
+    {%- set ixgbedevs = [] %}
+    {%- for key in hostvars[ansible_hostname].keys() %}
+        {%- if key.startswith('ansible_') %}
+            {%- set value = hostvars[ansible_hostname][key] %}
+            {%- if value is iterable and 'device' in value and 'module' in value and value['module'] == 'ixgbe' %}
+                {%- if ixgbedevs.append(value['device']) %}{%- endif %}
+            {%- endif %}
+        {%- endif %}
+    {%- endfor %}
+{%- else %}
+    {%- set host_provider_network_interfaces = {} %}
+    {%- set dpdk_in_use = False %}
+{%- endif %}
+{%- set external_ceph_cidr = None %}
+{%- if config_phase != 'setup' and 'external_ceph' in storage['backends'] %}
+    {%- set ext_ceph = storage['backends']['external_ceph'] %}
+    {%- if 'enabled' in ext_ceph and 'cidr' in ext_ceph and ext_ceph['enabled'] %}
+        {%- set external_ceph_cidr = ext_ceph['cidr'] %}
+    {%- endif %}
+{%- endif %}
+
+{% macro generate_linux_bonding_options(options) -%}
+    {%- set mode_mapping = {'active-backup' : 'active-backup', 'lacp' : '802.3ad'} -%}
+    {%- set default_options = {
+                                'active-backup' : 'miimon=100',
+                                'lacp' : 'lacp_rate=fast miimon=100'
+                              } -%}
+    {%- for i in options.split() -%}
+        {%- set key, value = i.split('=') -%}
+        {%- if key == 'mode' -%}
+            {%- if default_options[value] -%}
+                {{ 'mode=' ~ mode_mapping[value] ~ ' ' ~ default_options[value] }}
+            {%- else -%}
+                {{ 'mode=' ~ mode_mapping[value] }}
+            {%- endif -%}
+        {%- endif -%}
+    {%- endfor -%}
+{%- endmacro %}
+
+{% macro generate_ovs_bonding_options(options) -%}
+    {%- set mode_mapping = {'active-backup' : 'active-backup', 'lacp' : 'balance-slb', 'lacp-layer34' : 'balance-tcp'} -%}
+    {%- set default_options = {
+                                'active-backup' : '',
+                                'lacp' : 'lacp=active other_config:lacp-time=fast other_config:bond-detect-mode=carrier',
+                                'lacp-layer34' : 'lacp=active other_config:lacp-time=fast other_config:bond-detect-mode=carrier'
+                              } -%}
+    {%- for i in options.split() -%}
+        {%- set key, value = i.split('=') -%}
+        {%- if key == 'mode' -%}
+            {%- if default_options[value] -%}
+                {{ 'bond_mode=' ~ mode_mapping[value] ~ ' ' ~ default_options[value] }}
+            {%- else -%}
+                {{ 'bond_mode=' ~ mode_mapping[value] }}
+            {%- endif -%}
+        {%- endif -%}
+    {%- endfor -%}
+{%- endmacro %}
+
+{% macro add_static_routes(routes) -%}
+    [
+    {%- for route in routes %}
+        {
+            "ip_netmask": "{{ route.to }}", "next_hop": "{{ route.via }}"
+        } {% if not loop.last %},{% endif %}
+    {%- endfor %}
+    ]
+{%- endmacro %}
+
+{#- create network configuration input for the os-net-config -#}
+{
+"network_config": [
+{%- set loopvar = {'first_entry': True} %}
+{%- set configured_phys_ifaces = [] %}
+
+{#- single nic ifra networks are configured with the ovs provider networks -#}
+{%- if not single_nic_setup %}
+
+{#-
+If all infra ifaces on some phys iface are vlan ifaces it is configured here.
+Otherwise it gets configured normally on infra iface configuration in the next loop.
+-#}
+{%- for iface,infras in host_interface_net_mapping.iteritems() %}
+    {%- set ifacevars = {'create': True, 'mtu': 0} %}
+    {%- for infra,value in host_networking.iteritems() %}
+        {%- if infra in infras %}
+            {%- if value['interface'] == iface %}
+                {%- if ifacevars.update({'create': False}) %}{%- endif %}
+            {%- else %}
+                {%- if 'mtu' in value %}
+                    {%- set mtu = value['mtu'] %}
+                {%- else %}
+                    {%- set mtu = default_mtu %}
+                {%- endif %}
+                {%- if infra == CLOUD_TENANT %}
+                    {%- set mtu = mtu + VXLAN_HDR_LEN %}
+                {%- endif %}
+                {%- if mtu > ifacevars.mtu %}
+                    {%- if ifacevars.update({'mtu': mtu}) %}{%- endif %}
+                {%- endif %}
+            {%- endif %}
+        {%- endif %}
+    {%- endfor %}
+    {%- if ifacevars.create %}
+        {%- if not loopvar.first_entry %},{%- endif %}
+        {%- if loopvar.update({'first_entry': False}) %}{%- endif %}
+        {
+            "name": "{{iface}}",
+            {%- if 'bond' in iface %}
+                {%- for key,slaves in host_bonding_interfaces.iteritems() if key == iface %}
+                    "type": "linux_bond",
+                    {% if ifacevars.mtu > 0 %}"mtu": {{ifacevars['mtu']}},{% endif %}
+                    {%- if 'linux_bonding_options' in  host_network_profile_value %}
+                        "bonding_options": "{{ generate_linux_bonding_options(host_network_profile_value['linux_bonding_options']) }}",
+                    {%- endif %}
+                    "members": [ {% for slave in slaves %}
+                        {%- if configured_phys_ifaces.append(slave) %}{%- endif %}
+                        {
+                        "name": "{{slave}}",
+                        "type": "interface",
+                        {% if ifacevars.mtu > 0 %}"mtu": {{ifacevars['mtu']}},{% endif %}
+                        "use_dhcp": false
+                        }
+                        {% if not loop.last %},{% endif %}
+                    {%- endfor %}
+                    ],
+                {%- endfor %}
+            {%- else %}
+                {%- if configured_phys_ifaces.append(iface) %}{%- endif %}
+                "type": "interface",
+            {%- endif %}
+            {% if ifacevars.mtu > 0 %}"mtu": {{ifacevars['mtu']}},{% endif %}
+            "use_dhcp": false
+        }
+    {%- endif %}
+{%- endfor %}
+
+{#- configure all infra ifaces (except cloud_tenant if ovs-dpdk in use) -#}
+{%- for key,value in host_networking.iteritems() %}
+    {%- if value is iterable and 'interface' in value %}
+        {%- if key != CLOUD_TENANT or not dpdk_in_use %}{#- no dpdk or no cloud tenant -#}
+        {%- if 'mtu' in value %}{% set mtu = value['mtu'] %}{% else %}{% set mtu = default_mtu %}{% endif %}
+        {%- if key == CLOUD_TENANT %}{% set mtu = mtu + VXLAN_HDR_LEN %}{% endif %}
+        {%- if not loopvar.first_entry %},{%- endif %}
+        {%- if loopvar.update({'first_entry': False}) %}{%- endif %}
+        {
+        {%- if 'bond' in value['interface'] %}
+            {%- for bond_key,bond_value in host_bonding_interfaces.iteritems() if bond_key == value['interface'] %}
+                "name": "{{bond_key}}",
+                "type": "linux_bond",
+                "members": [ {% for member in bond_value %}
+                    {
+                    "name": "{{ member }}",
+                    "type": "interface",
+                    "mtu": {{mtu}},
+                    "use_dhcp": false
+                    }
+                    {% if not loop.last %},{% endif %}
+                {%- endfor %}
+                ],
+                {%- if 'linux_bonding_options' in  host_network_profile_value %}
+                    "bonding_options": "{{ generate_linux_bonding_options(host_network_profile_value['linux_bonding_options']) }}",
+                {%- endif %}
+            {%- endfor %}
+        {%- elif 'vlan' in value %}
+            "type": "vlan",
+            "vlan_id": {{ value['vlan'] }},
+            {%- for net_key,net_value in host_interface_net_mapping.iteritems() %}
+                {%- if key in net_value %}
+                    "device": "{{net_key}}",
+                {%- endif %}
+            {%- endfor %}
+        {%- else %}
+            {%- if configured_phys_ifaces.append(value['interface']) %}{%- endif %}
+            "name": "{{value['interface']}}",
+            "type": "interface",
+        {%- endif %}
+            "addresses": [ { "ip_netmask": "{{ value['ip'] }}/{{value['mask']}}" } ],
+            "mtu": {{mtu}},
+            {%- if (key == "infra_external" or key == "infra_access")
+                    and 'dns' in host_networking
+                    and (ansible_hostname not in groups.get('caas_nodes', [])) %}
+                "dns_servers": [{% for server in host_networking['dns'] %}"{{ server }}"{% if not loop.last %},{% endif %}{% endfor %}],
+            {%- endif %}
+            {%- set routes = [] %}
+            {%- if 'routes' in value %}
+                {%- set routes = value['routes'] %}
+            {%- endif %}
+            {%- if key == 'infra_external' and 'gateway' in value %}
+                {%- if '.' in value['gateway'] %}
+                    {% set defaultroute = '0.0.0.0/0'%}
+                {%- else %}
+                    {% set defaultroute = '::/0'%}
+                {%- endif %}
+                {%- set gw = {"to": defaultroute, "via": value['gateway']} %}
+                {%- if routes.append(gw) %}{%- endif %}
+            {%- endif %}
+            {%- if key == 'infra_access' and 'gateway' in value %}
+                {%- if 'dns' in host_networking %}
+                    {%- if '.' in value['gateway'] %}
+                        {% set mask = '/32' %}
+                    {%- else %}
+                        {% set mask = '/128' %}
+                    {%- endif %}
+                    {%- for server in host_networking['dns'] %}
+                        {%- set dnsroute = server ~ mask %}
+                        {%- set gw = {"to": dnsroute, "via": value['gateway']} %}
+                        {%- if routes.append(gw) %}{%- endif %}
+                    {%- endfor %}
+                {%- endif %}
+                {%- if external_ceph_cidr is not none %}
+                    {%- set gw = {"to": external_ceph_cidr, "via": value['gateway']} %}
+                    {%- if routes.append(gw) %}{%- endif %}
+                {%- endif %}
+            {%- endif %}
+            {%- if routes %}
+                "routes": {{ add_static_routes(routes) }},
+            {%- endif %}
+            "use_dhcp": false
+        }
+        {%- endif %}{#- no dpdk or no cloud tenant -#}
+    {%- endif %}
+{%- endfor %}
+
+{%- endif %}{#- if not single_nic_setup -#}
+
+{%- if config_phase != 'setup' or single_nic_setup %}
+
+{#- configure provider network interfaces -#}
+{%- for key,value in host_provider_network_interfaces|dictsort(true) %}
+    {%- set keyloop = loop %}
+    {%- if 'ovs' in value['type'] %}
+        {%- if not loopvar.first_entry %},{%- endif %}
+        {%- if loopvar.update({'first_entry': False}) %}{%- endif %}
+        {%- if value['type'] == 'ovs-dpdk' %}
+            {%- for bond_key,bond_value in host_bonding_interfaces.iteritems() if bond_key == key %}
+                {%- for member in bond_value %}
+                    {%- if member not in ixgbedevs %}
+                        {%- if configured_phys_ifaces.append(member) %}{%- endif %}
+                        {
+                            "name": "{{member}}",
+                            "type": "interface",
+                            "mtu": {{max_mtu}},
+                            "use_dhcp": false
+                        },
+                    {%- endif %}
+                {%- endfor %}
+            {%- endfor %}
+            {%- if 'bond' not in key and key not in ixgbedevs %}
+                {%- if configured_phys_ifaces.append(key) %}{%- endif %}
+                {
+                    "name": "{{key}}",
+                    "type": "interface",
+                    "mtu": {{max_mtu}},
+                    "use_dhcp": false
+                },
+            {%- endif %}
+        {%- endif %}
+        {
+        "name": "br-pro{{keyloop.index0}}",
+        {%- if value['type'] == 'ovs-dpdk' %}
+            "type": "ovs_user_bridge",
+        {%- else %}
+            "type": "ovs_bridge",
+        {%- endif %}
+        "members": [
+            {
+            "mtu": {{max_mtu}},
+            {%- if 'bond' in key %}
+                {%- for bond_key,bond_value in host_bonding_interfaces.iteritems() if bond_key == key %}
+                    {%- if 'ovs_bonding_options' in  host_network_profile_value %}
+                        "ovs_options": "{{ generate_ovs_bonding_options(host_network_profile_value['ovs_bonding_options']) }}",
+                    {%- endif %}
+                    "name": "{{key}}",
+                    {%- if value['type'] == 'ovs-dpdk' %}
+                        "type": "ovs_dpdk_bond",
+                        {%- if 'dpdk_max_rx_queues' in value %}
+                            "rx_queue": {{ value['dpdk_max_rx_queues'] }},
+                        {%- endif %}
+                        "members": [ {%- for member in bond_value %}
+                            {%- if configured_phys_ifaces.append(member) %}{%- endif %}
+                            {
+                            "name": "dpdk-{{member}}",
+                            "type": "ovs_dpdk_port",
+                            "mtu": {{max_mtu}},
+                            "members": [ { "name": "{{member}}", "type": "interface", "mtu": {{max_mtu}}, "use_dhcp": false } ],
+                            "use_dhcp": false
+                            }
+                            {% if not loop.last %},{% endif %}
+                        {%- endfor %}
+                        ],
+                    {%- else %}
+                        "type": "ovs_bond",
+                        "members": [ {% for member in bond_value %}
+                            {%- if configured_phys_ifaces.append(member) %}{%- endif %}
+                            {
+                            "name": "{{ member }}",
+                            "type": "interface",
+                            "mtu": {{max_mtu}},
+                            "use_dhcp": false
+                            }
+                            {% if not loop.last %},{% endif %}
+                        {%- endfor %}
+                        ],
+                    {%- endif %}
+                {%- endfor %}
+            {%- else %}
+                {%- if configured_phys_ifaces.append(key) %}{%- endif %}
+                {%- if value['type'] == 'ovs-dpdk' %}
+                    "name": "dpdk-{{key}}",
+                    "type": "ovs_dpdk_port",
+                    "mtu": {{max_mtu}},
+                    {%- if 'dpdk_max_rx_queues' in value %}
+                        "rx_queue": {{ value['dpdk_max_rx_queues'] }},
+                    {%- endif %}
+                    "members": [ { "name": "{{key}}", "type": "interface", "mtu": {{max_mtu}}, "use_dhcp": false } ],
+                {%- else %}
+                    "name": "{{key}}",
+                    "type": "interface",
+                {%- endif %}
+            {%- endif %}
+            "use_dhcp": false
+            }
+            {%- for net in value['provider_networks'] %}
+                ,
+                {
+                "name": "pro{{keyloop.index0}}-pro{{keyloop.index0}}.{{loop.index0}}",
+                "bridge_name": "br-pro{{keyloop.index0}}",
+                "type": "ovs_patch_port",
+                "peer": "pro{{keyloop.index0}}.{{loop.index0}}-pro{{keyloop.index0}}"
+                }
+            {%- endfor %}
+            {%- if single_nic_setup %}
+                {#- configure all infra ifaces -#}
+                {%- for key,value in host_networking.iteritems() %}
+                    {%- if value is iterable and 'interface' in value %}
+                        {%- if 'mtu' in value %}{% set mtu = value['mtu'] %}{% else %}{% set mtu = default_mtu %}{% endif %}
+                        {%- if key == CLOUD_TENANT %}{% set mtu = mtu + VXLAN_HDR_LEN %}{% endif %}
+                        ,
+                        {
+                        "type": "vlan",
+                        "vlan_id": {{ value['vlan'] }},
+                        "addresses": [ { "ip_netmask": "{{ value['ip'] }}/{{value['mask']}}" } ],
+                        "mtu": {{mtu}},
+                        {%- if (key == "infra_external" or key == "infra_access")
+                            and 'dns' in host_networking
+                            and (ansible_hostname not in groups.get('caas_nodes', [])) %}
+                            "dns_servers": [{% for server in host_networking['dns'] %}"{{ server }}"{% if not loop.last %},{% endif %}{% endfor %}],
+                        {%- endif %}
+                        {%- set routes = [] %}
+                        {%- if 'routes' in value %}
+                            {%- set routes = value['routes'] %}
+                        {%- endif %}
+                        {%- if key == 'infra_external' and 'gateway' in value %}
+                            {%- if '.' in value['gateway'] %}
+                                {% set defaultroute = '0.0.0.0/0'%}
+                            {%- else %}
+                                {% set defaultroute = '::/0'%}
+                            {%- endif %}
+                            {%- set gw = {"to": defaultroute, "via": value['gateway']} %}
+                            {%- if routes.append(gw) %}{%- endif %}
+                        {%- endif %}
+                        {%- if key == 'infra_access' and 'gateway' in value %}
+                            {%- if 'dns' in host_networking %}
+                                {%- if '.' in value['gateway'] %}
+                                    {% set mask = '/32' %}
+                                {%- else %}
+                                    {% set mask = '/128' %}
+                                {%- endif %}
+                                {%- for server in host_networking['dns'] %}
+                                    {%- set dnsroute = server ~ mask %}
+                                    {%- set gw = {"to": dnsroute, "via": value['gateway']} %}
+                                    {%- if routes.append(gw) %}{%- endif %}
+                                {%- endfor %}
+                            {%- endif %}
+                            {%- if external_ceph_cidr is not none %}
+                                {%- set gw = {"to": external_ceph_cidr, "via": value['gateway']} %}
+                                {%- if routes.append(gw) %}{%- endif %}
+                            {%- endif %}
+                        {%- endif %}
+                        {%- if routes %}
+                            "routes": {{ add_static_routes(routes) }},
+                        {%- endif %}
+                        "use_dhcp": false
+                        }
+                    {%- endif %}
+                {%- endfor %}
+            {%- endif %}{#- if single_nic_setup -#}
+        ]
+        }
+        {%- for net in value['provider_networks'] %}
+            ,
+            {
+            "name": "br-pro{{keyloop.index0}}.{{loop.index0}}",
+            {%- if value['type'] == 'ovs-dpdk' %}
+                "type": "ovs_user_bridge",
+            {%- else %}
+                "type": "ovs_bridge",
+            {%- endif %}
+            "ovs_fail_mode": "secure",
+            "members": [
+                {
+                "name": "pro{{keyloop.index0}}.{{loop.index0}}-pro{{keyloop.index0}}",
+                "bridge_name": "br-pro{{keyloop.index0}}.{{loop.index0}}",
+                "type": "ovs_patch_port",
+                "peer": "pro{{keyloop.index0}}-pro{{keyloop.index0}}.{{loop.index0}}"
+                }
+            ]
+            }
+        {%- endfor %}
+    {%- endif %}
+{%- endfor %}
+
+{#- configure vxlan bridge for dpdk cloud tenant -#}
+{%- if CLOUD_TENANT in host_networking.keys() and dpdk_in_use %}
+    {%- set net = host_networking[CLOUD_TENANT] %}
+    {%- if not loopvar.first_entry %},{%- endif %}
+    {%- if loopvar.update({'first_entry': False}) %}{%- endif %}
+    {
+        "type": "ovs_user_bridge",
+        "name": "br-vxlan",
+        "addresses": [ { "ip_netmask": "{{ net['ip'] }}/{{net['mask']}}" } ],
+        {%- if 'routes' in net %}
+            "routes": {{ add_static_routes(net['routes']) }},
+        {%- endif %}
+        "members": [{
+            "type": "vlan",
+            "vlan_id": {{ net['vlan'] }},
+            {%- for net_key,net_value in host_interface_net_mapping.iteritems() %}
+                {%- if CLOUD_TENANT in net_value %}
+                    "device": "{{net_key}}",
+                {%- endif %}
+            {%- endfor %}
+            {%- if 'mtu' in net %}{% set mtu = net['mtu'] %}{% else %}{% set mtu = default_mtu %}{% endif %}
+            {% set mtu = mtu + VXLAN_HDR_LEN %}
+            "mtu": {{mtu}},
+            "use_dhcp": false
+        }],
+        "ovs_extra": [ "br-set-external-id br-vxlan bridge-id br-vxlan" ]
+    }
+{%- endif %}
+{%- endif %}{#- if config_phase != 'setup' or single_nic_setup -#}
+
+{#- configure sr-iov ifaces -#}
+{%- if config_phase != 'setup' %}
+{%- if 'sriov_provider_networks' in host_network_profile_value %}
+    {%- for net,net_info in host_network_profile_value['sriov_provider_networks'].iteritems() %}
+        {%- for iface in net_info['interfaces'] %}
+            {%- if iface not in configured_phys_ifaces %}
+                {%- if not loopvar.first_entry %},{%- endif %}
+                {%- if loopvar.update({'first_entry': False}) %}{%- endif %}
+                {
+                "name": "{{iface}}",
+                "type": "interface",
+                "mtu": {{sriov_mtu}},
+                "use_dhcp": false
+                }
+            {%- endif %}
+        {%- endfor %}
+    {%- endfor %}
+{%- endif %}
+{%- endif %}{#- if config_phase != 'setup' -#}
+]
+}
diff --git a/roles/baremetal_provision/defaults/main.yml b/roles/baremetal_provision/defaults/main.yml
new file mode 100644 (file)
index 0000000..98bdb9a
--- /dev/null
@@ -0,0 +1,33 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+## Verbosity Options
+debug: False
+
+net_conn_details: []
+baremetal_ironic_nodes_ids: []
+config_drive_templates:
+    - src: "meta_data.json.j2"
+      dest: "meta_data.json"
+      config_type: "json"
+    - src: "user_data.j2"
+      dest: "user_data"
+      config_type: "yaml"
+
+golden_image_http_port: 61400
+base_console_port: 61401
+base_vbmc_port: 61600
diff --git a/roles/baremetal_provision/files/guest-img-nginx.service b/roles/baremetal_provision/files/guest-img-nginx.service
new file mode 100644 (file)
index 0000000..b821707
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+[Unit]
+Description=The nginx HTTP for hosting guest-image.img during ironic node provisioning
+After=network.target remote-fs.target nss-lookup.target
+
+[Service]
+Type=forking
+# Nginx will fail to start if /run/guest-img-nginx.pid already exists but has the wrong
+# SELinux context. This might happen when running `nginx -t` from the cmdline.
+# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
+ExecStartPre=/usr/bin/rm -f /run/guest-img-nginx.pid
+ExecStartPre=/usr/sbin/nginx -t -c /opt/guest-img-nginx/nginx.conf
+ExecStart=/usr/sbin/nginx -c /opt/guest-img-nginx/nginx.conf
+ExecReload=/bin/kill -s HUP $MAINPID
+KillSignal=SIGQUIT
+TimeoutStopSec=5
+KillMode=process
+#PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/baremetal_provision/files/tmux_setup/log.inc b/roles/baremetal_provision/files/tmux_setup/log.inc
new file mode 100755 (executable)
index 0000000..ef8bf34
--- /dev/null
@@ -0,0 +1,130 @@
+#!/bin/bash
+# vim:noet:sw=4:ts=4:ft=sh
+
+# Copyright 2019 Nokia
+
+# 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.
+
+[ -n "$__AUTOCOM_LIB_LOG_INC__" ] && return || __AUTOCOM_LIB_LOG_INC__=1
+
+LOGGING_TIMESTAMP_FORMAT='%b %d %H:%M:%S'
+
+_logging_fmt()
+{
+       local fmt="%7s : ${1}%s\n"
+
+       [ -n "${LOGGING_TIMESTAMPS}" -a "${LOGGING_TIMESTAMPS}" != "0" ] \
+               && printf -v fmt "%(${LOGGING_TIMESTAMP_FORMAT})T %s" -1 "${fmt}"
+
+       printf "%s" "${fmt}"
+}
+
+debug()
+{
+       local f
+       local fmt="$(_logging_fmt "${1}")"
+       local src=""
+
+       shift
+
+       [ -n "${LOGGING_SOURCES}" -a "${LOGGING_SOURCES}" != "0" ] \
+               && src=" [${FUNCNAME[1]}()]"
+
+       [ -n "${LOGGING_DEBUG}" ] && [ "${LOGGING_DEBUG}" -ne 0 ] \
+               && printf "${fmt}" "DEBUG" "${@}" "${src}" 1>&2
+
+       for f in "${LOGGING_HOOKS_DEBUG[@]}" "${LOGGING_HOOKS_ALL[@]}"; do "${f}" "${@}" ; done
+
+       return 0
+}
+
+info()
+{
+       local f
+       local fmt="$(_logging_fmt "${1}")"
+       local src=""
+
+       shift
+
+       [ -n "${LOGGING_SOURCES}" -a "${LOGGING_SOURCES}" != "0" ] \
+               && src=" [${FUNCNAME[1]}()]"
+
+       ( [ -z "${LOGGING_QUIET}" ] || [ "${LOGGING_QUIET}" -eq 0 ] ) \
+               && printf "${fmt}" "INFO" "${@}" "${src}"
+
+       for f in "${LOGGING_HOOKS_INFO[@]}" "${LOGGING_HOOKS_ALL[@]}"; do "${f}" "${@}" ; done
+
+       return 0
+}
+
+_logging_log_err()
+{
+       local f
+       local fmt="$(_logging_fmt "${2}")"
+       local src=""
+       local label="${1:-ERROR}"
+
+       shift 2
+
+       [ -n "${LOGGING_SOURCES}" -a "${LOGGING_SOURCES}" != "0" ] \
+               && src=" [${FUNCNAME[2]}()]"
+
+       printf "${fmt}" "${label}" "${@}" "${src}" 1>&2
+
+       for f in $(eval "echo \"\${LOGGING_HOOKS_${label}[@]}\"") "${LOGGING_HOOKS_ALL[@]}" ; do "${f}" "${@}" ; done
+}
+
+notice()
+{
+       _logging_log_err NOTICE "${@}"
+}
+
+warn()
+{
+       _logging_log_err WARNING "${@}"
+}
+
+error()
+{
+       _logging_log_err ERROR "${@}"
+}
+
+alert()
+{
+       _logging_log_err ALERT "${@}"
+}
+
+emerg()
+{
+       _logging_log_err EMERG "${@}"
+}
+
+crit()
+{
+       _logging_log_err CRIT "${@}"
+}
+
+_main()
+{
+       local f="${1}"
+       shift
+       "${f}" "$@"
+}
+
+
+[ "${BASH_SOURCE}" != "${0}" ] || _main "${@}"
+
+# Local Variables:
+# mode: sh
+# tab-width: 4
+# End:
diff --git a/roles/baremetal_provision/files/tmux_setup/tmux.conf b/roles/baremetal_provision/files/tmux_setup/tmux.conf
new file mode 100644 (file)
index 0000000..e11a0b1
--- /dev/null
@@ -0,0 +1,5 @@
+set-option -g set-remain-on-exit on
+set-option -g status off
+set-option -g status-left-length 50
+set-option -g update-environment "HOME SESSION_ID SESSION_DIR TMUX_TMPDIR TMUX_SESSION TMUX_LOGDIR TMUX_RC_FILE"
+
diff --git a/roles/baremetal_provision/files/tmux_setup/tmux.inc b/roles/baremetal_provision/files/tmux_setup/tmux.inc
new file mode 100644 (file)
index 0000000..026f392
--- /dev/null
@@ -0,0 +1,328 @@
+#!/bin/bash
+# vim:noet:sw=4:ts=4:ft=sh
+
+# Copyright 2019 Nokia
+
+# 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.
+
+[ -n "$__AUTOCOM_LIB_TMUX_INC__" ] && return || __AUTOCOM_LIB_TMUX_INC__=1
+
+source "$(dirname "$BASH_SOURCE")/log.inc"
+
+TMUX_SESSION_PREFIX="tmux-session-"
+TMUX_TMPDIR="/tmp/tmp_console"
+TMUX_SESSION="${TMUX_SESSION_PREFIX}deploy"
+TMUX_LOGDIR="/var/log/ironic/console_logs/"
+TMUX_RC_FILE="$(dirname "$BASH_SOURCE")/tmux.conf"
+
+tmux_log_start()
+{
+       local name="$1"
+
+       TMUX="" tmux -C -f "$TMUX_RC_FILE" \
+                       attach-session -t "$TMUX_SESSION" \; \
+                       select-window -t "$name" \; \
+                       pipe-pane -o "exec cat>>\"$TMUX_LOGDIR/$name.log\"" \; \
+                       detach &>/dev/null \
+               || crit "Failed to start logging tmux window '%s'." "$name"
+}
+
+tmux_session_env_set()
+{
+       local tmpdir="${1:-$TMUX_TMPDIR}"
+       local session="$2"
+       local name="$3"
+       local value="$4"
+
+       TMUX_TMPDIR="$tmpdir" tmux -f "$TMUX_RC_FILE" set-environment ${session:+-t "$session"} "$name" "$value" \
+               || crit "Failed to set session '%s' environment variable '%s' to '%s'." "$session" "$name" "$value"
+}
+
+tmux_env_set()
+{
+       tmux_session_env_set "" "$TMUX_SESSION" "$@"
+}
+
+tmux_session_env_get()
+{
+       local tmpdir="${1:-$TMUX_TMPDIR}"
+       local session="$2"
+       local name="$3"
+       local output
+
+       output="$(TMUX_TMPDIR="$tmpdir" tmux 2>/dev/null -f "$TMUX_RC_FILE" show-environment ${session:+-t "$session"} "$name")" || :
+
+       echo "${output#$name=}"
+}
+
+tmux_env_get()
+{
+       tmux_session_env_get "" "$TMUX_SESSION" "$@"
+}
+
+tmux_session_start()
+{
+       local name="$1"
+       shift
+
+       debug "Starting new tmux session with window '%s'." "$name"
+
+       tmux -f "$TMUX_RC_FILE" new-session -s "$TMUX_SESSION" -d -n "$name" "$(printf "'%s' " "$@")" \
+               || crit "Failed to start a new tmux session with '%s' running in it." "$name"
+
+       tmux_log_start "$name"
+}
+
+tmux_list_sessions()
+{
+       local tmpdir="${1:-$TMUX_TMPDIR}"
+
+       debug "Listing tmux sessions found from the temporary directory '%s'." "$tmpdir"
+
+       TMUX_TMPDIR="$tmpdir" tmux ${TMUX_RC_FILE:+-f "$TMUX_RC_FILE"} list-sessions -F '#{session_name}' 2> /dev/null
+}
+
+tmux_session_is_running()
+{
+       tmux -f "$TMUX_RC_FILE" has-session -t "$TMUX_SESSION" &>/dev/null
+}
+
+_tmux_cmd_title_is_new()
+{
+       local name="$1"
+
+       debug "Checking that a tmux window with name '%s' is not already running." "$name"
+
+       ! tmux_cmd_is_running "$name"
+}
+
+tmux_cmd_exists()
+{
+       local name="$1"
+
+       debug "Checking if a command with the name '%s' exists." "$name"
+
+       tmux_cmd_list | grep -q "^$name\$"
+}
+
+tmux_cmd_pid()
+{
+       local name="$1"
+       local output pid
+
+       debug "Fetching pid of tmux command '%s'." "$name"
+
+       output="$(tmux -f "$TMUX_RC_FILE" list-windows -t "$TMUX_SESSION" -F '#{window_name}-pid=#{pane_pid}')" \
+               || crit "Failed to list tmux session's windows."
+
+       pid="$(grep -m1 "^${name}-pid=" <<< "$output")"
+
+       [ -n "$pid" ] || return 1
+
+       echo "${pid##*=}"
+}
+
+tmux_cmd()
+{
+       local name="$1"
+       shift
+
+       debug "Executing '%s' in a new tmux window." "$name"
+
+       ! tmux_cmd_exists "$name" \
+               || crit "A command with the name '%s' already exists." "$name"
+
+       tmux -f "$TMUX_RC_FILE" new-window -n "$name" -d "/bin/bash -c \"sleep .2 ; $(printf "'%s' " "$@") ; echo \\\"@@@@@ autocom:tmux_cmd:exit_value: \\\$? @@@@@\\\" ; sleep 1\" " \
+               || crit "Failed to execute command '%s' / '%s'." "$name" "$*"
+
+       tmux_log_start "$name"
+}
+
+tmux_cmd_list()
+{
+       local name="$name"
+
+       debug "Listing tmux commands / windows in session '%s'." "$TMUX_SESSION"
+
+       tmux -f "$TMUX_RC_FILE" list-windows -F '#{window_name}' \
+               || crit "Failed to list tmux session's windows."
+}
+
+tmux_attach()
+{
+       local foreground name new_prefix
+
+       [ "$1" != "--foreground" ] \
+               || { foreground="set-option exit-unattached on ;" ; shift ; }
+
+       name="$1"
+       new_prefix="$2"
+
+       debug "Attaching %sto window '%s' in session '%s' with prefix '%s'." \
+               "${foreground:+"with foreground option "}" "$name" "$SESSION_ID" "$new_prefix"
+
+       tmux_cmd_exists "$name" \
+               || name=""
+
+       tmux \
+                       new-session -t "$TMUX_SESSION" -s "${TMUX_SESSION/$TMUX_SESSION_PREFIX/$new_prefix}" \; \
+                       select-window ${name:+-t "$name"} \; \
+                       set status on \; \
+                       set destroy-unattached on \; \
+                       $foreground \
+                       set-window-option remain-on-exit off \
+               || crit "Failed to attach to session %s's window '%s' with new prefix '%s'." "$SESSION_ID" "$name" "$new_prefix"
+}
+
+tmux_cmd_assert()
+{
+       local delay="$1"
+       shift
+
+       tmux_cmd "$@"
+
+       sleep "$delay"
+
+       tmux_cmd_is_running "$1" \
+               || crit "Executing '%s' in a tmux window seems to have failed soon after starting." "$1"
+}
+
+tmux_kill_try()
+{
+       local name="$1"
+
+       debug "Killing '%s' from a tmux session." "$name"
+
+       tmux -f "$TMUX_RC_FILE" kill-window -t "$name"
+}
+
+tmux_kill()
+{
+       local name="$1"
+
+       tmux_kill_try "$name" \
+               || crit "Failed to kill '%s' from the tmux session." "$name"
+}
+
+tmux_get_window_count()
+{
+       tmux_cmd_list | wc -l
+}
+
+tmux_cmd_is_running()
+{
+       local name="$1"
+
+       debug "Checking whether '%s' is running in tmux." "$name"
+
+       tmux -f "$TMUX_RC_FILE" list-windows -F "#{window_name}-dead=#{pane_dead}" \
+               | grep -q "^$name-dead=0\$"
+}
+
+tmux_count_zombies()
+{
+       debug "Counting dead tmux windows."
+
+       tmux -f "$TMUX_RC_FILE" list-windows -F "window-is-dead=#{pane_dead}" \
+               | grep -c "^window-is-dead=1\$"
+}
+
+tmux_cmd_exit_status()
+{
+       local name="$1" e
+
+       debug "Checking whether '%s' has returned an error." "$name"
+
+       ! tmux_cmd_is_running "$name" \
+               || crit "Cannot check if command returned an error; command is still running."
+
+       e="$(tmux -f "$TMUX_RC_FILE" capture-pane -t "$name" -p | grep -o '@@@@@ autocom:tmux_cmd:exit_value: [0-9]\+ @@@@@' | grep -o '[0-9]\+')"
+
+       [[ "$e" =~ ^[0-9]+$ ]] \
+               || crit "Command %s's exit status '%s' doesn't look like a number." "$name" "$e"
+
+       return $e
+}
+
+tmux_session_init()
+{
+       export TMUX_TMPDIR="$1"
+       export TMUX_SESSION="${TMUX_SESSION_PREFIX}$2"
+       export TMUX_LOGDIR="$3"
+       export TMUX_RC_FILE="$4"
+
+       debug "Initializing tmux session '%s': tmpdir='%s', logdir='%s'" \
+               "$TMUX_SESSION" "$TMUX_TMPDIR" "$TMUX_LOGDIR"
+
+       mkdir -p "$TMUX_TMPDIR" \
+               || crit "Failed to create tmux's temporary directory '%s'." "$TMUX_TMPDIR"
+
+       mkdir -p "$TMUX_LOGDIR" \
+               || crit "Failed to create tmux's log file directory."
+}
+
+tmux_kill_other_sessions()
+{
+       local session sessions
+
+       debug "Killing other tmux sessions than '%s' (that are still related to the same autocom session)." \
+               "$TMUX_SESSION"
+
+       sessions="$(tmux_list_sessions)" \
+               || crit "Failed to get a list of sessions to kill."
+
+       sessions="$(echo "$sessions" | grep "${TMUX_SESSION/$TMUX_SESSION_PREFIX/}")" \
+               || crit "No tmux sessions found for the running autocom session."
+
+       sessions="$(echo "$sessions" | grep -v "$TMUX_SESSION")" \
+               || debug "No other tmux sessions in this autocom session."
+
+       for session in $sessions
+       do
+               tmux -f "$TMUX_RC_FILE" kill-session -t "$session" \
+                       || crit "Failed to kill tmux session '%s'." "$session"
+       done
+}
+
+tmux_kill_other_windows()
+{
+       local name="$1"
+
+       [ -n "$name" ] \
+               && debug "Killing all other tmux windows than '%s'." "$name" \
+               || debug "Killing all other tmux windows."
+
+       tmux -f "$TMUX_RC_FILE" kill-window -a ${name:+-t "$name"}
+}
+
+tmux_session_uninit()
+{
+       local name="$1"
+
+       debug "Uninitializing tmux session (name='%s')." "$name"
+
+       tmux_kill_other_sessions
+       tmux_kill_other_windows "$name"
+}
+
+tmux_set_alternate_prefix()
+{
+       local prefix="$1"
+
+       TMUX_SESSION_PREFIX="${prefix}-"
+}
+
+# Local Variables:
+# mode: sh
+# tab-width: 4
+# End:
diff --git a/roles/baremetal_provision/files/virtualbmc.conf b/roles/baremetal_provision/files/virtualbmc.conf
new file mode 100644 (file)
index 0000000..e9ec3bf
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+[log]
+logfile = /var/log/vbmc.log
+debug = True
diff --git a/roles/baremetal_provision/library/README.rst b/roles/baremetal_provision/library/README.rst
new file mode 100644 (file)
index 0000000..c2d007b
--- /dev/null
@@ -0,0 +1,2 @@
+This library os_ironic.py is cloned from /usr/lib/python2.7/site-packages/ansible/modules/core/cloud/openstack/os_ironic.py. 
+As there was no support for properties/capabilities parameter in the native lib.
diff --git a/roles/baremetal_provision/library/os_node_power_check.py b/roles/baremetal_provision/library/os_node_power_check.py
new file mode 100644 (file)
index 0000000..2950248
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 fnmatch
+
+try:
+    import shade
+    from shade import meta
+    HAS_SHADE = True
+except ImportError:
+    HAS_SHADE = False
+
+DOCUMENTATION = '''
+---
+module: os_node_power_check
+short_description: Retrieve facts about ironic nodes list provided,
+                   Returns a list of nodes which are not in specified power state
+version_added: "2.0"
+description:
+    - Retrieve facts about ironic nodes list provided,
+      Returns a list of nodes which are not in specified power state
+requirements:
+    - "python >= 2.6"
+    - "shade"
+options:
+   nodes_details:
+     description:
+       - List of dicts [{uuid: <ironic_node_id>, name: <ironic_node_name>},....], containing ironic node ids and names.
+     required: True
+     default: None
+   ironic_url:
+     description:
+       - The ironic URL to connect to
+     required: True
+     default: None
+   power_state:
+     description:
+       - The specified power state in which nodes are expected to be
+     required: True
+     default: None
+returns:
+     power_pending_list
+extends_documentation_fragment: openstack
+'''
+
+EXAMPLES = '''
+- os_node_power_check:
+    nodes_details:
+      - uuid: <id-1>
+        name: <name-1>
+      - uuid: <id-2>
+        name: <name-2>
+    power_state: 'power on'
+'''
+
+def main():
+    argument_spec = openstack_full_argument_spec(
+        nodes_details=dict(type='list', required=True), 
+        ironic_url=dict(required=False),
+        power_state=dict(required=True),
+    )
+    module_kwargs = openstack_module_kwargs()
+    module = AnsibleModule(argument_spec, **module_kwargs)
+
+    if not HAS_SHADE:
+        module.fail_json(msg='shade is required for this module')
+    if (module.params['auth_type'] in [None, 'None'] and
+            module.params['ironic_url'] is None):
+        module.fail_json(msg="Authentication appears to be disabled, "
+                             "Please define an ironic_url parameter")
+
+    if (module.params['ironic_url'] and
+            module.params['auth_type'] in [None, 'None']):
+        module.params['auth'] = dict(
+            endpoint=module.params['ironic_url']
+        )
+
+    try:
+        cloud = shade.operator_cloud(**module.params)
+
+        nodes_details = module.params['nodes_details']
+        power_state = module.params['power_state']
+        power_pending_list = []
+
+        for node in nodes_details:
+            node_name = node['uuid']
+            node_details = cloud.get_machine(node_name)
+
+            if not node_details['power_state'] == power_state:
+                power_pending_list.append(node_name)
+
+        module.exit_json(changed=False, ansible_facts=dict(power_pending_list=power_pending_list))
+
+    except shade.OpenStackCloudException as e:
+        module.fail_json(msg=str(e))
+
+# this is magic, see lib/ansible/module_common.py
+from ansible.module_utils.basic import *
+from ansible.module_utils.openstack import *
+if __name__ == '__main__':
+    main()
diff --git a/roles/baremetal_provision/library/os_node_provision_check.py b/roles/baremetal_provision/library/os_node_provision_check.py
new file mode 100644 (file)
index 0000000..6534863
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 fnmatch
+
+try:
+    import shade
+    from shade import meta
+    HAS_SHADE = True
+except ImportError:
+    HAS_SHADE = False
+
+DOCUMENTATION = '''
+---
+module: os_node_provision_check
+short_description: Retrieve facts about ironic nodes list provided,
+                   Returns a list of nodes which are not in deploying and failed states
+version_added: "2.0"
+description:
+    - Retrieve facts about ironic nodes list provided,
+      Returns a list of nodes which are not in deploying and failed states
+requirements:
+    - "python >= 2.6"
+    - "shade"
+options:
+   nodes_details:
+     description:
+       - List of dicts [{id: <ironic_node_id>, name: <ironic_node_name>},....], containing ironic node ids and names.
+         This modules runs through all the ironic nodes and returns list of nodes in deploying and failed state.
+     required: True
+     default: None
+returns:
+     provision_pending_list
+     provision_failed_list
+extends_documentation_fragment: openstack
+'''
+
+EXAMPLES = '''
+# Gather facts about all nodes named C<web*>:
+- os_node_provision_check:
+    cloud: rax-dfw
+    nodes_details:
+      - id: <id-1>
+        name: <name-1>
+      - id: <id-2>
+        name: <name-2>
+'''
+
+
+def main():
+
+    argument_spec = openstack_full_argument_spec(
+        nodes_details=dict(type='list', required=True), 
+        ironic_url=dict(required=False),
+    )
+    module_kwargs = openstack_module_kwargs()
+    module = AnsibleModule(argument_spec, **module_kwargs)
+
+    if not HAS_SHADE:
+        module.fail_json(msg='shade is required for this module')
+    if (module.params['auth_type'] in [None, 'None'] and
+            module.params['ironic_url'] is None):
+        module.fail_json(msg="Authentication appears to be disabled, "
+                             "Please define an ironic_url parameter")
+
+    if (module.params['ironic_url'] and
+            module.params['auth_type'] in [None, 'None']):
+        module.params['auth'] = dict(
+            endpoint=module.params['ironic_url']
+        )
+
+    try:
+        cloud = shade.operator_cloud(**module.params)
+
+        nodes_details = module.params['nodes_details']
+        provision_pending_list = []
+        provision_failed_list = []
+
+        for node in nodes_details:
+            node_name = node['name']
+            node_details = cloud.get_machine(node_name)
+
+            if node_details['provision_state'] in ['deploying', 'wait call-back']:
+                provision_pending_list.append(node_name)
+
+            if node_details['provision_state'] in ['deploy failed']:
+                node_provision_state = {}
+                node_provision_state['name'] = node_name
+                node_provision_state['provision_state'] = node_details['provision_state']
+                provision_failed_list.append(node_provision_state)
+
+        module.exit_json(changed=False, ansible_facts=dict(provision_pending_list=provision_pending_list, provision_failed_list=provision_failed_list))
+
+    except shade.OpenStackCloudException as e:
+        module.fail_json(msg=str(e))
+
+# this is magic, see lib/ansible/module_common.py
+from ansible.module_utils.basic import *
+from ansible.module_utils.openstack import *
+if __name__ == '__main__':
+    main()
diff --git a/roles/baremetal_provision/tasks/convert_qcow_raw.yml b/roles/baremetal_provision/tasks/convert_qcow_raw.yml
new file mode 100644 (file)
index 0000000..34cbbbf
--- /dev/null
@@ -0,0 +1,34 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Check the image type
+  shell: 'qemu-img info /opt/images/guest-image.img | grep "file format:"| cut -d ":" -f2'
+  register: qemu_img
+
+- name: Convert QCOW2 image to RAW
+  command: 'qemu-img convert -O raw /opt/images/guest-image.img /opt/images/guest-image.img.raw'
+  when:
+    - qemu_img.stdout == " qcow2"
+
+- name: Move the QCOW2 to bkp
+  command: 'mv /opt/images/guest-image.img /opt/images/guest-image.qcow2'
+  when:
+    - qemu_img.stdout == " qcow2"
+
+- name: Move the RAW image to guest-image.img
+  command: 'mv /opt/images/guest-image.img.raw /opt/images/guest-image.img'
+  when:
+    - qemu_img.stdout == " qcow2"
diff --git a/roles/baremetal_provision/tasks/ironic_nodes_create.yml b/roles/baremetal_provision/tasks/ironic_nodes_create.yml
new file mode 100644 (file)
index 0000000..4f10cd7
--- /dev/null
@@ -0,0 +1,100 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Checking the details of Provisioning images
+  stat:
+    path: "{{ item }}"
+    get_md5: no
+    get_checksum: no
+  with_items:
+    - "/opt/images/guest-image.img"
+  register: stat_list
+  no_log: True
+
+- name: Change ownership of provisioning images
+  file:
+    path: "{{ item.stat.path }}"
+    owner: "ironic"
+    group: "ironic"
+  with_items: "{{stat_list.results}}"
+  when: item.stat.pw_name != 'ironic'
+  no_log: True
+
+- name: Write os_net_config to tmp files
+  copy:
+    content: "{{ item.driver_info.power.os_net_config }}"
+    dest: "/tmp/{{item.name}}_config.yaml"
+    mode: 0444
+  with_items: "{{ baremetal_ironic_nodes }}"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Create baremetal ironic nodes
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_ironic:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    state: present
+    name: "{{ item.1.name }}"
+    driver: "{{ item.1.driver }}"
+    nics: "{{ item.1.nics }}"
+    properties: "{{ item.1.properties }}"
+    driver_info: "{{ item.1.driver_info | combine({'power': {'os_net_config': lookup('file', '/tmp/'+item.1.name+'_config.yaml'), 'ipmi_terminal_port': hosts[item.1.name]['ipmi_terminal_port'] }}, recursive=True ) }}"
+  with_indexed_items: "{{ baremetal_ironic_nodes }}"
+  register: baremetal_ironic_nodes_results
+  when: installation_phase == "provisioning-started"
+  loop_control:
+    label: "{{ item.1.name }}"
+
+- name: Create list of nodes which are not in active state and not the installation controller.
+  set_fact:
+    baremetal_ironic_nodes_ids: "{{ baremetal_ironic_nodes_ids  +  [{'uuid': item.uuid, 'name': item.item.1.name}] }}"
+  with_items: "{{ baremetal_ironic_nodes_results.results }}"
+  when:
+    - installation_phase == "provisioning-started"
+    - hosts[item.item.1.name]['installation_host'] is undefined
+    - item.provision_state != 'active'
+  no_log: True
+
+- name: Create baremetal ironic nodes
+  os_ironic:
+    cloud: default
+    endpoint_type: internal
+    auth_type: password
+    state: present
+    name: "{{ item.1.name }}"
+    driver: "{{ item.1.driver }}"
+    nics: "{{ item.1.nics }}"
+    properties: "{{ item.1.properties }}"
+    driver_info: "{{ item.1.driver_info | combine({'power': {'os_net_config': lookup('file', '/tmp/'+item.1.name+'_config.yaml'), 'ipmi_terminal_port': hosts[item.1.name]['ipmi_terminal_port'] }}, recursive=True ) }}"
+  with_indexed_items: "{{ baremetal_ironic_nodes }}"
+  register: baremetal_ironic_nodes_results
+  when: (installation_phase != "provisioning-started" and reinitialized_nodes is not defined and scaled_out_nodes is not defined) or (reinitialized_nodes is defined and item.1.name in reinitialized_nodes) or (scaled_out_nodes is defined and item.1.name in scaled_out_nodes)
+  loop_control:
+    label: "{{ item.1.name }}"
+
+- name: Create list of nodes which are not in active state and not the installation controller.
+  set_fact:
+    baremetal_ironic_nodes_ids: "{{ baremetal_ironic_nodes_ids  +  [{'uuid': item.uuid, 'name': item.item.1.name}] }}"
+  with_items: "{{ baremetal_ironic_nodes_results.results }}"
+  when:
+    - installation_phase != "provisioning-started"
+    - (hosts[item.item.1.name]['installation_host'] is undefined and reinitialized_nodes is not defined and scaled_out_nodes is not defined) or (reinitialized_nodes is defined and item.item.1.name in reinitialized_nodes) or (scaled_out_nodes is defined and item.item.1.name in scaled_out_nodes)
+    - item.provision_state != 'active'
+  no_log: True
diff --git a/roles/baremetal_provision/tasks/ironic_nodes_deploy.yml b/roles/baremetal_provision/tasks/ironic_nodes_deploy.yml
new file mode 100644 (file)
index 0000000..cb5ba95
--- /dev/null
@@ -0,0 +1,338 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# Block traffic during nodes power on/off so that possible old deployment
+# clients cannot connect new deployment services (like mysql)  and ruin
+# the installation.
+- name: Block traffic on infra_internal
+  iptables:
+    state: present
+    action: insert
+    chain: INPUT
+    jump: REJECT
+    in_interface: "{{ networking['infra_internal']['interface'] }}"
+  when:
+    - installation_phase == "provisioning-started"
+
+- name: Power off nodes
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  command: "/usr/bin/ironic node-set-power-state {{item.uuid}} off"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  when:
+    - not virtual_env
+    - installation_phase == "provisioning-started"
+  retries: 5
+  delay: 10
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Power off nodes
+  command: "openstack --os-cloud default baremetal node power off {{item.uuid}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  when:
+    - not virtual_env
+    - installation_phase != "provisioning-started"
+  retries: 5
+  delay: 10
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Ensure nodes are powered off
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_node_power_check:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    nodes_details: "{{ baremetal_ironic_nodes_ids }}"
+    power_state: 'power off'
+  until: power_pending_list | length == 0
+  retries: 30
+  delay: 6
+  when:
+    - not virtual_env and baremetal_ironic_nodes_ids | length > 0
+    - installation_phase == "provisioning-started"
+  no_log: True
+
+- name: Ensure nodes are powered off
+  os_node_power_check:
+    cloud: default
+    auth_type: password
+    ironic_url: "{{ ironic_service_adminurl }}"
+    nodes_details: "{{ baremetal_ironic_nodes_ids }}"
+    power_state: 'power off'
+    endpoint_type: internal
+  until: power_pending_list | length == 0
+  retries: 30
+  delay: 6
+  when:
+    - not virtual_env and baremetal_ironic_nodes_ids | length > 0
+    - installation_phase != "provisioning-started"
+  no_log: True
+
+# Sleep to make sure power is off
+- name: Sleep for 15 seconds
+  pause:
+    seconds: 15
+  when: not virtual_env and baremetal_ironic_nodes_ids | length > 0
+
+- name: Create config-drive directories for all nodes
+  file:
+    path: "/var/lib/ironic/confdrive/{{item.name}}/openstack/latest/"
+    state: "directory"
+    owner: "ironic"
+    group: "ironic"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Generate config-drive files
+  config_template:
+    src: "{{ item[1].src }}"
+    dest: "/var/lib/ironic/confdrive/{{item[0].name}}/openstack/latest/{{ item[1].dest }}"
+    owner: "ironic"
+    group: "ironic"
+    mode: "0644"
+    config_type: "{{ item[1].config_type }}"
+  with_nested: 
+    - "{{ baremetal_ironic_nodes_ids }}"
+    - "{{ config_drive_templates }}"
+  loop_control:
+    label: "{{ item[0].name }}"
+
+- name: Stat config-drive files to check if they exists
+  stat:
+    path: "/var/lib/ironic/confdrive/{{ item.name }}.base64"
+  register: confdrive_stat
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+
+- name: Prepare Config-drive ISO file
+  shell: |
+    # Generated ISO
+    genisoimage -o /var/lib/ironic/confdrive/{{ item.item.name }}.iso -ldots -allow-lowercase -allow-multidot -l -publisher 'ironicclient-configdrive 0.1' -quiet -J -r -V config-2 /var/lib/ironic/confdrive/{{ item.item.name }}
+    # Zip it!
+    gzip /var/lib/ironic/confdrive/{{ item.item.name }}.iso
+    # Encode it to base64
+    base64 -w 0 /var/lib/ironic/confdrive/{{ item.item.name }}.iso.gz > /var/lib/ironic/confdrive/{{ item.item.name }}.base64
+  when: not item.stat.exists
+  with_items: "{{confdrive_stat.results}}"
+
+- name: Remove os_net_config temp files
+  file:
+    dest: "/tmp/{{item.name}}_config.yaml"
+    state: absent
+  with_items: "{{ baremetal_ironic_nodes }}"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Calculate md5sum of Golden image
+  stat:
+    path: "/opt/images/guest-image.img"
+    get_md5: yes
+  register: golden_img_md5sum
+  when: baremetal_ironic_nodes_ids | length > 0
+
+- name: Enable traffic on infra_internal
+  iptables:
+    state: absent
+    chain: INPUT
+    jump: REJECT
+    in_interface: "{{ networking['infra_internal']['interface'] }}"
+  when:
+    - installation_phase == "provisioning-started"
+
+- name: Configure Baremetal deployment
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_ironic_node:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    uuid: "{{item.uuid}}"
+    deploy: False
+    state: present
+    power: absent
+    maintenance: False
+    instance_info:
+      root_gb: 10
+      image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
+      image_checksum: "{{golden_img_md5sum.stat.md5}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase == "provisioning-started"
+
+- name: Configure Baremetal deployment
+  os_ironic_node:
+    cloud: default
+    endpoint_type: internal
+    auth_type: password
+    uuid: "{{item.uuid}}"
+    deploy: False
+    state: present
+    power: absent
+    maintenance: False
+    instance_info:
+      root_gb: 10
+      image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
+      image_checksum: "{{golden_img_md5sum.stat.md5}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase != "provisioning-started"
+
+- name: Start Baremetal deployment
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_ironic_node:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    deploy: True
+    power: present
+    config_drive: "{{lookup('file', '/var/lib/ironic/confdrive/{{ item.name }}.base64')}}"
+    uuid: "{{item.uuid}}"
+    instance_info:
+      root_gb: 10
+      image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
+      image_checksum: "{{golden_img_md5sum.stat.md5}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase == "provisioning-started"
+
+- name: Start Baremetal deployment
+  os_ironic_node:
+    cloud: default
+    endpoint_type: internal
+    auth_type: password
+    deploy: True
+    power: present
+    config_drive: "{{lookup('file', '/var/lib/ironic/confdrive/{{ item.name }}.base64')}}"
+    uuid: "{{item.uuid}}"
+    instance_info:
+      root_gb: 10
+      image_source: "http://{{ansible_host}}:{{golden_image_http_port}}/guest-image.img"
+      image_checksum: "{{golden_img_md5sum.stat.md5}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase != "provisioning-started"
+
+- name: Verify node provisioning state. Waiting for 60mins max.
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_node_provision_check:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    nodes_details: "{{baremetal_ironic_nodes_ids}}"
+  register: baremetal_ironic_node_provisionin_results
+  until: provision_pending_list | length == 0
+  retries: 360
+  delay: 10
+  when:
+    - installation_phase == "provisioning-started"
+
+- name: Checking for any deployment failures
+  fail:
+    msg: "One or more nodes failed in deployment. {{baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] }}"
+  when:
+    - installation_phase == "provisioning-started"
+    - baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] | length > 0
+
+- name: Verify node provisioning state. Waiting for 60mins max.
+  os_node_provision_check:
+    cloud: default
+    endpoint_type: internal
+    auth_type: password
+    nodes_details: "{{baremetal_ironic_nodes_ids}}"
+  register: baremetal_ironic_node_provisionin_results
+  until: provision_pending_list | length == 0
+  retries: 360
+  delay: 10
+  when:
+    - installation_phase != "provisioning-started"
+
+- name: Checking for any deployment failures
+  fail:
+    msg: "One or more nodes failed in deployment. {{baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] }}"
+  when:
+    - installation_phase != "provisioning-started"
+    - baremetal_ironic_node_provisionin_results['ansible_facts']['provision_failed_list'] | length > 0
+
+# JanneS: until looping is a fix for the problem in wait_for module; it does not catch socket error in recv if peer closes the connection.
+- name: Verify remote node ssh ports active. Waiting for 60mins max.
+  wait_for:
+     host: "{{ item.node_ip[0] }}"
+     port: 22
+     search_regex: OpenSSH
+     sleep: 5
+     timeout: 3600
+  register: remote_success
+  until: remote_success | success
+  retries: 3
+  with_items: "{{net_conn_details}}"
+
+- name: Wait for remote node ssh login. Waiting for 10mins max.
+  become: "{{ ansible_env.SUDO_USER }}"
+  local_action: shell ssh -oBatchMode=yes -4 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null {{ item.node_ip[0] }} "echo success"
+  register: user_enabled
+  with_items: "{{net_conn_details}}"
+  until: user_enabled.stdout.find("success") != -1
+  retries: 90
+  delay: 10
+
+- name: Set Ironic maintenance mode to all nodes.
+  os_ironic_node:
+    cloud: default
+    endpoint_type: internal
+    auth_type: password
+    uuid: "{{item.name}}"
+    maintenance: True
+    deploy: False
+  with_items: "{{ baremetal_ironic_nodes }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase != "provisioning-started"
+
+- name: Set Ironic maintenance mode to all nodes.
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  os_ironic_node:
+    auth:
+    auth_type: 'None'
+    ironic_url: "{{ ironic_service_adminurl }}"
+    uuid: "{{item.name}}"
+    maintenance: True
+    deploy: False
+  with_items: "{{ baremetal_ironic_nodes }}"
+  loop_control:
+    label: "{{ item.name }}"
+  when:
+    - installation_phase == "provisioning-started"
diff --git a/roles/baremetal_provision/tasks/main.yml b/roles/baremetal_provision/tasks/main.yml
new file mode 100644 (file)
index 0000000..38b4675
--- /dev/null
@@ -0,0 +1,81 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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: convert_qcow_raw.yml
+
+- name: Convert baremetal_nodes.j2 Jinja2 template to json file
+  template:
+    src: 'baremetal_nodes.j2'
+    dest: '/tmp/baremetal_nodes.json'
+
+- name: Include variables from baremetal_nodes.json
+  include_vars: '/tmp/baremetal_nodes.json'
+
+- name: Remove /tmp/baremetal_nodes.json
+  file:
+    path: "/tmp/baremetal_nodes.json"
+    state: "absent"
+
+- name: Restore baremetal_ironic_nodes variable with ironic_nodes variable
+  set_fact:
+    baremetal_ironic_nodes: "{{ironic_nodes}}"
+  when: baremetal_ironic_nodes is undefined
+
+- name: Create vbmc ports for virtual hosts
+  include: vbmc_port_setup.yml
+  when: virtual_env
+
+- set_fact:
+    net_conn_details: "{{net_conn_details + [{'node_name': item.name, 'node_ip': item.driver_info.power.os_net_config | json_query('network_config[*].addresses[0].ip_netmask') |  ipaddr('address')}] }}"
+  with_items: "{{ baremetal_ironic_nodes }}"
+  when: item.driver_info.power.os_net_config.network_config[0].type != 'ovs_bridge'
+  no_log: True
+
+- set_fact:
+    net_conn_details: "{{net_conn_details + [{'node_name': item.name, 'node_ip': item.driver_info.power.os_net_config | json_query('network_config[*].members[*].addresses[0].ip_netmask')|first | ipaddr('address')}] }}"
+  with_items: "{{ baremetal_ironic_nodes }}"
+  when: item.driver_info.power.os_net_config.network_config[0].type == 'ovs_bridge'
+  no_log: True
+
+- include: setup_http.yml
+  tags: http_provision
+
+- name: Setup tmux
+  copy:
+    src: "tmux_setup"
+    dest: "/opt/"
+
+- include: ironic_nodes_create.yml
+  tags:
+    - baremetal-ironic-nodes-create
+
+- include: start_console_logging.yml
+  tags:
+    - baremetal-ironic-nodes-deploy
+  when: virtual_env == false
+
+- include: ironic_nodes_deploy.yml
+  tags:
+    - baremetal-ironic-nodes-deploy
+
+- include: stop_console_logging.yml
+  tags:
+    - baremetal-ironic-nodes-deploy
+  when: virtual_env == false
+
+- include: teardown_http.yml
+  tags: http_provision
diff --git a/roles/baremetal_provision/tasks/setup_http.yml b/roles/baremetal_provision/tasks/setup_http.yml
new file mode 100644 (file)
index 0000000..ffe2caa
--- /dev/null
@@ -0,0 +1,39 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create a directory for nginx
+  file:
+    path: "/opt/guest-img-nginx/"
+    state: directory
+    mode: 0755
+
+- name: Create nginx conf file
+  template:
+    src: "guest-img-nginx.conf.j2"
+    dest: "/opt/guest-img-nginx/nginx.conf"
+
+- name: Create nginx service for provisioning
+  copy:
+    src: "guest-img-nginx.service"
+    dest: "/usr/lib/systemd/system/"
+
+- name: start guest-img-nginx.service service
+  systemd:
+      name: guest-img-nginx.service
+      enabled: no
+      masked: no
+      state: started
+      daemon_reload: yes
diff --git a/roles/baremetal_provision/tasks/start_console_logging.yml b/roles/baremetal_provision/tasks/start_console_logging.yml
new file mode 100644 (file)
index 0000000..061c722
--- /dev/null
@@ -0,0 +1,61 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Deactivate ipmi sol
+  command: "/usr/bin/ipmitool -I lanplus -H {{hosts[item.name]['hwmgmt']['address']}} -U {{hosts[item.name]['hwmgmt']['user']}} -P {{hosts[item.name]['hwmgmt']['password']}} sol deactivate"
+  with_items: "{{baremetal_ironic_nodes_ids}}"
+  ignore_errors: yes
+  no_log: True
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Disable shellinabox console logging for target nodes
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  command: "ironic node-set-console-mode {{item.name}} false"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  when:
+    - installation_phase == "provisioning-started"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Disable shellinabox console logging for target nodes
+  command: "openstack --os-cloud default baremetal node console disable {{item.name}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  when:
+    - installation_phase != "provisioning-started"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Create directories for tmux
+  file:
+    path: "{{item}}"
+    state: directory
+    mode: u=rwx,g=rwx,o=rwx
+  with_items:
+    - "/var/log/ironic/console_logs"
+    - "/tmp/tmp_console"
+
+- name: Start tmux console session
+  shell: "source /opt/tmux_setup/tmux.inc; tmux_session_start bash /bin/bash"
+
+- name: Start tmux windows for each nodes
+  shell: "source /opt/tmux_setup/tmux.inc; tmux_cmd {{item.name}} /usr/bin/ipmitool -I lanplus -H {{hosts[item.name]['hwmgmt']['address']}} -U {{hosts[item.name]['hwmgmt']['user']}} -P {{hosts[item.name]['hwmgmt']['password']}} sol activate"
+  no_log: True
+  with_items: "{{baremetal_ironic_nodes_ids}}"
+  loop_control:
+    label: "{{ item.name }}"
diff --git a/roles/baremetal_provision/tasks/stop_console_logging.yml b/roles/baremetal_provision/tasks/stop_console_logging.yml
new file mode 100644 (file)
index 0000000..1e4cd35
--- /dev/null
@@ -0,0 +1,56 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Stop tmux console windows
+  shell: "source /opt/tmux_setup/tmux.inc; tmux_kill {{item.name}}"
+  with_items: "{{baremetal_ironic_nodes_ids}}"
+  ignore_errors: yes
+  loop_control:
+    label: "{{ item.name }}"
+
+
+- name: Stop tmux console session
+  shell: "source /opt/tmux_setup/tmux.inc; tmux_kill tmux-session-deploy"
+  ignore_errors: yes
+
+- name: Deactivate ipmi sol
+  command: "/usr/bin/ipmitool -I lanplus -H {{hosts[item.name]['hwmgmt']['address']}} -U {{hosts[item.name]['hwmgmt']['user']}} -P {{hosts[item.name]['hwmgmt']['password']}} sol deactivate"
+  with_items: "{{baremetal_ironic_nodes_ids}}"
+  ignore_errors: yes
+  no_log: True
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Enable shellinabox console logging for target nodes
+  environment:
+    OS_AUTH_TOKEN: "fake-token"
+    IRONIC_URL: "{{ ironic_service_adminurl }}"
+  command: "ironic node-set-console-mode {{item.name}} true"
+  with_items:
+    - "{{ baremetal_ironic_nodes_ids }}"
+    - {"name": "{{installation_controller}}"}
+  when:
+    - installation_phase == "provisioning-started"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Enable shellinabox console logging for target nodes
+  command: "openstack --os-cloud default baremetal node console enable {{item.name}}"
+  with_items: "{{ baremetal_ironic_nodes_ids }}"
+  when:
+    - installation_phase != "provisioning-started"
+  loop_control:
+    label: "{{ item.name }}"
diff --git a/roles/baremetal_provision/tasks/teardown_http.yml b/roles/baremetal_provision/tasks/teardown_http.yml
new file mode 100644 (file)
index 0000000..4a1ba70
--- /dev/null
@@ -0,0 +1,22 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: stop guest-img-nginx.service service
+  systemd:
+      name: guest-img-nginx.service
+      enabled: no
+      masked: no
+      state: stopped
diff --git a/roles/baremetal_provision/tasks/vbmc_port_setup.yml b/roles/baremetal_provision/tasks/vbmc_port_setup.yml
new file mode 100644 (file)
index 0000000..7061aa3
--- /dev/null
@@ -0,0 +1,42 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create a directory for virtualbmc.conf
+  file:
+    path: "/etc/virtualbmc/"
+    state: directory
+    mode: 0755
+
+- name: Copy in virtualbmc.conf file
+  copy:
+    src: "virtualbmc.conf"
+    dest: "/etc/virtualbmc/"
+
+- name: Create vbmc nodes
+  command: /usr/bin/vbmc add {{ item.name }} --libvirt-uri "qemu+ssh://root@{{item.driver_info['power']['ssh_address'] | ipwrap}}/system?no_verify=1" --port {{ item.driver_info['power']['ipmi_port'] }}
+  become: True
+  become_flags: '-H'
+  register: vbmc_out
+  with_items: "{{ baremetal_ironic_nodes }}"
+  failed_when: "vbmc_out.rc != 0 and 'already exists' not in vbmc_out.stderr"
+  loop_control:
+    label: "{{ item.name }}"
+
+- name: Start vbmc node ports
+  command: sudo /usr/bin/vbmc start {{ item.name }}
+  with_items: "{{ baremetal_ironic_nodes }}"
+  loop_control:
+    label: "{{ item.name }}"
diff --git a/roles/baremetal_provision/templates/baremetal_nodes.j2 b/roles/baremetal_provision/templates/baremetal_nodes.j2
new file mode 100644 (file)
index 0000000..480d205
--- /dev/null
@@ -0,0 +1,291 @@
+{#
+This file is written with conditional check and for loop based indentation.
+It improved code readability. The output json is not pretty. Run cat <output.json> | python -m json.tool
+for pretty printing the same.
+#}
+
+{% macro generate_linux_bonding_options(options) -%}
+    {%- set mode_mapping = {'active-backup' : 'active-backup', 'lacp' : '802.3ad'} -%}
+    {%- set default_options = {
+                                'active-backup' : 'miimon=100',
+                                'lacp' : 'lacp_rate=fast miimon=100'
+                              } -%}
+    {%- for i in options.split() -%}
+        {%- set key, value = i.split('=') -%}
+        {%- if key == 'mode' -%}
+            {%- if default_options[value] -%}
+                {{ 'mode=' ~ mode_mapping[value] ~ ' ' ~ default_options[value] }}
+            {%- else -%}
+                {{ 'mode=' ~ mode_mapping[value] }}
+            {%- endif -%}
+        {%- endif -%}
+    {%- endfor -%}
+{%- endmacro %}
+
+{% macro generate_ovs_bonding_options(options) -%}
+    {%- set mode_mapping = {'active-backup' : 'active-backup', 'lacp' : 'balance-slb', 'lacp-layer34' : 'balance-tcp'} -%}
+    {%- set default_options = {
+                                'active-backup' : '',
+                                'lacp' : 'lacp=active other_config:lacp-time=fast other_config:bond-detect-mode=carrier',
+                                'lacp-layer34' : 'lacp=active other_config:lacp-time=fast other_config:bond-detect-mode=carrier'
+                              } -%}
+    {%- for i in options.split() -%}
+        {%- set key, value = i.split('=') -%}
+        {%- if key == 'mode' -%}
+            {%- if default_options[value] -%}
+                {{ 'bond_mode=' ~ mode_mapping[value] ~ ' ' ~ default_options[value] }}
+            {%- else -%}
+                {{ 'bond_mode=' ~ mode_mapping[value] }}
+            {%- endif -%}
+        {%- endif -%}
+    {%- endfor -%}
+{%- endmacro %}
+
+{% macro add_static_routes(routes) -%}
+    [
+    {%- for route in routes %}
+        {
+            "ip_netmask": "{{ route.to }}", "next_hop": "{{ route.via }}"
+        } {% if not loop.last %},{% endif %}
+    {%- endfor %}
+    ]
+{%- endmacro %}
+
+{%- set nfs_server_ip = hostvars[installation_controller]['networking']['infra_external']['ip'] %}
+{
+"ironic_nodes": [
+{% for host_key,host_value in hosts.iteritems() %}
+
+{%- set host_networking = hostvars[host_key]['networking'] %}
+{%- set host_network_profiles_list = hosts[host_key]['network_profiles'] %}
+{%- set host_network_profile_value = hostvars[host_key]['network_profiles'][host_network_profiles_list[0]] %}
+{%- set host_interface_net_mapping = host_network_profile_value['interface_net_mapping'] %}
+{%- set host_hdd_mapping = hostvars[host_key]['by_path_disks'] %}
+
+{%- set infra_bond = {'in_use': false} %}
+{%- if 'bonding_interfaces' in host_network_profile_value %}
+    {%- set host_bonding_interfaces = host_network_profile_value['bonding_interfaces'] %}
+{%- endif %}
+
+{%- set single_nic_setup = False %}
+{%- if 'provider_network_interfaces' in host_network_profile_value %}
+    {%- set host_provider_network_interfaces = host_network_profile_value['provider_network_interfaces'] %}
+    {%- if host_interface_net_mapping|length == 1 and host_provider_network_interfaces|length == 1 %}
+        {%- if host_interface_net_mapping.keys()[0] == host_provider_network_interfaces.keys()[0] %}
+            {%- set single_nic_setup = True %}
+        {%-endif %}
+    {%-endif %}
+{%-endif %}
+
+{%- set mtu = 1500 %}
+{%- if 'mtu' in host_networking['infra_internal'] %}
+    {%- set mtu = host_networking['infra_internal']['mtu'] %}
+{%- elif 'mtu' in host_networking %}
+    {%- set mtu = host_networking['mtu'] %}
+{%- endif %}
+
+{%- set phys_iface = {'mtu': 1500} %}
+{%- if 'vlan' in host_networking['infra_internal'] %}
+    {%- for iface,infras in host_interface_net_mapping.iteritems() %}
+        {%- if "infra_internal" in infras %}
+            {%- for infra in infras %}
+                {%- set tmp_mtu = 0 %}
+                {%- if 'mtu' in host_networking[infra] %}
+                    {%- set tmp_mtu = host_networking[infra]['mtu'] %}
+                {%- elif 'mtu' in host_networking %}
+                    {%- set tmp_mtu = host_networking['mtu'] %}
+                {%- endif %}
+                {%- if infra == 'cloud_tenant' %}
+                    {%- set tmp_mtu = tmp_mtu + 50 %}
+                {%- endif %}
+                {%- if tmp_mtu > phys_iface.mtu %}
+                    {%- if phys_iface.update({'mtu': tmp_mtu}) %}{%- endif %}
+                {%- endif %}
+            {%- endfor %}
+        {%- endif %}
+    {%- endfor %}
+{%- endif %}
+
+    {
+    "name": "{{ host_key }}",
+    "network_interface": "noop",
+    "nics":  [ {%- if 'mgmt_mac' in host_value %}
+                   {%- for mac_members in host_value['mgmt_mac'] %}
+                       {
+                       "mac": "{{ mac_members }}"
+                       }
+                       {%- if not loop.last %},{%- endif %}
+                   {%- endfor %}
+               {%- else: %}
+                   {
+                   "mac": "{{ hw_inventory_details[host_key]['mgmt_mac'] }}"
+                   }
+               {%- endif %}
+             ],
+    "driver_info": { "power": {
+        "os_net_config": {
+            "network_config": [
+            {%- if 'interface' in host_networking['infra_internal'] %}
+                {%- if not single_nic_setup %}
+                {%- if 'bonding_interfaces' in host_network_profile_value %}
+                    {%- for net_key,net_value in host_interface_net_mapping.iteritems() %}
+                        {%- if "bond" in net_key and "infra_internal" in net_value %}
+                        {
+                            "name": "{{net_key}}",
+                            "type": "linux_bond",
+                            "members": [
+                            {%- for member in host_bonding_interfaces[net_key] %}
+                            {
+                                {%- if 'bond' in host_networking['infra_internal']['interface'] %}
+                                    "mtu": {{mtu}},
+                                {%- else %}
+                                    "mtu": {{phys_iface['mtu']}},
+                                {%- endif %}
+                                "name": "{{ member }}",
+                                "type": "interface",
+                                "use_dhcp": false
+                            }    {%- if not loop.last %},{%- endif %}
+                            {% endfor %} ],
+                            {%- if 'linux_bonding_options' in host_network_profile_value %}
+                                "bonding_options": "{{ generate_linux_bonding_options(host_network_profile_value['linux_bonding_options']) }}",
+                            {%- endif %}
+                            {%- if 'bond' in host_networking['infra_internal']['interface'] %}
+                                "addresses": [ { "ip_netmask": "{{ host_networking['infra_internal']['ip'] }}/{{host_networking['infra_internal']['mask']}}" } ],
+                                "mtu": {{mtu}},
+                                {%- if 'routes' in host_networking['infra_internal'] %}
+                                    {%- set routes = host_networking['infra_internal']['routes'] %}
+                                    "routes": {{ add_static_routes(routes) }},
+                                {%- endif %}
+                            {%- else %}
+                                "mtu": {{phys_iface['mtu']}},
+                            {%- endif %}
+                            "use_dhcp": false
+                            {%- if infra_bond.update({'in_use': true}) %}{%- endif %}
+                        },
+                        {%- endif %}
+                    {%- endfor %}
+                {%- endif %}
+                {%- if 'vlan' in host_networking['infra_internal'] %}
+                    {
+                    "type": "vlan",
+                    "addresses": [ { "ip_netmask": "{{ host_networking['infra_internal']['ip'] }}/{{host_networking['infra_internal']['mask']}}" } ],
+                    "vlan_id": {{ host_networking['infra_internal']['vlan'] }},
+                    {%- for net_key,net_value in host_interface_net_mapping.iteritems() %}
+                        {%- if "infra_internal" in net_value %}
+                            "device": "{{net_key}}",
+                        {%- endif %}
+                    {%- endfor %}
+                    "mtu": {{mtu}},
+                    {%- if 'routes' in host_networking['infra_internal'] %}
+                        {%- set routes = host_networking['infra_internal']['routes'] %}
+                        "routes": {{ add_static_routes(routes) }},
+                    {%- endif %}
+                    "use_dhcp": false
+                    }
+                    {%- if not infra_bond.in_use %}
+                        ,
+                        {
+                        {%- for net_key,net_value in host_interface_net_mapping.iteritems() %}
+                            {%- if "infra_internal" in net_value %}
+                                "name": "{{net_key}}",
+                            {%- endif %}
+                        {%- endfor %}
+                        "type": "interface",
+                        "mtu": {{phys_iface['mtu']}},
+                        "use_dhcp": false
+                        }
+                    {%- endif %}
+                {%- elif not infra_bond.in_use %}
+                    {
+                    "name": "{{host_networking['infra_internal']['interface']}}",
+                    "type": "interface",
+                    "addresses": [ { "ip_netmask": "{{ host_networking['infra_internal']['ip'] }}/{{host_networking['infra_internal']['mask']}}" } ],
+                    "mtu": {{mtu}},
+                    {%- if 'routes' in host_networking['infra_internal'] %}
+                        {%- set routes = host_networking['infra_internal']['routes'] %}
+                        "routes": {{ add_static_routes(routes) }},
+                     {%- endif %}
+                    "use_dhcp": false
+                    }
+                {%- endif %}
+                {%- else %}{#- if not single_nic_setup -#}
+                    {
+                    "name": "br-pro0",
+                    "type": "ovs_bridge",
+                    "members": [
+                        {
+                        "mtu": {{phys_iface['mtu']}},
+                        {%- set iface = host_interface_net_mapping.keys()[0] %}
+                        {%- if 'bond' in iface %}
+                            {%- for bond_iface,bond_value in host_bonding_interfaces.iteritems() if bond_iface == iface %}
+                                {%- if 'ovs_bonding_options' in  host_network_profile_value %}
+                                    "ovs_options": "{{ generate_ovs_bonding_options(host_network_profile_value['ovs_bonding_options']) }}",
+                                {%- endif %}
+                                "name": "{{iface}}",
+                                "type": "ovs_bond",
+                                "members": [ {% for member in bond_value %}
+                                    {
+                                    "name": "{{ member }}",
+                                    "type": "interface",
+                                    "mtu": {{phys_iface['mtu']}},
+                                    "use_dhcp": false
+                                    }
+                                    {% if not loop.last %},{% endif %}
+                                {%- endfor %}
+                                ],
+                            {%- endfor %}
+                        {%- else %}
+                            "name": "{{iface}}",
+                            "type": "interface",
+                        {%- endif %}
+                        "use_dhcp": false
+                        }
+                        ,
+                        {
+                        {%- set infra = host_networking['infra_internal'] %}
+                        "type": "vlan",
+                        "vlan_id": {{ infra['vlan'] }},
+                        "addresses": [ { "ip_netmask": "{{ infra['ip'] }}/{{infra['mask']}}" } ],
+                        "mtu": {{mtu}},
+                        {%- if 'routes' in infra %}
+                            {%- set routes = infra['routes'] %}
+                            "routes": {{ add_static_routes(routes) }},
+                        {%- endif %}
+                        "use_dhcp": false
+                        }
+                    ]
+                    }
+                {%- endif %}{#- if not single_nic_setup -#}
+            {%- endif %}
+            ]
+        },
+    "provisioning_server": "{{nfs_server_ip}}",
+    "provisioning_server_http_port": "{{golden_image_http_port}}",
+    "virtmedia_deploy_iso": "file:///opt/images/ironic-deploy.iso",
+    {% if virtual_env == true %}
+        "ssh_address": "{{ host_value['hwmgmt']['address'] }}",
+        "ssh_key_contents": "{{ '{{' }} lookup('file', '/etc/userconfig/id_rsa') {{ '}}' }}",
+        "ssh_username": "{{ host_value['hwmgmt']['user'] }}",
+        "ipmi_address": "{{hostvars[installation_controller]['networking']['infra_internal']['ip']}}",
+        "ipmi_username": "admin",
+        "ipmi_password": "password",
+        "ipmi_port": "{{ hosts[host_key]['vbmc_port'] }}"
+        } },
+        "driver": "ssh_virtmedia",
+        "properties": { "capabilities": "boot_option:local", "cpu_arch": "x86_64", "cpus": 8, "disk_size": 40, "ram": 16384, "root_device":{ "by_path": "{{ host_hdd_mapping['os']}}" } }
+    {%- else %}
+        "ipmi_address": "{{ host_value['hwmgmt']['address'] }}",
+        "ipmi_password": "{{ host_value['hwmgmt']['password'] }}",
+        "ipmi_username": "{{ host_value['hwmgmt']['user'] }}",
+        "product_family": "{{ hw_inventory_details[host_key]['product_family'] }}",
+        "vendor": "{{ hw_inventory_details[host_key]['vendor'] }}"
+    }
+},
+        "driver": "ipmi_virtmedia",
+        "properties": { "capabilities": "boot_option:local", "cpu_arch": "x86_64", "cpus": 8, "disk_size": 40, "ram": 16384, "root_device":{ {% if host_hdd_mapping['os'] != "/dev/sda" %} "by_path": "{{ host_hdd_mapping['os']}}" {% else %} "name": "{{ host_hdd_mapping['os']}}" {% endif %} } }
+    {% endif %}
+    }
+    {% if not loop.last %},{% endif %}
+{%- endfor %}
+]
+}
diff --git a/roles/baremetal_provision/templates/guest-img-nginx.conf.j2 b/roles/baremetal_provision/templates/guest-img-nginx.conf.j2
new file mode 100644 (file)
index 0000000..1985655
--- /dev/null
@@ -0,0 +1,12 @@
+http{
+    server {
+            listen {{golden_image_http_port}};
+            root /opt/images/;
+            location / {
+            }
+            location /bootimages {
+                alias /remote_image_share_root/;
+            }
+        }
+    }
+events{}
diff --git a/roles/baremetal_provision/templates/guest-img-nginx.service b/roles/baremetal_provision/templates/guest-img-nginx.service
new file mode 100644 (file)
index 0000000..a9d19a7
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+[Unit]
+Description=The nginx HTTP for hosting guest-image.img during ironic node provisioning
+After=network.target remote-fs.target nss-lookup.target
+
+[Service]
+Type=forking
+PIDFile=/run/guest-img-nginx.pid
+# Nginx will fail to start if /run/guest-img-nginx.pid already exists but has the wrong
+# SELinux context. This might happen when running `nginx -t` from the cmdline.
+# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
+ExecStartPre=/usr/bin/rm -f /run/guest-img-nginx.pid
+ExecStartPre=/usr/sbin/nginx -t -c /opt/guest-img-nginx/nginx.conf
+ExecStart=/usr/sbin/nginx -c /opt/guest-img-nginx/nginx.conf
+ExecReload=/bin/kill -s HUP $MAINPID
+KillSignal=SIGQUIT
+TimeoutStopSec=5
+KillMode=process
+#PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/baremetal_provision/templates/meta_data.json.j2 b/roles/baremetal_provision/templates/meta_data.json.j2
new file mode 100644 (file)
index 0000000..6c47cb3
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "availability_zone": "",
+    "hostname": "{{item[0].name}}",
+    "launch_index": 0,
+    "name": "{{item[0].name}}",
+    "uuid": ""
+}
+
diff --git a/roles/baremetal_provision/templates/nginx.conf b/roles/baremetal_provision/templates/nginx.conf
new file mode 100644 (file)
index 0000000..1c8a4d5
--- /dev/null
@@ -0,0 +1,50 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# For more information on configuration, see:
+#   * Official English Documentation: http://nginx.org/en/docs/
+#   * Official Russian Documentation: http://nginx.org/ru/docs/
+
+worker_processes auto;
+error_log /var/log/guest-img-nginx-error.log;
+pid /run/guest-img-nginx.pid;
+
+# Load dynamic modules. See /usr/share/nginx/README.dynamic.
+include /usr/share/nginx/modules/*.conf;
+
+events {
+    worker_connections 1024;
+}
+
+http {
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log  /var/log/guest-img-nginx-access.log  main;
+
+    sendfile            on;
+    tcp_nopush          on;
+    tcp_nodelay         on;
+    keepalive_timeout   65;
+    types_hash_max_size 2048;
+
+    include             /etc/nginx/mime.types;
+    default_type        application/octet-stream;
+
+    # Load modular configuration files from the /opt/guest-img-nginx/conf.d directory.
+    include /opt/guest-img-nginx/guest-img-nginx.conf;
+
+
+}
diff --git a/roles/baremetal_provision/templates/user_data.j2 b/roles/baremetal_provision/templates/user_data.j2
new file mode 100644 (file)
index 0000000..16dbace
--- /dev/null
@@ -0,0 +1,34 @@
+Content-Type: multipart/mixed; boundary="===============9156907225490855809=="
+MIME-Version: 1.0
+
+--===============9156907225490855809==
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename
+
+#cloud-config
+disable_root: 0
+ssh_pwauth: 1
+cloud_init_modules: [migrator, bootcmd, write-files, update_etc_hosts, rsyslog, users-groups, ssh]
+preserve_hostname: true
+manage-resolv-conf: false
+users:
+  - name: "{{users.admin_user_name}}"
+    sudo: ['ALL=(ALL) NOPASSWD:ALL']
+    ssh-authorized-keys:
+      - "{{ lookup('file', ansible_env.PWD + '/.ssh/id_rsa.pub') }}"
+    passwd: {{users.admin_user_password}}
+    lock_passwd: False
+
+--===============9156907225490855809==
+Content-Type: text/cloud-boothook; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename="boothook.sh"
+
+#!/bin/bash
+mkdir -p /etc/os-net-config/
+echo '{{lookup('file', '/tmp/'+item[0].name+'_config.yaml')}}' > /etc/os-net-config/config.yaml
+/usr/bin/os-net-config
+--===============9156907225490855809==--
diff --git a/roles/bootstrap-host/defaults/main.yml b/roles/bootstrap-host/defaults/main.yml
new file mode 100644 (file)
index 0000000..9bfefa0
--- /dev/null
@@ -0,0 +1,216 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+## AIO user-space configuration options
+# Scenario used to bootstrap the host
+bootstrap_host_scenario: aio
+#
+# Boolean option to implement OpenStack-Ansible configuration for an AIO
+# Switch to no for a multi-node configuration
+bootstrap_host_aio_config: yes
+#
+# Path to the location of the bootstrapping configuration files
+bootstrap_host_aio_config_path: "{{ playbook_dir }}/../etc/openstack_deploy"
+#
+
+bootstrap_host_aio_config_name: "openstack_user_config.yml.aio"
+
+# Path to the location of the scripts the bootstrap scripts use
+bootstrap_host_aio_script_path: "{{ playbook_dir }}/../scripts"
+#
+# The user space configuration file names to use
+bootstrap_host_user_variables_filename: "user_variables.yml"
+bootstrap_host_user_secrets_filename: "user_secrets.yml"
+
+## Swap memory
+# If there is no swap memory present, the bootstrap will create a loopback disk
+# for the purpose of having swap memory available. Swap is required for some of
+# the services deployed and is useful for AIO's built with less than 16GB memory.
+# By default the swap size is set to 8GB unless the host memory is less than 8GB,
+# in which case it is set to 4GB.
+bootstrap_host_swap_size: "{% if ansible_memory_mb['real']['total'] < 8*1024 %}4{% else %}8{% endif %}"
+
+## Loopback volumes
+# Sparse loopback disks are used for Cinder, Swift and Nova (instance storage).
+# The size of the loopback volumes can be customized here (in gigabytes).
+#
+# Boolean option to deploy the loopback disk for Cinder
+bootstrap_host_loopback_cinder: yes
+# Size of the Cinder loopback disk in gigabytes (GB).
+bootstrap_host_loopback_cinder_size: 1024
+#
+# Boolean option to deploy the loopback disk for Swift
+bootstrap_host_loopback_swift: yes
+# Size of the Swift loopback disk in gigabytes (GB).
+bootstrap_host_loopback_swift_size: 1024
+#
+# Boolean option to deploy the loopback disk for Nova
+bootstrap_host_loopback_nova: yes
+# Size of the Nova loopback disk in gigabytes (GB).
+bootstrap_host_loopback_nova_size: 1024
+
+# Boolean option to deploy the OSD loopback disks and cluster UUID for Ceph
+bootstrap_host_ceph: "{{ (bootstrap_host_scenario == 'ceph') | bool }}"
+# Size of the Ceph OSD loopbacks
+bootstrap_host_loopback_ceph_size: 1024
+# Ceph OSDs to create on the AIO host
+ceph_osd_images:
+  - 'ceph1'
+  - 'ceph2'
+  - 'ceph3'
+
+## Network configuration
+# The AIO bootstrap configures bridges for use with the AIO deployment.
+# By default, these bridges are configured to be independent of any physical
+# interfaces, and they have their 'bridge_ports' set to 'none'.  However,
+# deployers can add a physical interface to 'bridge_ports' to connect the
+# bridge to a real physical interface.
+#
+# A setting of 'none' keeps the bridges as independent from physical
+# interfaces (the default).
+#
+# Setting the value to 'eth1' would mean that the bridge is directly connected
+# to the eth1 device.
+#
+# See https://wiki.debian.org/BridgeNetworkConnections for more details.
+bootstrap_host_bridge_mgmt_ports: none
+bootstrap_host_bridge_vxlan_ports: none
+bootstrap_host_bridge_storage_ports: none
+bootstrap_host_bridge_vlan_ports: "br-vlan-veth"
+# This enables the VXLAN encapsulation the traditional bridges
+# (br-mgmt, br-vxlan, br-storage)
+bootstrap_host_encapsulation_enabled: "{{ not bootstrap_host_aio_config | bool }}"
+#
+# Default network IP ranges
+mgmt_range: "172.29.236"
+vxlan_range: "172.29.240"
+storage_range: "172.29.244"
+vlan_range: "172.29.248"
+netmask: "255.255.252.0"
+#
+# NICs
+bootstrap_host_public_interface: "{{ ansible_default_ipv4.interface }}"
+bootstrap_host_encapsulation_interface: eth1
+#
+#Encapsulations
+bootstrap_host_encapsulation_interfaces:
+  encap-mgmt:
+    id: 236
+    underlay_device: "{{ bootstrap_host_encapsulation_interface }}"
+    friendly_name: "Encapsulation of br-mgmt with VXLAN"
+  encap-vxlan:
+    id: 240
+    underlay_device: "{{ bootstrap_host_encapsulation_interface }}"
+    friendly_name: "Encapsulation of br-vxlan with VXLAN"
+  encap-storage:
+    id: 244
+    underlay_device: "{{ bootstrap_host_encapsulation_interface }}"
+    friendly_name: "Encapsulation of br-storage with VXLAN"
+  encap-vlan:
+    id: 248
+    underlay_device: "{{ bootstrap_host_encapsulation_interface }}"
+    friendly_name: "Encapsulation of br-vlan with VXLAN"
+#
+# Bridges
+bridges:
+  - name: "br-mgmt"
+    ip_addr: "172.29.236.100"
+    netmask: "255.255.252.0"
+  - name: "br-vxlan"
+    ip_addr: "172.29.240.100"
+    netmask: "255.255.252.0"
+  - name: "br-storage"
+    ip_addr: "172.29.244.100"
+    netmask: "255.255.252.0"
+  - name: "br-vlan"
+    ip_addr: "172.29.248.100"
+    alias: "172.29.248.1"
+    veth_peer: "eth12"
+    netmask: "255.255.252.0"
+
+bootstrap_host_bridges_interfaces:
+  br-mgmt:
+    ports: "{{ bootstrap_host_encapsulation_enabled | bool | ternary ('encap-mgmt', bootstrap_host_bridge_mgmt_ports) }}"
+    ip_address_range: "{{ mgmt_range }}"
+    ip_netmask: "{{ netmask }}"
+  br-storage:
+    ports: "{{ bootstrap_host_encapsulation_enabled | bool | ternary ('encap-storage', bootstrap_host_bridge_storage_ports) }}"
+    ip_address_range: "{{ storage_range }}"
+    ip_netmask: "{{ netmask }}"
+  br-vxlan:
+    ports: "{{ bootstrap_host_encapsulation_enabled | bool | ternary ('encap-vxlan', bootstrap_host_bridge_vxlan_ports) }}"
+    ip_address_range: "{{ vxlan_range }}"
+    ip_netmask: "{{ netmask }}"
+  br-vlan:
+    mode: "{{ bridge_vlan_inet_mode | default('static') }}"
+    ports: "{{ bootstrap_host_encapsulation_enabled | bool | ternary ('encap-vlan', bootstrap_host_bridge_vlan_ports) }}"
+    ip_address_range: "{{ vlan_range }}"
+    ip_netmask: "{{ netmask }}"
+    state_change_scripts: "{{ bridge_vlan_state_change_scripts }}"
+#
+# Convenience scripts
+bridge_vlan_state_change_scripts: |
+  pre-up ip link add br-vlan-veth type veth peer name eth12 || true
+  pre-up ip link set br-vlan-veth up
+  pre-up ip link set eth12 up
+  post-down ip link del br-vlan-veth || true
+bridge_iptables_rules: |
+  # To ensure ssh checksum is correct
+  up /sbin/iptables -A POSTROUTING -t mangle -p tcp -o {{ bootstrap_host_public_interface }} -j CHECKSUM --checksum-fill
+  down /sbin/iptables -D POSTROUTING -t mangle -p tcp -o {{ bootstrap_host_public_interface }} -j CHECKSUM --checksum-fill
+  # To provide internet connectivity to instances
+  up /sbin/iptables -t nat -A POSTROUTING -o {{ bootstrap_host_public_interface }} -j MASQUERADE
+  down /sbin/iptables -t nat -D POSTROUTING -o {{ bootstrap_host_public_interface }} -j MASQUERADE
+
+## Extra storage
+# An AIO may optionally be built using a second storage device. If a
+# secondary disk device to use is not specified, then the AIO will be
+# built on any existing disk partitions.
+#
+# WARNING: The data on a secondary storage device specified here will
+# be destroyed and repartitioned.
+#
+# Specify the secondary disk device to use.
+bootstrap_host_data_disk_device: null
+#
+# Boolean value to force the repartitioning of the secondary device.
+bootstrap_host_data_disk_device_force: no
+#
+# If the storage capacity on this device is greater than or equal to this
+# size (in GB), the bootstrap process will use it.
+bootstrap_host_data_disk_min_size: 50
+
+### Optional Settings ###
+
+# Set the apt repository URL's configured for the host and containers.
+# By default the configuration will be derived from the host.
+#bootstrap_host_ubuntu_repo: http://archive.ubuntu.com/ubuntu/
+#bootstrap_host_ubuntu_security_repo: http://archive.ubuntu.com/ubuntu/
+
+# Set the components that will be included in the apt repository configuration
+bootstrap_host_apt_components:
+  - main
+  - universe
+
+# Specify the public IP address for the host.
+# By default the address will be set to the ipv4 address of the
+# host's network interface that has the default route on it.
+#bootstrap_host_public_address: 0.0.0.0
+
+
+sudo_user: "ncioadmin"
+# password: ncioadmin
+# Generated with command "openssl passwd -1 -salt ncioadmin ncioadmin"
+sudo_user_password: "$1$ncioadmi$vDa1mNhcMDKMBSI27RqW51"
diff --git a/roles/bootstrap-host/tasks/check-requirements.yml b/roles/bootstrap-host/tasks/check-requirements.yml
new file mode 100644 (file)
index 0000000..5cf0d97
--- /dev/null
@@ -0,0 +1,88 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Check for a supported Operating System
+  assert:
+    that:
+      - (ansible_distribution == 'Ubuntu' and ansible_distribution_release == 'xenial') or
+        (ansible_os_family == 'RedHat' and ansible_distribution_major_version == '7')
+    msg: "The only supported platforms for this release are Ubuntu 16.04 LTS (Xenial) and CentOS 7 (WIP)"
+  tags:
+    - check-operating-system
+
+- name: Identify the space available in /
+  shell: |
+    df -BK / | awk '/^[^Filesystem]/ {print $4}' | sed 's/K//'
+  when: bootstrap_host_data_disk_device == None
+  changed_when: false
+  register: root_space_available
+  tags:
+    - check-disk-size
+
+# Convert root_space_available to bytes.
+- name: Set root disk facts
+  set_fact:
+    host_root_space_available_bytes: "{{ ( root_space_available.stdout | int) * 1024 | int }}"
+  when:
+    - bootstrap_host_data_disk_device == None
+  tags:
+    - check-disk-size
+
+- name: Set data disk facts
+  set_fact:
+    host_data_disk_sectors: "{{ (ansible_devices[bootstrap_host_data_disk_device]['sectors'] | int) }}"
+    host_data_disk_sectorsize: "{{ (ansible_devices[bootstrap_host_data_disk_device]['sectorsize'] | int) }}"
+  when:
+    - bootstrap_host_data_disk_device != None
+  tags:
+    - check-disk-size
+
+# Calculate the size of the bootstrap_host_data_disk_device by muliplying sectors with sectorsize.
+- name: Calculate data disk size
+  set_fact:
+    host_data_disk_size_bytes: "{{ ((host_data_disk_sectors | int) * (host_data_disk_sectorsize | int)) | int }}"
+  when: bootstrap_host_data_disk_device != None
+  tags:
+    - check-disk-size
+
+# Convert bootstrap_host_data_disk_min_size to bytes.
+- name: Set min size fact
+  set_fact:
+    host_data_disk_min_size_bytes: "{{ ((bootstrap_host_data_disk_min_size | int) * 1024**3) | int }}"
+  tags:
+    - check-disk-size
+
+- name: Fail if there is not enough space available in /
+  assert:
+    that: |
+      (host_root_space_available_bytes | int) >= (host_data_disk_min_size_bytes | int)
+  when: bootstrap_host_data_disk_device == None
+  tags:
+    - check-disk-size
+
+- name: Fail if there is not enough disk space available (disk specified)
+  assert:
+    that: |
+      (host_data_disk_size_bytes | int) >= (host_data_disk_min_size_bytes | int)
+  when: bootstrap_host_data_disk_device != None
+  tags:
+    - check-disk-size
+
+- name: Ensure that the kernel has VXLAN support
+  modprobe:
+    name: vxlan
+    state: present
+  tags:
+    - check-vxlan
diff --git a/roles/bootstrap-host/tasks/create_sudo_user.yml b/roles/bootstrap-host/tasks/create_sudo_user.yml
new file mode 100644 (file)
index 0000000..bfab595
--- /dev/null
@@ -0,0 +1,77 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+
+- name: Create Sudo user and ssh key pair for it.
+  user:
+    name: "{{ sudo_user }}"
+    password: "{{ sudo_user_password }}"
+    generate_ssh_key: yes
+    ssh_key_bits: 2048
+    ssh_key_file: .ssh/id_rsa
+  tags:
+    - ssh-key-generate
+
+- name: Add to sudoer list
+  copy:
+    content: "{{ sudo_user }} ALL=(ALL) NOPASSWD:ALL"
+    dest: "/etc/sudoers.d/{{ sudo_user }}"
+    mode: 0440
+
+- name: Fetch the generated public ssh key
+  fetch:
+    src: "/home/{{ sudo_user }}/.ssh/id_rsa.pub"
+    dest: "/tmp/id_rsa.pub"
+    flat: yes
+  when: inventory_hostname == groups['all'][0]
+  tags:
+    - ssh-key-authorized
+
+- name: Ensure root's new public ssh key is in authorized_keys
+  authorized_key:
+    user: "{{ sudo_user }}"
+    key: "{{ lookup('file','/tmp/id_rsa.pub') }}"
+    manage_dir: no
+  tags:
+    - ssh-key-authorized
+
+- name: Ensure there is a private key /etc/userconfig/id_rsa in virtual env. Provide read permissions to all users
+  file:
+    path: "/etc/userconfig/id_rsa"
+    mode: 0644
+  when: facter_virtual == "kvm"
+
+- name: Ensure root has a .ssh directory
+  file:
+    path: /root/.ssh
+    state: directory
+    owner: root
+    group: root
+    mode: 0700
+  when: facter_virtual == "kvm"
+
+- name: Copy /etc/userconfig/id_rsa /root/.ssh/id_rsa
+  copy:
+    src: /etc/userconfig/id_rsa
+    dest: /root/.ssh/id_rsa
+    owner: root
+    group: root
+    mode: 0400
+  when: facter_virtual == "kvm"
+
+- name: Default http config listens on port 80, comment it.
+  lineinfile:
+    path: "/etc/httpd/conf/httpd.conf"
+    line: "Listen 80"
+    state: "absent"
diff --git a/roles/bootstrap-host/tasks/install_packages.yml b/roles/bootstrap-host/tasks/install_packages.yml
new file mode 100644 (file)
index 0000000..19c1805
--- /dev/null
@@ -0,0 +1,114 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+# Ubuntu
+- block:
+  - name: Ensure that apt supports HTTPS package sources
+    apt:
+      name: apt-transport-https
+      state: present
+    tags:
+      - apt-install-prerequisites
+
+  - name: Determine the existing Ubuntu repo configuration
+    command: 'grep -oP "^deb \K(\[?.*\]?.*ubuntu\S*\/?)(?= {{ ansible_distribution_release }} main)" /etc/apt/sources.list'
+    register: ubuntu_repo
+    when:
+      - bootstrap_host_ubuntu_repo is not defined
+    changed_when: false
+    tags:
+      - find-apt-repo
+
+  - name: Determine the existing Ubuntu Security repo configuration
+    command: 'grep -oP "^deb \K(\[?.*\]?.*ubuntu\S*\/?)(?= {{ ansible_distribution_release }}-security main)" /etc/apt/sources.list'
+    register: ubuntu_security_repo
+    when:
+      - bootstrap_host_ubuntu_security_repo is not defined
+    changed_when: false
+    tags:
+      - find-apt-security-repo
+
+  - name: Set apt repo facts based on discovered information
+    set_fact:
+      bootstrap_host_ubuntu_repo: "{{ ubuntu_repo.stdout_lines[0] }}"
+      bootstrap_host_ubuntu_security_repo: "{{ ubuntu_security_repo.stdout_lines[0] }}"
+    when:
+      - bootstrap_host_ubuntu_repo is not defined
+      - bootstrap_host_ubuntu_security_repo is not defined
+      - ubuntu_repo is defined
+      - ubuntu_security_repo is defined
+
+  - name: Configure apt's sources.list (Ubuntu only)
+    template:
+      src: apt-sources.list.j2
+      dest: /etc/apt/sources.list
+      backup: yes
+    when:
+      - ansible_distribution == 'Ubuntu'
+      - bootstrap_host_ubuntu_repo is defined
+      - bootstrap_host_ubuntu_security_repo is defined
+    register: apt_sources_configure
+
+  - name: Update apt-cache
+    apt:
+      update_cache: yes
+    when:
+      - apt_sources_configure is defined
+      - apt_sources_configure | changed
+    tags:
+      - apt-cache-update
+
+  when:
+    - ansible_pkg_mgr == 'apt'
+
+# CentOS
+- block:
+  - name: Install RDO package
+    package:
+      name: "{{ rdo_package }}"
+      state: "present"
+    register: install_cloud_rdo_package
+    until: install_cloud_rdo_package | success
+    retries: 5
+    delay: 2
+
+  - name: Install epel package
+    package:
+      name: "{{ epel_package }}"
+      state: "present"
+    register: install_epel_package
+    until: install_epel_package | success
+    retries: 5
+    delay: 2
+
+  when:
+    - ansible_pkg_mgr == 'yum'
+
+- name: Remove known problem packages
+  package:
+    name: "{{ item }}"
+    state: absent
+  with_items: "{{ packages_remove }}"
+  tags:
+    - remove-packages
+
+- name: Install packages
+  package:
+    name: "{{ item }}"
+    state: present
+  with_items: "{{ packages_install }}"
+  tags:
+    - install-packages
+
diff --git a/roles/bootstrap-host/tasks/main.yml b/roles/bootstrap-host/tasks/main.yml
new file mode 100644 (file)
index 0000000..927001f
--- /dev/null
@@ -0,0 +1,141 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+# Before we do anything, check the minimum requirements
+- include: check-requirements.yml
+  tags:
+    - check-requirements
+
+# We will look for the most specific variable files first and eventually
+# end up with the least-specific files.
+- name: Gather variables for each operating system
+  include_vars: "{{ item }}"
+  with_first_found:
+    - "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml"
+    - "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
+    - "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
+    - "{{ ansible_distribution | lower }}.yml"
+    - "{{ ansible_os_family | lower }}.yml"
+  tags:
+    - always
+
+- name: Create the required directories
+  file:
+    path: "{{ item }}"
+    state: directory
+    mode: u=rwx,g=rwx,o=rwx
+  with_items:
+    - "/openstack"
+  tags:
+    - create-directories
+
+# Create sudo user
+- include: create_sudo_user.yml
+  tags:
+    - create-sudo-user
+
+- include: install_packages.yml
+  tags:
+    - install-packages
+
+# Prepare the data disk, if one is provided
+- include: prepare_data_disk.yml
+  when: bootstrap_host_data_disk_device != None
+  tags:
+    - prepare-data-disk
+
+# Prepare the swap space loopback disk
+# This is only necessary if there isn't swap already
+- include: prepare_loopback_swap.yml
+  when:
+    - ansible_swaptotal_mb < 1
+  tags:
+    - prepare-loopback-swap
+
+# Prepare the Cinder LVM VG loopback disk
+# This is only necessary if bootstrap_host_loopback_cinder is set to yes
+- include: prepare_loopback_cinder.yml
+  when:
+    - bootstrap_host_loopback_cinder | bool
+  tags:
+    - prepare-loopback-cinder
+
+# Prepare the Nova instance storage loopback disk
+- include: prepare_loopback_nova.yml
+  when:
+    - bootstrap_host_loopback_nova | bool
+  tags:
+    - prepare-loopback-nova
+
+# Prepare the Swift data storage loopback disks
+- include: prepare_loopback_swift.yml
+  when:
+    - bootstrap_host_loopback_swift | bool
+  tags:
+    - prepare-loopback-swift
+
+# Prepare the Ceph cluster UUID and loopback disks
+- include: prepare_ceph.yml
+  when:
+    - bootstrap_host_ceph | bool
+  tags:
+    - prepare-ceph
+
+# Prepare the network interfaces
+- include: prepare_networking.yml
+  tags:
+    - prepare-networking
+
+# Prepare the network interfaces using os-net-config
+- include: prepare_os_net_config.yml
+  tags:
+    - prepare-os-net-config
+
+# Ensure that there are both private and public ssh keys for root
+- include: prepare_ssh_keys.yml
+  tags:
+    - prepare-ssh-keys
+
+# Put the OpenStack-Ansible configuration for an All-In-One on the host
+- include: prepare_aio_config.yml
+  when: bootstrap_host_aio_config | bool
+  tags:
+    - prepare-aio-config
+
+# Change owner for /etc/openstack_deploy
+- name: Set permissions for /etc/openstack_deploy
+  file:
+    path: "/etc/openstack_deploy"
+    owner: "{{ sudo_user }}"
+    group: "{{ sudo_user }}"
+    recurse: yes
+    mode: 0700
+
+- name: 2nd phase, set different permissions only for /etc/openstack_deploy -directory
+  file:
+    path: "/etc/openstack_deploy"
+    owner: "{{ sudo_user }}"
+    group: "{{ sudo_user }}"
+    recurse: no
+    mode: u=rwX,g=rX,o=rX
+
+# Change owner of /etc/userconfig
+- name: Set permissions for /etc/userconfig
+  file:
+    path: "/etc/userconfig"
+    owner: "{{ sudo_user }}"
+    group: "{{ sudo_user }}"
+    recurse: yes
+    mode: 0700
diff --git a/roles/bootstrap-host/tasks/prepare_aio_config.yml b/roles/bootstrap-host/tasks/prepare_aio_config.yml
new file mode 100644 (file)
index 0000000..46c340f
--- /dev/null
@@ -0,0 +1,154 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+
+- name: Create the required deployment directories
+  file:
+    path: "{{ item }}"
+    state: directory
+    mode: u=rwx,g=rwx,o=rwx
+  with_items:
+    - "/etc/openstack_deploy/"
+    - "/etc/openstack_deploy/conf.d"
+  tags:
+    - create-directories
+
+
+- name: Deploy user conf.d configuration
+  config_template:
+    src: "{{ item.path | default(bootstrap_host_aio_config_path ~ '/conf.d') }}/{{ item.name }}"
+    dest: "/etc/openstack_deploy/conf.d/{{ item.name | regex_replace('.aio$', '') }}"
+    config_overrides: "{{ item.override | default({}) }}"
+    config_type: "yaml"
+  with_items: "{{ openstack_confd_entries | default([]) }}"
+  tags:
+    - deploy-confd
+
+- name: Deploy openstack_user_config
+  copy:
+    src: "{{ bootstrap_host_aio_config_path }}/{{ bootstrap_host_aio_config_name }}"
+    dest: "/etc/openstack_deploy/openstack_user_config.yml"
+  tags:
+    - deploy-openstack-user-config
+
+- name: Deploy user_secrets file
+  config_template:
+    src: "{{ bootstrap_host_aio_config_path }}/user_secrets.yml"
+    dest: "/etc/openstack_deploy/{{ bootstrap_host_user_secrets_filename }}"
+    config_overrides: "{{ user_secrets_overrides | default({}) }}"
+    config_type: "yaml"
+  tags:
+    - deploy-user-secrets
+
+- name: Generate any missing values in user_secrets
+  command: "{{ bootstrap_host_aio_script_path }}/pw-token-gen.py --file /etc/openstack_deploy/{{ bootstrap_host_user_secrets_filename }}"
+  changed_when: false
+  tags:
+    - generate_secrets
+
+- name: Detect whether the host is an OpenStack-CI host
+  stat:
+    path: /etc/nodepool
+  register: nodepool_dir
+
+- name: Set the UCA repository URL in OpenStack-CI
+  set_fact:
+    uca_apt_repo_url: "{{ bootstrap_host_ubuntu_repo | netorigin }}/ubuntu-cloud-archive"
+  when:
+    - nodepool_dir.stat.exists
+    - bootstrap_host_ubuntu_repo is defined
+
+- name: Set the package cache timeout to 60 mins in OpenStack-CI
+  set_fact:
+    cache_timeout: 3600
+  when:
+    - cache_timeout is not defined
+    - nodepool_dir.stat.exists
+
+- name: Determine if the host has a global pip config file
+  stat:
+    path: /etc/pip.conf
+  register: pip_conf_file
+
+- name: Determine the fastest available OpenStack-Infra wheel mirror
+  command: "{{ bootstrap_host_aio_script_path }}/fastest-infra-wheel-mirror.py"
+  register: fastest_wheel_mirror
+  when: not pip_conf_file.stat.exists
+
+- name: Set repo_build_pip_extra_indexes fact
+  set_fact:
+    repo_build_pip_extra_indexes: "{{ fastest_wheel_mirror.stdout_lines }}"
+  when: not pip_conf_file.stat.exists
+
+- name: Check whether the host has a git cache
+  stat:
+    path: /opt/git/openstack
+  register: _local_git_cache
+
+- name: Set repo_build_git_cache fact
+  set_fact:
+    repo_build_git_cache: /opt/git/openstack
+  when: _local_git_cache.stat.exists
+
+- name: Copy example user_variables
+  copy:
+    src: "{{ bootstrap_host_aio_config_path }}/{{ bootstrap_host_user_variables_filename }}"
+    dest: "/etc/openstack_deploy/user_variables.yml"
+
+- name: Create /etc/openstack_deploy/env.d/ directories
+  file:
+    path: "/etc/openstack_deploy/env.d/"
+    state: directory
+  when: bootstrap_env_file is defined
+
+- name: Copy example user_variables
+  copy:
+    src: "{{ bootstrap_env_file }}"
+    dest: "/etc/openstack_deploy/env.d/"
+  when: bootstrap_env_file is defined
+
+- name: Add user_conf_files to contain the list of files to copy into containers
+  file:
+    path: /etc/openstack_deploy/user_conf_files.yml
+    state: touch
+  when: pip_conf_file.stat.exists
+  tags:
+    - container-conf-files
+
+- name: Ensure that the first line in user_conf_files is correct
+  lineinfile:
+    dest: /etc/openstack_deploy/user_conf_files.yml
+    line: "---"
+    insertbefore: BOF
+  when: pip_conf_file.stat.exists
+  tags:
+    - container-conf-files
+
+- name: Ensure that the second line in user_conf_files is correct
+  lineinfile:
+    dest: /etc/openstack_deploy/user_conf_files.yml
+    line: "lxc_container_cache_files:"
+    insertafter: "^---"
+  when: pip_conf_file.stat.exists
+  tags:
+    - container-conf-files
+
+- name: Add the dict to copy the global pip config file into user_conf_files
+  lineinfile:
+    dest: /etc/openstack_deploy/user_conf_files.yml
+    line: " - { src: '/etc/pip.conf', dest: '/etc/pip.conf' }"
+  when: pip_conf_file.stat.exists
+  tags:
+    - container-conf-files
diff --git a/roles/bootstrap-host/tasks/prepare_ceph.yml b/roles/bootstrap-host/tasks/prepare_ceph.yml
new file mode 100644 (file)
index 0000000..e1794f3
--- /dev/null
@@ -0,0 +1,74 @@
+---
+# Copyright 2016, Logan Vig <logan2211@gmail.com>
+#
+# 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.
+
+- name: Create sparse ceph OSD files
+  command: truncate -s {{ bootstrap_host_loopback_ceph_size }}G /openstack/{{ item }}.img
+  args:
+    creates: "/openstack/{{ item }}.img"
+  with_items: "{{ ceph_osd_images }}"
+  register: ceph_create
+  changed_when: false
+  tags:
+    - ceph-file-create
+
+- name: Create the ceph loopback device
+  command: losetup -f /openstack/{{ item.item }}.img --show
+  with_items: "{{ ceph_create.results }}"
+  register: ceph_create_loopback
+  when: not item|skipped
+  changed_when: false
+  tags:
+    - skip_ansible_lint
+
+- name: Ensure that rc.local exists
+  file:
+    path: /etc/rc.local
+    state: touch
+    mode: "u+x"
+  tags:
+    - ceph-rc-file
+
+- name: Create ceph loopback at boot time
+  lineinfile:
+    dest: /etc/rc.local
+    line: "losetup -f /openstack/{{ item }}.img"
+  with_items: "{{ ceph_osd_images }}"
+
+# TODO(logan): Move these vars to user_variables.ceph.yml.j2 once LP #1649381
+# is fixed and eliminate this task.
+- name: Write ceph cluster config
+  copy:
+    content: |
+      ---
+      devices: {{ ceph_create_loopback.results | map(attribute='stdout') | list | to_yaml | trim }}
+      # The OSA ceph_client role does not support loading IPs from an inventory group,
+      # so we have to feed it a list of IPs
+      ceph_mons: "{% raw %}[ {% for host in groups[mon_group_name] %}'{{ hostvars[host]['ansible_host'] }}'{% if not loop.last %},{% endif %}{% endfor %} ]{% endraw %}"
+      cinder_backends:
+        "RBD":
+          volume_driver: cinder.volume.drivers.rbd.RBDDriver
+          rbd_pool: volumes
+          rbd_ceph_conf: /etc/ceph/ceph.conf
+          rbd_store_chunk_size: 8
+          volume_backend_name: rbddriver
+          rbd_user: cinder
+          rbd_secret_uuid: "{% raw %}{{ cinder_ceph_client_uuid }}{% endraw %}"
+          report_discard_supported: true
+    dest: /etc/openstack_deploy/user_ceph_aio.yml
+    force: no
+  become: false
+  when: not ceph_create_loopback|skipped
+  tags:
+    - skip_ansible_lint
diff --git a/roles/bootstrap-host/tasks/prepare_data_disk.yml b/roles/bootstrap-host/tasks/prepare_data_disk.yml
new file mode 100644 (file)
index 0000000..8cfd01c
--- /dev/null
@@ -0,0 +1,73 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+
+# Only execute the disk partitioning process if a partition labeled
+#  'openstack-data{1,2}' is not present and that partition is not
+#  formatted as ext4. This is an attempt to achieve idempotency just
+#  in case these tasks are executed multiple times.
+- name: Determine whether partitions labeled openstack-data{1,2} are present
+  shell: |
+    parted --script -l -m | egrep -q ':ext4:openstack-data[12]:;$'
+  register: data_disk_partitions
+  changed_when: false
+  failed_when: false
+  tags:
+    - check-data-disk-partitions
+
+- name: Dismount and remove fstab entries for anything on the data disk device
+  mount:
+    name: "{{ item.mount }}"
+    src: "{{ item.device }}"
+    fstype: ext4
+    state: absent
+  when:
+    - data_disk_partitions.rc == 1 or bootstrap_host_data_disk_device_force | bool
+    - item.device | search(bootstrap_host_data_disk_device)
+  with_items:
+    - "{{ ansible_mounts }}"
+
+- name: Partition the whole data disk for our usage
+  command: "{{ item }}"
+  when: data_disk_partitions.rc == 1 or bootstrap_host_data_disk_device_force | bool
+  with_items:
+    - "parted --script /dev/{{ bootstrap_host_data_disk_device | regex_replace('!','/') }} mklabel gpt"
+    - "parted --align optimal --script /dev/{{ bootstrap_host_data_disk_device | regex_replace('!','/') }} mkpart openstack-data1 ext4 0% 40%"
+    - "parted --align optimal --script /dev/{{ bootstrap_host_data_disk_device | regex_replace('!','/') }} mkpart openstack-data2 ext4 40% 100%"
+  tags:
+    - create-data-disk-partitions
+
+- name: Format the partitions
+  filesystem:
+    fstype: ext4
+    dev: "{{ item }}"
+  when: data_disk_partitions.rc == 1 or bootstrap_host_data_disk_device_force | bool
+  with_items:
+    - "/dev/{{ bootstrap_host_data_disk_device | regex_replace('!(.*)$','/\\1p') }}1"
+    - "/dev/{{ bootstrap_host_data_disk_device | regex_replace('!(.*)$','/\\1p') }}2"
+  tags:
+    - format-data-partitions
+
+- name: Create the mount points, fstab entries and mount the file systems
+  mount:
+    name: "{{ item.mount_point }}"
+    src: "{{ item.device }}"
+    fstype: ext4
+    state: mounted
+  with_items:
+    - { mount_point: /openstack, device: "/dev/{{ bootstrap_host_data_disk_device | regex_replace('!(.*)$','/\\1p') }}1"}
+    - { mount_point: /var/lib/lxc, device: "/dev/{{ bootstrap_host_data_disk_device | regex_replace('!(.*)$','/\\1p') }}2"}
+  tags:
+    - mount-data-partitions
diff --git a/roles/bootstrap-host/tasks/prepare_loopback_cinder.yml b/roles/bootstrap-host/tasks/prepare_loopback_cinder.yml
new file mode 100644 (file)
index 0000000..38fd224
--- /dev/null
@@ -0,0 +1,72 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Create sparse Cinder file
+  command: "truncate -s {{ bootstrap_host_loopback_cinder_size }}G /openstack/cinder.img"
+  args:
+    creates: /openstack/cinder.img
+  register: cinder_create
+  tags:
+    - cinder-file-create
+
+- name: Get a loopback device for cinder file
+  command: losetup -f
+  when: cinder_create | changed
+  register: cinder_losetup
+  tags:
+    - cinder-device-get
+
+- name: Create the loopback device
+  command: "losetup {{ cinder_losetup.stdout }} /openstack/cinder.img"
+  when: cinder_create | changed
+  tags:
+    - cinder-device-create
+
+- name: Ensure that rc.local exists
+  file:
+    path: "{{ rc_local }}"
+    state: touch
+    mode: "u+x"
+  tags:
+    - cinder-rc-file
+
+# As the cinder loopback is an LVM VG, it needs to be mounted differently
+#  to the other loopback files. It requires the use of rc.local to attach
+#  the loopback device on boot so that the VG becomes available immediately
+#  after the boot process completes.
+- name: Create loopback devices at boot time
+  lineinfile:
+    dest:  "{{ rc_local }}"
+    line: "losetup $(losetup -f) /openstack/cinder.img"
+    insertbefore: "{{ rc_local_insert_before }}"
+  tags:
+    - cinder-rc-config
+
+- name: Make LVM physical volume on the cinder device
+  command: "{{ item }}"
+  when: cinder_create | changed
+  with_items:
+    - "pvcreate {{ cinder_losetup.stdout }}"
+    - "pvscan"
+  tags:
+    - cinder-lvm-pv
+
+- name: Add cinder-volumes volume group
+  lvg:
+    vg: cinder-volumes
+    pvs: "{{ cinder_losetup.stdout }}"
+  when: cinder_create | changed
+  tags:
+    - cinder-lvm-vg
diff --git a/roles/bootstrap-host/tasks/prepare_loopback_nova.yml b/roles/bootstrap-host/tasks/prepare_loopback_nova.yml
new file mode 100644 (file)
index 0000000..37a6f89
--- /dev/null
@@ -0,0 +1,39 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Create sparse Nova file
+  command: "truncate -s {{ bootstrap_host_loopback_nova_size }}G /openstack/nova.img"
+  args:
+    creates: /openstack/nova.img
+  register: nova_create
+  tags:
+    - nova-file-create
+
+- name: Format the Nova file
+  filesystem:
+    fstype: ext4
+    dev: /openstack/nova.img
+  when: nova_create | changed
+  tags:
+    - nova-format-file
+
+- name: Create the mount points, fstab entries and mount the file systems
+  mount:
+    name: /var/lib/nova/instances
+    src: /openstack/nova.img
+    fstype: ext4
+    state: mounted
+  tags:
+    - nova-file-mount
diff --git a/roles/bootstrap-host/tasks/prepare_loopback_swap.yml b/roles/bootstrap-host/tasks/prepare_loopback_swap.yml
new file mode 100644 (file)
index 0000000..56c9ae7
--- /dev/null
@@ -0,0 +1,65 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- block:
+    - name: Check if swap is already enabled
+      command: grep /openstack/swap.img /proc/swaps
+
+  rescue:
+    - name: Create swap file
+      command: "{{ swap_create_command }}"
+      args:
+        creates: /openstack/swap.img
+      register: swap_create
+      tags:
+        - swap-file-create
+
+    - name: Set swap file permissions to 0600
+      file:
+        path: /openstack/swap.img
+        mode: 0600
+      tags:
+        - swap-permissions
+
+    - name: Format the swap file
+      command: mkswap /openstack/swap.img
+      when: swap_create | changed
+      tags:
+        - swap-format
+
+    - name: Ensure that the swap file entry is in /etc/fstab
+      mount:
+        name: none
+        src: /openstack/swap.img
+        fstype: swap
+        opts: sw
+        passno: 0
+        dump: 0
+        state: present
+      tags:
+        - swap-fstab
+
+    - name: Bring swap file online
+      command: swapon /openstack/swap.img
+      tags:
+        - swap-online
+
+- name: Set system swappiness
+  sysctl:
+    name: vm.swappiness
+    value: 10
+    state: present
+  tags:
+    - swap-sysctl
diff --git a/roles/bootstrap-host/tasks/prepare_loopback_swift.yml b/roles/bootstrap-host/tasks/prepare_loopback_swift.yml
new file mode 100644 (file)
index 0000000..4901942
--- /dev/null
@@ -0,0 +1,55 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Create sparse Swift files
+  command: "truncate -s {{ bootstrap_host_loopback_swift_size }}G /openstack/{{ item }}.img"
+  args:
+    creates: "/openstack/{{ item }}.img"
+  with_items:
+    - 'swift1'
+    - 'swift2'
+    - 'swift3'
+  register: swift_create
+  tags:
+    - swift-file-create
+
+- name: Format the Swift files
+  filesystem:
+    fstype: xfs
+    opts: '-K'
+    dev: "/openstack/{{ item }}.img"
+  when: swift_create | changed
+  with_items:
+    - 'swift1'
+    - 'swift2'
+    - 'swift3'
+  tags:
+    - swift-format-file
+
+- name: Create the Swift mount points, fstab entries and mount the file systems
+  mount:
+    name: "/srv/{{ item }}.img"
+    src: "/openstack/{{ item }}.img"
+    fstype: xfs
+    opts: 'loop,noatime,nodiratime,nobarrier,logbufs=8'
+    passno: 0
+    dump: 0
+    state: mounted
+  with_items:
+    - 'swift1'
+    - 'swift2'
+    - 'swift3'
+  tags:
+    - swift-file-mount
diff --git a/roles/bootstrap-host/tasks/prepare_networking.yml b/roles/bootstrap-host/tasks/prepare_networking.yml
new file mode 100644 (file)
index 0000000..3bebb8a
--- /dev/null
@@ -0,0 +1,134 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Ensure that /etc/network/interfaces.d/ exists (Debian)
+  file:
+    path: /etc/network/interfaces.d/
+    state: directory
+  tags:
+    - networking-dir-create
+  when:
+    - ansible_pkg_mgr == 'apt'
+
+- name: Copy AIO network configuration (Debian)
+  template:
+    src: osa_interfaces.cfg.j2
+    dest: /etc/network/interfaces.d/osa_interfaces.cfg
+  register: osa_interfaces
+  when:
+    - bootstrap_host_aio_config | bool
+    - ansible_pkg_mgr == 'apt'
+  tags:
+    - networking-interfaces-file
+
+- name: Copy network configuration (RedHat)
+  template:
+    src: "redhat_interface_{{ item.type | default('default') }}.cfg.j2"
+    dest: "/etc/sysconfig/network-scripts/ifcfg-{{ item.name | default('br-mgmt') }}"
+  with_items: "{{ bridges }}"
+  register: network_interfaces_rhel
+  when:
+    - ansible_pkg_mgr == 'yum'
+
+- name: Create alias file when required (RedHat)
+  template:
+    src: "redhat_interface_alias.cfg.j2"
+    dest: "/etc/sysconfig/network-scripts/ifcfg-{{ item.name | default('br-mgmt')}}:0"
+  with_items: "{{ bridges }}"
+  when:
+    - ansible_pkg_mgr == 'yum'
+    - item.alias is defined
+
+- name: Put down post-up script for veth-peer interfaces (RedHat)
+  template:
+    src: "redhat_interface_{{ item[0] | default('default') }}.cfg.j2"
+    dest: "/etc/sysconfig/network-scripts/{{ item[0] }}-veth-{{ item[1].name | default('br-mgmt') }}-2-{{ item[1].veth_peer | default('eth1') }}"
+    mode: "0755"
+  with_nested:
+    - [ "ifup-post", "ifdown-post" ]
+    - "{{ bridges }}"
+  when:
+    - item[1].veth_peer is defined
+    - ansible_pkg_mgr == 'yum'
+
+- name: Ensure the postup/postdown scripts are loaded (RedHat)
+  lineinfile:
+    dest: "/etc/sysconfig/network-scripts/{{ item[0] }}"
+    line: ". /etc/sysconfig/network-scripts/{{ item[0] }}-veth-{{ item[1].name | default('br-mgmt') }}-2-{{ item[1].veth_peer | default('eth1') }}"
+    insertbefore: "^exit 0"
+  with_nested:
+    - [ "ifup-post", "ifdown-post" ]
+    - "{{ bridges }}"
+  when:
+    - item[1].veth_peer is defined
+    - ansible_pkg_mgr == 'yum'
+
+- name: Copy multinode network configuration (Debian)
+  template:
+    src: osa_interfaces_multinode.cfg.j2
+    dest: /etc/network/interfaces.d/osa_interfaces.cfg
+  register: osa_multinode_interfaces
+  when:
+    - not bootstrap_host_aio_config | bool
+    - ansible_pkg_mgr == 'apt'
+  tags:
+    - networking-interfaces-file
+
+- name: Ensure our interfaces.d configuration files are loaded automatically (Debian)
+  lineinfile:
+    dest: /etc/network/interfaces
+    line: "source /etc/network/interfaces.d/*.cfg"
+  when:
+    - ansible_pkg_mgr == 'apt'
+  tags:
+    - networking-interfaces-load
+
+- name: Shut down the network interfaces
+  command: "ifdown {{ item.name }}"
+  when: osa_interfaces | changed or osa_multinode_interfaces | changed or network_interfaces_rhel | changed
+  with_items: "{{ bridges }}"
+  tags:
+    - networking-interfaces-stop
+
+- name: Shut down the encapsulation network interfaces
+  command: "ifdown {{ item.key }}"
+  when:
+   - osa_multinode_interfaces | changed
+   - bootstrap_host_encapsulation_enabled | bool
+  with_dict: "{{ bootstrap_host_encapsulation_interfaces }}"
+  tags:
+    - networking-interfaces-stop
+
+- name: Start the encapsulation network interfaces
+  command: "ifup {{ item.key }}"
+  when:
+    - osa_multinode_interfaces | changed
+    - bootstrap_host_encapsulation_enabled | bool
+  with_dict: "{{ bootstrap_host_encapsulation_interfaces }}"
+  tags:
+    - networking-interfaces-start
+
+- name: Start the network interfaces
+  command: "ifup {{ item.name }}"
+  when: osa_interfaces | changed or network_interfaces_rhel | changed
+  with_items: "{{ bridges }}"
+  tags:
+    - networking-interfaces-start
+
+- name: Updating the facts due to net changes
+  setup:
+    filter: "ansible_br*"
+  tags:
+    - networking
diff --git a/roles/bootstrap-host/tasks/prepare_os_net_config.yml b/roles/bootstrap-host/tasks/prepare_os_net_config.yml
new file mode 100644 (file)
index 0000000..6417f8d
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create directory /etc/os-net-config/
+  file:
+    path: "/etc/os-net-config/"
+    state: directory
+    mode: 0755
+
+- name: Create /tmp/os-net-config file
+  vars:
+    config_phase: "{{ lookup('env','CONFIG_PHASE') }}"
+  template:
+    src: "os_net_config.j2"
+    dest: "/tmp/os-net-config.json"
+    owner: "root"
+    mode: "0644"
+  changed_when: False
+
+- name: Create os-net-config file /etc/os-net-config/config.json
+  copy:
+    content: "{{ lookup('file','/tmp/os-net-config.json')  | from_json }}"
+    dest: "/etc/os-net-config/config.json"
+    mode: 0440
+
+- name: Run os-net-config command
+  command: "os-net-config --detailed-exit-codes -v -c /etc/os-net-config/config.json"
+  register: os_net_config_result
+  failed_when: not (os_net_config_result.rc == 0 or os_net_config_result.rc == 2)
+
+- debug: var=os_net_config_result.stderr_lines
+  when: os_net_config_result.rc == 2
+
+- name: Remove /tmp/os-net-config.json
+  file:
+    path: "/tmp/os-net-config.json"
+    state: absent
+  changed_when: False
diff --git a/roles/bootstrap-host/tasks/prepare_ssh_keys.yml b/roles/bootstrap-host/tasks/prepare_ssh_keys.yml
new file mode 100644 (file)
index 0000000..e3f8914
--- /dev/null
@@ -0,0 +1,75 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+- name: Ensure root has a .ssh directory
+  file:
+    path: /root/.ssh
+    state: directory
+    owner: root
+    group: root
+    mode: 0700
+  tags:
+    - ssh-key-dir
+
+- name: Check for existing ssh private key file
+  stat:
+    path: /root/.ssh/id_rsa
+  register: ssh_key_private
+  tags:
+    - ssh-key-check
+
+- name: Check for existing ssh public key file
+  stat:
+    path: /root/.ssh/id_rsa.pub
+  register: ssh_key_public
+  tags:
+    - ssh-key-check
+
+- name: Remove an existing private/public ssh keys if one is missing
+  file:
+    path: "/root/.ssh/{{ item }}"
+    state: absent
+  when: not ssh_key_public.stat.exists or not ssh_key_private.stat.exists
+  with_items:
+    - 'id_rsa'
+    - 'id_rsa.pub'
+  tags:
+    - ssh-key-clean
+
+- name: Create ssh key pair for root
+  user:
+    name: root
+    generate_ssh_key: yes
+    ssh_key_bits: 2048
+    ssh_key_file: /root/.ssh/id_rsa
+  tags:
+    - ssh-key-generate
+
+- name: Fetch the generated public ssh key
+  fetch:
+    src: "/root/.ssh/id_rsa.pub"
+    dest: "/tmp/id_rsa.pub"
+    flat: yes
+  when: inventory_hostname == groups['all'][0]
+  tags:
+    - ssh-key-authorized
+
+- name: Ensure root's new public ssh key is in authorized_keys
+  authorized_key:
+    user: root
+    key: "{{ lookup('file','/tmp/id_rsa.pub') }}"
+    manage_dir: no
+  tags:
+    - ssh-key-authorized
\ No newline at end of file
diff --git a/roles/bootstrap-host/templates/apt-sources.list.j2 b/roles/bootstrap-host/templates/apt-sources.list.j2
new file mode 100644 (file)
index 0000000..8a632a1
--- /dev/null
@@ -0,0 +1,10 @@
+# {{ ansible_managed }}
+
+# Base repositories
+deb {{ bootstrap_host_ubuntu_repo }} {{ ansible_distribution_release }} {{ bootstrap_host_apt_components | join(" ") }}
+# Updates repositories
+deb {{ bootstrap_host_ubuntu_repo }} {{ ansible_distribution_release }}-updates {{ bootstrap_host_apt_components | join(" ") }}
+# Backports repositories
+deb {{ bootstrap_host_ubuntu_repo }} {{ ansible_distribution_release }}-backports {{ bootstrap_host_apt_components | join(" ") }}
+# Security repositories
+deb {{ bootstrap_host_ubuntu_security_repo }} {{ ansible_distribution_release }}-security {{ bootstrap_host_apt_components | join(" ") }}
diff --git a/roles/bootstrap-host/templates/osa_interfaces.cfg.j2 b/roles/bootstrap-host/templates/osa_interfaces.cfg.j2
new file mode 100644 (file)
index 0000000..3e8e149
--- /dev/null
@@ -0,0 +1,68 @@
+## The default networking requires several bridges. These bridges were named to be informative
+## however they can be named what ever you like and is adaptable to any network infrastructure
+## environment. This file serves as an example of how to setup basic networking and was ONLY
+## built for the purpose of being an example and used expressly in the building of an ALL IN
+## ONE development environment.
+
+auto br-mgmt
+iface br-mgmt inet static
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    # Notice the bridge port is the vlan tagged interface
+    bridge_ports {{ bootstrap_host_bridge_mgmt_ports }}
+    address 172.29.236.100
+    netmask 255.255.252.0
+    offload-sg off
+
+auto br-vxlan
+iface br-vxlan inet static
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    bridge_ports {{ bootstrap_host_bridge_vxlan_ports }}
+    address 172.29.240.100
+    netmask 255.255.252.0
+    offload-sg off
+    # To ensure ssh checksum is correct
+    up /sbin/iptables -A POSTROUTING -t mangle -p tcp --dport 22 -j CHECKSUM --checksum-fill
+    down /sbin/iptables -D POSTROUTING -t mangle -p tcp --dport 22 -j CHECKSUM --checksum-fill
+    # To provide internet connectivity to instances
+    up /sbin/iptables -t nat -A POSTROUTING -o {{ bootstrap_host_public_interface }} -j MASQUERADE
+    down /sbin/iptables -t nat -D POSTROUTING -o {{ bootstrap_host_public_interface }} -j MASQUERADE
+
+auto br-storage
+iface br-storage inet static
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    bridge_ports {{ bootstrap_host_bridge_storage_ports }}
+    address 172.29.244.100
+    netmask 255.255.252.0
+    offload-sg off
+
+auto br-vlan
+iface br-vlan inet static
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    address 172.29.248.100
+    netmask 255.255.252.0
+    offload-sg off
+    # Create veth pair, don't bomb if already exists
+    pre-up ip link add br-vlan-veth type veth peer name eth12 || true
+    # Set both ends UP
+    pre-up ip link set br-vlan-veth up
+    pre-up ip link set eth12 up
+    # Delete veth pair on DOWN
+    post-down ip link del br-vlan-veth || true
+    bridge_ports br-vlan-veth
+
+# Add an additional address to br-vlan
+iface br-vlan inet static
+    # Flat network default gateway
+    # -- This needs to exist somewhere for network reachability
+    # -- from the router namespace for floating IP paths.
+    # -- Putting this here is primarily for tempest to work.
+    address 172.29.248.1
+    netmask 255.255.252.0
diff --git a/roles/bootstrap-host/templates/osa_interfaces_multinode.cfg.j2 b/roles/bootstrap-host/templates/osa_interfaces_multinode.cfg.j2
new file mode 100644 (file)
index 0000000..a055c43
--- /dev/null
@@ -0,0 +1,28 @@
+{% if bootstrap_host_encapsulation_enabled | bool %}
+{% for nic_name, nic_details in bootstrap_host_encapsulation_interfaces.iteritems() %}
+# {{ nic_details.friendly_name }}
+auto {{ nic_name }}
+iface {{ nic_name }} inet manual
+    pre-up ip link add {{ nic_name }} type vxlan id {{ nic_details.id }} group 239.0.0.{{ nic_details.id }} dev {{ nic_details.underlay_device }} || true
+    up ip link set $IFACE up
+    down ip link set $IFACE down
+    post-down ip link del {{ nic_name }} || true
+
+{% endfor %}
+{% endif %}
+{%- for nic_name, nic_details in bootstrap_host_bridges_interfaces.iteritems() -%}
+auto {{ nic_name }}
+iface {{ nic_name }} inet {{ nic_details.mode | default('static') }}
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    bridge_ports {{ nic_details.ports }}
+    offload-sg {{ nic_details.offload_sg | default('off') }}
+    {% if nic_details.mode | default('static') == 'static' -%}
+    address {{ nic_details.ip_address_range }}.{{ node_id }}
+    netmask {{ nic_details.ip_netmask }}
+    {% endif %}
+    {%- if nic_details.state_change_scripts is defined %}{{ nic_details.state_change_scripts }}
+    {% endif %}
+
+{% endfor %}
\ No newline at end of file
diff --git a/roles/bootstrap-host/templates/redhat_interface_alias.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_alias.cfg.j2
new file mode 100644 (file)
index 0000000..79a04a8
--- /dev/null
@@ -0,0 +1,5 @@
+# This interface is an alias
+DEVICE={{ item.name | default('br-mgmt') }}:0
+IPADDR={{ item.alias | default('10.1.0.1') }}
+NETMASK={{ item.netmask | default('255.255.255.0') }}
+ONBOOT=yes
diff --git a/roles/bootstrap-host/templates/redhat_interface_default.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_default.cfg.j2
new file mode 100644 (file)
index 0000000..416bfbe
--- /dev/null
@@ -0,0 +1,11 @@
+{% if item.veth_peer is defined %}
+# This interface has a veth peer
+{% endif %}
+DEVICE={{ item.name | default('br-mgmt') }}
+TYPE=Bridge
+IPADDR={{ item.ip_addr | default('10.1.0.1') }}
+NETMASK={{ item.netmask | default('255.255.255.0') }}
+ONBOOT=yes
+BOOTPROTO=none
+NM_CONTROLLED=no
+DELAY=0
diff --git a/roles/bootstrap-host/templates/redhat_interface_ethernet.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_ethernet.cfg.j2
new file mode 100644 (file)
index 0000000..654bfc9
--- /dev/null
@@ -0,0 +1,8 @@
+DEVICE={{ item.name }}
+TYPE="Ethernet"
+IPADDR={{ item.ip_addr }}
+NETMASK={{ item.netmask }}
+ONBOOT=yes
+BOOTPROTO=none
+NM_CONTROLLED=no
+DELAY=0
diff --git a/roles/bootstrap-host/templates/redhat_interface_ifdown-post.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_ifdown-post.cfg.j2
new file mode 100644 (file)
index 0000000..40f147d
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+
+if [ "${DEVICE}" == "{{ item[1].name | default('br-mgmt') }}" ]; then
+    /usr/sbin/ip link set {{ item[1].name | default('br-mgmt') }}-veth nomaster || true
+    /usr/sbin/ip link del {{ item[1].name | default('br-mgmt') }}-veth || true
+fi
diff --git a/roles/bootstrap-host/templates/redhat_interface_ifup-post.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_ifup-post.cfg.j2
new file mode 100644 (file)
index 0000000..d28fb9d
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+
+if [ "${DEVICE}" == "{{ item[1].name | default('br-mgmt') }}" ]; then
+    # Create veth pair, don't bomb if already exists
+    echo "Creating veth"
+    /usr/sbin/ip link add {{ item[1].name | default('br-mgmt') }}-veth type veth peer name {{ item[1].veth_peer | default('eth0') }} || true
+    # Set both ends UP
+    /usr/sbin/ip link set {{ item[1].name | default('br-mgmt') }}-veth up || true
+    /usr/sbin/ip link set {{ item[1].veth_peer | default('eth0') }} up || true
+    # add eth12 to the bridge
+    /usr/sbin/ip link set {{ item[1].name | default('br-mgmt') }}-veth master {{ item[1].name | default('br-mgmt') }} || true
+fi
diff --git a/roles/bootstrap-host/templates/redhat_interface_vlan.cfg.j2 b/roles/bootstrap-host/templates/redhat_interface_vlan.cfg.j2
new file mode 100644 (file)
index 0000000..23cd8a7
--- /dev/null
@@ -0,0 +1,9 @@
+DEVICE={{ item.name }}
+TYPE=vlan
+VLAN=yes
+IPADDR={{ item.ip_addr }}
+NETMASK={{ item.netmask }}
+ONBOOT=yes
+BOOTPROTO=none
+NM_CONTROLLED=no
+DELAY=0
diff --git a/roles/bootstrap-host/templates/user_variables.aio.yml.j2 b/roles/bootstrap-host/templates/user_variables.aio.yml.j2
new file mode 100644 (file)
index 0000000..7fd053d
--- /dev/null
@@ -0,0 +1,102 @@
+---
+# Copyright 2014, Rackspace US, Inc.
+#
+# 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.
+
+## General options
+debug: True
+
+## Tempest settings
+tempest_public_subnet_cidr: 172.29.248.0/22
+tempest_public_subnet_allocation_pools: "172.29.249.110-172.29.249.200"
+
+## Galera settings
+galera_innodb_buffer_pool_size: 256M
+galera_innodb_log_buffer_size: 32M
+galera_wsrep_provider_options:
+ - { option: "gcache.size", value: "32M" }
+
+## Neutron settings
+neutron_metadata_checksum_fix: True
+
+## Set workers for all services to optimise memory usage
+ceilometer_api_workers: 2
+ceilometer_collector_workers: 2
+ceilometer_notification_workers: 2
+cinder_osapi_volume_workers: 2
+glance_api_workers: 2
+glance_registry_workers: 2
+heat_api_workers: 2
+heat_engine_workers: 2
+horizon_wsgi_processes: 2
+horizon_wsgi_threads: 2
+keystone_wsgi_processes: 2
+neutron_api_workers: 2
+neutron_metadata_workers: 1
+neutron_rpc_workers: 1
+nova_conductor_workers: 2
+nova_metadata_workers: 2
+nova_osapi_compute_workers: 2
+nova_wsgi_processes: 2
+swift_account_server_workers: 2
+swift_container_server_workers: 2
+swift_object_server_workers: 2
+swift_proxy_server_workers: 2
+
+# NOTE: hpcloud-b4's eth0 uses 10.0.3.0/24, which overlaps with the
+#       lxc_net_address default
+# TODO: We'll need to implement a mechanism to determine valid lxc_net_address
+#       value which will not overlap with an IP already assigned to the host.
+lxc_net_address: 10.255.255.1
+lxc_net_netmask: 255.255.255.0
+lxc_net_dhcp_range: 10.255.255.2,10.255.255.253
+
+{% if repo_build_pip_extra_indexes is defined %}
+## Wheel mirrors for the repo_build to use
+repo_build_pip_extra_indexes:
+{{ repo_build_pip_extra_indexes | to_nice_yaml }}
+{% endif %}
+
+{% if uca_apt_repo_url is defined %}
+## Ubuntu Cloud Archive mirror to use
+uca_apt_repo_url: {{ uca_apt_repo_url }}
+{% endif %}
+
+{% if cache_timeout is defined %}
+## Package cache timeout
+cache_timeout: {{ cache_timeout }}
+{% endif %}
+
+{% if repo_build_git_cache is defined %}
+## Git cache to use for the repo build process
+repo_build_git_cache: {{ repo_build_git_cache }}
+{% endif %}
+
+# The container backing store is set to 'overlayfs' to speed up the
+# AIO build time.
+lxc_container_backing_store: "{{ (ansible_kernel | version_compare('3.18.0-0-generic', '<')) | ternary('dir', 'overlayfs') }}"
+
+## Enable LBaaSv2 in the AIO
+neutron_plugin_base:
+  - router
+  - metering
+  - neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2
+
+## Always setup tempest, the resources for it, then execute tests
+tempest_install: yes
+tempest_run: yes
+
+{% if nodepool_dir.stat.exists %}
+# Disable chronyd in OpenStack CI
+security_rhel7_enable_chrony: no
+{% endif %}
diff --git a/roles/bootstrap-host/templates/user_variables.ceph.yml.j2 b/roles/bootstrap-host/templates/user_variables.ceph.yml.j2
new file mode 100644 (file)
index 0000000..212f2ad
--- /dev/null
@@ -0,0 +1,16 @@
+{% include 'user_variables.aio.yml.j2' %}
+
+## ceph-ansible AIO settings
+common_single_host_mode: true
+monitor_interface: eth1 # Management network in the AIO
+public_network: "{{ (mgmt_range ~ '.0/' ~ netmask) | ipaddr('net') }}"
+journal_size: 100
+journal_collocation: true
+pool_default_pg_num: 32
+openstack_config: true # Ceph ansible automatically creates pools & keys
+cinder_ceph_client: cinder
+cinder_default_volume_type: RBD
+glance_ceph_client: glance
+glance_default_store: rbd
+glance_rbd_store_pool: images
+nova_libvirt_images_rbd_pool: vms
diff --git a/roles/bootstrap-host/vars/redhat.yml b/roles/bootstrap-host/vars/redhat.yml
new file mode 100644 (file)
index 0000000..b40f2d2
--- /dev/null
@@ -0,0 +1,40 @@
+---
+# Copyright 2017, Rackspace US, Inc.
+#
+# 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.
+
+rdo_package: "centos-release-openstack-newton"
+epel_package: "epel-release"
+
+packages_install:
+  - '@Development Tools'
+  - bridge-utils
+  - curl
+  - ethtool
+  - git
+  - iputils
+  - lvm2
+  - python
+  - python-devel
+  - python-ipython
+  - tmux
+  - vconfig
+  - vim
+  - xfsprogs
+
+packages_remove: []
+
+swap_create_command: "dd if=/dev/zero of=/openstack/swap.img bs={{ bootstrap_host_swap_size }}G count=1"
+rc_local: /etc/rc.d/rc.local
+rc_local_insert_before: "^touch /var/lock/subsys/local$"
+
diff --git a/roles/bootstrap-host/vars/ubuntu.yml b/roles/bootstrap-host/vars/ubuntu.yml
new file mode 100644 (file)
index 0000000..2301af5
--- /dev/null
@@ -0,0 +1,39 @@
+---
+# Copyright 2015, Rackspace US, Inc.
+#
+# 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.
+
+packages_install:
+  - bridge-utils
+  - build-essential
+  - curl
+  - ethtool
+  - git-core
+  - ipython
+  - linux-image-extra-{{ ansible_kernel }}
+  - lvm2
+  - python2.7
+  - python-dev
+  - tmux
+  - vim
+  - vlan
+  - xfsprogs
+  - iputils-tracepath
+
+packages_remove:
+  - libmysqlclient18
+  - mysql-common
+
+swap_create_command: "fallocate -l {{ bootstrap_host_swap_size }}G /openstack/swap.img"
+rc_local: /etc/rc.local
+rc_local_insert_before: "^exit 0$"
diff --git a/roles/change_kernel_cmdline/README.rst b/roles/change_kernel_cmdline/README.rst
new file mode 100644 (file)
index 0000000..9806c71
--- /dev/null
@@ -0,0 +1 @@
+Ansible Role modules for adding kernel commandline arguments
diff --git a/roles/change_kernel_cmdline/defaults/main.yml b/roles/change_kernel_cmdline/defaults/main.yml
new file mode 100644 (file)
index 0000000..0c786c5
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# Common kernel arguments.
+kcmdline_list: ['console=tty0', 'console=ttyS1,115200', 'no_timer_check', 'audit=1']
+
+# Default kernel arguments.
+kcmdline_default_list: ['nofb', 'nomodeset', 'vga=normal', 'iommu=pt', 'intel_iommu=on', 'crashkernel=256M']
+
+# OS tuning conf file
+os_tuning_conf_file: /etc/sysctl.d/os-tuning.conf
diff --git a/roles/change_kernel_cmdline/filter_plugins/change_kernel_cmdline_helpers.py b/roles/change_kernel_cmdline/filter_plugins/change_kernel_cmdline_helpers.py
new file mode 100644 (file)
index 0000000..0fa9273
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 itertools
+import re
+
+def cpulist_to_set(cl):
+    r = set()
+    for e in cl.split(','):
+        if '-' in e:
+            p = e.split('-')
+        else:
+            p = [e, e]
+        r.update(map(str, range(int(p[0]), int(p[1]) + 1)))
+    return list(r)
+
+def set_to_cpulist(cs):
+    r = []
+    for k, g in itertools.groupby(enumerate(sorted(cs, key=int)), lambda (i, v): int(v) - i):
+        t = list(g)
+        if len(t) == 1:
+            r.append(str(t[0][1]))
+        else:
+            r.append('-'.join([str(t[0][1]), str(t[-1][1])]))
+    return ','.join(r)
+
+def cpulist_combine(conf, name, lst):
+    r = set()
+    for s in lst:
+        if s in conf:
+            r.update(conf[s]['set'])
+    if len(r) > 0:
+        conf[name] = { 'set': sorted(r), 'list': set_to_cpulist(r) }
+    return conf
+
+def cmdline_to_list(cmdl):
+    return re.findall('(?:[^" ]|"[^"]*")+', cmdl)
+
+def list_to_cmdline(lst):
+    return ' '.join(lst)
+
+class FilterModule(object):
+    def filters(self):
+        return {
+            'cpulist_to_set': cpulist_to_set,
+            'set_to_cpulist': set_to_cpulist,
+            'cpulist_combine': cpulist_combine,
+            'cmdline_to_list': cmdline_to_list,
+            'list_to_cmdline': list_to_cmdline
+        }
+
diff --git a/roles/change_kernel_cmdline/tasks/main.yml b/roles/change_kernel_cmdline/tasks/main.yml
new file mode 100644 (file)
index 0000000..a514f16
--- /dev/null
@@ -0,0 +1,161 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+- name: Get configuration.
+  set_fact:
+    perf_profile: "{{ performance_profiles[hosts[hostname]['performance_profiles'][0]] if 'performance_profiles' in hosts[hostname] else {} }}"
+    cpu_alloc: "{{ ansible_local.ncir_cpu_allocation | default([]) }}"
+- debug:
+    var: perf_profile
+- debug:
+    var: cpu_alloc
+
+- name: Make combined CPU lists.
+  set_fact:
+    cpu_alloc: "{{ cpu_alloc | cpulist_combine(item['name'], item['lists']) }}"
+  with_items:
+    - { 'name': 'app', 'lists': ['ovs_dpdk', 'vm'] }
+
+- name: Make sure configuration directory exists.
+  file:
+    path: /etc/systemd/system.conf.d
+    state: directory
+    mode: 0755
+
+- name: Set platform CPU affinity.
+  ini_file:
+    dest: /etc/systemd/system.conf.d/00affinity.conf
+    mode: 0644
+    section: Manager
+    option: CPUAffinity
+    value: "{{ cpu_alloc['platform']['set'] | join(' ') }}"
+    no_extra_spaces: True
+  register: platform_affinity
+  when: cpu_alloc | length > 0
+
+- name: Make CPU list parameters.
+  set_fact:
+    kcmdline_default_list: "{{ kcmdline_default_list + [ item['opt'] + '=' + cpu_alloc[item['list']]['list'] ] }}"
+  with_items:
+    - { 'opt': 'irqaffinity', 'list': 'platform' }
+    - { 'opt': 'kthread', 'list': 'platform' }
+    - { 'opt': 'nohz_full',   'list': 'app' }
+    - { 'opt': 'rcu_nocbs',   'list': 'app' }
+    - { 'opt': 'isolcpus',    'list': 'ovs_dpdk' }
+  when: "item['list'] in cpu_alloc"
+
+- name: Make hugepage parameters.
+  set_fact:
+    kcmdline_default_list: "{{ kcmdline_default_list + [ item + '=' + perf_profile[item] | string ] }}"
+  with_items: ['default_hugepagesz', 'hugepagesz', 'hugepages']
+  when: item in perf_profile
+
+- debug:
+    var: kcmdline_list
+
+- name: Set common kernel parameters.
+  lineinfile:
+    name: /etc/default/grub
+    regexp: "^GRUB_CMDLINE_LINUX="
+    line: "GRUB_CMDLINE_LINUX='{{ kcmdline_list | list_to_cmdline }}'"
+  register: grub_cmdline
+
+- debug:
+    var: kcmdline_default_list
+
+- name: Set default kernel parameters.
+  lineinfile:
+    name: /etc/default/grub
+    regexp: "^GRUB_CMDLINE_LINUX_DEFAULT="
+    line: "GRUB_CMDLINE_LINUX_DEFAULT='{{ kcmdline_default_list | list_to_cmdline }}'"
+  register: grub_cmdline_default
+
+- name: Generate grub configurations
+  command: grub2-mkconfig -o /boot/grub2/grub.cfg
+  when: grub_cmdline.changed or grub_cmdline_default.changed
+
+- name: Ensure network.service is enabled
+  systemd:
+    name: network
+    enabled: yes
+
+- name: Reboot node
+  shell: ( sleep 3 && /sbin/reboot & )
+  async: 0
+  poll: 0
+  ignore_errors: yes
+  when:
+    - grub_cmdline.changed or grub_cmdline_default.changed or platform_affinity.changed
+    - hostname != installation_controller
+    - installation_phase != "postconfig-ended" or (scaled_out_nodes is defined and hostname in scaled_out_nodes) or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+
+- name: Wait for the server to reboot
+  local_action: wait_for host="{{ansible_host}}" delay=15 state=started port=22 connect_timeout=10 timeout=720
+  when:
+    - grub_cmdline.changed or grub_cmdline_default.changed or platform_affinity.changed
+    - hostname != installation_controller
+    - installation_phase != "postconfig-ended" or (scaled_out_nodes is defined and hostname in scaled_out_nodes) or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+
+- name: Wait for remote node ssh login. Wating for 10mins max.
+  become: "{{ ansible_env.SUDO_USER }}"
+  local_action: shell ssh -oBatchMode=yes -4 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null {{ ansible_host }} "echo success"
+  register: user_enabled
+  until: user_enabled.stdout.find("success") != -1
+  retries: 90
+  delay: 10
+  no_log: True
+  when:
+    - grub_cmdline.changed or grub_cmdline_default.changed or platform_affinity.changed
+    - hostname != installation_controller
+    - installation_phase != "postconfig-ended" or (scaled_out_nodes is defined and hostname in scaled_out_nodes) or (reinitialized_nodes is defined and hostname in reinitialized_nodes)
+
+- name: Ensure directory for flag file
+  file:
+    path: /etc/ansible-change_kernel_cmdline/
+    mode: 0555
+    state: directory
+
+- name: Create a temporary flag file to indicate enabling of performance profile
+  copy:
+    content: ""
+    dest: /etc/ansible-change_kernel_cmdline/enabled
+    force: "no"
+    group: root
+    owner: root
+    mode: 0555
+  when:
+    - grub_cmdline.changed or grub_cmdline_default.changed or platform_affinity.changed
+    - hostname == installation_controller
+
+- name: Ensure finalize-bootstrap.service is enabled on the installation host
+  systemd:
+    name: finalize-bootstrap
+    enabled: "yes"
+  when:
+    - grub_cmdline.changed or grub_cmdline_default.changed or platform_affinity.changed
+    - hostname == installation_controller
+
+- name: Set OS tunables in /etc/sysctl.d/os-tuning.conf
+  sysctl:
+    name: "{{ item.name }}"
+    value: "{{ item.value }}"
+    state: present
+    sysctl_file: "{{ os_tuning_conf_file }}"
+    ignoreerrors: no
+  with_items:
+    - {name: 'vm.max_map_count', value: '300000'}
+    - {name: 'fs.inotify.max_user_instances', value: '1024'}
diff --git a/roles/cleanup_disks/defaults/main.yml b/roles/cleanup_disks/defaults/main.yml
new file mode 100644 (file)
index 0000000..479cbc5
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+creates_file: "/etc/storage/default_creates_file"
diff --git a/roles/cleanup_disks/tasks/destroy_data_and_partitions.yml b/roles/cleanup_disks/tasks/destroy_data_and_partitions.yml
new file mode 100644 (file)
index 0000000..48aeff5
--- /dev/null
@@ -0,0 +1,33 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: wipe off filesystems from disks
+  shell: "[ -b {{ item }} ] | /usr/sbin/wipefs --all --force {{ item }} || /usr/sbin/wipefs --all --force {{ item }}"
+  args:
+    creates: "{{ creates_file }}"
+  with_items: "{{ disks }}"
+
+- name: destroy data from disks
+  shell: "[ -b {{ item }} ] | dd if=/dev/zero of={{ item }} count=200 bs=1M"
+  args:
+    creates: "{{ creates_file }}"
+  with_items: "{{ disks }}"
+
+- name: destroy partitions from disks
+  shell: "[ -b {{ item }} ] | /usr/sbin/sgdisk --zap-all --clear --mbrtogpt -- {{ item }} || /usr/sbin/sgdisk --zap-all --clear --mbrtogpt -- {{ item }}"
+  args:
+    creates: "{{ creates_file }}"
+  with_items: "{{ disks }}"
diff --git a/roles/cleanup_disks/tasks/main.yml b/roles/cleanup_disks/tasks/main.yml
new file mode 100644 (file)
index 0000000..21a509d
--- /dev/null
@@ -0,0 +1,19 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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_tasks: remove_volume_groups.yml
+- include_tasks: destroy_data_and_partitions.yml
+
diff --git a/roles/cleanup_disks/tasks/remove_volume_groups.yml b/roles/cleanup_disks/tasks/remove_volume_groups.yml
new file mode 100644 (file)
index 0000000..85e21e0
--- /dev/null
@@ -0,0 +1,27 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: get volume groups
+  shell: "vgs -o vg_name --noheadings | sed 's/ //g'"
+  args:
+    creates: "{{ creates_file }}"
+  register: volumegroups
+
+- name:  remove volume groups
+  lvg: vg={{ item }} state=absent force=yes
+  ignore_errors: yes
+  with_items: "{{ volumegroups.stdout_lines }}"
+  when: volumegroups is defined
diff --git a/roles/cmserver-config/README.rst b/roles/cmserver-config/README.rst
new file mode 100644 (file)
index 0000000..a410a6e
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for cmserver configuration
diff --git a/roles/cmserver-config/defaults/main.yml b/roles/cmserver-config/defaults/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/cmserver-config/handlers/main.yml b/roles/cmserver-config/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/cmserver-config/tasks/generate_cmserver_config.yml b/roles/cmserver-config/tasks/generate_cmserver_config.yml
new file mode 100644 (file)
index 0000000..bb4cb7b
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the cmserver configuration directory
+  file:
+      path: "/etc/cmframework"
+      state: directory
+      mode: 0750
+
+- name: Generate cmserver configuration file
+  template:
+      src: config.ini.j2
+      dest: "/etc/cmframework/config.ini"
+      owner: root
+      group: root
+      mode: 0640
+
diff --git a/roles/cmserver-config/tasks/main.yml b/roles/cmserver-config/tasks/main.yml
new file mode 100644 (file)
index 0000000..4e175a3
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright 2019 Nokia
+
+# 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: generate_cmserver_config.yml
+  tags:
+      - cmserver_config_generate
+
+- name: Set permissions for /opt/cmframework/scripts
+  file:
+    path: "/opt/cmframework/scripts"
+    owner: "{{ users.admin_user_name }}"
+    group: "{{ users.admin_user_name }}"
+    recurse: yes
+    mode: 0700
+
+- name: Set permissions for /opt/bin/
+  file:
+    path: "/usr/local/bin/cmcli"
+    owner: "{{ users.admin_user_name }}"
+    group: "{{ users.admin_user_name }}"
+    mode: 0700
+
diff --git a/roles/cmserver-config/templates/config.ini.j2 b/roles/cmserver-config/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..ec27483
--- /dev/null
@@ -0,0 +1,20 @@
+[cmserver]
+ip=config-manager
+port=61100
+backend_api=cmframework.redisbackend.cmredisdb.CMRedisDB
+backend_uri=redis://:{{ redis_password }}@rediscontroller:6379
+log_level=debug
+log_dest=console
+validators=/opt/cmframework/validators
+activators=/opt/cmframework/activators
+disable_remote_activation=True
+verbose=True
+inventory_handlers=/opt/cmframework/inventoryhandlers
+inventory_data=/opt/cmframework/inventory.data
+install_phase=False
+activationstate_handler_api=cmframework.utils.cmdsshandler.CMDSSHandler
+activationstate_handler_uri=/run/.dss-server
+activator_workers=10
+snapshot_handler_api=cmframework.utils.cmdsshandler.CMDSSHandler
+snapshot_handler_uri=/run/.dss-server
+alarmhandler_api=cmframework.lib.cmalarmhandler_dummy.AlarmHandler_Dummy
diff --git a/roles/core-handling-config/files/01-enable-cores.conf b/roles/core-handling-config/files/01-enable-cores.conf
new file mode 100644 (file)
index 0000000..55bd4c5
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+[Coredump]
+Storage=external
diff --git a/roles/core-handling-config/files/02-only-backtrace.conf b/roles/core-handling-config/files/02-only-backtrace.conf
new file mode 100644 (file)
index 0000000..2d3a58b
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# If the core dumping should be enabled for this node,
+# rename this file to "02-only-backtrace.conf.disabled" 
+
+[Coredump]
+Storage=none
diff --git a/roles/core-handling-config/tasks/main.yml b/roles/core-handling-config/tasks/main.yml
new file mode 100644 (file)
index 0000000..3a38a3b
--- /dev/null
@@ -0,0 +1,55 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create coredump directory to log volume
+  file: path=/var/log/coredump state=directory
+
+- name: Remote old coredump directory
+  file: path=/var/lib/systemd/coredump state=absent 
+
+- name: Create link so that coredumps go to log volume
+  file:
+    src: '/var/log/coredump'
+    dest: '/var/lib/systemd/coredump'
+    state: link
+
+- name: Create coredump configuration directory
+  file: path=/etc/systemd/coredump.conf.d state=directory
+
+- name: Enable core files
+  copy:
+    src: "01-enable-cores.conf"
+    dest: "/etc/systemd/coredump.conf.d/01-enable-cores.conf"
+    owner: "root"
+    group: "root"
+  tags:
+    - core-handling-config
+
+- name: Enable only backtraces
+  copy:
+    src: "02-only-backtrace.conf"
+    dest: "/etc/systemd/coredump.conf.d/02-only-backtrace.conf"
+    owner: "root"
+    group: "root"
+  tags:
+    - core-handling-config
+
+- name: Enable core dumping
+  sysctl:
+    name: kernel.core_pattern 
+    value: '|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e'
+    sysctl_file: /etc/sysctl.d/50-coredump.conf
+
diff --git a/roles/dbwatchdog/README.rst b/roles/dbwatchdog/README.rst
new file mode 100644 (file)
index 0000000..2f1f01e
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for enabling dbwatchdog
diff --git a/roles/dbwatchdog/handlers/main.yml b/roles/dbwatchdog/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/dbwatchdog/tasks/generate_config.yml b/roles/dbwatchdog/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..22878ec
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate dbwatchdog mariadb wrapper
+  template:
+      src: mariadb.service.j2
+      dest: "/etc/systemd/system/mariadb.service"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Reload systemd configuration
+  shell: /usr/bin/systemctl daemon-reload
+
+- name: Mark maridb instances as running
+  shell: "/opt/monitoring/dbwatchdog.sh set-running {{ groups['management']|join(',') }}"
diff --git a/roles/dbwatchdog/tasks/main.yml b/roles/dbwatchdog/tasks/main.yml
new file mode 100644 (file)
index 0000000..ac7b9fb
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_config.yml
+  tags:
+      - dbwatchdog_config_generate
diff --git a/roles/dbwatchdog/templates/config.ini.j2 b/roles/dbwatchdog/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..728abfb
--- /dev/null
@@ -0,0 +1,9 @@
+[server]
+logging_level = info
+logging_destination = console
+verbose = true
+listening_uds = /var/run/.dbmonitor
+transport_type = stream
+hostname = {{ hostname }}
+use_systemd = True
+monitoring_interval = 5
diff --git a/roles/dbwatchdog/templates/mariadb.service.j2 b/roles/dbwatchdog/templates/mariadb.service.j2
new file mode 100644 (file)
index 0000000..a35ace5
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+
+[Service]
+PermissionsStartOnly=true
+ExecStartPre=/opt/monitoring/dbwatchdog.sh kill-old {{ groups['management']|join(',') }}
+ExecStartPre=/opt/monitoring/dbwatchdog.sh start-pre {{ groups['management']|join(',') }}
+
+.include /usr/lib/systemd/system/mariadb.service
+
+[Service]
+ExecStartPost=/opt/monitoring/dbwatchdog.sh start-post {{ groups['management']|join(',') }}
+ExecStop=/opt/monitoring/dbwatchdog.sh stop {{ groups['management']|join(',') }}
+ExecStopPost=/opt/monitoring/dbwatchdog.sh stop-post {{ groups['management']|join(',') }}
diff --git a/roles/disable-default-rsyslog/README.rst b/roles/disable-default-rsyslog/README.rst
new file mode 100644 (file)
index 0000000..a174d35
--- /dev/null
@@ -0,0 +1,2 @@
+Ansible role for disabling default node rsyslog service which came from golden image.
+It is replaced with new rsyslog configuration.
diff --git a/roles/disable-default-rsyslog/tasks/disable_rsyslog.yml b/roles/disable-default-rsyslog/tasks/disable_rsyslog.yml
new file mode 100644 (file)
index 0000000..c0156da
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Disable node rsyslog
+  service:
+    name: rsyslog
+    state: stopped
+    enabled: no
diff --git a/roles/disable-default-rsyslog/tasks/main.yml b/roles/disable-default-rsyslog/tasks/main.yml
new file mode 100644 (file)
index 0000000..e7b0f94
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright 2019 Nokia
+
+# 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: disable_rsyslog.yml
diff --git a/roles/distributed-state-server-etcd-plugin/README.rst b/roles/distributed-state-server-etcd-plugin/README.rst
new file mode 100644 (file)
index 0000000..7345eb1
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for deploying hwmgmt server ironic plugin.
diff --git a/roles/distributed-state-server-etcd-plugin/handlers/main.yml b/roles/distributed-state-server-etcd-plugin/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/distributed-state-server-etcd-plugin/tasks/generate_config.yml b/roles/distributed-state-server-etcd-plugin/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..a290b8b
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the distributed state server etcd plugin configuration directory
+  file:
+      path: "/etc/distributed-state-server-etcd-plugin"
+      state: directory
+      mode: 0750
+
+- name: Generate the distributed state server etcd plugin configuration
+  template: 
+      src: config.ini.j2 
+      dest: "/etc/distributed-state-server-etcd-plugin/config.ini"
+      owner: root 
+      group: root
+      mode: 0640
diff --git a/roles/distributed-state-server-etcd-plugin/tasks/main.yml b/roles/distributed-state-server-etcd-plugin/tasks/main.yml
new file mode 100644 (file)
index 0000000..cdd7c59
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_config.yml
+  tags:
+      - distributed_state_server_etcd_plugin_configure
diff --git a/roles/distributed-state-server-etcd-plugin/templates/config.ini.j2 b/roles/distributed-state-server-etcd-plugin/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..c120e09
--- /dev/null
@@ -0,0 +1,3 @@
+[etcd]
+host = {{ inventory_hostname }}
+port = 2379
diff --git a/roles/distributed-state-server-file-plugin/README.rst b/roles/distributed-state-server-file-plugin/README.rst
new file mode 100644 (file)
index 0000000..7345eb1
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for deploying hwmgmt server ironic plugin.
diff --git a/roles/distributed-state-server-file-plugin/handlers/main.yml b/roles/distributed-state-server-file-plugin/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/distributed-state-server-file-plugin/tasks/generate_config.yml b/roles/distributed-state-server-file-plugin/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..a585a35
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the distributed state server file plugin configuration directory
+  file:
+      path: "/etc/distributed-state-server-file-plugin"
+      state: directory
+      mode: 0750
+
+- name: Create the distributed state server file db directory
+  file:
+      path: "/etc/distributed-state-server-file-plugin/db"
+      state: directory
+      mode: 0750
+
+- name: Generate the distributed state server file plugin configuration
+  template: 
+      src: config.ini.j2 
+      dest: "/etc/distributed-state-server-file-plugin/config.ini"
+      owner: root 
+      group: root
+      mode: 0640
diff --git a/roles/distributed-state-server-file-plugin/tasks/main.yml b/roles/distributed-state-server-file-plugin/tasks/main.yml
new file mode 100644 (file)
index 0000000..af95645
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_config.yml
+  tags:
+      - distributed_state_server_file_plugin_configure
diff --git a/roles/distributed-state-server-file-plugin/templates/config.ini.j2 b/roles/distributed-state-server-file-plugin/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..7aa0862
--- /dev/null
@@ -0,0 +1,2 @@
+[default]
+directory = /etc/distributed-state-server-file-plugin/db
diff --git a/roles/distributed-state-server/README.rst b/roles/distributed-state-server/README.rst
new file mode 100644 (file)
index 0000000..545db30
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for deploying hwmgmt server
diff --git a/roles/distributed-state-server/handlers/main.yml b/roles/distributed-state-server/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/distributed-state-server/tasks/enable-dss-server.yml b/roles/distributed-state-server/tasks/enable-dss-server.yml
new file mode 100644 (file)
index 0000000..2555e3c
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate dss-server service unit file
+  template:
+      src: dss-server.service.j2
+      dest: "/usr/lib/systemd/system/dss-server.service"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Enable dss-server
+  systemd:
+      name: dss-server
+      enabled: yes
+      masked: no
+      state: started
+      daemon_reload: yes
diff --git a/roles/distributed-state-server/tasks/generate_config.yml b/roles/distributed-state-server/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..daec695
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the dss-server configuration directory
+  file:
+      path: "/etc/distributed-state-server"
+      state: directory
+      mode: 0750
+
+- name: Generate dss-server configuration file
+  template: 
+      src: config.ini.j2 
+      dest: "/etc/distributed-state-server/config.ini"
+      owner: root 
+      group: root
+      mode: 0640
diff --git a/roles/distributed-state-server/tasks/main.yml b/roles/distributed-state-server/tasks/main.yml
new file mode 100644 (file)
index 0000000..cfefc27
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2019 Nokia
+
+# 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: generate_config.yml
+  tags:
+      - dss_server_config_generate
+- include: enable-dss-server.yml
+  tags:
+      - enable_dss_server
diff --git a/roles/distributed-state-server/templates/config.ini.j2 b/roles/distributed-state-server/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..8c25428
--- /dev/null
@@ -0,0 +1,14 @@
+[server]
+logging_level = info
+logging_destination = console
+verbose = true
+listening_uds = /var/run/.dss-server
+transport_type = stream
+[plugin]
+{%if groups['management']|length > 1 %}
+plugin = /opt/dss-server/plugins/dssetcd.py
+config = /etc/distributed-state-server-etcd-plugin/config.ini
+{% else %}
+plugin = /opt/dss-server/plugins/dssfile.py
+config = /etc/distributed-state-server-file-plugin/config.ini
+{% endif %}
diff --git a/roles/distributed-state-server/templates/dss-server.service.j2 b/roles/distributed-state-server/templates/dss-server.service.j2
new file mode 100644 (file)
index 0000000..a2a7a42
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=distributed state server
+After=network.target
+{%if groups['management']|length > 1 %}
+Requires=etcd.service
+{% endif %}
+
+[Service]
+Type=simple
+ExecStart=/usr/local/bin/dss --config /etc/distributed-state-server/config.ini
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/etcdansible/README.rst b/roles/etcdansible/README.rst
new file mode 100644 (file)
index 0000000..4119ada
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for configuring etcd 
diff --git a/roles/etcdansible/handlers/main.yml b/roles/etcdansible/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/etcdansible/tasks/configure_etcd.yml b/roles/etcdansible/tasks/configure_etcd.yml
new file mode 100644 (file)
index 0000000..03f7d10
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate etcd configuration file
+  template:
+      src: etcd.conf.j2
+      dest: "/etc/etcd/etcd.conf"
+      owner: root
+      group: root
+      mode: 644
+  when: reinitialized_nodes is not defined or (inventory_hostname in reinitialized_nodes)
+
diff --git a/roles/etcdansible/tasks/enable_etcd.yml b/roles/etcdansible/tasks/enable_etcd.yml
new file mode 100644 (file)
index 0000000..d455f1f
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Enable etcd service
+  systemd:
+      name: etcd
+      enabled: yes
+      masked: no
+      state: started
+      daemon_reload: yes
+  when: reinitialized_nodes is not defined or (inventory_hostname in reinitialized_nodes)
diff --git a/roles/etcdansible/tasks/handle_reinitialized_etcd.yml b/roles/etcdansible/tasks/handle_reinitialized_etcd.yml
new file mode 100644 (file)
index 0000000..1ca76de
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Stop old etcd
+  systemd:
+   name: etcd
+   state: stopped
+  when: reinitialized_nodes is defined and inventory_hostname in reinitialized_nodes
+
+- name: Remove old etcd directory
+  file:
+      state: absent
+      path: /var/lib/etcd/default.etcd/
+  when: reinitialized_nodes is defined and inventory_hostname in reinitialized_nodes
+
+- name: Remove and add reinitialized members
+  shell: |
+     echo "{{item.key}}" >> /tmp/out.txt
+     id=$(/bin/etcdctl --endpoints http://{{installation_controller}}:2379 member list | grep "{{item.key}}" | /usr/bin/awk -F[:\[] '{print $1}')
+     if [ $? -eq 0 ]; then
+        /bin/etcdctl --endpoints http://{{installation_controller}}:2379 member remove $id
+     fi
+     /bin/etcdctl --endpoints http://{{installation_controller}}:2379 member add "{{item.key}}" http://"{{hostvars[item.key]['networking']['infra_internal']['ip']}}":2380
+  with_dict: "{{ reinitialized_nodes }}"
+  when: reinitialized_nodes is defined and inventory_hostname == installation_controller and item.key in groups['management']
diff --git a/roles/etcdansible/tasks/main.yml b/roles/etcdansible/tasks/main.yml
new file mode 100644 (file)
index 0000000..1bf39ae
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2019 Nokia
+
+# 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: handle_reinitialized_etcd.yml
+  tags:
+      - reinitialize_etcd
+
+- include: configure_etcd.yml
+  tags:
+      - configure_etcd
+
+- include: enable_etcd.yml
+  tags:
+      - enable_etcd
diff --git a/roles/etcdansible/templates/etcd.conf.j2 b/roles/etcdansible/templates/etcd.conf.j2
new file mode 100644 (file)
index 0000000..c4bad14
--- /dev/null
@@ -0,0 +1,14 @@
+ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
+ETCD_NAME={{ inventory_hostname }}
+ETCD_LISTEN_PEER_URLS=http://{{ networking['infra_internal']['ip'] }}:2380
+ETCD_LISTEN_CLIENT_URLS=http://{{ networking['infra_internal']['ip'] }}:2379
+ETCD_INITIAL_ADVERTISE_PEER_URLS=http://{{ networking['infra_internal']['ip'] }}:2380
+ETCD_INITIAL_CLUSTER={% for node in groups['management'] %}{{ node }}=http://{{ hostvars[node]['networking']['infra_internal']['ip'] }}:2380{% if not loop.last %},{% endif %}{% endfor %}
+
+{% if reinitialized_nodes is defined and inventory_hostname in reinitialized_nodes %}
+ETCD_INITIAL_CLUSTER_STATE=existing
+{% else %}
+ETCD_INITIAL_CLUSTER_STATE=new
+{% endif %}
+ETCD_INITIAL_CLUSTER_TOKEN={{ name }}
+ETCD_ADVERTISE_CLIENT_URLS=http://{{ networking['infra_internal']['ip'] }}:2379
diff --git a/roles/hostcli/handlers/main.yml b/roles/hostcli/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/hostcli/tasks/generate_bash_auto_complete.yml b/roles/hostcli/tasks/generate_bash_auto_complete.yml
new file mode 100644 (file)
index 0000000..1b9e639
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate bash auto complete for hostcli
+  shell: /usr/local/bin/hostcli complete > /etc/bash_completion.d/hostcli
+
+- name: Generate bash auto complete for openstack
+  shell: /usr/bin/openstack complete > /etc/bash_completion.d/openstack
diff --git a/roles/hostcli/tasks/main.yml b/roles/hostcli/tasks/main.yml
new file mode 100644 (file)
index 0000000..7c8352d
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_bash_auto_complete.yml
+  tags:
+      - generate_bash_auto_complete
diff --git a/roles/in_host_traffic_filtering_controller/defaults/main.yml b/roles/in_host_traffic_filtering_controller/defaults/main.yml
new file mode 100644 (file)
index 0000000..2651ba3
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+sysconfig_dir: /etc/sysconfig/
+iptables_file: iptables
+iptables_path: "{{sysconfig_dir}}{{iptables_file}}"
+ip6tables_file: ip6tables
+ip6tables_path: "{{sysconfig_dir}}{{ip6tables_file}}"
+number_of_nodes: "{{ hosts | length }}"
+base_shell_inabox_port: 61401
diff --git a/roles/in_host_traffic_filtering_controller/handlers/main.yml b/roles/in_host_traffic_filtering_controller/handlers/main.yml
new file mode 100644 (file)
index 0000000..b95d32d
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Restart iptables
+  service:
+    name: "iptables"
+    state: "restarted"
+    enabled: "yes"
+
+- name: Restart ip6tables
+  service:
+    name: "ip6tables"
+    state: "restarted"
+    enabled: "yes"
diff --git a/roles/in_host_traffic_filtering_controller/tasks/main.yml b/roles/in_host_traffic_filtering_controller/tasks/main.yml
new file mode 100644 (file)
index 0000000..c825d9b
--- /dev/null
@@ -0,0 +1,30 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Configure IPv4 firewall rules
+  template:
+    src: iptables.j2
+    dest: "{{ iptables_path }}"
+  notify:
+    - Restart iptables
+
+- name: Configure IPv6 firewall rules
+  when: ansible_default_ipv6|length > 0
+  template:
+    src: ip6tables.j2
+    dest: "{{ ip6tables_path }}"
+  notify:
+    - Restart ip6tables
diff --git a/roles/in_host_traffic_filtering_controller/templates/ip6tables.j2 b/roles/in_host_traffic_filtering_controller/templates/ip6tables.j2
new file mode 100644 (file)
index 0000000..cbcc0a8
--- /dev/null
@@ -0,0 +1,91 @@
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [0:0]
+
+
+######INPUT Chain
+#### Platform traffic
+{% set infra_external = networking['infra_external']['interface'] %}
+-6 -A INPUT ! -i {{ infra_external }} -m comment --comment "Allow Non-OAM IPv6 Traffic" -j ACCEPT
+{% if 'infra_access' in networking %}
+{% set infra_access = networking['infra_access']['interface'] %}
+-6 -A INPUT ! -i {{ infra_access }} -m comment --comment "Allow Non-OAM IPv6 Traffic" -j ACCEPT
+{% endif %}
+-6 -A INPUT -m comment --comment "Allow Related IPv6 Traffic" -m state --state RELATED,ESTABLISHED -j ACCEPT
+-6 -A INPUT -p tcp -m multiport --dports 22 -m comment --comment "Allow SSH IPv6 Connection" -j ACCEPT
+-6 -A INPUT -p tcp -m multiport --sports 6514 -m comment --comment "Allow Incoming Remote Logging" -m state --state NEW,ESTABLISHED -j ACCEPT
+
+## ICMPV6 - Allow required types
+-6 -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -m comment --comment "ICMPv6 Destination Unreachable" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type packet-too-big -m comment --comment "ICMPv6 Packet Too Big" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type time-exceeded -m comment --comment "ICMPv6 Time Exceeded - Code 0 only" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type parameter-problem -m comment --comment "ICMPv6 Parameter Problem - Codes 1 and 2 only" -j ACCEPT
+
+# Allow connectivity checking messages, but rate limit.
+-6 -A INPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 900/min -m comment --comment "ICMPv6 Echo Request" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type echo-reply -m limit --limit 900/min -m comment --comment "ICMPv6 Echo Reply" -j ACCEPT
+
+# Allow others ICMPv6 types but only if the hop limit field is 255.
+-6 -A INPUT -p icmpv6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -m comment --comment "ICMPv6 Router Solicitation" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -m comment --comment "ICMPv6 Router Advertisement" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -m comment --comment "ICMPv6 Neighbor Solicitation" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -m comment --comment "ICMPv6 Neighbor Advertisement" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -m comment --comment "ICMPv6 Redirect" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 141 -m hl --hl-eq 255 -m comment --comment "ICMPv6 Inverse Neighbor Discovery Solicitation" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 142 -m hl --hl-eq 255 -m comment --comment "ICMPv6 Inverse Neighbor Discovery Advertisement" -j ACCEPT
+
+# Allow ICMPv6 Certificate Path Notification
+-6 -A INPUT -p icmpv6 --icmpv6-type 148 -m hl --hl-eq 255 -m comment --comment "ICMPv6 Certificate Path Solicitation" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 149 -m hl --hl-eq 255 -m comment --comment "ICMPv6 Certificate Path Advertisement" -j ACCEPT
+
+# Allow ICMPv6 link local multicast
+-6 -A INPUT -p icmpv6 --icmpv6-type 130 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Link-Local Multicast Listener Query" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 131 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Link-Local Multicast Listener Report" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 132 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Link-Local Multicast Listener Done" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 143 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Link-Local Multicast Listener Report v2" -j ACCEPT
+
+# Allow multicast router discovery
+-6 -A INPUT -p icmpv6 --icmpv6-type 151 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Multicast Router Advertisement" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 152 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Multicast Router Solicitation" -j ACCEPT
+-6 -A INPUT -p icmpv6 --icmpv6-type 153 -m hl --hl-eq 1 -m comment --comment "ICMPv6 Multicast Router Termination" -j ACCEPT
+
+# NTP and DNS
+-6 -A INPUT -p udp -m multiport --dports 123 -m comment --comment "Allow Incoming NTP" -j ACCEPT
+-6 -A INPUT -p udp -m multiport --dports 53 -m comment --comment "Allow Incoming DNS" -m state --state ESTABLISHED -j ACCEPT
+
+# SNMP traps to be received from BMC's
+-6 -A INPUT -p udp -m multiport --dports 162 -m comment --comment "Allow Incoming SNMP Traps" -j ACCEPT
+
+-6 -A INPUT -p tcp -m multiport --dports 80 -m comment --comment "Allow Incoming Horizon Dashboard" -j ACCEPT
+{% if haproxy_ssl|default(False) %}
+-6 -A INPUT -p tcp -m multiport --dports 443 -m comment --comment "Allow Incoming Horizon Dashboard" -j ACCEPT
+{% endif %}
+
+#### External HTTP interfaces
+{% set numhosts = number_of_nodes| int %}
+{% if hosts[ansible_hostname]['installation_host']|default(False) %}
+-6 -A INPUT -p tcp -m multiport --dports 8082 -m comment --comment "Allow Installer WebUI" -j ACCEPT
+-6 -A INPUT -i lo -j ACCEPT
+{% endif %}
+-6 -A INPUT -p tcp -m multiport --dports 6385 -m comment --comment "Allow Incoming Ironic Api" -j ACCEPT
+-6 -A INPUT -p tcp -m multiport --dports 5000 -m comment --comment "Allow Incoming Keystone Api" -j ACCEPT
+-6 -A INPUT -p tcp -m multiport --dports 8888 -m comment --comment "Allow Netact Interface " -j ACCEPT
+-6 -A INPUT -p tcp -m multiport --dports 61200 -m comment --comment "Allow Restful Service" -j ACCEPT
+
+-6 -A INPUT -m comment --comment "Log Dropped IPv6 Traffic" -m limit --limit 2/min -j LOG --log-prefix "iptables-in-dropped: "
+-6 -A INPUT -m comment --comment "Drop All Other Traffic" -j DROP
+
+######FORWARD Chain
+-6 -A FORWARD ! -i {{ infra_external }} -m comment --comment "Allow Forward Non-OAM IPv6 Traffic" -j ACCEPT
+{% if networking['infra_access'] is defined  and ansible_hostname in groups['compute'] %}
+-6 -A FORWARD -i {{ infra_access }} -m comment --comment "Allow Forward Non-OAM IPv6 Traffic" -j DROP
+{% endif %}
+-6 -A FORWARD -m comment --comment "Allow Forward Related IPv6 Traffic" -m state --state RELATED,ESTABLISHED -j ACCEPT
+-6 -A FORWARD -m comment --comment "Log Dropped Forwarded IPv6 Traffic" -m limit --limit 2/min -j LOG --log-prefix "iptables-fwd-dropped: "
+
+###### OUTPUT Chain
+-6 -A OUTPUT -p udp -m multiport --dports 53 -m comment --comment "Allow Outgoing DNS" -m state --state NEW,ESTABLISHED -j ACCEPT
+-6 -A OUTPUT -p tcp -m multiport --dports 6514 -m comment --comment "Allow Outgoing Remote Logging" -m state --state NEW,ESTABLISHED -j ACCEPT
+
+COMMIT
diff --git a/roles/in_host_traffic_filtering_controller/templates/iptables.j2 b/roles/in_host_traffic_filtering_controller/templates/iptables.j2
new file mode 100644 (file)
index 0000000..612a59d
--- /dev/null
@@ -0,0 +1,71 @@
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [0:0]
+
+
+######INPUT Chain
+#### Platform traffic
+{% set infra_external = networking['infra_external']['interface'] %}
+-A INPUT ! -i {{ infra_external }} -m comment --comment "Allow Non-OAM IPv4 Traffic" -j ACCEPT
+{% if 'infra_access' in networking %}
+{% set infra_access = networking['infra_access']['interface'] %}
+-A INPUT ! -i {{ infra_access }} -m comment --comment "Allow Non-OAM IPv4 Traffic" -j ACCEPT
+{% endif %}
+-A INPUT -m comment --comment "Allow related IPv4 traffic" -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A INPUT -p tcp -m multiport --dports 22 -m comment --comment "Allow SSH IPv4 Connection" -j ACCEPT
+-A INPUT -p tcp -m multiport --sports 6514 -m comment --comment "Allow Incoming Remote Logging" -m state --state NEW,ESTABLISHED -j ACCEPT
+
+# Drop all packets from same source over the rate limit
+# To prevent Sockstress TCP DoS attack
+-A INPUT -p tcp -m state --state NEW -m recent --set
+-A INPUT -p tcp -m state --state NEW -m recent --update --seconds 1 --hitcount 20 -j DROP
+
+# Drop all NULL packets.
+-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
+
+# ICMP - Allow required types
+-A INPUT -p icmp -m icmp --icmp-type 8 -m comment --comment "ICMP Echo Requests" -j ACCEPT
+-A INPUT -p icmp -m icmp --icmp-type 0 -m comment --comment "ICMP Echo Replies" -j ACCEPT
+-A INPUT -p icmp -m icmp --icmp-type 11 -m comment --comment "ICMP TTL Exceeded" -j ACCEPT
+-A INPUT -p icmp -m icmp --icmp-type 3 -m comment --comment "ICMP Destination Unreachable" -j ACCEPT
+
+# NTP and DNS
+-A INPUT -p udp -m multiport --dports 123 -m comment --comment "Allow Incoming NTP" -j ACCEPT
+-A INPUT -p udp -m multiport --dports 53 -m comment --comment "Allow Incoming DNS" -m state --state ESTABLISHED -j ACCEPT
+
+# SNMP traps to be received from BMC's
+-A INPUT -p udp -m multiport --dports 162 -m comment --comment "Allow Incoming SNMP Traps" -j ACCEPT
+
+-A INPUT -p tcp -m multiport --dports 80 -m comment --comment "Allow Incoming Horizon Dashboard" -j ACCEPT
+{% if haproxy_ssl|default(False) %}
+-A INPUT -p tcp -m multiport --dports 443 -m comment --comment "Allow Incoming Horizon Dashboard" -j ACCEPT
+{% endif %}
+
+#### External HTTP interfaces
+{% if hosts[ansible_hostname]['installation_host']|default(False) %}
+-A INPUT -p tcp -m multiport --dports 8082 -m comment --comment "Allow Installer WebUI" -j ACCEPT
+-A INPUT -i lo -j ACCEPT
+{% endif %}
+-A INPUT -p tcp -m multiport --dports 6385 -m comment --comment "Allow Incoming Ironic Api" -j ACCEPT
+-A INPUT -p tcp -m multiport --dports 5000 -m comment --comment "Allow Incoming Keystone Api" -j ACCEPT
+-A INPUT -p tcp -m multiport --dports 8888 -m comment --comment "Allow Netact Interface " -j ACCEPT
+-A INPUT -p tcp -m multiport --dports 61200 -m comment --comment "Allow Restful Service" -j ACCEPT
+-A INPUT -p tcp -m multiport --dports {{base_shell_inabox_port}}{% if number_of_nodes|int > 1%}:{{base_shell_inabox_port + number_of_nodes|int - 1}}{% endif %} -m comment --comment "Allow Shell in a box" -j ACCEPT
+
+-A INPUT -m comment --comment "Log Dropped IPv4 Traffic" -m limit --limit 2/min -j LOG --log-prefix "iptables-in-dropped: "
+-A INPUT -m comment --comment "Drop All Other Traffic" -j DROP
+
+######FORWARD Chain
+-A FORWARD ! -i {{ infra_external }} -m comment --comment "Allow Forward Non-OAM IPv4 Traffic" -j ACCEPT
+{% if networking['infra_access'] is defined and ansible_hostname in groups['compute']%}
+-A FORWARD -i {{ infra_access }} -m comment --comment "Allow Forward Non-OAM IPv4 Traffic" -j DROP
+{% endif %}
+-A FORWARD -m comment --comment "Allow Forward Related IPv4 Traffic" -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -m comment --comment "Log Dropped Forwarded IPv4 Traffic" -m limit --limit 2/min -j LOG --log-prefix "iptables-fwd-dropped: "
+
+######OUTPUT Chain
+-A OUTPUT -p tcp -m multiport --dports 6514 -m comment --comment "Allow Outgoing remote logging" -m state --state NEW,ESTABLISHED -j ACCEPT
+-A OUTPUT -p udp -m multiport --dports 53 -m comment --comment "Allow Outgoing DNS" -m state --state NEW,ESTABLISHED -j ACCEPT
+
+COMMIT
diff --git a/roles/initial_poweroff_hosts/README.rst b/roles/initial_poweroff_hosts/README.rst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/roles/initial_poweroff_hosts/defaults/main.yml b/roles/initial_poweroff_hosts/defaults/main.yml
new file mode 100644 (file)
index 0000000..b8ff312
--- /dev/null
@@ -0,0 +1,21 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+## Verbosity Options
+debug: False
+nodes_to_power_off: {}
+domains_poweroff_list: []
diff --git a/roles/initial_poweroff_hosts/handlers/main.yml b/roles/initial_poweroff_hosts/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/initial_poweroff_hosts/library/xml_parse_macs.py b/roles/initial_poweroff_hosts/library/xml_parse_macs.py
new file mode 100644 (file)
index 0000000..8b833af
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 xml.etree.ElementTree as ET
+
+DOCUMENTATION = '''
+---
+'''
+
+def main():
+    module = AnsibleModule(
+        argument_spec=dict(
+            xml_file=dict(required=True),
+        ),
+    )
+
+    defaults = module.params.copy()
+    xml_file = defaults.pop('xml_file', None)
+
+    try:
+        tree = ET.parse(xml_file)
+        root = tree.getroot()
+    except IOError as e:
+        module.fail_json(msg=str(e))
+
+    for child in root:
+        if child.tag == 'devices':
+            devices=child
+            break;
+
+    mac_list = []
+    for child in devices:
+        if child.tag == 'interface':
+            for detail in child:
+                if detail.tag == 'mac':
+                    mac_list.append(detail.attrib['address'])
+
+    module.exit_json(
+        changed=True,
+        mac_list=mac_list,
+    )
+
+from ansible.module_utils.basic import *
+
+
+if __name__ == '__main__':
+    main()
diff --git a/roles/initial_poweroff_hosts/tasks/mac_matcher.yml b/roles/initial_poweroff_hosts/tasks/mac_matcher.yml
new file mode 100644 (file)
index 0000000..0cf67d8
--- /dev/null
@@ -0,0 +1,25 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- debug:
+    msg: "Processing host: {{node.key}}"
+
+- set_fact:
+    domains_poweroff_list: "{{ domains_poweroff_list  + [domain_name] }}"
+  with_nested:
+    - "{{node.value.mgmt_mac}}"
+    - "{{macs_result.mac_list}}"
+  when: item[0] in item[1]
diff --git a/roles/initial_poweroff_hosts/tasks/main.yml b/roles/initial_poweroff_hosts/tasks/main.yml
new file mode 100644 (file)
index 0000000..70a6a0a
--- /dev/null
@@ -0,0 +1,24 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- set_fact:
+    nodes_to_power_off: "{{nodes_to_power_off |combine({item.key: item.value})}}"
+  when: item.key != installation_controller
+  with_dict: "{{hosts}}"
+  no_log: True
+
+- include: poweroff_real_nodes.yml
+  when: virtual_env == false
diff --git a/roles/initial_poweroff_hosts/tasks/poweroff_real_nodes.yml b/roles/initial_poweroff_hosts/tasks/poweroff_real_nodes.yml
new file mode 100644 (file)
index 0000000..6a188f4
--- /dev/null
@@ -0,0 +1,24 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Ensure all the nodes in the deployment are powered-off.
+  command: "/usr/bin/ipmitool -I lanplus -H {{item.value['hwmgmt']['address']}} -U {{item.value['hwmgmt']['user']}} -P {{item.value['hwmgmt']['password']}} chassis power off"
+  with_dict: "{{nodes_to_power_off}}"
+  no_log: True
+  when:
+    - installation_phase == "bootstrapping-started"
+  ignore_errors: yes
+
diff --git a/roles/initial_poweroff_hosts/tasks/poweroff_virtual_node.yml b/roles/initial_poweroff_hosts/tasks/poweroff_virtual_node.yml
new file mode 100644 (file)
index 0000000..78ef91c
--- /dev/null
@@ -0,0 +1,52 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- debug:
+    msg: "Processing domain: {{domain_name}}"
+
+- name: Get VM info
+  vars:
+    ansible_ssh_private_key_file: /etc/userconfig/id_rsa
+    ansible_user: root
+  virt:
+    uri: "qemu:///system"
+    command: get_xml 
+    name: "{{domain_name}}"
+  delegate_to: "{{hosts[installation_controller]['hwmgmt']['address']}}"
+  register: vm_info_result
+
+- name: Create domain xml files
+  copy:
+    content: "{{vm_info_result.get_xml}}"
+    dest: "/tmp/{{domain_name}}.xml"
+    mode: 0440
+
+- name: Get mac addresses
+  xml_parse_macs:
+    xml_file: "/tmp/{{domain_name}}.xml"
+  register: macs_result
+
+- name: Remove domain xml files
+  file:
+    path: "/tmp/{{domain_name}}.xml"
+    state: absent
+
+- include: mac_matcher.yml
+  vars: 
+    node: "{{node_item}}"
+  with_dict: "{{nodes_to_power_off}}"
+  loop_control:
+    loop_var: node_item
diff --git a/roles/initial_poweroff_hosts/tasks/poweroff_virtual_nodes.yml b/roles/initial_poweroff_hosts/tasks/poweroff_virtual_nodes.yml
new file mode 100644 (file)
index 0000000..729ae61
--- /dev/null
@@ -0,0 +1,52 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- add_host: 
+    name: "{{hosts[installation_controller]['hwmgmt']['address']}}"
+
+- name: Get VM list
+  vars:
+    ansible_ssh_private_key_file: /etc/userconfig/id_rsa
+    ansible_user: root
+  virt:
+    uri: "qemu:///system"
+    command: list_vms
+  delegate_to: "{{hosts[installation_controller]['hwmgmt']['address']}}"
+  register: vm_list_result
+
+- name: Take action per node
+  vars:
+    domain_name: "{{domain_item}}"
+  include: poweroff_virtual_node.yml
+#  with_items: ["chandra_compute_1"]
+  with_items: "{{vm_list_result.list_vms}}"
+  loop_control:
+    loop_var: domain_item
+
+- debug:
+    msg: "Powering off Domains: {{domains_poweroff_list| unique}}"
+
+- name: Power off nodes
+  vars:
+    ansible_ssh_private_key_file: /etc/userconfig/id_rsa
+    ansible_user: root
+  virt:
+    uri: "qemu:///system"
+    command: destroy
+    name: "{{item}}"
+  delegate_to: "{{hosts[installation_controller]['hwmgmt']['address']}}"
+  with_items: "{{domains_poweroff_list | unique}}"
+  ignore_errors: True
diff --git a/roles/initial_poweroff_hosts/vars/redhat-7.yml b/roles/initial_poweroff_hosts/vars/redhat-7.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/initial_poweroff_hosts/vars/ubuntu-16.04.yml b/roles/initial_poweroff_hosts/vars/ubuntu-16.04.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/kernel-core-handling-config/handlers/main.yml b/roles/kernel-core-handling-config/handlers/main.yml
new file mode 100644 (file)
index 0000000..b38aea6
--- /dev/null
@@ -0,0 +1,20 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Restart kdump
+  systemd:
+    name: "kdump"
+    state: "restarted"
diff --git a/roles/kernel-core-handling-config/tasks/main.yml b/roles/kernel-core-handling-config/tasks/main.yml
new file mode 100644 (file)
index 0000000..fa4403c
--- /dev/null
@@ -0,0 +1,22 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Remove restriction of used cpus (not compatible with our own options)
+  replace:
+    path: /etc/sysconfig/kdump
+    regexp: '^(KDUMP_COMMANDLINE_APPEND=.*["\s])nr_cpus=1(["\s].*)$'
+    replace: '\1nr_cpus=0\2'
+  notify: Restart kdump
diff --git a/roles/logging/README.rst b/roles/logging/README.rst
new file mode 100644 (file)
index 0000000..1a9ba54
--- /dev/null
@@ -0,0 +1,3 @@
+Ansible module for creating log forwarding configuration for controller nodes.
+Based on CM backend data for log forwarding.
+At the end restarts the active centralized rsyslogd instance to take updated configuration into use.
diff --git a/roles/logging/handlers/main.yml b/roles/logging/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/logging/tasks/generate_log_forwarding_config.yml b/roles/logging/tasks/generate_log_forwarding_config.yml
new file mode 100644 (file)
index 0000000..9b9c771
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate log forwarding configuration
+  template: 
+      src: logforwarding.j2
+      dest: "/etc/rsyslog-master.d/50-log-forwarding.conf"
+      owner: root 
+      group: root
+      mode: 0640
diff --git a/roles/logging/tasks/main.yml b/roles/logging/tasks/main.yml
new file mode 100644 (file)
index 0000000..c57be00
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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: generate_log_forwarding_config.yml
+  tags:
+      - generate_log_forwarding_config
+
+- include: restart_centralized_instance.yml
+  tags:
+      - restart_centralized_instance
diff --git a/roles/logging/tasks/restart_centralized_instance.yml b/roles/logging/tasks/restart_centralized_instance.yml
new file mode 100644 (file)
index 0000000..ae29d0e
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Restart the centralized rsyslogd to activate updated configuration
+  shell: /usr/local/bin/hascli -r -o /rsyslog-master
+  ignore_errors: yes
diff --git a/roles/logging/templates/logforwarding.j2 b/roles/logging/templates/logforwarding.j2
new file mode 100644 (file)
index 0000000..857592c
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Ansible managed
+#
+# This is the runtime configuration for log forwarding to external server.
+# If a configuration is active, the rsyslog-master instance will forward
+# logs to the configured external server.
+#
+# Last written: {{ lookup('pipe','date --rfc-3339=seconds') }}
+#
+{% if log_forwarding is defined %}
+template(name="RSYSLOG_SyslogProtocol23Format_with_cloudname" type="string"
+     string="<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME%.{{ name }} %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n")
+
+{% if log_forwarding['tls'] == "on" %}
+$DefaultNetstreamDriver gtls
+$ActionSendStreamDriverMode 1
+$ActionSendStreamDriverAuthMode anon
+$DefaultNetstreamDriverCAFile /dev/null
+
+*.* @@(o)[{{ log_forwarding['ip_address'] }}]:{{ log_forwarding['port'] }}; RSYSLOG_SyslogProtocol23Format_with_cloudname
+{% else %}
+*.* action(type="omfwd" target="{{ log_forwarding['ip_address'] }}" port="{{ log_forwarding['port'] }}" protocol="{{ log_forwarding['protocol'] }}" template="RSYSLOG_SyslogProtocol23Format_with_cloudname")
+{% endif %}
+{% else %}
+# No active configuration
+#
+{% endif %}
diff --git a/roles/manage_linux_user/tasks/main.yml b/roles/manage_linux_user/tasks/main.yml
new file mode 100644 (file)
index 0000000..9640717
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+---
+- name: "create or delete linux user"
+  user:
+    name: "{{ item.name }}"
+    password: "{{ item.password | default('') }}"
+    remove: "{{ item.remove | default('yes') }}"
+    force: "{{ item.remove | default('yes') }}"
+    state: "{{ item.state | default('absent') }}"
+  with_items: "{{ linuxuser | default([]) }}"
+
+- name: "remove the old public ssh key"
+  file:
+    path: /home/{{ item.name }}/.ssh/{{ item.name }}
+    state: absent
+  with_items: "{{ linuxuser | default([]) }}"
+
+- name: "Create the user .ssh directory"
+  when: item.state == 'present'
+  file:
+    path: /home/{{ item.name }}/.ssh
+    state: directory
+    owner: "{{ item.name }}"
+    group: "{{ item.name }}"
+    mode: 0700
+  with_items: "{{ linuxuser | default([]) }}"
+
+- name: "add a new public ssh key"
+  when: item.state == 'present' and item.public_key != ""
+  lineinfile:
+    path: /home/{{ item.name }}/.ssh/{{ item.name }}
+    create: yes
+    regexp: '.*'
+    state: "{{ item.state | default('absent') }}"
+    line: "{{ item.public_key | default('') }}"
+    group: "{{ item.name }}"
+    owner: "{{ item.name }}"
+    mode: 0400
+  with_items: "{{ linuxuser | default([]) }}"
+
+- name: Locking and Unlocking the user
+  when: item.state == 'present' and item.password != ""
+  command: sudo passwd "{{ item.name }}" "{{ item.lock_state }}"
+  with_items: "{{ linuxuser | default([]) }}"
diff --git a/roles/manage_user/tasks/main.yml b/roles/manage_user/tasks/main.yml
new file mode 100644 (file)
index 0000000..765a09f
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+---
+- name: "create or delete chroot user"
+  user:
+    name: "{{ item.name }}"
+    groups: "{{ item.group }}"
+    password: "{{ item.password | default('')}}"
+    remove: "{{ item.remove | default('yes')}}"
+    state: "{{ item.state | default('absent')}}"
+    system: no
+    shell: /bin/nologin
+    createhome: no
+  with_items: "{{ chroot | default([]) }}"
+
+- name: "Create the ssh-keys directory"
+  file:
+    path: /etc/ssh-keys
+    state: directory
+
+- name: "remove the old public ssh key"
+  file:
+    path: /etc/ssh-keys/{{ item.name }}
+    state: absent
+  with_items: "{{ chroot | default([]) }}"
+
+- name: "add a new public ssh key"
+  when: item.state == 'present'
+  lineinfile:
+    path: /etc/ssh-keys/{{ item.name }}
+    create: yes
+    regexp: '.*'
+    state: "{{ item.state | default('absent') }}"
+    line: "{{ item.public_key }}"
+    owner: "{{ item.name }}"
+    mode: 0400
+  with_items: "{{ chroot | default([]) }}"
+
+- name: Locking and Unlocking the user
+  when: item.state == 'present' and item.password != ""
+  command: sudo passwd "{{ item.name }}" "{{ item.lock_state }}"
+  with_items: "{{ chroot | default([]) }}"
diff --git a/roles/monitoring/README.rst b/roles/monitoring/README.rst
new file mode 100644 (file)
index 0000000..fa1da33
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for deploying keepalived based monitoring
diff --git a/roles/monitoring/defaults/main.yaml b/roles/monitoring/defaults/main.yaml
new file mode 100644 (file)
index 0000000..e535511
--- /dev/null
@@ -0,0 +1,17 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+keepalivedmonitor_port : 64000
diff --git a/roles/monitoring/handlers/main.yml b/roles/monitoring/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/monitoring/tasks/generate_active_standby_controller_file.yml b/roles/monitoring/tasks/generate_active_standby_controller_file.yml
new file mode 100644 (file)
index 0000000..4942a9a
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate active standby controller systemd service unit file
+  template:
+      src: active-standby-controller.service.j2
+      dest: "/usr/lib/systemd/system/active-standby-controller.service"
+      owner: root
+      group: root
+      mode: 0644
diff --git a/roles/monitoring/tasks/generate_config.yml b/roles/monitoring/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..772c48e
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the keepalivedmonitor configuration dir
+  file:
+      path: "/etc/keepalivedmonitor"
+      state: directory
+      mode: 0750
+
+- name: Create the keepalivedmonitor configuration
+  template: 
+      src: keepalivedmonitor.conf.j2 
+      dest: "/etc/keepalivedmonitor/keepalivedmonitor.conf"
+      owner: root 
+      group: root
+      mode: 0640
+
+- name: Generate keepalivedmonitor agent service unit file
+  template:
+      src: keepalivedmonitoragent.service.j2
+      dest: "/usr/lib/systemd/system/keepalivedmonitoragent.service"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Generate keepalivedmonitor service unit file
+  template:
+      src: keepalivedmonitor.service.j2
+      dest: "/usr/lib/systemd/system/keepalivedmonitor.service"
+      owner: root
+      group: root
+      mode: 0644
diff --git a/roles/monitoring/tasks/generate_rediscontroller_systemd_unit_file.yml b/roles/monitoring/tasks/generate_rediscontroller_systemd_unit_file.yml
new file mode 100644 (file)
index 0000000..0f799c7
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate rediscontroller systemd service unit file
+  template:
+      src: rediscontroller.service.j2
+      dest: "/usr/lib/systemd/system/rediscontroller.service"
+      owner: root
+      group: root
+      mode: 0644
diff --git a/roles/monitoring/tasks/generate_redismonitor_systemd_unit_file.yml b/roles/monitoring/tasks/generate_redismonitor_systemd_unit_file.yml
new file mode 100644 (file)
index 0000000..390f253
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate redis monitor systemd service unit file
+  template:
+      src: redismonitor.service.j2
+      dest: "/usr/lib/systemd/system/redismonitor.service"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Start redis monitor service
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: redismonitor
diff --git a/roles/monitoring/tasks/main.yml b/roles/monitoring/tasks/main.yml
new file mode 100644 (file)
index 0000000..c0a23ce
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright 2019 Nokia
+
+# 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: generate_rediscontroller_systemd_unit_file.yml
+  tags:
+      - rediscontroller_systemd_unit_file_generate
+
+- include: generate_redismonitor_systemd_unit_file.yml
+  tags:
+      - redismonitor_systemd_unit_file_generate
+
+- include: generate_active_standby_controller_file.yml
+  tags:
+      - active_standby_controller_generate
+
+- include: generate_config.yml
+  tags:
+      - generate_config
+
+- include: update_hosts.yml
+  tags:
+      - update_hosts
+
+- include: start_services.yml
+  tags:
+      - start_services
diff --git a/roles/monitoring/tasks/start_services.yml b/roles/monitoring/tasks/start_services.yml
new file mode 100644 (file)
index 0000000..7551cfd
--- /dev/null
@@ -0,0 +1,63 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Start active standby controller
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: active-standby-controller
+
+- name: Start redismonitor
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: redismonitor
+
+- name: Start redis
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: redis
+
+- name: Start restapi
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: restapi
+
+- name: Start keepalivedmonitor agent
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: keepalivedmonitoragent
+
+- name: Start keepalivedmonitor
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: keepalivedmonitor
+
+- name: Start auth-server
+  systemd:
+      state: restarted
+      enabled: yes
+      daemon_reload: yes
+      name: auth-server
+
diff --git a/roles/monitoring/tasks/update_hosts.yml b/roles/monitoring/tasks/update_hosts.yml
new file mode 100644 (file)
index 0000000..459ad6b
--- /dev/null
@@ -0,0 +1,26 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Check active standby services
+  find:
+      paths: /etc/monitoring/active-standby-services/
+      patterns: '*.service'
+  register: service_files_list
+
+- name: Added entries to /etc/hosts for service groups vip(s)
+  lineinfile:
+      name: "/etc/hosts"
+      state: present
+      line: "{{ internal_lb_vip_address }} {{item.path.split('.service')[0]|basename}}"
+  with_items: "{{ service_files_list.files }}"
diff --git a/roles/monitoring/templates/active-standby-controller.service.j2 b/roles/monitoring/templates/active-standby-controller.service.j2
new file mode 100644 (file)
index 0000000..93cff36
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=active standby controller
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/opt/monitoring/active-standby-monitor.sh "{{ networking['vips']['infra_internal']['internal_vip'] }}"
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/monitoring/templates/keepalivedmonitor.conf.j2 b/roles/monitoring/templates/keepalivedmonitor.conf.j2
new file mode 100644 (file)
index 0000000..98ed5e3
--- /dev/null
@@ -0,0 +1,72 @@
+global_defs {
+    enable_script_security
+    script_user root
+}
+
+vrrp_script check_master {
+    script  "/opt/monitoring/monitoring_can_become_master.sh"
+    interval 5
+    fall 1
+    rise 1
+}
+
+vrrp_instance virtual_vip {
+    interface {{ networking['infra_internal']['interface'] }}
+
+    track_interface {
+               {{ networking['infra_internal']['interface'] }}
+               {{ networking['infra_external']['interface'] }}
+    }
+
+    state BACKUP
+
+    virtual_router_id 50
+
+    priority 100
+
+    unicast_src_ip {{ networking['infra_internal']['ip'] }}
+
+       {% for peer in groups['management'] %}
+       {% if peer != inventory_hostname %}
+       unicast_peer {
+               {{ hostvars[peer]['networking']['infra_internal']['ip'] }}
+       }
+    {% endif %}
+       {% endfor %}
+
+    advert_int 5
+
+    virtual_ipaddress {
+        {{ internal_lb_vip_address }}/{{ networking['infra_internal']['mask'] }} dev {{ networking['infra_internal']['interface'] }}
+        {{ external_lb_vip_address }}/32 dev {{ networking['infra_external']['interface'] }}
+    }
+
+    track_script {
+        check_master
+    }
+
+    notify /opt/monitoring/monitoring_state_changed.sh
+
+}
+
+{% if groups['management']|length > 1 %}
+virtual_server group management {
+    delay_loop 10
+    quorum 2
+    quorum_up /opt/monitoring/monitoring_quorum_up.sh
+    quorum_down /opt/monitoring/monitoring_quorum_down.sh
+
+       {% for peer in groups['management'] %}
+    real_server {{ hostvars[peer]['networking']['infra_internal']['ip'] }} {{ keepalivedmonitor_port }} {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+            fwmark 10
+            warmup 120
+            retry 5
+            delay_before_retry 3
+        }
+    }
+       {% endfor %}
+}
+{% endif %}
diff --git a/roles/monitoring/templates/keepalivedmonitor.service.j2 b/roles/monitoring/templates/keepalivedmonitor.service.j2
new file mode 100644 (file)
index 0000000..dd0d355
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=keepalived monitor 
+After=network.target
+After=keepalivedmonitoragent.service
+
+[Service]
+Type=simple
+ExecStart=/sbin/keepalived -n -l -f /etc/keepalivedmonitor/keepalivedmonitor.conf
+Restart=always
+RestartSec=3
+StartLimitInterval=0
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/monitoring/templates/keepalivedmonitoragent.service.j2 b/roles/monitoring/templates/keepalivedmonitoragent.service.j2
new file mode 100644 (file)
index 0000000..54a4e55
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=keepalived monitor agent
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/opt/monitoring/keepalivedmonitor.py {{ keepalivedmonitor_port }}
+Restart=always
+RestartSec=3
+StartLimitInterval=0
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/monitoring/templates/rediscontroller.service.j2 b/roles/monitoring/templates/rediscontroller.service.j2
new file mode 100644 (file)
index 0000000..2d05184
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=redis controlling service
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/opt/monitoring/rediscontroller.sh
+ExecStopPost=/opt/monitoring/become-redis-slave.sh "{{ internal_lb_vip_address }}"
+ExecStartPost=/opt/monitoring/become-redis-master.sh
+Restart=always
+
+#[Install]
+#WantedBy=multi-user.target
diff --git a/roles/monitoring/templates/redismonitor.service.j2 b/roles/monitoring/templates/redismonitor.service.j2
new file mode 100644 (file)
index 0000000..a972252
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=redis monitoring service
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/opt/monitoring/redismonitor.sh "{{ internal_lb_vip_address }}"
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/motd/README.rst b/roles/motd/README.rst
new file mode 100644 (file)
index 0000000..66e6f54
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for enabling redis controller
diff --git a/roles/motd/handlers/main.yml b/roles/motd/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/motd/tasks/generate_motd_config.yml b/roles/motd/tasks/generate_motd_config.yml
new file mode 100644 (file)
index 0000000..3142055
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate MOTD configuration
+  template: 
+      src: motd.j2
+      dest: "/etc/motd"
+      owner: root 
+      group: root
+      mode: 644
diff --git a/roles/motd/tasks/main.yml b/roles/motd/tasks/main.yml
new file mode 100644 (file)
index 0000000..acb4f38
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_motd_config.yml
+  tags:
+      - generate_motd_config
diff --git a/roles/motd/templates/motd.j2 b/roles/motd/templates/motd.j2
new file mode 100644 (file)
index 0000000..9315719
--- /dev/null
@@ -0,0 +1,7 @@
+{% if motd is defined %}
+
+
+{{ motd }}
+
+
+{% endif %}
diff --git a/roles/oom-config/tasks/main.yml b/roles/oom-config/tasks/main.yml
new file mode 100644 (file)
index 0000000..364a798
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Panic in an out-of-memory situation
+  sysctl:
+    name: vm.panic_on_oom
+    value: 2
+    sysctl_file: /etc/sysctl.d/01-oom.conf
diff --git a/roles/ops-hardening/tasks/main.yaml b/roles/ops-hardening/tasks/main.yaml
new file mode 100644 (file)
index 0000000..d56e893
--- /dev/null
@@ -0,0 +1,348 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+#
+# Linux password hardening
+#
+
+- name: "Set Password Strength Minimum Digit Characters."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*dcredit'
+    line: 'dcredit = -1'
+
+- name: "Set Password Minimum Length."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*minlen'
+    line: 'minlen = 8'
+
+- name: "Set Password Strength Minimum Uppercase Characters."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*ucredit'
+    line: 'ucredit = -1'
+
+- name: "Set Password Strength Minimum Special Characters."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*ocredit'
+    line: 'ocredit = -1'
+
+- name: "Set Password Strength Minimum Lowercase Characters."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*lcredit'
+    line: 'lcredit = -1'
+
+- name: "Set Password Strength Minimum Different Categories."
+  lineinfile:
+    path: /etc/security/pwquality.conf
+    regexp: '^[#\s]*minclass'
+    line: 'minclass = 3'
+
+- name: "Set Password Minimum Length in login.defs"
+  lineinfile:
+    path: /etc/login.defs
+    regexp: '^PASS_MIN_LEN[\s]*[0-9]*$'
+    line: 'PASS_MIN_LEN   8'
+
+- name: "Set Password Minimum Age"
+  lineinfile:
+    path: /etc/login.defs
+    regexp: '^PASS_MIN_DAYS[\s]*[0-9]*$'
+    line: 'PASS_MIN_DAYS   0'
+
+#
+# YUM config
+#
+
+- name: "Ensure YUM Removes Previous Package Versions"
+  lineinfile:
+    path: /etc/yum.conf
+    insertafter: '^[#\s]*\[main\]'
+    line: 'clean_requirements_on_remove = 1'
+
+- name: "Ensure gpgcheck Enabled for Local Packages"
+  lineinfile:
+    path: /etc/yum.conf
+    insertafter: '^[#\s]*\[main\]'
+    line: 'localpkg_gpgcheck = 1'
+
+#
+# Setting Ctrl-Alt-Del action
+#
+
+- name: "Disable Ctrl-Alt-Del Burst Action"
+  lineinfile:
+    path: /etc/systemd/system.conf
+    insertafter: '^[#\s]*CtrlAltDelBurstAction'
+    line: 'CtrlAltDelBurstAction=none'
+
+- name: "Disable Ctrl-Alt-Del Reboot Activation"
+  command: systemctl mask ctrl-alt-del.target
+
+#
+# Configure kernel modules
+#
+
+- name: "kernel module setting"
+  lineinfile:
+    create=yes
+    dest="/etc/modprobe.d/{{item}}.conf"
+    regexp="{{item}}"
+    line="install {{item}} /bin/true"
+  with_items:
+    - bluetooth
+    - dccp
+    - squashfs
+    - hfsplus
+    - hfs
+    - jffs2
+    - freevxfs
+    - cramfs
+    - usb-storage
+    - udf
+
+#
+# Disable interactive boot
+#
+
+- name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX Setting
+  lineinfile:
+    path: /etc/default/grub
+    backrefs: yes
+    regexp: '^GRUB_CMDLINE_LINUX=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
+    line: 'GRUB_CMDLINE_LINUX=\1\3'
+
+- name:  Verify that Interactive Boot is Disabled GRUB_CMDLINE_LINUX_DEFAULT Setting
+  lineinfile:
+    path: /etc/default/grub
+    backrefs: yes
+    regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=(.*)systemd\.confirm_spawn=(1|yes|true|on)\s*(.*)$'
+    line: 'GRUB_CMDLINE_LINUX_DEFAULT=\1\3'
+
+#
+# Set file permissions
+#
+
+- name: "Set set the 600 file permissions"
+  file:
+    path: "{{item}}"
+    state: touch
+    mode: 600
+  with_items:
+    - /boot/grub2/grub.cfg
+    - /var/log/boot.log
+    - /var/log/cron
+
+#
+# Disable direct root login
+#
+
+- name: "Direct root Logins Not Allowed"
+  shell: echo > /etc/securetty
+
+#
+# Configure IPv6
+#
+
+- name: Disable ipv6 support if the ipv6 is not needed
+  when: ansible_default_ipv6|length == 0
+  sysctl:
+    name: net.ipv6.conf.all.disable_ipv6
+    value: 1
+    state: present
+    reload: yes
+
+- name: Disable Support for udp6
+  when: ansible_default_ipv6|length == 0
+  lineinfile:
+    path: /etc/netconfig
+    state: absent
+    regexp: '^udp6.*'
+
+- name: Disable Support for tcp6
+  when: ansible_default_ipv6|length == 0
+  lineinfile:
+    path: /etc/netconfig
+    state: absent
+    regexp: '^tcp6.*'
+
+- name: Disable automatic ipv6 configuration
+  when: ansible_default_ipv6|length > 0
+  sysctl:
+    name: "{{ item.name }}"
+    value: "{{ item.value }}"
+    state: present
+    reload: yes
+  with_items:
+    - { name: 'net.ipv6.conf.all.accept_source_route', value: 0 }
+    - { name: 'net.ipv6.conf.all.accept_ra', value: 0 }
+    - { name: 'net.ipv6.conf.default.accept_ra', value: 0 }
+    - { name: 'net.ipv6.conf.all.accept_redirects', value: 0 }
+    - { name: 'net.ipv6.conf.default.accept_redirects', value: 0 }
+    - { name: 'net.ipv6.conf.default.accept_source_route', value: 0 }
+    - { name: 'net.ipv6.conf.all.forwarding', value: 0 }
+
+#
+# Configure kernel parameters
+#
+
+- name: Configure the kernel parameters
+  sysctl:
+    name: "{{ item.name }}"
+    value: "{{ item.value }}"
+    state: present
+    reload: yes
+  with_items:
+    - { name: 'net.ipv4.conf.default.send_redirects', value: 0 }
+    - { name: 'net.ipv4.conf.all.send_redirects', value: 0 }
+    - { name: 'net.ipv4.ip_forward', value: 0 }
+    - { name: 'net.ipv4.conf.all.accept_redirects', value: 0 }
+    - { name: 'net.ipv4.conf.all.secure_redirects', value: 0 }
+    - { name: 'net.ipv4.conf.all.log_martians', value: 1 }
+    - { name: 'net.ipv4.conf.default.log_martians', value: 1 }
+    - { name: 'net.ipv4.conf.default.accept_redirects', value: 0 }
+    - { name: 'net.ipv4.conf.default.secure_redirects', value: 0 }
+    - { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: 1 }
+    - { name: 'net.ipv4.icmp_ignore_bogus_error_responses', value: 1 }
+    - { name: 'net.ipv4.tcp_syncookies', value: 1 }
+    - { name: 'fs.suid_dumpable', value: 0 }
+    - { name: 'kernel.dmesg_restrict', value: 1 }
+    - { name: 'kernel.core_uses_pid', value: 1 }
+    - { name: 'kernel.randomize_va_space', value: 2 }
+    - { name: 'kernel.core_pattern', value: '/var/core/core'}
+
+#
+# Configure core dump
+#
+
+- name: "Disable core dump for all user"
+  lineinfile:
+    path: /etc/security/limits.conf
+    insertbefore: '^[a-z].*'
+    line: '*               hard    core            0'
+
+- name: "Configure systemd not to store core dumps"
+  lineinfile:
+    path: /etc/systemd/coredump.conf
+    insertafter: '^\[Coredump\]'
+    line: 'Storage=none'
+
+#
+# Configure syslog
+#
+- name: "Stop rsyslog Service"
+  shell: systemctl stop rsyslog.service
+
+- name: "Disable rsyslog Service"
+  shell: systemctl disable rsyslog.service
+
+- name: "Ensure the /var/log/boot.log Rotated by logrotate"
+  lineinfile:
+    path: /etc/logrotate.d/syslog
+    insertbefore: 'cron$'
+    line: /var/log/boot.log
+
+- name: "Set the umasks by profile file"
+  lineinfile:
+    path: /etc/profile
+    regexp: '{{ item.old }}'
+    line: '{{ item.new }}'
+  with_items:
+    - { old: 'umask 002', new: umask 027 }
+    - { old: 'umask 022', new: umask 077 }
+
+#
+# Keystone config
+#
+
+- name: Set the max_request_body_size in the keystone.conf
+  lineinfile:
+    path: /etc/keystone/keystone.conf
+    insertafter: 'DEFAULT'
+    line: "# enforced by optional sizelimit middleware (keystone.middleware:RequestBodySizeLimiter)\nmax_request_body_size = 114688\n"
+
+- name: Set the insecure_debug in the keystone.conf
+  lineinfile:
+    path: /etc/keystone/keystone.conf
+    insertafter: 'DEFAULT'
+    line: "# If set to true, then the server will return information in HTTP responses\n# that may allow an unauthenticated or authenticated user to get more\n# information than normal, such as additional details about why authentication\n# failed. This may be useful for debugging but is insecure. (boolean value)\ninsecure_debug = false\n"
+
+#
+#Setting bootloader password
+#
+- name: set host os variable
+  when: host_os is defined
+  set_fact:
+    grub2_pass: "{{  host_os.grub2_password | default('Empty')  }}"
+
+- name: protect grub with root password
+  when: grub2_pass is defined and grub2_pass != 'Empty'
+  blockinfile:
+    dest: /etc/grub.d/40_custom
+    state: present
+    insertafter: 'EOF'
+    content: |
+      # define superusers
+      set superusers="root"
+      #define users
+      password_pbkdf2 root "{{ grub2_pass }}"
+
+- name: generate grub config
+  when: grub2_pass is defined and grub2_pass != 'Empty'
+  command: /usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg
+
+#
+#Setting the noexec option to the /dev/shm mount dir
+#
+
+- name: get back device associated to mountpoint
+  shell: mount | grep ' /dev/shm ' |cut -d ' ' -f 1
+  register: device_name
+  check_mode: no
+
+- name: get back device previous mount option
+  shell: mount | grep ' /dev/shm ' | sed -re 's:.*\((.*)\):\1:'
+  register: device_cur_mountoption
+  check_mode: no
+
+- name: get back device fstype
+  shell: mount | grep ' /dev/shm ' | cut -d ' ' -f 5
+  register: device_fstype
+  check_mode: no
+
+- name: Ensure permission noexec are set on /dev/shm
+  mount:
+    path: "/dev/shm"
+    src: "{{device_name.stdout}}"
+    opts: "{{device_cur_mountoption.stdout}},noexec"
+    state: "mounted"
+    fstype: "{{device_fstype.stdout}}"
+
+#
+# Setting file permissions
+#
+
+#- name: "Remove the other user write permission from the system directorys"
+#  command: find / -xdev \( -perm -0002 -a ! -perm -1000 \) -type d -exec chmod o-w {} \;
+#
+#- name: "Remove the other user write permission from the system files"
+#  command: find / -xdev -perm -0002 -type f -exec chmod o-w {} \;
+#
+#- name: "Modified the unauthorized SUID/SGID system executables"
+#  command: sudo chmod -s $(sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | grep -v sudo)
diff --git a/roles/partfs_rootdisk/defaults/main.yml b/roles/partfs_rootdisk/defaults/main.yml
new file mode 100644 (file)
index 0000000..210e0cd
--- /dev/null
@@ -0,0 +1,30 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
+## Verbosity Options
+debug: False
+root_disk: "{{ by_path_disks['os'] }}"
+all_disk_size_for_volume_group_vg: "1"
+
+first_part_size: 50
+second_part_percentage: "{{ rootdisk_vg_percentage }}"
+root_disk_left_size: "{{ root_disk_total_size.stdout | int - first_part_size | int }}"
+second_part_size: "{{ root_disk_left_size | float * second_part_percentage | float  }}"
+
+second_part_start: "{{ first_part_size }}"
+second_part_end: "{{first_part_size | int + second_part_size | int }}"
+third_part_start: "{{ second_part_end }}"
diff --git a/roles/partfs_rootdisk/handlers/main.yml b/roles/partfs_rootdisk/handlers/main.yml
new file mode 100644 (file)
index 0000000..22a6d31
--- /dev/null
@@ -0,0 +1,17 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+
diff --git a/roles/partfs_rootdisk/scripts/old_vol_rm.sh b/roles/partfs_rootdisk/scripts/old_vol_rm.sh
new file mode 100755 (executable)
index 0000000..887cd2b
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# Copyright 2019 Nokia
+
+# 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.
+
+exec >> /tmp/old_vol_rm_logfile
+exec 2>&1
+
+lvm_paths=`lvs --noheadings -o vg_name,lvname,lv_dmpath`
+
+if [[ $lvm_paths ]];then
+
+  echo "Already available lvm_paths:"
+  echo "$lvm_paths"
+
+  while read -r -a lvm_path; do
+    grep ${lvm_path[2]} /etc/fstab > /dev/null 2>&1
+    if [[ $? != 0 ]];then
+      lvm_rm_path=`echo ${lvm_path[0]}/${lvm_path[1]}`
+      echo "Removing LVM $lvm_rm_path"
+      sudo lvremove -f $lvm_rm_path
+    fi
+  done
+
+else
+    echo "No logical volumes to remove (lvm_paths: \"${lvm_paths}\")."
+    exit 0
+fi <<< "$lvm_paths"
diff --git a/roles/partfs_rootdisk/scripts/vol_mgmt.sh b/roles/partfs_rootdisk/scripts/vol_mgmt.sh
new file mode 100755 (executable)
index 0000000..b1ac984
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright 2019 Nokia
+
+# 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.
+
+# This tool is meant to stop processes running in a given directory.
+# Evacuate its contents to a temp location.
+# Mount a given LVM to the Directory
+# Start those services again
+
+#arg1: Directory to evacuate
+#arg2: Volume dev path to mount
+
+exec >> /tmp/vol_mgmt_logfile
+exec 2>&1
+
+
+if [[ $# != 2 ]];then
+  echo "Improper number of arguments passed!!"
+  exit 1
+fi
+
+evac_dir=$1
+mount_vol_dev=$2
+
+echo "Trying to mount $mount_vol_dev on $evac_dir"
+
+# Run partprobe to load new volumes
+/usr/sbin/partprobe
+
+if [ ! -d $evac_dir ];then
+  echo "Provided directory $evac_dir does not exist, so lets create it."
+  mkdir -p "$evac_dir"
+fi
+
+if [ ! -b $mount_vol_dev ];then
+  echo "Provided volume $mount_vol_dev is not a block device!!"
+  exit 1
+fi
+
+# check if given directory is already mounted from needed volume
+df -k $evac_dir | grep $mount_vol_dev > /dev/null 2>&1
+if [[ $? == 0 ]];then
+  echo "$evac_dir is already mounted from $mount_vol_dev"
+  exit 0
+fi
+
+running_process_list=`lsof | grep ${evac_dir} | awk -F " " {'print $2'}| uniq`
+systemd_service_list=`systemctl --state=active --type=socket,service | grep "loaded active" | awk -F " " {'print $1'}`
+
+declare -a matching_systemd_services
+for process in ${running_process_list}; do
+  for systemd_service in ${systemd_service_list}; do
+    systemd_MainPID=`systemctl show -p MainPID ${systemd_service} | awk -F "MainPID=" {'print $2'}`
+    if [[ $process == $systemd_MainPID ]];then
+      matching_systemd_services+=(${systemd_service})
+      break
+    fi
+  done
+done
+
+# Stop running services which were using old dir
+echo "Stopping services ${matching_systemd_services[@]}"
+for service_name in ${matching_systemd_services[@]}; do
+  systemctl stop $service_name > /dev/null 2>&1
+  if [[ $? != 0 ]];then
+    service_base_name=`echo $service_name | awk -F ".service" {'print $1'}`
+    service $service_base_name stop > /dev/null 2>&1
+  fi
+
+  service_wait_count=10
+  systemd_status=0
+  while [[ $service_wait_count != 0 && $systemd_status == 0 ]]; do
+    echo "waiting for $service_name to stop"
+    sleep 1
+    ((service_wait_count--))
+    systemctl status $service_name > /dev/null 2>&1
+    systemd_status=$?
+  done
+
+  if [[ $service_wait_count == 0 ]];then
+    echo "$service_name did not stop gracefully. Stopping it forcefully."
+    systemctl -f stop $service_name > /dev/null 2>&1
+  fi
+done
+
+# Move old dir contents to tmp location
+tmp_dir="/tmp/`basename ${evac_dir}`"
+mkdir -p $tmp_dir
+cp -rpf ${evac_dir}/* $tmp_dir
+rm -rf ${evac_dir}/*
+
+# Mount the volume on dir
+mount $evac_dir
+
+cp -rpf $tmp_dir/* ${evac_dir}/
+rm -rf $tmp_dir
+
+# Start the services again
+echo "Starting services ${matching_systemd_services[@]}"
+for service_name in ${matching_systemd_services[@]}; do
+  systemctl start $service_name > /dev/null 2>&1
+done
diff --git a/roles/partfs_rootdisk/tasks/main.yml b/roles/partfs_rootdisk/tasks/main.yml
new file mode 100644 (file)
index 0000000..dd84759
--- /dev/null
@@ -0,0 +1,125 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Gather variables for each operating system
+  include_vars: "{{ item }}"
+  with_first_found:
+    - "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml"
+    - "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
+    - "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
+    - "{{ ansible_distribution | lower }}.yml"
+    - "{{ ansible_os_family | lower }}-{{ ansible_distribution_version.split('.')[0] }}.yml"
+    - "{{ ansible_os_family | lower }}.yml"
+  tags:
+    - always
+
+- name: Stop all cloud-init services and disable them
+  systemd:
+    name: "{{item}}"
+    enabled: no
+    state: stopped
+  with_items:
+    - "cloud-config"
+    - "cloud-final"
+    - "cloud-init"
+    - "cloud-init-local"
+
+- name: Remove udev rule which enables dhcp on the first interface
+  file: path="/etc/udev/rules.d/70-persistent-net.rules" state=absent
+
+- name: Remove interface configuration which use dhcp
+  shell: rm -f $(grep -li BOOTPROTO.*dhcp /etc/sysconfig/network-scripts/ifcfg-* | sort -u)
+
+- set_fact:
+    root_disk_part1: "{% if root_disk == default_rootdisk_device %}{{root_disk}}{{first_part_number}}{% else %}{{root_disk}}-part{{first_part_number}}{% endif %}"
+
+- name: get volume pools
+  shell: dmsetup ls | awk '{print $1}'
+  register: volume_pools
+  ignore_errors: yes
+
+- debug:
+    msg: "volume pools: {{ volume_pools.stdout_lines }}"
+
+- name: Delete old LVMs if not mounted already
+  script: "{{role_path}}/scripts/old_vol_rm.sh"
+  args:
+    creates: /etc/partfs_rootdisk_created
+
+- name: get volume groups
+  shell: "vgs -o vg_name --noheadings | sed 's/ //g'"
+  register: volumegroups
+  ignore_errors: yes
+
+- debug:
+    msg: "volume groups: {{ volumegroups.stdout_lines }}"
+
+- name: get volume pools
+  shell: dmsetup ls | awk '{print $1}'
+  register: volume_pools
+  ignore_errors: yes
+
+- debug:
+    msg: "volume pools: {{ volume_pools.stdout_lines }}"
+
+- name: remove old volume groups
+  include: remove_old_instance_vg.yml
+
+- name: delete temporary partition
+  parted:
+    device: "{{root_disk}}"
+    number: "{{delete_partition}}"
+    state: absent
+  when: delete_partition is defined
+
+- name: system disk total size
+  shell: parted {{root_disk}} unit GB print | grep "Disk /dev/" | awk '{print $3}' | tr -d 'a-z,A-Z'
+  register: root_disk_total_size
+
+- debug:
+    msg: "root_disk_total_size.stdout {{ root_disk_total_size.stdout }}"
+
+- name: configure root volume groups
+  include: root_disk_volume_groups.yml
+  vars:
+    part_start: "{{second_part_start}}GiB"
+    part_end: "{{second_part_end}}GB"
+    phy_disk_part_number: 2
+    create_disk_part: True
+
+- name: system disk first partition size
+  shell: parted {{root_disk_part1}} unit GB print | grep "Disk /dev/" | awk '{print $3}' | tr -d 'a-z,A-Z'
+  register: first_part
+
+- debug:
+     msg: "first_part.stdout {{ first_part.stdout }}"
+
+- name: configure instance disk partition
+  parted:
+    device: "{{root_disk}}"
+    number: 3
+    part_start: "{{third_part_start}}GB"
+    flags: [ lvm ]
+    state: present
+  when: rootdisk_vg_percentage != all_disk_size_for_volume_group_vg
+
+- name: remove old volume groups
+  include: remove_old_instance_vg.yml
+
+- name: create /etc/partfs_rootdisk_created file
+  command: touch /etc/partfs_rootdisk_created
+  args:
+    creates: /etc/partfs_rootdisk_created
diff --git a/roles/partfs_rootdisk/tasks/remove_old_instance_vg.yml b/roles/partfs_rootdisk/tasks/remove_old_instance_vg.yml
new file mode 100644 (file)
index 0000000..ed58fa2
--- /dev/null
@@ -0,0 +1,84 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- set_fact:
+    root_disk_part3: "{% if root_disk == default_rootdisk_device %}{{root_disk}}3{% else %}{{root_disk}}-part3{% endif %}"
+
+- debug:
+    msg: "root disk part3: {{ root_disk_part3 }}"
+
+- name: get volume pools
+  shell: dmsetup ls | awk '/volumes/ {print $1}'
+  register: volume_pools
+  ignore_errors: yes
+
+- debug:
+    msg: "volume pools: {{ volume_pools.stdout_lines }}"
+
+- name: remove volume pools 1 round
+  shell: dmsetup remove {{ item }}
+  with_items: "{{ volume_pools.stdout_lines }}"
+  ignore_errors: yes
+  when: volume_pools.stdout_lines
+
+- name: get volume pools
+  shell: dmsetup ls | awk '/volumes/ {print $1}'
+  register: volume_pools
+  ignore_errors: yes
+
+- debug:
+    msg: "volume pools: {{ volume_pools.stdout_lines }}"
+
+- name: remove volume pools 2 round
+  shell: dmsetup remove {{ item }}
+  with_items: "{{ volume_pools.stdout_lines }}"
+  ignore_errors: yes
+  when: volume_pools.stdout_lines
+
+- name: get volume groups
+  shell: "vgs -o vg_name --noheadings | sed 's/ //g'"
+  register: volumegroups
+
+- debug:
+    msg: "volume groups: {{ volumegroups.stdout_lines }}"
+
+- name: remove volume groups
+  lvg: vg={{ item }} state=absent force=yes
+  ignore_errors: yes
+  with_items: "{{ volumegroups.stdout_lines }}"
+  when:
+    - volumegroups.stdout_lines
+    - item != "VG"
+
+- name: remove physical volume (if any)
+  shell: pvremove {{ root_disk_part3 }}
+  ignore_errors: yes
+
+- name: get volume groups
+  shell: "vgs -o vg_name --noheadings | sed 's/ //g'"
+  register: volumegroups
+  ignore_errors: yes
+
+- debug:
+    msg: "volume groups: {{ volumegroups.stdout_lines }}"
+
+- name: get volume pools
+  shell: dmsetup ls | awk '{print $1}'
+  register: volume_pools
+  ignore_errors: yes
+
+- debug:
+    msg: "volume pools: {{ volume_pools.stdout_lines }}"
diff --git a/roles/partfs_rootdisk/tasks/root_disk_volume_groups.yml b/roles/partfs_rootdisk/tasks/root_disk_volume_groups.yml
new file mode 100644 (file)
index 0000000..d0d5d84
--- /dev/null
@@ -0,0 +1,140 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: check if this is partfs_rootdisk re-run
+  stat:
+    path: /etc/partfs_rootdisk_created
+  ignore_errors: yes
+  register: rerun_case
+
+- name: Create /tmp/<node_name>localstorage.json file
+  template:
+    src: "localstorage.j2"
+    dest: "/tmp/{{inventory_hostname}}_localstorage.json"
+    owner: "root"
+    mode: "0644"
+  delegate_to: "{{installation_controller}}"
+
+- name: Load variables from the json file
+  include_vars: "/tmp/{{inventory_hostname}}_localstorage.json"
+
+- name: Remove /tmp/<node_name>localstorage.json file
+  file:
+    path: "/tmp/{{inventory_hostname}}_localstorage.json"
+    state: "absent"
+  delegate_to: "{{installation_controller}}"
+
+- name: Create Partition for LVMs
+  parted:
+    device: "{{root_disk}}"
+    number: "{{phy_disk_part_number}}"
+    flags: [ lvm ]
+    state: present
+    part_start: "{{part_start}}"
+    part_end: "{{part_end}}"
+  when:
+    - create_disk_part | bool
+    - rootdisk_vg_percentage != all_disk_size_for_volume_group_vg
+
+- name: Create Partition for LVMs
+  parted:
+    device: "{{root_disk}}"
+    number: "{{phy_disk_part_number}}"
+    flags: [ lvm ]
+    state: present
+    part_start: "{{part_start}}"
+  when:
+    - create_disk_part | bool
+    - rootdisk_vg_percentage == all_disk_size_for_volume_group_vg
+
+- set_fact:
+    vg_disk: "{% if root_disk == default_rootdisk_device %}{{root_disk}}{{phy_disk_part_number}}{% else %}{{root_disk}}-part{{phy_disk_part_number}}{% endif %}"
+
+- debug:
+    msg: "{{vg_disk}}"
+
+- name: Create PV VG
+  lvg:
+    vg: VG
+    pvs: "{{vg_disk}}"
+
+- name: Delete old LVMs if not mounted already
+  script: "{{role_path}}/scripts/old_vol_rm.sh"
+  args:
+    creates: /etc/partfs_rootdisk_created
+
+- name: Creating LVM
+  lvol:
+    vg: VG
+    lv: "{{vol['lvm_name']}}"
+    size: "{{vol['lvm_size']}}"
+  with_items: "{{device_mapping|sort(attribute='mount_point')}}"
+  loop_control:
+    loop_var: vol
+  when:
+    - rerun_case.stat.exists is undefined or rerun_case.stat.exists == false
+
+- name: Create XFS filesystem on LVM
+  filesystem:
+    fstype: xfs
+    dev: "/dev/mapper/VG-{{vol['lvm_name']}}"
+  with_items: "{{device_mapping|sort(attribute='mount_point')}}"
+  loop_control:
+    loop_var: vol
+
+- name: Create fstab entry.
+  mount:
+    path: "{{vol['mount_point']}}"
+    src: "/dev/mapper/VG-{{vol['lvm_name']}}"
+    fstype: xfs
+    opts: "{{vol['mount_opts']}}"
+    state: present
+  with_items: "{{device_mapping|sort(attribute='mount_point')}}"
+  loop_control:
+    loop_var: vol
+
+# Run below script to do the following tasks
+#-  Stop existing services
+#-  Move the current files to a tmp location
+#-  mount LVM on mount dir
+#-  restore old files
+#-  Start old services
+#- It creates logs in the target node at /tmp/vol_mgmt_logfile
+- name: Running a script to remount volume on target dir
+  script: "{{role_path}}/scripts/vol_mgmt.sh {{vol['mount_point']}} /dev/mapper/VG-{{vol['lvm_name']}}"
+  with_items: "{{device_mapping|sort(attribute='mount_point')}}"
+  loop_control:
+    loop_var: vol
+  args:
+    creates: /etc/partfs_rootdisk_created
+
+- name: Check if Root partition can grow
+  shell: "growpart --dry-run $(readlink -f {{root_disk}}) 1"
+  register: rootpart
+  ignore_errors: yes
+  args:
+    creates: /etc/partfs_rootdisk_created
+
+- name: Grow Root partition
+  shell: "growpart $(readlink -f {{root_disk}}) 1"
+  when: rootpart.rc == 0
+  args:
+    creates: /etc/partfs_rootdisk_created
+
+- name: Grow xfs filesystem on Root partition
+  command: "xfs_growfs /"
+  args:
+    creates: /etc/partfs_rootdisk_created
diff --git a/roles/partfs_rootdisk/templates/localstorage.j2 b/roles/partfs_rootdisk/templates/localstorage.j2
new file mode 100644 (file)
index 0000000..a75c8c2
--- /dev/null
@@ -0,0 +1,55 @@
+{%- set node_service_profiles = hosts[inventory_hostname]['service_profiles'] %}
+{%- if (openstack is defined) and (openstack != '') -%}
+  {%- if (('management' in node_service_profiles) and (ceph_configured | default(False))) -%}
+    {%- set _ = node_service_profiles.append("cephcontroller") -%}
+  {%- endif -%}
+{%- endif -%}
+{%- if node_service_profiles|length > 1 %}
+
+  {%- set device_mapping = {} %}
+  {% if device_mapping.update(localstorage[node_service_profiles[0]]) %}{%- endif %}
+
+  {%- macro update_bigger_hash(hash) -%}
+    {%- set vol_names1 = device_mapping.keys()|list %}
+    {%- set vol_names2 = hash.keys()| list %}
+    {%- set vol_names =  vol_names1 + vol_names2| unique|list%}
+
+    {%- for vol_name in vol_names %}
+      {% if vol_name in device_mapping.keys() and vol_name not in hash.keys() %}
+        {% if device_mapping.update({ vol_name:  device_mapping[vol_name]}) %}{%- endif %}
+      {% elif vol_name not in device_mapping.keys() and vol_name in hash.keys() %}
+        {% if device_mapping.update({ vol_name: hash[vol_name]} ) %}{%- endif %}
+      {%- elif device_mapping[vol_name]["lvm_size"]|replace("%VG", "")|int > hash[vol_name]["lvm_size"]|replace("%VG", "")|int %}
+        {% if device_mapping.update({ vol_name: device_mapping[vol_name]}) %}{%- endif %}
+      {%- else %}
+        {% if device_mapping.update({ vol_name: hash[vol_name]} ) %}{%- endif %}
+      {%- endif %}
+    {%- endfor -%}
+  {%- endmacro -%}
+
+  {%- for index in range(1, node_service_profiles | length) -%}
+    {%-if update_bigger_hash(localstorage[node_service_profiles[index]]) -%}{%- endif %}
+  {%- endfor -%}
+
+{%- else %}
+  {%- set device_mapping = localstorage[node_service_profiles[0]] %}
+{%- endif %}
+
+{% set allocated_vg = device_mapping.values() | map(attribute="lvm_size") | map("replace", "%VG", "") | map("int") | sum %}
+{% set variable_found = device_mapping.values() | selectattr("lvm_size", "search", "variable") | list %}
+{% if variable_found %}
+  {% set variable_size = (100-allocated_vg) | string + '%VG'%}
+  {% set _ = variable_found[0].update({'lvm_size': variable_size}) %}
+{% endif %}
+
+{
+"device_mapping": [
+{%- for vol_value in device_mapping.values() %}
+   {
+   {%- for vol_details_key,vol_details_value in vol_value.iteritems()  %}
+   "{{vol_details_key}}":"{{vol_details_value}}"{% if not loop.last %},{% endif %}
+   {%- endfor -%}
+   }{% if not loop.last %},{% endif %}
+{%- endfor -%}
+]
+}
diff --git a/roles/partfs_rootdisk/vars/redhat-7.yml b/roles/partfs_rootdisk/vars/redhat-7.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/partfs_rootdisk/vars/ubuntu-16.04.yml b/roles/partfs_rootdisk/vars/ubuntu-16.04.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/performance_nodes/defaults/main.yml b/roles/performance_nodes/defaults/main.yml
new file mode 100644 (file)
index 0000000..c579788
--- /dev/null
@@ -0,0 +1,17 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+provider_network_type: ''
diff --git a/roles/performance_nodes/files/configure_ovsdpdk.py b/roles/performance_nodes/files/configure_ovsdpdk.py
new file mode 100644 (file)
index 0000000..31e784c
--- /dev/null
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+
+# Copyright 2019 Nokia
+
+# 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 argparse
+import subprocess
+import sys
+
+
+class CoreHandler(object):
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def hex_to_set(hexstr):
+        hexn = int(hexstr, 16)
+        b = 1
+        cpuset = set()
+        for i in range(0, 64):
+            if hexn & b != 0:
+                cpuset.add(i)
+            b = b << 1
+        return cpuset
+
+    @staticmethod
+    def set_to_hex(cpuset):
+        cpumask = 0
+        for i in cpuset:
+            b = 1 << i
+            cpumask += b
+        return '0x{:x}'.format(cpumask)
+
+    @staticmethod
+    def string_to_set(cpustr):
+        if cpustr == '' or cpustr is None:
+            raise Exception("Empty string")
+        cpuset_ids = set()
+        cpuset_reject_ids = set()
+        for rule in cpustr.split(','):
+            rule = rule.strip()
+            # Handle multi ','
+            if len(rule) < 1:
+                continue
+            # Note the count limit in the .split() call
+            range_parts = rule.split('-', 1)
+            if len(range_parts) > 1:
+                # So, this was a range; start by converting the parts to ints
+                try:
+                    start, end = [int(p.strip()) for p in range_parts]
+                except ValueError:
+                    raise Exception("Invalid range expression {}".format(rule))
+                # Make sure it's a valid range
+                if start > end:
+                    raise Exception("Invalid range expression (start > end): {}".format(rule))
+                # Add available CPU ids to set
+                cpuset_ids |= set(range(start, end + 1))
+            elif rule[0] == '^':
+                # Not a range, the rule is an exclusion rule; convert to int
+                try:
+                    cpuset_reject_ids.add(int(rule[1:].strip()))
+                except ValueError:
+                    raise Exception("Invalid exclusion expression {}".format(rule))
+            else:
+                # OK, a single CPU to include; convert to int
+                try:
+                    cpuset_ids.add(int(rule))
+                except ValueError:
+                    raise Exception("Invalid inclusion expression {}".format(rule))
+
+        # Use sets to handle the exclusion rules for us
+        cpuset_ids -= cpuset_reject_ids
+        return cpuset_ids
+
+    @staticmethod
+    def set_to_string(cpuset):
+        ranges = []
+        previndex = None
+        for cpuindex in sorted(cpuset):
+            if previndex is None or previndex != (cpuindex - 1):
+                ranges.append([])
+            ranges[-1].append(cpuindex)
+            previndex = cpuindex
+
+        parts = []
+        for entry in ranges:
+            if len(entry) == 1:
+                parts.append(str(entry[0]))
+            else:
+                parts.append("{}-{}".format(entry[0], entry[len(entry) - 1]))
+        return ",".join(parts)
+
+    def hex_to_string(self, hexstr):
+        """
+        :param hexstr: CPU mask as hex string
+        :returns: a formatted CPU range string
+        """
+        cpuset = self.hex_to_set(hexstr)
+        return self.set_to_string(cpuset)
+
+    def string_to_hex(self, cpustr):
+        cpuset = self.string_to_set(cpustr)
+        return self.set_to_hex(cpuset)
+
+
+class OvsVsctl(object):
+    def __init__(self, cores, pcore, tcore, sockets):
+        self.cores = cores
+        self.pcore = pcore
+        self.threads_per_core = tcore
+        self.sockets = sockets
+
+    def is_hyperthreading_enabled(self):
+        if int(self.threads_per_core) >= 2:
+            return True
+        return False
+
+    def is_single_socket(self):
+        if int(self.sockets) == 1:
+            return True
+        return False
+
+    @staticmethod
+    def get_value(field):
+        """Get value for specified field in Open_vSwitch other_config.
+        Returns:
+            Value without quotes or newlines
+            None if field is not set
+        """
+        try:
+            current_value = subprocess.check_output(["ovs-vsctl", "get", "Open_vSwitch", ".", "other_config:{}".format(field)])
+        except Exception:
+            return None
+        return current_value.lstrip('\"').strip('\n').rstrip('\"')
+
+    def set_pmd_cpu_mask(self, value):
+        """Set DPDK core mask."""
+        current_value = self.get_value('pmd-cpu-mask')
+        print "INFO: New core mask {}, current_value {}".format(value, current_value)
+        if current_value == value:
+            return False
+        try:
+            subprocess.check_output(["ovs-vsctl", "set", "Open_vSwitch", ".", "other_config:pmd-cpu-mask=\"{}\"".format(value)])
+        except Exception:
+            sys.exit(2)
+        return True
+
+    def set_lcore_mask(self):
+        """Set DPDK library mask."""
+        #if self.is_single_socket():
+        mask = '0x0'
+        # TODO: measure if it would be beneficial to reserve more cores and from second socket
+        current_value = self.get_value('dpdk-lcore-mask')
+        print "INFO: Mask {},  current_value {}".format(mask, current_value)
+
+        if current_value == mask:
+            return False
+        try:
+            subprocess.check_output(["ovs-vsctl", "set", "Open_vSwitch", ".", "other_config:dpdk-lcore-mask=\"{}\"".format(mask)])
+        except Exception:
+            sys.exit(2)
+        return True
+
+    def set_socket_mem(self, value):
+        """Set DPDK memory."""
+        if self.is_single_socket():
+            mem = '{0},0'.format(value)
+        else:
+            mem = '{0},{0}'.format(value)
+        current_value = self.get_value('dpdk-socket-mem')
+        print "INFO: New mem {},  current_value {}".format(mem, current_value)
+
+        if current_value == mem:
+            return False
+        try:
+            subprocess.check_output(["ovs-vsctl", "set", "Open_vSwitch", ".", "other_config:dpdk-socket-mem=\"{}\"".format(mem)])
+        except Exception:
+            sys.exit(2)
+        return True
+
+    def enable_dpdk(self):
+        """Enable DPDK."""
+        current_value = self.get_value('dpdk-init')
+        print "INFO: Enable DPDK, current_value {}".format(current_value)
+        if current_value == 'true':
+            return False
+
+        try:
+            with open('/etc/performance-nodes/dpdk.enabled', 'a'):
+                pass
+        except IOError:
+            sys.exit(2)
+
+        return True
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--dpdkcores', dest='dpdkcores', help='DPDK cores', required=False, type=str)
+    parser.add_argument('--cores', dest='cores', help='Logical cores', required=False, type=str)
+    parser.add_argument('--pcore', dest='pcore', help='Cores per processor', required=False, type=str)
+    parser.add_argument('--tcore', dest='tcore', help='Threads per core', required=False, type=str)
+    parser.add_argument('--sockets', dest='sockets', help='Number of sockets', required=False, type=str)
+    parser.add_argument('--mem', dest='mem', help='Socket mem', required=False, type=str, default='4096')
+    args = parser.parse_args()
+
+    ovsvsctl = OvsVsctl(args.cores, args.pcore, args.tcore, args.sockets)
+    coreh = CoreHandler()
+
+    dpdkcoreset = None
+    try:
+        print "INFO: dpdk cores: {}, cpu count: {}".format(args.dpdkcores, args.cores)
+        if args.dpdkcores:
+            dpdkcoreset = coreh.string_to_set(args.dpdkcores)
+    except Exception as exp:
+        print "ERROR: Calculating of cpu/core set failed: {}".format(exp)
+        sys.exit(2)
+
+    if max(dpdkcoreset) > int(args.cores):
+        print "ERROR: invalid DPDK cores (too big)"
+        sys.exit(2)
+
+    # Check if hyperthreading is off and we can calculate new core set so that
+    # DPDK has a chance to start.
+    if not ovsvsctl.is_hyperthreading_enabled() and max(dpdkcoreset) > int(args.cores):
+        print "INFO: Hyperthreading off, DPDK cores contain too big core"
+        dpdkcoreset = set([x for x in dpdkcoreset if x < int(args.cores)])
+        print "INFO: new dpdkcoreset {}".format(dpdkcoreset)
+    else:
+        dpdkcoreset = dpdkcoreset
+    dpdkcoremask = coreh.set_to_hex(dpdkcoreset)
+
+    changed = False
+
+    changed |= ovsvsctl.set_pmd_cpu_mask(dpdkcoremask)
+    #changed |= ovsvsctl.set_lcore_mask()
+    changed |= ovsvsctl.set_socket_mem(args.mem)
+    changed |= ovsvsctl.enable_dpdk()
+    if changed:
+        exit(0)
+    else:
+        exit(1)
+
+if __name__ == "__main__":
+    main()
diff --git a/roles/performance_nodes/tasks/main.yaml b/roles/performance_nodes/tasks/main.yaml
new file mode 100644 (file)
index 0000000..7c10288
--- /dev/null
@@ -0,0 +1,40 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Setup hostname
+  hostname:
+    name: "{{ physical_host }}"
+
+- name: Updating the facts due to hostname change
+  setup:
+
+- set_fact:
+    host_network_profile_name: "{{hosts[ansible_hostname]['network_profiles']}}"
+
+- set_fact:
+    provider_network_type: "{{network_profiles[host_network_profile_name[0]]['provider_network_interfaces']|json_query('*.type')}}"
+  when: "'provider_network_interfaces' in network_profiles[host_network_profile_name[0]]"
+
+- name: Stop unnecessary services
+  include: services.yaml
+
+- debug:
+    msg: "OvS-DPDK profiles: {{host_network_profile_name}}, type: {{provider_network_type}}"
+  when: "'ovs-dpdk' in provider_network_type"
+
+- name: Handle OvS-DPDK
+  include: ovsdpdk.yaml
+  when: "'ovs-dpdk' in provider_network_type"
diff --git a/roles/performance_nodes/tasks/ovsdpdk.yaml b/roles/performance_nodes/tasks/ovsdpdk.yaml
new file mode 100644 (file)
index 0000000..a72e76f
--- /dev/null
@@ -0,0 +1,81 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- debug:
+    msg:
+      - "DPDK cores {{ ansible_local.ncir_cpu_allocation['ovs_dpdk']['list'] }}"
+      - "Platform cores {{ ansible_local.ncir_cpu_allocation['platform']['list'] }}"
+      - "Host VPUs  {{ansible_processor_vcpus}}, Processor cores {{ansible_processor_cores}}"
+      - "Threads per core {{ansible_processor_threads_per_core}}, Sockets {{ansible_processor_count}}"
+
+- name: Add vfio.conf to modules-load.d
+  lineinfile:
+    path: /etc/modules-load.d/vfio.conf
+    create: "yes"
+    state: present
+    line: 'vfio-pci'
+
+- name: Modprobe vfio-pci
+  modprobe:
+    name: vfio-pci
+    state: present
+
+- name: Ensure openvswitch.service is started
+  systemd:
+    name: openvswitch
+    state: started
+
+- name: configure DPDK cores
+  script: >
+      configure_ovsdpdk.py --cores {{ansible_processor_vcpus}} --pcore {{ansible_processor_cores}}
+      --tcore {{ansible_processor_threads_per_core}} --sockets {{ansible_processor_count}}
+      --dpdkcores {{ ansible_local.ncir_cpu_allocation['ovs_dpdk']['list'] }}
+  register: result
+  changed_when: result.rc == 0
+  failed_when: result.rc == 2
+
+- debug:
+    msg: "RC: {{ result.rc }}"
+
+- debug:
+    var=result.stdout_lines
+  when: result.rc != 0
+
+- name: Ensure enable-dpdk.service is enabled
+  systemd:
+    name: enable-dpdk
+    enabled: "yes"
+  when: result.rc == 0
+
+- name: Start enable-dpdk.service on other than installation host
+  systemd:
+    name: enable-dpdk
+    state: started
+  when:
+    - result.rc == 0
+    - hostname != installation_controller
+
+- name: restart openvswitch.service
+  systemd:
+    name: openvswitch
+    state: restarted
+  when: result.rc == 0
+
+- name: restart libvirtd.service
+  systemd:
+    name: libvirtd
+    state: restarted
+  when: result.rc == 0
diff --git a/roles/performance_nodes/tasks/services.yaml b/roles/performance_nodes/tasks/services.yaml
new file mode 100644 (file)
index 0000000..0dd7987
--- /dev/null
@@ -0,0 +1,27 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Stop ksm
+  systemd:
+    name: ksm
+    enabled: "no"
+    state: stopped
+
+- name: Stop ksmtuned
+  systemd:
+    name: ksmtuned
+    enabled: "no"
+    state: stopped
diff --git a/roles/performance_nodes_post/defaults/main.yml b/roles/performance_nodes_post/defaults/main.yml
new file mode 100644 (file)
index 0000000..c579788
--- /dev/null
@@ -0,0 +1,17 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+provider_network_type: ''
diff --git a/roles/performance_nodes_post/tasks/main.yaml b/roles/performance_nodes_post/tasks/main.yaml
new file mode 100644 (file)
index 0000000..5b45507
--- /dev/null
@@ -0,0 +1,35 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- set_fact:
+    host_network_profile_name: "{{hosts[ansible_hostname]['network_profiles']}}"
+
+- set_fact:
+    provider_network_type: "{{network_profiles[host_network_profile_name[0]]['provider_network_interfaces']|json_query('*.type')}}"
+  when: "'provider_network_interfaces' in network_profiles[host_network_profile_name[0]]"
+
+- set_fact:
+    host_performance_profile_name: "{{hosts[ansible_hostname]['performance_profiles']}}"
+
+- name: Handle nova config changes
+  include: nova.yaml
+
+- debug:
+    msg: "OvS profiles: {{host_network_profile_name}}, type: {{provider_network_type}}"
+
+- name: Handle OvS-DPDK
+  include: ovsdpdk_post.yaml
+  when: "'ovs-dpdk' in provider_network_type"
diff --git a/roles/performance_nodes_post/tasks/nova.yaml b/roles/performance_nodes_post/tasks/nova.yaml
new file mode 100644 (file)
index 0000000..e94bfcf
--- /dev/null
@@ -0,0 +1,71 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Set vcpu_pin_set
+  ini_file: dest=/etc/nova/nova.conf section=DEFAULT option=vcpu_pin_set value={{ ansible_local.ncir_cpu_allocation['vm']['list'] }} backup=no
+  register: nova1_result
+
+- name: Get performance profile configuration
+  set_fact:
+    perf_profile: "{{ performance_profiles[hosts[hostname]['performance_profiles'][0]] if 'performance_profiles' in hosts[hostname] else {} }}"
+
+- debug:
+    msg:
+      - "Hugepagesz: {{perf_profile['hugepagesz']}}"
+
+- name: Construct reserved_huge_pages line for 1G case
+  set_fact:
+      numa0line: "reserved_huge_pages=node:0,size:1GB,count:4"
+      numa1line: "reserved_huge_pages=node:1,size:1GB,count:4"
+  when:
+    - perf_profile['hugepagesz'] == "1G"
+
+- name: Construct reserved_huge_pages line for 2M case
+  set_fact:
+      numa0line: "reserved_huge_pages=node:0,size:2048,count:2048"
+      numa1line: "reserved_huge_pages=node:1,size:2048,count:2048"
+  when:
+    - perf_profile['hugepagesz'] == "2M"
+
+- debug:
+    msg:
+      - "CPUs: {{ansible_processor_count}}"
+      - "NUMA0 conf: {{numa0line}}"
+      - "NUMA1 conf: {{numa1line}}"
+
+- name: Set huge page reservation for NUMA 0
+  lineinfile:
+    path: /etc/nova/nova.conf
+    insertafter: 'DEFAULT'
+    line: "{{numa0line}}"
+  register: nova2_result
+
+- name: Set huge page reservation for NUMA 1
+  lineinfile:
+    path: /etc/nova/nova.conf
+    insertafter: '{{numa0line}}'
+    line: "{{numa1line}}"
+  when:
+    - ansible_processor_count | int == 2
+  register: nova3_result
+
+- name: Restart nova compute
+  systemd:
+    name: nova-compute
+    state: "restarted"
+  when:
+    - nova1_result.changed or nova2_result.changed or nova3_result.changed
+    - "'compute' in hosts[ansible_hostname]['service_profiles']"
diff --git a/roles/performance_nodes_post/tasks/ovsdpdk_post.yaml b/roles/performance_nodes_post/tasks/ovsdpdk_post.yaml
new file mode 100644 (file)
index 0000000..86e1c5d
--- /dev/null
@@ -0,0 +1,29 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Modify ovs agent datapath_type
+  ini_file: dest=/etc/neutron/plugins/ml2/openvswitch_agent.ini section=ovs option=datapath_type value=netdev backup=no
+  register: datapath_result
+
+- name: Modify ovs agent vhostuser_socket_dir
+  ini_file: dest=/etc/neutron/plugins/ml2/openvswitch_agent.ini section=ovs option=vhostuser_socket_dir value=/var/run/openvswitch backup=no
+  register: socketdir_result
+
+- name: Restart neutron openvswitch agent
+  systemd:
+    name: neutron-openvswitch-agent
+    state: "restarted"
+  when: datapath_result.changed or socketdir_result.changed
diff --git a/roles/redisconfigure/README.rst b/roles/redisconfigure/README.rst
new file mode 100644 (file)
index 0000000..9527f45
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for creating redis configuration
diff --git a/roles/redisconfigure/handlers/main.yml b/roles/redisconfigure/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/redisconfigure/tasks/generate_redis_config.yml b/roles/redisconfigure/tasks/generate_redis_config.yml
new file mode 100644 (file)
index 0000000..365ec70
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate redis configuration file
+  template:
+      src: redis.conf.j2
+      dest: "/etc/redis.conf"
+      owner: redis
+      group: redis
+      mode: 0600
diff --git a/roles/redisconfigure/tasks/main.yml b/roles/redisconfigure/tasks/main.yml
new file mode 100644 (file)
index 0000000..46ee432
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_redis_config.yml
+  tags:
+      - generate_redis_config
diff --git a/roles/redisconfigure/templates/redis.conf.j2 b/roles/redisconfigure/templates/redis.conf.j2
new file mode 100644 (file)
index 0000000..e665a30
--- /dev/null
@@ -0,0 +1,57 @@
+bind 0.0.0.0
+protected-mode yes
+port 6379
+tcp-backlog 511
+timeout 0
+tcp-keepalive 300
+daemonize no
+supervised no
+pidfile /var/run/redis_6379.pid
+loglevel notice
+logfile /var/log/redis/redis.log
+databases 16
+save 900 1
+save 300 10
+save 60 10000
+stop-writes-on-bgsave-error yes
+rdbcompression yes
+rdbchecksum yes
+dbfilename dump.rdb
+dir /var/lib/redis
+{% if hostname != installation_controller %}
+slaveof {{ internal_lb_vip_address }} 6379
+{% endif %}
+slave-serve-stale-data yes
+slave-read-only yes
+repl-diskless-sync no
+repl-diskless-sync-delay 5
+repl-disable-tcp-nodelay no
+slave-priority 100
+appendonly no
+appendfilename "appendonly.aof"
+appendfsync everysec
+no-appendfsync-on-rewrite no
+auto-aof-rewrite-percentage 100
+auto-aof-rewrite-min-size 64mb
+aof-load-truncated yes
+lua-time-limit 5000
+slowlog-log-slower-than 10000
+slowlog-max-len 128
+latency-monitor-threshold 0
+notify-keyspace-events ""
+hash-max-ziplist-entries 512
+hash-max-ziplist-value 64
+list-max-ziplist-size -2
+list-compress-depth 0
+set-max-intset-entries 512
+zset-max-ziplist-entries 128
+zset-max-ziplist-value 64
+hll-sparse-max-bytes 3000
+activerehashing yes
+client-output-buffer-limit normal 0 0 0
+client-output-buffer-limit slave 256mb 64mb 60
+client-output-buffer-limit pubsub 32mb 8mb 60
+hz 10
+aof-rewrite-incremental-fsync yes
+requirepass {{ redis_password }}
+masterauth {{ redis_password }}
diff --git a/roles/removevips/handlers/main.yml b/roles/removevips/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/removevips/tasks/main.yml b/roles/removevips/tasks/main.yml
new file mode 100644 (file)
index 0000000..0fe6b98
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: remove external IPv4 vip
+  shell: "/sbin/ip a d {{ networking['vips']['infra_external']['external_vip'] }}/32 dev {{ networking['infra_external']['interface'] }}"
+  when: hostname == installation_controller
+
+- name: remove internal IPv4 vip
+  shell: "/sbin/ip a d {{ networking['vips']['infra_internal']['internal_vip'] }}/32 dev {{ networking['infra_internal']['interface'] }}"
+  when: hostname == installation_controller
diff --git a/roles/rpmdatabase/defaults/main.yml b/roles/rpmdatabase/defaults/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/rpmdatabase/handlers/main.yml b/roles/rpmdatabase/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/rpmdatabase/tasks/check_rpm_database.yml b/roles/rpmdatabase/tasks/check_rpm_database.yml
new file mode 100644 (file)
index 0000000..58c0261
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Check rpm database integrity
+  command: "rpm -qf /etc/redhat-release"
+  register: rpmcheck
+  ignore_errors: True
+
+
+- name: Re-generate rpm database in case of failure
+  command: "rpm --rebuilddb"
+  when: rpmcheck|failed
+
diff --git a/roles/rpmdatabase/tasks/main.yml b/roles/rpmdatabase/tasks/main.yml
new file mode 100644 (file)
index 0000000..392c08f
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: check_rpm_database.yml
+  tags:
+      - rpmcheck
diff --git a/roles/secretsextend/README.rst b/roles/secretsextend/README.rst
new file mode 100644 (file)
index 0000000..66e6f54
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for enabling redis controller
diff --git a/roles/secretsextend/handlers/main.yml b/roles/secretsextend/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/secretsextend/tasks/main.yml b/roles/secretsextend/tasks/main.yml
new file mode 100644 (file)
index 0000000..fe5ac7f
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: secrets_extend.yml
+  tags:
+      - extend_secrets
diff --git a/roles/secretsextend/tasks/secrets_extend.yml b/roles/secretsextend/tasks/secrets_extend.yml
new file mode 100644 (file)
index 0000000..637474c
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Assemble final user_secrets.yml
+  assemble:
+    src: /etc/required-secrets
+    dest: /opt/openstack-ansible/etc/openstack_deploy/user_secrets.yml
+    delimiter: '\n'
+    owner: root
+    group: root
+    mode: 0644
+    ignore_hidden: true
+
diff --git a/roles/service-profiles/README.rst b/roles/service-profiles/README.rst
new file mode 100644 (file)
index 0000000..783ed1f
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for creating mapping between nodes and there service profiles.
diff --git a/roles/service-profiles/handlers/main.yml b/roles/service-profiles/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/service-profiles/tasks/generate_config.yml b/roles/service-profiles/tasks/generate_config.yml
new file mode 100644 (file)
index 0000000..df5cf6e
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create the configuration directory
+  file:
+      path: "/etc/service-profiles/"
+      state: directory
+      mode: 0755
+
+- name: Generate service-profiles configuration file
+  template: 
+      src: config.ini.j2 
+      dest: "/etc/service-profiles/config.ini"
+      owner: root 
+      group: root
+      mode: 0644
diff --git a/roles/service-profiles/tasks/main.yml b/roles/service-profiles/tasks/main.yml
new file mode 100644 (file)
index 0000000..325e641
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: generate_config.yml
+  tags:
+      - hwmgmt_server_config_generate
diff --git a/roles/service-profiles/templates/config.ini.j2 b/roles/service-profiles/templates/config.ini.j2
new file mode 100644 (file)
index 0000000..03fe2d9
--- /dev/null
@@ -0,0 +1,3 @@
+{% for host in hosts %}
+{{host}}:{{hosts[host]['service_profiles']|join(',')}}
+{% endfor %}
diff --git a/roles/sriov_nodes/files/configure_vf_count.sh b/roles/sriov_nodes/files/configure_vf_count.sh
new file mode 100644 (file)
index 0000000..871d1a3
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/bash
+set -e
+
+# Copyright 2019 Nokia
+
+# 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.
+
+set_max_vf_count()
+{
+    local iface vf_count device
+    iface=$1
+    vf_count=$2
+
+    echo "Setting interface $iface max vf count to $vf_count"
+    device=$(/bin/mst status -v | grep -E "net-${iface}[[:space:]]+" | awk '{print $2}')
+    /bin/mlxconfig --yes --dev $device set NUM_OF_VFS=$vf_count
+}
+
+main()
+{
+    local -r CONF_FILE="/etc/sriov/sriov.conf"
+    local res=0
+    local mst_started=0
+    local item iface vf_count
+
+    [[ -r $CONF_FILE ]] && source $CONF_FILE
+
+    if [[ -n "$SRIOV_VF_COUNTS" ]]
+    then
+        for item in $SRIOV_VF_COUNTS
+        do
+            iface=${item%:*}
+            vf_count=${item##*:}
+            if /sbin/ethtool -i $iface | grep -qE '^driver:[[:space:]]+mlx5_core$'
+            then
+                old_count=$(</sys/class/net/$iface/device/sriov_totalvfs)
+                [[ $old_count -eq $vf_count ]] && continue
+                [[ $mst_started -eq 0 ]] && /bin/mst start
+                mst_started=1
+                set_max_vf_count $iface $vf_count
+                res=2
+            fi
+        done
+    fi
+
+    return $res
+}
+
+main "$@"
diff --git a/roles/sriov_nodes/tasks/main.yaml b/roles/sriov_nodes/tasks/main.yaml
new file mode 100644 (file)
index 0000000..195da15
--- /dev/null
@@ -0,0 +1,36 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Setup hostname
+  hostname:
+    name: "{{ physical_host }}"
+
+- name: Updating the facts due to hostname change
+  setup:
+
+- set_fact:
+    host_network_profile_name: "{{hosts[ansible_hostname]['network_profiles']}}"
+
+- name: Check provider network type
+  set_fact:
+    provider_network_type: "{{network_profiles[host_network_profile_name[0]]['provider_network_interfaces']|json_query('*.type')}}"
+  when: "'provider_network_interfaces' in network_profiles[host_network_profile_name[0]]"
+
+- name: Handle SR-IOV
+  include: sriov.yaml
+  when: ('sriov_provider_networks' in network_profiles[host_network_profile_name[0]]) or
+        (provider_network_type is defined and
+        ('ovs-offload-sriov' in provider_network_type))
diff --git a/roles/sriov_nodes/tasks/sriov.yaml b/roles/sriov_nodes/tasks/sriov.yaml
new file mode 100644 (file)
index 0000000..27703d3
--- /dev/null
@@ -0,0 +1,53 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Set sriov config dir variable
+  set_fact:
+    sriov_conf_dir: "/etc/sriov"
+
+- name:  ensure sriov config dir exists
+  file:
+    path: "{{ sriov_conf_dir }}"
+    recurse: "yes"
+    state: "directory"
+    mode: "0755"
+
+- name: Create /etc/sriov/sriov.conf file
+  template:
+    src: "sriov.conf.j2"
+    dest: "{{ sriov_conf_dir }}/sriov.conf"
+    owner: "root"
+    mode: "0644"
+
+- name: Configure VF count
+  script: configure_vf_count.sh
+  register: configure_vf_count_result
+  failed_when: not (configure_vf_count_result.rc == 0 or configure_vf_count_result.rc == 2)
+  changed_when: configure_vf_count_result.rc == 2
+
+- debug: var=configure_vf_count_result.stdout_lines
+  when: configure_vf_count_result.rc != 0
+
+- debug: var=configure_vf_count_result.stderr_lines
+  when: configure_vf_count_result.rc != 0
+
+- name: Restart sriov service
+  systemd:
+    service: sriov
+    state: restarted
+  when:
+    - hostname == installation_controller
+    - ('caas_master' in hosts[hostname]['service_profiles']) or ('caas_worker' in hosts[hostname]['service_profiles'])
diff --git a/roles/sriov_nodes/templates/sriov.conf.j2 b/roles/sriov_nodes/templates/sriov.conf.j2
new file mode 100644 (file)
index 0000000..1a2a8f3
--- /dev/null
@@ -0,0 +1,83 @@
+{%- set host_network_profiles_list = hosts[ansible_hostname]['network_profiles'] -%}
+{%- set sriov_ifaces = [] -%}
+{%- set trusted_ifaces = [] -%}
+{%- set vf_counts = [] -%}
+{%- if 'sriov_provider_networks' in network_profiles[host_network_profiles_list[0]] -%}
+    {%- set sriov_provider_networks = network_profiles[host_network_profiles_list[0]]['sriov_provider_networks'] -%}
+    {%- for net,net_info in sriov_provider_networks.iteritems() -%}
+        {%- if 'trusted' in net_info -%}
+            {%- set is_trusted = net_info['trusted'] -%}
+        {%- else -%}
+            {%- set is_trusted = False -%}
+        {%- endif -%}
+        {%- if 'vf_count' in net_info -%}
+            {%- set vf_count = net_info['vf_count'] -%}
+        {%- else -%}
+            {%- set vf_count = 0 -%}
+        {%- endif -%}
+        {%- for iface in net_info['interfaces'] -%}
+            {%- if sriov_ifaces.append(iface) -%}{%- endif -%}
+            {%- if is_trusted -%}
+                {%- if trusted_ifaces.append(iface) -%}{%- endif -%}
+            {%- endif -%}
+            {%- if vf_count > 0 -%}
+                {%- set count_info = iface ~ ':' ~ vf_count -%}
+                {%- if vf_counts.append(count_info) -%}{%- endif -%}
+            {%- endif -%}
+        {%- endfor -%}
+    {%- endfor -%}
+{%- endif -%}
+{%- set offloaded_ifaces = [] -%}
+{%- set trusted_offloaded_ifaces = [] -%}
+{%- set vf_counts_offloaded = [] -%}
+{%- if 'provider_network_interfaces' in network_profiles[host_network_profiles_list[0]] -%}
+    {%- set provider_network_interfaces = network_profiles[host_network_profiles_list[0]]['provider_network_interfaces'] -%}
+    {%- set bonding_interfaces = network_profiles[host_network_profiles_list[0]]['bonding_interfaces'] -%}
+    {%- for net,net_info in provider_network_interfaces.iteritems() -%}
+        {% if net_info['type'] == 'ovs-offload-sriov' -%}
+            {%- if 'trusted' in net_info -%}
+                {%- set is_trusted = net_info['trusted'] -%}
+            {%- else -%}
+                {%- set is_trusted = False -%}
+            {%- endif -%}
+            {%- if 'vf_count' in net_info -%}
+                {%- set vf_count = net_info['vf_count'] -%}
+            {%- else -%}
+                {%- set vf_count = 0 -%}
+            {%- endif -%}
+            {%- if net in bonding_interfaces -%}
+                {%- for iface in bonding_interfaces[net] -%}
+                    {%- if sriov_ifaces.append(iface) -%}{%- endif -%}
+                    {%- if offloaded_ifaces.append(iface) -%}{%- endif -%}
+                    {%- if is_trusted -%}
+{#-                     {%- if trusted_offloaded_ifaces.append(iface) -%}{%- endif -%} -#}
+                        {%- if trusted_ifaces.append(iface) -%}{%- endif -%}
+                    {%- endif -%}
+                    {%- if vf_count > 0 -%}
+                        {%- set count_info = iface ~ ':' ~ vf_count -%}
+{#-                     {%- if vf_counts_offloaded.append(count_info) -%}{%- endif -%} -#}
+                        {%- if vf_counts.append(count_info) -%}{%- endif -%}
+                    {%- endif -%}
+                {%- endfor -%}
+             {%- else -%}
+                {%- if offloaded_ifaces.append(net) -%}{%- endif -%}
+                {%- if sriov_ifaces.append(net) -%}{%- endif -%}
+                {%- if is_trusted -%}
+                    {%- if trusted_offloaded_ifaces.append(net) -%}{%- endif -%}
+                    {%- if trusted_ifaces.append(net) -%}{%- endif -%}
+                {%- endif -%}
+                {%- if vf_count > 0 -%}
+                    {%- set count_info = net ~ ':' ~ vf_count -%}
+                    {%- if vf_counts_offloaded.append(count_info) -%}{%- endif -%}
+                    {%- if vf_counts.append(count_info) -%}{%- endif -%}
+                {%- endif -%}
+             {% endif -%}
+        {%- endif -%}
+    {%- endfor -%}
+{%- endif -%}
+SRIOV_INTERFACES="{{sriov_ifaces | join(' ')}}"
+SRIOV_TRUSTED_INTERFACES="{{trusted_ifaces | join(' ')}}"
+SRIOV_VF_COUNTS="{{vf_counts | join(' ')}}"
+SRIOV_INTERFACES_OFFLOADED="{{offloaded_ifaces | join(' ')}}"
+{#- SRIOV_TRUSTED_INTERFACES_OFFLOADED="{{trusted_offloaded_ifaces | join(' ')}}" -#}
+{#- SRIOV_VF_COUNTS_OFFLOADED="{{vf_counts_offloaded | join(' ')}}" -#}
diff --git a/roles/sriovdp_config/defaults/main.yaml b/roles/sriovdp_config/defaults/main.yaml
new file mode 100644 (file)
index 0000000..8e34c4f
--- /dev/null
@@ -0,0 +1,17 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+sriovdp_config_path: "/etc/pcidp/"
diff --git a/roles/sriovdp_config/tasks/main.yaml b/roles/sriovdp_config/tasks/main.yaml
new file mode 100644 (file)
index 0000000..3440c82
--- /dev/null
@@ -0,0 +1,54 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: collect network device PCI addresses
+  shell: dpdk-devbind --status-dev net | grep "^0000.*if=en"
+  register: devbind
+
+- set_fact:
+    pci: []
+    iface: []
+
+- set_fact:
+    pci: "{{ pci }} + {{ [ item.split()[0][5:12] ] }}"
+    iface: "{{ iface }} + {{ [ item.split(' if=')[1].split()[0] ] }}"
+  with_items: "{{ devbind.stdout_lines }}"
+
+- set_fact:
+    ifacepcimap: "{{ dict( iface | zip(pci) ) }}"
+
+- debug: var=ifacepcimap
+
+- name: "create {{ sriovdp_config_path }} directory"
+  file:
+    path: "{{ sriovdp_config_path }}"
+    mode: "0700"
+    state: directory
+
+- name: "create {{ sriovdp_config_path }}config.yaml"
+  template:
+    src: sriovdp_config.yaml.j2
+    dest: "{{ sriovdp_config_path }}config.yaml"
+
+- name: "convert {{ sriovdp_config_path }}config.yaml to config.json"
+  shell: "python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)' <{{ sriovdp_config_path }}config.yaml >{{ sriovdp_config_path }}config.json"
+
+- name: limit file permissions to root user
+  file:
+    path: "{{ item }}"
+    state: file
+    mode: "0600"
+  with_fileglob: "{{ sriovdp_config_path }}*"
diff --git a/roles/sriovdp_config/templates/sriovdp_config.yaml.j2 b/roles/sriovdp_config/templates/sriovdp_config.yaml.j2
new file mode 100644 (file)
index 0000000..2ef5e92
--- /dev/null
@@ -0,0 +1,15 @@
+resourceList:
+{% for nprof in network_profiles %}
+{%   if nprof in hosts[ansible_hostname].network_profiles %}
+{%     if network_profiles[nprof].sriov_provider_networks is defined %}
+{%       for pool in network_profiles[nprof].sriov_provider_networks %}
+{%         for iface in network_profiles[nprof].sriov_provider_networks[pool].interfaces %}
+- resourceName: "sriov_{{ iface }}"
+  rootDevices: [ "{{ ifacepcimap[iface] }}" ]
+  sriovMode: true
+  deviceType: netdevice
+{%         endfor %}
+{%       endfor %}
+{%     endif %}
+{%   endif %}
+{% endfor %}
diff --git a/roles/ssh_conf_hardening/library/ssh_conf.py b/roles/ssh_conf_hardening/library/ssh_conf.py
new file mode 100644 (file)
index 0000000..aebe74b
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/python
+
+# Copyright 2019 Nokia
+
+# 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 os
+import re
+from ansible.module_utils.basic import AnsibleModule
+
+class SshdConf(object):
+
+    def __init__(self):
+        self.module = AnsibleModule(argument_spec=dict(regexp=dict(required=True),
+                                                       values=dict(required=True)))
+        self.used_regexp = self.module.params["regexp"]
+        self.set_values = self.module.params["values"]
+        self.sshd_contents = None
+        self.changed = False
+        self.target = "/etc/ssh/sshd_config"
+
+    def _read_sshd_conf(self):
+        os.system("sync")
+        with open(self.target, "r") as sshd_file:
+            self.sshd_contents = sshd_file.readlines()
+
+    def _write_sshd_conf(self):
+        os.system("sync")
+        os.remove(self.target)
+        os.system("sync")
+        for line in self.sshd_contents:
+            with open(self.target, "a") as out:
+                out.write(line)
+                os.system("sync")
+        os.system("sync")
+        os.system("chmod 600 "+ self.target)
+        os.system("sync")
+        os.system("chown root:root "+ self.target)
+        os.system("sync")
+
+    def _start_finder(self):
+        end = start = None
+        index = 0
+
+        for line in self.sshd_contents:
+            if start is None and re.compile("^[A-Za-z].*").search(line):
+                start = index + 1
+            if re.compile("^[#\s]*Match ").search(line):
+                end = index
+                break
+            index += 1
+
+        if end is None:
+            end = index - 1
+
+        if start is None:
+            start = 0
+
+        return start, end
+
+    def ssh_checker_and_setter(self, line):
+        if self.changed:
+            self.sshd_contents[line] = ''
+        else:
+            self.sshd_contents[line] = self.module.params["values"]
+            self.changed = True
+
+    def _configuration(self, start, end):
+        for line in range(0, end):
+            if re.compile("^"+self.module.params["regexp"]).search(self.sshd_contents[line]):
+                self.ssh_checker_and_setter(line)
+        if not self.changed:
+            for line in range(0, end):
+                if re.compile("^#"+self.module.params["regexp"]).search(self.sshd_contents[line]) and not self.changed:
+                    self.sshd_contents[line] = self.sshd_contents[line]+self.module.params["values"]
+                    self.changed = True
+            if not self.changed:
+                self.sshd_contents.insert(start, self.module.params["values"])
+                self.changed = True
+
+    def run(self):
+        self._read_sshd_conf()
+
+        indexes = self._start_finder()
+        start_index = indexes[0]
+        end_index = indexes[1]
+
+        self._configuration(start_index, end_index)
+
+        self._write_sshd_conf()
+
+        self.module.exit_json(changed=self.changed, msg=self.module.params["values"]+" configured")
+
+    @staticmethod
+    def main():
+        SshdConf().run()
+
+if __name__ == '__main__':
+    SshdConf.main()
diff --git a/roles/ssh_conf_hardening/tasks/main.yaml b/roles/ssh_conf_hardening/tasks/main.yaml
new file mode 100644 (file)
index 0000000..1058a52
--- /dev/null
@@ -0,0 +1,182 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Ssh protocol setting
+  ssh_conf:
+    regexp: '[\s]*Protocol'
+    values: "Protocol 2\n"
+
+- name: Disable ssh root login
+  ssh_conf:
+    regexp: '[\s]*PermitRootLogin [y|n]'
+    values: "PermitRootLogin no\n"
+
+- name: Listening address setting
+  ssh_conf:
+    regexp: '[\s]*ListenAddress'
+    values: "ListenAddress 0.0.0.0\n"
+
+- name: Disable the hostbasedauthentication
+  ssh_conf:
+    regexp: '[\s]*HostbasedAuthentication [y|n]'
+    values: "HostbasedAuthentication no\n"
+
+- name: Disable the passwordauthentication
+  ssh_conf:
+    regexp: '[\s]*PasswordAuthentication [y|n]'
+    values: "PasswordAuthentication yes\n"
+
+- name: Disable the empty password
+  ssh_conf:
+    regexp: '[\s]*PermitEmptyPasswords [y|n]'
+    values: "PermitEmptyPasswords no\n"
+
+- name: Ciphers setting
+  ssh_conf:
+    regexp: '[\s]*Ciphers'
+    values: "Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com\n"
+
+- name: MACs setting
+  ssh_conf:
+    regexp: '[\s]*MACs'
+    values: "MACs hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com\n"
+
+- name: Login Gracetime setting
+  ssh_conf:
+    regexp: '[\s]*LoginGraceTime'
+    values: "LoginGraceTime 60\n"
+
+- name: User Alive Interval setting
+  ssh_conf:
+    regexp: '[\s]*ClientAliveInterval'
+    values: "ClientAliveInterval 900\n"
+
+- name: Disable the X11forwarding
+  ssh_conf:
+    regexp: '[\s]*X11Forwarding [y|n]'
+    values: "X11Forwarding no\n"
+
+- name: Disable SSH agent forwarding
+  ssh_conf:
+    regexp: '[\s]*AllowAgentForwarding [y|n]'
+    values: "AllowAgentForwarding no\n"
+
+- name: Disable TCP forwarding
+  ssh_conf:
+    regexp: '[\s]*AllowTcpForwarding [y|n]'
+    values: "AllowTcpForwarding no\n"
+
+- name: Activate the strict mode
+  ssh_conf:
+    regexp: '[\s]*StrictModes [y|n]'
+    values: "StrictModes yes\n"
+
+- name: Port setting
+  ssh_conf:
+    regexp: '[\s]*Port'
+    values: "Port 22\n"
+
+- name: HostKeyAlgorithms setting
+  ssh_conf:
+    regexp: '[\s]*HostKeyAlgorithms'
+    values: "HostKeyAlgorithms ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-rsa-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-ed25519\n"
+
+- name: PubkeyAcceptedKeyTypes setting
+  ssh_conf:
+    regexp: '[\s]*PubkeyAcceptedKeyTypes'
+    values: "PubkeyAcceptedKeyTypes ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-rsa-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-ed25519\n"
+
+- name: KexAlgorithms
+  ssh_conf:
+    regexp: '[\s]*KexAlgorithms'
+    values: "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256\n"
+
+- name: MaxAuthTries setting
+  ssh_conf:
+    regexp: '[\s]*MaxAuthTries'
+    values: "MaxAuthTries 6\n"
+
+- name: Banner creation
+  ssh_conf:
+    regexp: '[\s]*Banner'
+    values: "Banner /etc/banner\n"
+
+- name: "Enable the Ipv6"
+  lineinfile:
+    path: /etc/ssh/sshd_config
+    insertafter: '^[\s]*ListenAddress 0.0.0.0'
+    line: 'ListenAddress ::'
+
+- name: "Disable Kerberos Authentication"
+  ssh_conf:
+    regexp: '[\s]*KerberosAuthentication'
+    values: "KerberosAuthentication no\n"
+
+- name: "Enable Use of Privilege Separation"
+  ssh_conf:
+    regexp: '[\s]*UsePrivilegeSeparation'
+    values: "UsePrivilegeSeparation sandbox\n"
+
+- name: "Disable Compression"
+  ssh_conf:
+    regexp: '[\s]*Compression'
+    values: "Compression no\n"
+
+- name: "Set SSH Client Alive Count"
+  ssh_conf:
+    regexp: '[\s]*ClientAliveCountMax'
+    values: "ClientAliveCountMax 0\n"
+
+- name: "Disable SSH Support for User Known Hosts"
+  ssh_conf:
+    regexp: '[\s]*IgnoreUserKnownHosts'
+    values: "IgnoreUserKnownHosts yes\n"
+
+- name: "Do Not Allow SSH Environment Options"
+  ssh_conf:
+    regexp: '[\s]*PermitUserEnvironment'
+    values: "PermitUserEnvironment no\n"
+
+- service:
+    name: sshd
+    state: restarted
+
+- name : create a banner file
+  lineinfile:
+    path: /etc/banner
+    create: yes
+    regexp: '^.*'
+    state: present
+    line: "This is a PRIVATE computer system. All unauthorized use or unauthorized access is prohibited according to local laws and may lead to prosecution. Your operations are logged."
+
+- name: "Set the maximum number of days a ssh password may be used."
+  lineinfile:
+    path: /etc/login.defs
+    regexp: '^PASS_MAX_DAYS[\s]*[0-9]*$'
+    line: 'PASS_MAX_DAYS   90'
+
+- name: "Set the number of days warning given before a password expires."
+  lineinfile:
+    path: /etc/login.defs
+    regexp: '^PASS_WARN_AGE[\s]*[0-9]*$'
+    line: 'PASS_WARN_AGE   5'
+
+- name: "Set the unique last password count."
+  lineinfile:
+    path: /etc/pam.d/system-auth-ac
+    regexp: '^password[\s]*sufficient.*pam_unix.so(.*)$'
+    line: 'password    sufficient    pam_unix.so\1 remember=12'
+    backrefs: yes
diff --git a/roles/take-pam-tty-audit-into-use/README.rst b/roles/take-pam-tty-audit-into-use/README.rst
new file mode 100644 (file)
index 0000000..058e26e
--- /dev/null
@@ -0,0 +1 @@
+Ansible role for configuring auth config to use PAM tty audit for auditing bash commands.
diff --git a/roles/take-pam-tty-audit-into-use/tasks/create-added-configuration.yml b/roles/take-pam-tty-audit-into-use/tasks/create-added-configuration.yml
new file mode 100644 (file)
index 0000000..c6f8a77
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Create additional system auth configuration
+  template:
+      src: added-system-configuration.j2
+      dest: "/etc/pam.d/system-auth-local"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Create additional password auth configuration
+  template:
+      src: added-password-configuration.j2
+      dest: "/etc/pam.d/password-auth-local"
+      owner: root
+      group: root
+      mode: 0644
+
+- name: Update audisp syslog plugin configuration
+  template:
+      src: updated-audisp-syslog.configuration.j2
+      dest: "/etc/audisp/plugins.d/syslog.conf"
+      owner: root
+      group: root
+      mode: 0640
diff --git a/roles/take-pam-tty-audit-into-use/tasks/disable-systemd-audit-log-reading.yml b/roles/take-pam-tty-audit-into-use/tasks/disable-systemd-audit-log-reading.yml
new file mode 100644 (file)
index 0000000..3e08968
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Mask out audit socket reading
+  systemd:
+    name: systemd-journald-audit.socket
+    masked: yes
+
+- name: Restart journal to enforce masking
+  service:
+    name: systemd-journald
+    state: restarted
diff --git a/roles/take-pam-tty-audit-into-use/tasks/main.yml b/roles/take-pam-tty-audit-into-use/tasks/main.yml
new file mode 100644 (file)
index 0000000..5a620d6
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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: disable-systemd-audit-log-reading.yml
+
+- include: create-added-configuration.yml
+
+- include: take-added-configuration-into-use.yml
diff --git a/roles/take-pam-tty-audit-into-use/tasks/take-added-configuration-into-use.yml b/roles/take-pam-tty-audit-into-use/tasks/take-added-configuration-into-use.yml
new file mode 100644 (file)
index 0000000..41929d7
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Update symlink for system auth configuration
+  file:
+    src: system-auth-local
+    dest: "/etc/pam.d/system-auth"
+    state: link
+
+- name: Update symlink for password auth configuration
+  file:
+    src: password-auth-local
+    dest: "/etc/pam.d/password-auth"
+    state: link
+
+- name: Activate audisp syslog plugin
+  shell: pkill --signal SIGHUP --exact auditd
diff --git a/roles/take-pam-tty-audit-into-use/templates/added-password-configuration.j2 b/roles/take-pam-tty-audit-into-use/templates/added-password-configuration.j2
new file mode 100644 (file)
index 0000000..d272570
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# {{ ansible_managed }}
+#
+session    required     pam_tty_audit.so enable=*
+
+auth include password-auth-ac
+account include password-auth-ac
+password include password-auth-ac
+session include password-auth-ac
diff --git a/roles/take-pam-tty-audit-into-use/templates/added-system-configuration.j2 b/roles/take-pam-tty-audit-into-use/templates/added-system-configuration.j2
new file mode 100644 (file)
index 0000000..98bcfe4
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# {{ ansible_managed }}
+#
+session    required     pam_tty_audit.so enable=*
+
+auth include system-auth-ac
+account include system-auth-ac
+password    required    pam_pwquality.so retry=3
+password include system-auth-ac
+session include system-auth-ac
diff --git a/roles/take-pam-tty-audit-into-use/templates/updated-audisp-syslog.configuration.j2 b/roles/take-pam-tty-audit-into-use/templates/updated-audisp-syslog.configuration.j2
new file mode 100644 (file)
index 0000000..0dd0603
--- /dev/null
@@ -0,0 +1,14 @@
+# This file controls the configuration of the syslog plugin.
+# It simply takes events and writes them to syslog. The
+# arguments provided can be the default priority that you
+# want the events written with. And optionally, you can give
+# a second argument indicating the facility that you want events
+# logged to. Valid options are LOG_LOCAL0 through 7, LOG_AUTH,
+# LOG_AUTHPRIV, LOG_DAEMON, LOG_SYSLOG, and LOG_USER.
+
+active = yes
+direction = out
+path = builtin_syslog
+type = builtin
+args = LOG_INFO LOG_AUTH
+format = string
diff --git a/roles/update_cert/tasks/main.yml b/roles/update_cert/tasks/main.yml
new file mode 100644 (file)
index 0000000..2606ef4
--- /dev/null
@@ -0,0 +1,102 @@
+---
+
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Set basic facts
+  set_fact:
+    deploy_pem: False
+    upload_pem: False
+    pem_location: ""
+  tags:
+    - runtime
+
+- name: Check if custom pem installed during deploy
+  stat:
+    path: "/opt/installer-ui/certificates/certificate.pem"
+  register: stat_result_deploy
+  tags:
+   - runtime
+
+- name: Set fact deploy_pem
+  set_fact:
+    deploy_pem: True
+    upload_pem: False
+    pem_location: "/opt/installer-ui/certificates/certificate.pem"
+  when: stat_result_deploy.stat.exists == True
+  tags:
+    - runtime
+
+- name: Check if pem is uploaded
+  stat:
+    path: "/tmp/certificate.pem"
+  register: stat_result_uploaded
+  tags:
+    - runtime
+  when: deploy_pem == False
+
+- name: Set fact upload_pem
+  set_fact:
+    upload_pem: True
+    deploy_pem: False
+    pem_location: "/tmp/certificate.pem"
+  when: stat_result_uploaded.stat.exists == True
+  tags:
+    - runtime
+
+- name: Validate certificate
+  openssl_certificate:
+    path: "{{ pem_location }}"
+    provider: assertonly
+    has_expired: False
+  tags:
+    - runtime
+  when: upload_pem == True or deploy_pem == True
+
+- name: Synchronize pem
+  synchronize:
+    src: "{{ pem_location }}"
+    dest: "/tmp/certificate.pem"
+  tags:
+    - runtime
+  become: yes
+  when: upload_pem == True or deploy_pem == True
+
+- name: Copy pem
+  copy:
+    src: "/tmp/certificate.pem"
+    dest: "/etc/ssl/private/certificate.pem"
+  tags:
+    - runtime
+  when: upload_pem == True or deploy_pem == True
+
+- name: Set permissions for pem
+  file:
+    path: "/etc/ssl/private/certificate.pem"
+    mode: '0440'
+    group: 'ironic'
+    owner: 'root'
+  tags:
+    - runtime
+  when: upload_pem == True or deploy_pem == True
+
+- name: Restart haproxy
+  service:
+    name: "haproxy"
+    state: "restarted"
+    enabled: yes
+    daemon_reload: "{{ (ansible_service_mgr == 'systemd') | ternary('yes', omit) }}"
+  tags:
+    - runtime
+  when: upload_pem == True or deploy_pem == True
diff --git a/roles/userskeyssync/README.rst b/roles/userskeyssync/README.rst
new file mode 100644 (file)
index 0000000..66e6f54
--- /dev/null
@@ -0,0 +1 @@
+Ansible module for enabling redis controller
diff --git a/roles/userskeyssync/handlers/main.yml b/roles/userskeyssync/handlers/main.yml
new file mode 100644 (file)
index 0000000..41eaa50
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright 2019 Nokia
+
+# 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.
diff --git a/roles/userskeyssync/tasks/main.yml b/roles/userskeyssync/tasks/main.yml
new file mode 100644 (file)
index 0000000..b167630
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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: sync_users_keys.yml
+  tags:
+      - sync_users_keys
diff --git a/roles/userskeyssync/tasks/sync_users_keys.yml b/roles/userskeyssync/tasks/sync_users_keys.yml
new file mode 100644 (file)
index 0000000..c910193
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Sync user(s) keys to all nodes
+  synchronize:
+    src: "/home/{{ item }}/.ssh/"
+    dest: "/home/{{ item }}/.ssh/"
+  with_items: "{{ users.admin_user_name }}"
diff --git a/roles/yarf/defaults/main.yml b/roles/yarf/defaults/main.yml
new file mode 100644 (file)
index 0000000..e23268f
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+## Service Type and Data
+restful_service_region: RegionOne
+restful_service_name: restfulframework
+restful_service_port: 61200
+restful_service_proto: http
+restful_service_type: restfulapi
+restful_debug_mode: false
+restful_service_description: "Restful API"
+restful_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(restful_service_proto) }}"
+restful_service_internaluri_proto: "{{ openstack_service_internaluri_proto | default(restful_service_proto) }}"
+restful_service_publicuri: "{{ restful_service_publicuri_proto }}://{{ external_lb_vip_address | ipwrap }}:{{ restful_service_port }}"
+restful_service_publicurl: "{{ restful_service_publicuri }}"
+restful_service_internaluri: "{{ restful_service_internaluri_proto }}://{{ internal_lb_vip_address }}:{{ restful_service_port }}"
+restful_service_internalurl: "{{ restful_service_internaluri }}"
+
+restful_service_user_name: restful
+restful_service_project_name: service
+restful_service_project_domain_id: default
+restful_service_user_domain_id: default
+restful_role_name: admin
+restful_service_password: "foobar"
+restful_authentication_method: yarf.authentication.keystone.KeystoneAuth
+
diff --git a/roles/yarf/handlers/main.yml b/roles/yarf/handlers/main.yml
new file mode 100644 (file)
index 0000000..92240ba
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Restart haproxy
+  service:
+    name: "haproxy"
+    state: "reloaded"
+    enabled: "yes"
+
+- name: Restart restapi
+  service:
+    name: "restapi"
+    state: "restarted"
diff --git a/roles/yarf/tasks/generate_config_and_reload_haproxy.yml b/roles/yarf/tasks/generate_config_and_reload_haproxy.yml
new file mode 100644 (file)
index 0000000..1a0398b
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate restful configuration file
+  template: 
+    src: restful_ha_proxy.j2 
+    dest: "/etc/haproxy/conf.d/restapi"
+    owner: root 
+    group: root
+    mode: 644
+
+- name: Regenerate haproxy configuration
+  assemble:
+    src: "/etc/haproxy/conf.d"
+    dest: "/etc/haproxy/haproxy.cfg"
+  notify: Restart haproxy
+
diff --git a/roles/yarf/tasks/generate_restful_config.yml b/roles/yarf/tasks/generate_restful_config.yml
new file mode 100644 (file)
index 0000000..5c4b68c
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+- name: Generate restful configuration file
+  template: 
+      src: restful_config.j2 
+      dest: "/etc/yarf/config.ini"
+      owner: root 
+      group: root
+      mode: 644
+#  notify: Restart restapi
+
diff --git a/roles/yarf/tasks/main.yml b/roles/yarf/tasks/main.yml
new file mode 100644 (file)
index 0000000..027d00a
--- /dev/null
@@ -0,0 +1,26 @@
+# Copyright 2019 Nokia
+
+# 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: generate_restful_config.yml
+  tags:
+      - restful
+
+- include: generate_config_and_reload_haproxy.yml
+  tags:
+      - restful
+
+- include: restful_service_setup.yml
+  when: inventory_hostname == installation_controller
+  tags:
+      - restful
diff --git a/roles/yarf/tasks/restful_service_setup.yml b/roles/yarf/tasks/restful_service_setup.yml
new file mode 100644 (file)
index 0000000..8da3b96
--- /dev/null
@@ -0,0 +1,86 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# Create a service
+- name: Ensure restful service
+  keystone:
+    command: "ensure_service"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    service_name: "{{ restful_service_name }}"
+    service_type: "{{ restful_service_type }}"
+    description: "{{ restful_service_description }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 2
+
+# Create an admin user
+- name: Ensure restful user
+  keystone:
+    command: "ensure_user"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    user_name: "{{ restful_service_user_name }}"
+    tenant_name: "{{ restful_service_project_name }}"
+    password: "{{ restful_service_password }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+
+# Add a role to the user
+- name: Ensure restful user to admin role
+  keystone:
+    command: "ensure_user_role"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    user_name: "{{ restful_service_user_name }}"
+    tenant_name: "{{ restful_service_project_name }}"
+    role_name: "{{ restful_role_name }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+
+# Create an endpoint
+- name: Ensure restful endpoint
+  keystone:
+    command: "ensure_endpoint"
+    endpoint: "{{ keystone_service_adminurl }}"
+    login_user: "{{ keystone_admin_user_name }}"
+    login_password: "{{ keystone_auth_admin_password }}"
+    login_project_name: "{{ keystone_admin_tenant_name }}"
+    region_name: "{{ restful_service_region }}"
+    service_name: "{{ restful_service_name }}"
+    service_type: "{{ restful_service_type }}"
+    insecure: "{{ keystone_service_adminuri_insecure }}"
+    endpoint_list:
+      - url: "{{ restful_service_publicurl }}"
+        interface: "public"
+      - url: "{{ restful_service_internalurl }}"
+        interface: "internal"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
diff --git a/roles/yarf/templates/restful_config.j2 b/roles/yarf/templates/restful_config.j2
new file mode 100644 (file)
index 0000000..9dbab95
--- /dev/null
@@ -0,0 +1,32 @@
+# {{ ansible_managed }}
+[restframe]
+
+#The port that the restful app will listen DEFAULT:61200
+port=61200
+#The IP address that the restful app will bind to DEFAULT:127.0.0.1
+ip_address={{ hostname }}
+
+# This option tells the restful app to run in debug mode or not. Defaults to True
+debug={{ restful_debug_mode }}
+
+#Authentication method to be used
+auth_method={{ restful_authentication_method }}
+
+#Use SSL or not
+#If true then private key and certificate has to be also given DEFAULT:False
+use_ssl=false
+#ssl_private_key=PATHTOKEY/KEY.key
+#ssl_certificate=PATHTOCERTIFICATE/CERT.crt
+
+#The directory where the handlers are 
+#Defaults to /usr/lib64/python2.7/site-packages/restfulframework/handlers
+#handler_directory=/usr/lib64/python2.7/site-packages/restfulframework/handlers
+
+[keystone]
+user={{ restful_service_user_name }}
+password={{ restful_service_password }}
+auth_uri={{ keystone_service_internaluri }}
+
+[AM]
+host={{ auth_server_service_address }}
+port={{ auth_server_service_port }}
diff --git a/roles/yarf/templates/restful_ha_proxy.j2 b/roles/yarf/templates/restful_ha_proxy.j2
new file mode 100644 (file)
index 0000000..a4c18bb
--- /dev/null
@@ -0,0 +1,33 @@
+# {{ ansible_managed }}
+frontend restful-front-1
+    bind {{ external_lb_vip_address }}:61200 ssl crt {{ haproxy_ssl_pem }}
+    option httplog
+    option forwardfor except 127.0.0.0/8
+    option http-server-close
+    reqadd X-Forwarded-Proto:\ https
+    rspadd X-Frame-Options:\ SAMEORIGIN
+    rspadd Strict-Transport-Security:\ max-age=15768000
+    mode http
+    default_backend restful-back
+
+frontend restful-front-2
+    bind {{ internal_lb_vip_address }}:61200
+    option httplog
+    option forwardfor except 127.0.0.0/8
+    option http-server-close
+    rspadd X-Frame-Options:\ SAMEORIGIN
+    rspadd Strict-Transport-Security:\ max-age=15768000
+    mode http
+    default_backend restful-back
+
+
+backend restful-back
+    mode http
+    balance leastconn
+    stick store-request src
+    stick-table type ip size 256k expire 30m
+    option forwardfor
+    option httplog
+{% for con in groups['management'] %}
+    server {{ con }} {{ hostvars[con]['networking']['infra_internal']['ip'] }}:61200 check port 61200 inter 12000 rise 3 fall 3
+{% endfor %}
diff --git a/secrets/aaa-secrets.yaml b/secrets/aaa-secrets.yaml
new file mode 100644 (file)
index 0000000..b65baec
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+# MariaDB Options
+aaa_db_user_password:
+aaa_db_user_backend_password:
diff --git a/secrets/redis-secrets.yaml b/secrets/redis-secrets.yaml
new file mode 100644 (file)
index 0000000..a9ae4ba
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+## Redis password
+redis_password:
diff --git a/systemd/finalize-bootstrap.service b/systemd/finalize-bootstrap.service
new file mode 100644 (file)
index 0000000..4867de8
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 2019 Nokia
+
+# 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.
+
+[Unit]
+Description=finalize-bootstrap service
+After=openvswitch.service
+Before=enable-dpdk.service
+Wants=openvswitch.service
+ConditionPathExists=/etc/ansible-change_kernel_cmdline/enabled
+
+[Service]
+Type=oneshot
+RemainAfterExit=True
+ExecStart=/opt/ansible-change_kernel_cmdline/finalize-bootstrap.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/systemd/finalize-bootstrap.sh b/systemd/finalize-bootstrap.sh
new file mode 100644 (file)
index 0000000..f2b12bc
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+# Copyright 2019 Nokia
+
+# 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.
+
+set -o nounset
+set -o errexit
+set -o pipefail
+
+source /opt/cmframework/scripts/common.sh
+
+rm -rf /etc/ansible-change_kernel_cmdline/enabled
+
+if [ ! -f /etc/performance-nodes/dpdk.enabled ]
+then
+    if has_kernel_parameters_changed;
+    then
+       log_installation_failure
+    else
+       log_installation_success
+    fi
+fi
diff --git a/systemd/sriov.service b/systemd/sriov.service
new file mode 100644 (file)
index 0000000..d2e7ae5
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright 2019 Nokia
+#
+# 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.
+#
+
+[Unit]
+Description=SR-IOV sysfs settings
+After=network.target
+Before=nova-compute.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/opt/sriov/sriov.sh start
+ExecStopPost=/opt/sriov/sriov.sh stop
+TimeoutStopSec=600
+
+[Install]
+WantedBy=multi-user.target
diff --git a/systemd/sriov.sh b/systemd/sriov.sh
new file mode 100644 (file)
index 0000000..5f74d9c
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/bash
+# Copyright 2019 Nokia
+#
+# 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.
+#
+
+start()
+{
+    local iface vf_count
+    local res=0
+
+    for iface in $SRIOV_INTERFACES
+    do
+        vf_count=$SRIOV_VF_COUNT
+        if [[ -z "$vf_count" ]]
+        then
+            if ! vf_count=$(</sys/class/net/$iface/device/sriov_totalvfs)
+            then
+                echo "Failed to get supported VF count for the interface $iface" >&2
+                res=1
+                continue
+            fi
+        fi
+
+        echo "Creating $vf_count SR-IOV VFs for the interface $iface"
+        if ! echo $vf_count > /sys/class/net/$iface/device/sriov_numvfs
+        then
+            echo "Failed to create SR-IOV VFs for the interface $iface" >&2
+            res=1
+        fi
+    done
+
+    return $res
+}
+
+stop()
+{
+    local iface
+    local res=0
+
+    for iface in $SRIOV_INTERFACES
+    do
+        echo "Removing SR-IOV VFs from the interface $iface"
+        if ! echo 0 > /sys/class/net/$iface/device/sriov_numvfs
+        then
+            echo "Failed to remove SR-IOV VFs from the interface $iface" >&2
+            res=1
+        fi
+    done
+
+    return $res
+}
+
+main()
+{
+    local -r CONF_FILE="/etc/sriov/sriov.conf"
+    local -r ACTION=$1
+
+    if [[ $# -ne 1 || ! $ACTION =~ ^(start|stop)$ ]]
+    then
+        echo "usage: $0 [start|stop]" >&2
+        return 1
+    fi
+
+    [[ -r $CONF_FILE ]] && source $CONF_FILE
+
+    if [[ -n "$SRIOV_INTERFACES" ]]
+    then
+        $ACTION
+    else
+        echo "No SR-IOV interfaces to configure" >&2
+        return 1
+    fi
+}
+
+main "$@"