# Required vars
# - openqa_email
##       string - Email address of admin user
# - openqa_nickname
##       string - Short name of admin user (shown in the web UI for e.g.)
# - openqa_fullname
##       string - Full name of admin user
# - openqa_key
# - openqa_secret
##       string - MUST be 16-character hexadecimals, and are secrets
# openqa_userid
##       string - User ID of admin user: for Fedora should be a Fedora openID URL,
##                http://fasname.id.fedoraproject.org

# Required vars with defaults
# - external_hostname
##       string - The public hostname for the server (will be used as ServerName)
##       default - ansible_nodename

# Optional vars
# - openqa_static_uid
##       int - a static ID for the geekotest user and group if desired
##             this is useful for NFS mounting openQA data files
# - openqa_dbname
##       string - The name of the database to use
# - openqa_dbhost
##       string - The hostname of the database server
# - openqa_dbuser
##       string - The database username
# - openqa_dbpassword
##       string - The database password
# - openqa_assetsize
##       int - the asset size limit to set in GB (upstream default is 100GB)
##             higher is recommended for normal Fedora testing, 300GB is good
##             FIXME: this only works for pgsql ATM
# - openqa_assetsize_updates
##       int - the asset size limit to set for update job groups in GB
##             (upstream default is 100GB). Lower is recommended for normal
##             Fedora testing, 50GB is good
##             FIXME: this only works for pgsql ATM
# - deployment_type
##      string - Fedora Infrastructure thing; for this role, decides
##               whether to enable some openQA plugins that should be
##               enabled only in Fedora infra. Don't set it outside
##               Fedora infra.
#
# If openqa_dbhost is set, the others must be too, and the server will be
# configured to use a pgsql database accordingly. If openqa_dbhost is not
# set, the server will use a local SQLite database and the other values
# are ignored.

- name: Create geekotest group with static GID
  group: "name=geekotest gid={{ openqa_static_uid }} system=yes"
  when: "openqa_static_uid is defined"

- name: Create geekotest user with static UID
  user:
    name: geekotest
    comment: "openQA user"
    uid: "{{ openqa_static_uid }}"
    group: geekotest
    home: "/var/lib/openqa"
    createhome: no
    system: yes
    shell: /sbin/nologin
  when: "openqa_static_uid is defined"

# this is separate from the step below so we can easily flip it between
# stable and testing
- name: Install openQA packages
  dnf:
    name: ['openqa', 'openqa-httpd', 'openqa-plugin-fedmsg', 'openqa-plugin-fedoraupdaterestart',
           'python3-fedfind']
    state: present
#    enablerepo: "updates-testing"
  tags:
  - packages

- name: Install various other required packages
  dnf:
    name: ['libselinux-python', 'git', 'json_diff', 'libselinux-utils', 'libsemanage-python',
           'nfs-utils', 'perl(Class::DBI::Pg)', 'expect', 'libguestfs-tools-c', 'libguestfs-xfs',
           'libvirt-daemon-config-network', 'libvirt-python3', 'python3-libguestfs',
           'virt-install', 'withlock']
    state: present
  tags:
  - packages

- name: Check test directory exists with correct ownership
  file: path=/var/lib/openqa/share/tests/fedora state=directory owner=geekotest group=geekotest recurse=yes

# we don't want to run the checkout if the tests are on a non-standard
# branch, as that usually means we're messing around on staging and
# don't want the checkout reset to HEAD.
- name: Check if tests are checked out and on a non-standard branch
  command: "git status"
  args:
    chdir: /var/lib/openqa/share/tests/fedora
  register: testsbranch
  failed_when: "1 != 1"
  changed_when: "1 != 1"
  check_mode: no

- name: Check out the tests
  git:
    repo: https://pagure.io/fedora-qa/os-autoinst-distri-fedora.git
    dest: /var/lib/openqa/share/tests/fedora
  register: gittests
  become: true
  become_user: geekotest
  when: "(testsbranch.stderr.find('Not a git repository') != -1) or (testsbranch.stdout.find('On branch master') != -1 and testsbranch.stdout.find('Changes not staged') == -1)"

- name: Remove old openqa_fedora_tools checkout
  file: path=/root/openqa_fedora_tools state=absent

- name: Check out createhdds
  git:
    repo: https://pagure.io/fedora-qa/createhdds.git
    dest: /root/createhdds

- name: Create asset directories
  file: path={{ item }} state=directory owner=geekotest group=root mode=0755
  with_items:
  - /var/lib/openqa/share/factory/iso
  - /var/lib/openqa/share/factory/hdd
  - /var/lib/openqa/share/factory/hdd/fixed
  - /var/lib/openqa/share/factory/repo
  - /var/lib/openqa/share/factory/other

#- name: Set up createhdds cron job
#  copy: src=createhdds dest=/etc/cron.daily/createhdds owner=root group=root mode=0755

# While #1539330 is a thing, we probably don't want the servers
# crashing every day...
- name: Remove createhdds cron job (#1539330)
  file: path=/etc/cron.daily/createhdds state=absent

- name: Check if any hard disk images need (re)building
  command: "/root/createhdds/createhdds.py check"
  args:
    chdir: /var/lib/openqa/share/factory/hdd/fixed
  register: diskcheck
  failed_when: "1 != 1"
  changed_when: "1 != 1"
  check_mode: no

- name: Ensure libvirt is running if needed to create images
  service: name=libvirtd enabled=yes state=started
  when: "diskcheck.rc > 1"

# > 1 is not a typo; check exits with 1 if all images are present but some
# are outdated, and 2 if any images are missing. We only want to handle
# outright *missing* images here in the playbook (to handle the case of
# first deployment). Outdated images are handled by the daily cron run.

# disabled due to #1539330
#- name: Create hard disk images (this may take a long time!)
#  command: "/etc/cron.daily/createhdds"
#  when: "diskcheck.rc > 1"
#  ignore_errors: yes

- name: Create exports file
  template: src=exports.j2 dest=/etc/exports.d/openqa.exports owner=root group=root mode=0644
  tags:
  - config

- name: Enable and start NFS server
  service: name=nfs-server enabled=yes state=started

- name: Set up Apache config
  template: src=openqa.conf.httpd.j2 dest=/etc/httpd/conf.d/openqa.conf owner=root group=root mode=0644
  notify:
  - reload httpd
  tags:
  - config

- name: OpenQA config
  template: src=openqa.ini.j2 dest=/etc/openqa/openqa.ini owner=geekotest group=root mode=0644
  tags:
  - config

- name: Create database
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  postgresql_db: db={{ openqa_dbname }}
  when: "openqa_dbhost is defined"

- name: Ensure db user has access to database
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  postgresql_user: db={{ openqa_dbname }} user={{ openqa_dbuser }} password={{ openqa_dbpassword }} role_attr_flags=NOSUPERUSER
  when: "openqa_dbhost is defined"

- name: Database config
  template: src=database.ini.pgsql.j2 dest=/etc/openqa/database.ini owner=geekotest group=root mode=0640
  when: "openqa_dbhost is defined"
  tags:
  - config

- name: Initialize database
  shell: "/usr/share/openqa/script/initdb --user geekotest --init_database"
  register: initdb
  changed_when: "initdb.rc == 0"
  failed_when: "(initdb.rc > 0) and (initdb.stdout is not defined or initdb.stdout.find('already exists') == -1)"

- name: Enable and start services
  service: name={{ item }} enabled=yes state=started
  register: services
  with_items:
  - openqa-livehandler
  - openqa-scheduler
  - openqa-webui
  - openqa-websockets
  - openqa-gru

# This is using a big hammer until #1277312 is resolved
- name: Allow Apache to connect to openQA
  seboolean: name=httpd_can_network_connect state=yes persistent=yes

- name: Allow Apache to read from NFS (as we store test data files there now)
  seboolean: name=httpd_use_nfs state=yes persistent=yes

# services is undefined in check mode
- name: Wait for openQA to be fully started
  pause: seconds=5
  when: "services is defined and services is changed"

# the 'dispatcher' role requires this to be root.fedmsg 0640. so we
# don't enforce ownership here and set mode to 0640 so we don't wind
# up ping-ponging it between server and dispatcher roles.
- name: openQA client config
  template: src=client.conf.j2 dest=/etc/openqa/client.conf mode=0640
  tags:
  - config

- name: Create admin user
  command: "/var/lib/openqa/script/create_admin --email {{ openqa_email }} --nickname {{ openqa_nickname }} --fullname '{{ openqa_fullname }}' --key {{ openqa_key }} --secret {{ openqa_secret }} {{ openqa_userid }}"
  register: admin
  changed_when: "admin.rc == 0"
  failed_when: "(admin.rc > 0) and (admin.stderr is not defined or admin.stderr.find('already exists') == -1)"

- name: Dump existing config for checking changes
  shell: "/usr/share/openqa/script/dump_templates --json > /tmp/tmpl-old.json"
  when: "(gittests is defined) and (gittests is changed)"
  changed_when: "1 != 1"

# Because of the boring details of how template loading works, getting
# a correct 'changed' for this step is too difficult. Instead we have
# the prior and following steps; when the templates actually changed,
# the *following* step will register as changed.
- name: Load main tests
  command: "/var/lib/openqa/share/tests/fedora/templates --clean"
  when: "(gittests is defined) and (gittests is changed)"
  changed_when: "1 != 1"

- name: Load update tests
  command: "/var/lib/openqa/share/tests/fedora/templates-updates --update"
  when: "(gittests is defined) and (gittests is changed)"
  changed_when: "1 != 1"

- name: Check if the tests changed in previous step
  shell: "/usr/share/openqa/script/dump_templates --json > /tmp/tmpl-new.json && json_diff /tmp/tmpl-old.json /tmp/tmpl-new.json"
  when: "(gittests is defined) and (gittests is changed)"
  register: testsdiff
  changed_when: "testsdiff.rc > 0"
  failed_when: "1 != 1"

- name: Set 'fedora' asset size limit (if specified) (pgsql)
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  command: "psql -d {{ openqa_dbname }} -c \"UPDATE job_groups SET size_limit_gb = {{ openqa_assetsize }} WHERE name = 'fedora' AND (size_limit_gb != {{ openqa_assetsize }} OR size_limit_gb IS NULL);\""
  when: "openqa_dbhost is defined and openqa_assetsize is defined"
  register: pgsqlsize
  changed_when: "pgsqlsize.stdout.find('UPDATE 0') == -1"

- name: Set 'Fedora PowerPC' asset size limit (if specified) (pgsql)
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  command: "psql -d {{ openqa_dbname }} -c \"UPDATE job_groups SET size_limit_gb = {{ openqa_assetsize_ppc }} WHERE name = 'Fedora PowerPC' AND (size_limit_gb != {{ openqa_assetsize_ppc }} OR size_limit_gb IS NULL);\""
  when: "openqa_dbhost is defined and openqa_assetsize_ppc is defined"
  register: pgsqlsize
  changed_when: "pgsqlsize.stdout.find('UPDATE 0') == -1"

- name: Set 'Fedora AArch64' asset size limit (if specified) (pgsql)
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  command: "psql -d {{ openqa_dbname }} -c \"UPDATE job_groups SET size_limit_gb = {{ openqa_assetsize_aarch64 }} WHERE name = 'Fedora AArch64' AND (size_limit_gb != {{ openqa_assetsize_aarch64 }} OR size_limit_gb IS NULL);\""
  when: "openqa_dbhost is defined and openqa_assetsize_aarch64 is defined"
  register: pgsqlsize
  changed_when: "pgsqlsize.stdout.find('UPDATE 0') == -1"

- name: Set update job group asset size limit (if specified) (pgsql)
  delegate_to: "{{ openqa_dbhost }}"
  become_user: postgres
  become: true
  command: "psql -d {{ openqa_dbname }} -c \"UPDATE job_groups SET size_limit_gb = {{ openqa_assetsize_updates }} WHERE name LIKE '%Updates%' AND (size_limit_gb != {{ openqa_assetsize_updates }} OR size_limit_gb IS NULL);\""
  when: "openqa_dbhost is defined and openqa_assetsize_updates is defined"
  register: pgsqlupdatesize
  changed_when: "pgsqlupdatesize.stdout.find('UPDATE 0') == -1"
