diff --git a/roles/apache2/tasks/apacheRedHat.yml b/roles/apache2/tasks/apacheRedHat.yml index 584ed275655dbff3b919d20679e9c8ce3a56be03..71e520a982b4be7552aaeea70c55bb83b68c9b4c 100644 --- a/roles/apache2/tasks/apacheRedHat.yml +++ b/roles/apache2/tasks/apacheRedHat.yml @@ -3,7 +3,7 @@ - name: "Installing Apache" sudo: true - yum: name={{ item }} state=latest + yum: name={{ item }} state=present with_items: - mod_ssl - mod_wsgi diff --git a/roles/extra_rpms/tasks/main.yml b/roles/extra_rpms/tasks/main.yml index 8dcf07de56a4a03f8cf52aaf3349a5a8193d224d..2a85fba6ddd111326b878ba24e599bc1dc12f5d2 100644 --- a/roles/extra_rpms/tasks/main.yml +++ b/roles/extra_rpms/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: "Install extra packages" - yum: "name={{ item }} state=latest" + yum: "name={{ item }} state=present" with_items: pkgs sudo: true diff --git a/roles/fastest_mirror/tasks/main.yml b/roles/fastest_mirror/tasks/main.yml index b5f720a809cca3eb72381fbaea754def989fafd3..7b18f9451a9a422eb2f25fbef9faa60cb608960a 100644 --- a/roles/fastest_mirror/tasks/main.yml +++ b/roles/fastest_mirror/tasks/main.yml @@ -11,3 +11,10 @@ command: yum makecache sudo: true when: ansible_os_family == 'RedHat' + +# For some reason ed went missing from the NeCTAR official CentOS 7 image +# This meant that fail2ban could ban you, but could never unban you +- name: "make sure ed is installed" + yum: name=ed state=installed + sudo: true + when: ansible_os_family == 'RedHat' diff --git a/roles/gluster_server/files/glusterfs-epel.repo b/roles/gluster_server/files/glusterfs-epel.repo index 843b4baef3cf4d81aca369e49c44b92c1599c3cf..6cac832a40534526c9e689321cb8a8b1f271c5f7 100644 --- a/roles/gluster_server/files/glusterfs-epel.repo +++ b/roles/gluster_server/files/glusterfs-epel.repo @@ -2,21 +2,21 @@ [glusterfs-epel] name=GlusterFS is a clustered file-system capable of scaling to several petabytes. -baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.6/LATEST/EPEL.repo/epel-$releasever/$basearch/ +baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.7/LATEST/EPEL.repo/epel-$releasever/$basearch/ enabled=1 skip_if_unavailable=1 gpgcheck=0 [glusterfs-noarch-epel] name=GlusterFS is a clustered file-system capable of scaling to several petabytes. -baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.6/LATEST/EPEL.repo/epel-$releasever/noarch +baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.7/LATEST/EPEL.repo/epel-$releasever/noarch enabled=1 skip_if_unavailable=1 gpgcheck=0 [glusterfs-source-epel] name=GlusterFS is a clustered file-system capable of scaling to several petabytes. - Source -baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.6/LATEST/EPEL.repo/epel-$releasever/SRPMS +baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.7/LATEST/EPEL.repo/epel-$releasever/SRPMS enabled=0 skip_if_unavailable=1 gpgcheck=0 diff --git a/roles/installPackage/tasks/main.yml b/roles/installPackage/tasks/main.yml index d8605ffc42082e877b9714363c88ce3182b57166..a42426cb3e5fe964c18da7a8870c1729446ce213 100644 --- a/roles/installPackage/tasks/main.yml +++ b/roles/installPackage/tasks/main.yml @@ -14,7 +14,7 @@ when: ansible_distribution == 'CentOS' and importRepo is defined - name: Install yum packages - yum: name={{ item }} state=latest + yum: name={{ item }} state=present with_items: yumPackageList sudo: true when: ansible_distribution == 'CentOS' and yumPackageList is defined diff --git a/roles/karaage2.7/tasks/main.yml b/roles/karaage2.7/tasks/main.yml index 279b5d5250b99d667a2b51ec9b1e4f881760343a..4512a69b07c8243dc057b1034c90a821d42331ce 100644 --- a/roles/karaage2.7/tasks/main.yml +++ b/roles/karaage2.7/tasks/main.yml @@ -2,7 +2,7 @@ - include_vars: "{{ ansible_distribution }}_{{ ansible_distribution_version }}_{{ ansible_architecture }}.yml" - name: install system packages apt - apt: name={{ item }} state=installed update_cache=true + apt: name={{ item }} state=installed sudo: true with_items: system_packages when: ansible_os_family == 'Debian' diff --git a/roles/karaage3.1.17/tasks/karaage.yml b/roles/karaage3.1.17/tasks/karaage.yml index 3ee091ecb4b0458a9fe070492c3c4343265edd8c..c93567691305ebdc4efcc535e2ecd478e0286546 100644 --- a/roles/karaage3.1.17/tasks/karaage.yml +++ b/roles/karaage3.1.17/tasks/karaage.yml @@ -26,7 +26,7 @@ - name: "Installing prerequisites Redhat" - yum: name={{ item }} state=latest + yum: name={{ item }} state=present sudo: true with_items: - libxml2-devel diff --git a/roles/ldapclient/tasks/installOpenLdap.yml b/roles/ldapclient/tasks/installOpenLdap.yml index 31a12286fd7b829b272cb6a68812f15478274b75..b11a480d754812d7c4f7139611502dcb1219fcf4 100644 --- a/roles/ldapclient/tasks/installOpenLdap.yml +++ b/roles/ldapclient/tasks/installOpenLdap.yml @@ -1,6 +1,6 @@ --- - name: "Install open ldap package yum" - yum: name={{ item }} state=latest + yum: name={{ item }} state=present with_items: - openldap - openldap-clients @@ -13,7 +13,7 @@ when: ansible_os_family == 'RedHat' - name: "Install open ldap package apt" - action: apt pkg={{ item }} state=installed + action: apt pkg={{ item }} state=present with_items: - ldap-utils - sssd diff --git a/roles/link_usr_local/tasks/main.yml b/roles/link_usr_local/tasks/main.yml index 72847692aec9dcbd7d0a654449cfac308243c549..091d49c29e80bcb470bd909a41c1ff84f2ab3b75 100644 --- a/roles/link_usr_local/tasks/main.yml +++ b/roles/link_usr_local/tasks/main.yml @@ -3,6 +3,10 @@ stat: path={{ dest }} register: stat_r + +- name: debug1 + debug: var=stat_r + - name: mv command: mv "{{ dest }}" "{{ dest }}_old" when: stat_r.stat.exists and stat_r.stat.isdir @@ -12,6 +16,8 @@ stat: path={{ dest }} register: stat_r +- name: debug2 + debug: var=stat_r - name: link file: src="{{ src }}" dest="{{ dest }}" state=link diff --git a/roles/mellanox_drivers/tasks/main.yml b/roles/mellanox_drivers/tasks/main.yml index a240e27b1918784dd6629e0baabca37e5cc5cb65..a662dc369342369848fe56b0d4a1bf1590463901 100644 --- a/roles/mellanox_drivers/tasks/main.yml +++ b/roles/mellanox_drivers/tasks/main.yml @@ -14,30 +14,32 @@ register: drivers_installed ignore_errors: true -- name: yum update to upgrade kernel - shell: "yum update -y" - sudo: true - ignore_errors: true - when: ansible_os_family == "RedHat" and drivers_installed|failed + +# This is NASTY. Don't upgrade production systems without taking them out of the queue first. +#- name: yum update to upgrade kernel +# shell: "yum update -y" +# sudo: true +# ignore_errors: true +# when: ansible_os_family == "RedHat" and drivers_installed|failed # # A REBOOT IS NEEDED AFTER a KERNEL UPDATE # -- name: restart machine - shell: sleep 5; sudo shutdown -r now "Ansible updates triggered" - async: 2 - poll: 0 - ignore_errors: true - sudo: true - when: ansible_os_family == "RedHat" and drivers_installed|failed - -- name: waiting for server to come back - local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH - sudo: false - -- name: waiting for server to come back number 2 - local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH - sudo: false +#- name: restart machine +# shell: sleep 5; sudo shutdown -r now "Ansible updates triggered" +# async: 2 +# poll: 0 +# ignore_errors: true +# sudo: true +# when: ansible_os_family == "RedHat" and drivers_installed|failed +# +#- name: waiting for server to come back +# local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH +# sudo: false +# +#- name: waiting for server to come back number 2 +# local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH +# sudo: false - name: copy driver source @@ -89,6 +91,7 @@ insertafter: "auto {{ MELLANOX_DEVICE_NAME }}" sudo: true when: ansible_os_family=="Debian" and drivers_installed|failed + - name: Ubuntu network interfaces - line 3 lineinfile: args: @@ -107,7 +110,7 @@ poll: 0 ignore_errors: true sudo: true - when: ansible_os_family=="Centos" and drivers_installed|failed + when: ansible_os_family=="RedHat" and drivers_installed|failed - name: restart machine for Ubuntu -cos it is 'special' shell: "sleep 5; sudo shutdown -r now" @@ -115,19 +118,21 @@ poll: 1 ignore_errors: true sudo: true - when: ansible_os_family=="Debian" + when: ansible_os_family=="Debian" and drivers_installed|failed - name: waiting for server to come back local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH sudo: false + when: drivers_installed|failed - name: waiting for server to come back 2 local_action: wait_for host={{ ansible_ssh_host }} state=started port=22 delay=10 search_regex=OpenSSH + when: drivers_installed|failed - name: bring up interface #variable=eth0 or ens6 command: ifup {{ MELLANOX_DEVICE_NAME }} sudo: true - when: ansible_distribution_major_version == "7" + when: ansible_os_family=="RedHat" and ansible_distribution_major_version == "7" diff --git a/roles/move_homedir/tasks/main.yml b/roles/move_homedir/tasks/main.yml index d81c8fe3bc0711b5d9fa3389577f60d11fbc37ae..9ed97c5d5d6dcd1098e8a734af3d8d926aa67260 100644 --- a/roles/move_homedir/tasks/main.yml +++ b/roles/move_homedir/tasks/main.yml @@ -13,43 +13,12 @@ lineinfile: args: dest: /etc/passwd - regexp: "{{ ansible_ssh_user }}:x:1001:1001::/home/{{ ansible_ssh_user }}:.*" - line: "{{ ansible_ssh_user }}:x:1001:1001::/local_home/{{ ansible_ssh_user }}:/bin/bash" + regexp: '{{ ansible_ssh_user }}:x:(.*):(.*):(.*):/home/{{ ansible_ssh_user }}:(.*)' + line: '{{ ansible_ssh_user }}:x:\1:\2:\3:/local_home/{{ ansible_ssh_user }}:\4' backrefs: yes sudo: true - register: edit1 + register: edit -- name: edit passwd file - lineinfile: - args: - dest: /etc/passwd - regexp: "{{ ansible_ssh_user }}:x:500:500::/home/{{ ansible_ssh_user }}:.*" - line: "{{ ansible_ssh_user }}:x:500:500::/local_home/{{ ansible_ssh_user }}:/bin/bash" - backrefs: yes - sudo: true - register: edit2 - - - -- name: edit passwd file - lineinfile: - args: - dest: /etc/passwd - regexp: "{{ ansible_ssh_user }}:x:1000:1000::/home/{{ ansible_ssh_user }}:.*" - line: "{{ ansible_ssh_user }}:x:1000:1000::/local_home/{{ ansible_ssh_user }}:/bin/bash" - backrefs: yes - sudo: true - register: edit3 -# ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash -- name: edit passwd file for ubuntu 14 - lineinfile: - args: - dest: /etc/passwd - regexp: "{{ ansible_ssh_user }}:x:1000:1000:Ubuntu:/home/{{ ansible_ssh_user }}:.*" - line: "{{ ansible_ssh_user }}:x:1000:1000:Ubuntu:/local_home/{{ ansible_ssh_user }}:/bin/bash" - backrefs: yes - sudo: true - register: edit4 diff --git a/roles/mysql/tasks/mysql_client.yml b/roles/mysql/tasks/mysql_client.yml index f8c23a1ce160d20be5df10b9f76da1e0f5ca3801..05a1022d073868f6f2cd19bc21ae905871a6e64e 100644 --- a/roles/mysql/tasks/mysql_client.yml +++ b/roles/mysql/tasks/mysql_client.yml @@ -6,7 +6,7 @@ when: ansible_os_family == "Debian" - name: Installing MySQL RedHat - yum: name="{{ item }}" state=latest + yum: name="{{ item }}" state=present with_items: client_packages sudo: true when: ansible_os_family == "RedHat" diff --git a/roles/nfs-common/tasks/aptPackages.yml b/roles/nfs-common/tasks/aptPackages.yml index 364b2b73093be8d9ac7b80c63bd53025d3694713..3244c7d1890613902b95c7f572059d905619b79e 100644 --- a/roles/nfs-common/tasks/aptPackages.yml +++ b/roles/nfs-common/tasks/aptPackages.yml @@ -4,6 +4,6 @@ with_items: - nfs-common - nfs-kernel-server - apt: "name={{ item }} state=latest" + apt: "name={{ item }} state=present" sudo: true diff --git a/roles/nfs-common/tasks/yumPackages.yml b/roles/nfs-common/tasks/yumPackages.yml index c6daa0dc26c42e352d8027edeb938503fc2f7cf4..36da380ff649f49f291e153a26e352651111b4c3 100644 --- a/roles/nfs-common/tasks/yumPackages.yml +++ b/roles/nfs-common/tasks/yumPackages.yml @@ -4,5 +4,5 @@ with_items: - bind-utils - nfs-utils - yum: "name={{ item }} state=latest" + yum: "name={{ item }} state=present" sudo: true diff --git a/roles/nfs-server/tasks/main.yml b/roles/nfs-server/tasks/main.yml index bde7943086ed49798b340a43dcbad5808836e1d9..c317d2ae0b5fe6668f288ec074ae9f8dc0eff25c 100644 --- a/roles/nfs-server/tasks/main.yml +++ b/roles/nfs-server/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: install nfs kernel server - apt: name=nfs-kernel-server state=latest + apt: name=nfs-kernel-server state=present sudo: true when: ansible_os_family == "Debian" diff --git a/roles/package_update/tasks/main.yml b/roles/package_update/tasks/main.yml deleted file mode 100644 index acbd63e0395b03dd4fe71fd80d203d1c1abc1405..0000000000000000000000000000000000000000 --- a/roles/package_update/tasks/main.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- - -- name: "update cache centos" - shell: yum update -y - sudo: true - when: ansible_os_family == 'RedHat' - -- name: "update cache debian" - shell: apt-get update -y - sudo: true - when: ansible_os_family == 'Debian' - - diff --git a/roles/provision_homedir/tasks/main.yml b/roles/provision_homedir/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..a057f44fc0932ef5f67a2f2a5de9e1531a1120b5 --- /dev/null +++ b/roles/provision_homedir/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: make dir + file: path="{{ provision_homedir | dirname }}" state=directory mode=755 owner=root + sudo: true + run_once: true + +- name: install python packages + yum: name=python-ldap state=installed + sudo: true + when: ansible_os_family == 'RedHat' + +- name: install python packages + apt: name=python-ldap state=installed + sudo: true + when: ansible_os_family == 'Debian' + +- name: copy provision_homedir template + template: src=provision_homedir.py.j2 dest={{ provision_homedir }} mode=700 owner=root + sudo: true + run_once: true + +# the lockfile for makeing home directories should be located on the shared directory where the home directories will be created. Otherwise it will be racey +- name: provision_homedir cron job + cron: name=provision_homedir job="/usr/bin/flock -x -n /home/provision.lck -c {{ provision_homedir }}" user=root minute=*/30 state=present + sudo: true diff --git a/roles/provision_homedir/templates/provision_homedir.py.j2 b/roles/provision_homedir/templates/provision_homedir.py.j2 new file mode 100644 index 0000000000000000000000000000000000000000..b601f099540b6c3126bcc4137001d6579fe69278 --- /dev/null +++ b/roles/provision_homedir/templates/provision_homedir.py.j2 @@ -0,0 +1,73 @@ +#!/usr/bin/python +import ldap +import traceback +import os +import stat + +class ldapSearchConfig: + def __init__(self): + self.ldapserver="" + self.binddn="" + self.bindpw="" + self.baseDN="" + self.searchFilter="" + self.cacertfile='' + +class genericUser: + def __init__(self): + self.dn="" + self.cn="" + self.entry="" + self.uid="" + + +def get_users(server): +# ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,server.cacertfile) + ldap.set_option( ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER ) + l=ldap.initialize(server.ldapserver) + l.simple_bind_s(server.binddn,server.bindpw) + retrieveAttributes = ["*"] + searchScope=ldap.SCOPE_SUBTREE + try: + ldap_result_id = l.search(server.baseDN,searchScope,server.searchFilter,retrieveAttributes) + except ldap.LDAPError, e: + pass + rtype,rdata = l.result(ldap_result_id,1) + allusers={} + for user in rdata: + dn=user[0] + attrs=user[1] + allusers[dn]=genericUser() + allusers[dn].dn=dn + allusers[dn].entry=attrs + return allusers + + +def mk_homedir(path,uidNumber,gidNumber): + try: + statinfo = os.stat(path) + except OSError as e: + if 'No such file or directory' in e: + os.mkdir(path,0700) + statinfo = os.stat(path) + if stat.S_ISDIR(statinfo.st_mode): + if statinfo.st_gid != gidNumber or statinfo.st_uid!=uidNumber: + os.chown(path,uidNumber,gidNumber) + else: + raise Exception("users homedirectory is not a directory %s"%path) + +s=ldapSearchConfig() +s.ldapserver="{{ ldapURI }}" +s.binddn="{{ ldapBindDN }}" +s.bindpw="{{ ldapBindDNPassword }}" +s.baseDN="{{ ldapBase }}" +s.searchFilter = "{{ search_filter }}" +homeDirEntry= "{{ homeDirEntry }}" + +users=get_users(s) +for user in users: + try: + mk_homedir(users[user].entry[homeDirEntry][0],int(users[user].entry['uidNumber'][0]),int(users[user].entry['gidNumber'][0])) + except: + print traceback.format_exc() + pass diff --git a/roles/provision_homedir/vars/main.yml b/roles/provision_homedir/vars/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..f1b8ef6cdfbc9d1d7a245a3e607b5ec31dae9151 --- /dev/null +++ b/roles/provision_homedir/vars/main.yml @@ -0,0 +1,5 @@ +--- +use_active_directory: False +provision_homedir: /usr/local/sbin/provision_homedir.py +homeDirEntry: "{% if use_active_directory %}unixHomeDirectory{% else %}homeDirectory {% endif %}" +search_filter: "{% if use_active_directory %}(unixHomeDirectory=*){% else %} (objectClass=posixAccount) {% endif %}" diff --git a/roles/provision_slurm/tasks/main.yml b/roles/provision_slurm/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..6d4e6aa9ec44e1659825b4dce3ecfbb821550180 --- /dev/null +++ b/roles/provision_slurm/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: make dir + file: path="{{ provision_slurm | dirname }}" state=directory mode=755 owner=root + sudo: true + run_once: true + +- name: install python packages + yum: name=python-ldap state=installed + sudo: true + when: ansible_os_family == 'RedHat' + +- name: install python packages + apt: name=python-ldap state=installed + sudo: true + when: ansible_os_family == 'Debian' + +- name: copy provision_slurm template + template: src=provision_slurm.py.j2 dest={{ provision_slurm }} mode=700 owner=root + sudo: true + run_once: true + +# the lockfile for makeing home directories should be located on the shared directory where the home directories will be created. Otherwise it will be racey +- name: provision_slurm cron job + cron: name=provision_slurm job="/usr/bin/flock -x -n /home/provision.lck -c {{ provision_slurm }}" user=root minute=*/30 state=present + sudo: true diff --git a/roles/provision_slurm/templates/provision_slurm.py.j2 b/roles/provision_slurm/templates/provision_slurm.py.j2 new file mode 100644 index 0000000000000000000000000000000000000000..a8a6bca3cb4b0cb180364e13755b57595735410d --- /dev/null +++ b/roles/provision_slurm/templates/provision_slurm.py.j2 @@ -0,0 +1,76 @@ +#!/usr/bin/python +import ldap +import traceback +import os +import stat +import subprocess + +class ldapSearchConfig: + def __init__(self): + self.ldapserver="" + self.binddn="" + self.bindpw="" + self.baseDN="" + self.searchFilter="" + self.cacertfile='' + +class genericUser: + def __init__(self): + self.dn="" + self.cn="" + self.entry="" + self.uid="" + + +def get_users(server): +# ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,server.cacertfile) + ldap.set_option( ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER ) + l=ldap.initialize(server.ldapserver) + l.simple_bind_s(server.binddn,server.bindpw) + retrieveAttributes = ["*"] + searchScope=ldap.SCOPE_SUBTREE + try: + ldap_result_id = l.search(server.baseDN,searchScope,server.searchFilter,retrieveAttributes) + except ldap.LDAPError, e: + pass + rtype,rdata = l.result(ldap_result_id,1) + allusers={} + for user in rdata: + dn=user[0] + attrs=user[1] + allusers[dn]=genericUser() + allusers[dn].dn=dn + allusers[dn].entry=attrs + return allusers + + +def mk_slurmaccount(acct): + output=subprocess.check_output(["{{ slurm_dir }}/bin/sacctmgr","--noheader","list","account",acct]) + if acct in output: + return + else: + subprocess.call(["{{ slurm_dir }}/bin/sacctmgr","-i","create","account",acct]) + +def mk_slurmuser(user,acct): + output=subprocess.check_output(["{{ slurm_dir }}/bin/sacctmgr","--noheader","list","Association","user=%s"%user,"format=account"]) + if acct in output.splitlines(): + return + else: + subprocess.call(["{{ slurm_dir }}/bin/sacctmgr","-i","create","user",user,"account=%s"%acct,"DefaultAccount=%s"%acct]) + + +s=ldapSearchConfig() +s.ldapserver="{{ ldapURI }}" +s.binddn="{{ ldapBindDN }}" +s.bindpw="{{ ldapBindDNPassword }}" +s.baseDN="{{ ldapBase }}" +s.searchFilter = "{{ search_filter }}" + +users=get_users(s) +mk_slurmaccount("default") +for user in users: + try: + mk_slurmuser(users[user].entry['uid'][0],"default") + except: + print traceback.format_exc() + pass diff --git a/roles/provision_slurm/vars/main.yml b/roles/provision_slurm/vars/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..2254544f25b1faea9c11c8b6ec3cf8e6e4e4d794 --- /dev/null +++ b/roles/provision_slurm/vars/main.yml @@ -0,0 +1,4 @@ +--- +use_active_directory: False +provision_slurm: /usr/local/sbin/provision_slurm.py +search_filter: "{% if use_active_directory %}(unixHomeDirectory=*){% else %} (objectClass=posixAccount) {% endif %}" diff --git a/roles/slurm-build-rpms/tasks/main.yml b/roles/slurm-build-rpms/tasks/main.yml deleted file mode 100644 index cbb3dca56d066b803ed0024782c2703e146e1c5e..0000000000000000000000000000000000000000 --- a/roles/slurm-build-rpms/tasks/main.yml +++ /dev/null @@ -1,95 +0,0 @@ ---- -- name: install deps - yum: name={{ item }} state=installed - sudo: true - with_items: - - gcc - - rpm-build - - wget - - openssl-devel - - readline-devel - - pam-devel - - perl-ExtUtils-MakeMaker - - bzip2-devel - - mysql - - mysql-devel - when: ansible_os_family == "RedHat" - -- name: install deps - apt: name={{ item }} state=installed update_cache=yes - sudo: true - with_items: - - gcc - - wget - - libssl-dev - - libpam0g-dev - - libbz2-dev - when: ansible_os_family == "Debian" - -- name: get munge - shell: wget https://munge.googlecode.com/files/munge-{{ munge_version }}.tar.bz2 - args: - chdir: /tmp - creates: /tmp/munge-{{ munge_version }}.tar.bz2 - -- name: make munge rpms - shell: rpmbuild -ta --clean munge-{{ munge_version }}.tar.bz2 - sudo: true - args: - chdir: /tmp - creates: /root/rpmbuild/RPMS/x86_64/munge-{{ munge_version }}-1.el6.x86_64.rpm - when: ansible_os_family == "RedHat" - -- name: untar munge - shell: tar jxf /tmp/munge-{{ munge_version }}.tar.bz2 - sudo: true - args: - chdir: /tmp - creates: /tmp/munge-{{ munge_version }} - when: ansible_os_family == "Debian" - -- name: build munge - shell: configure && make && make install - sudo: true - args: - chdir: /tmp/munge-{{ munge_version }} - when: ansible_os_family == "Debian" - -- name: get slurm - shell: wget http://www.schedmd.com/download/latest/slurm-{{ slurm_version }}.tar.bz2 - args: - chdir: /tmp - creates: /tmp/slurm-{{ slurm_version }}.tar.bz2 - -- name: check munge installation - shell: rpm -qa munge - register: munge_installed - when: ansible_os_family == "RedHat" - -- name: install munge deps - shell: rpm -i /root/rpmbuild/RPMS/x86_64/munge-libs-{{ munge_version }}-1.el6.x86_64.rpm /root/rpmbuild/RPMS/x86_64/munge-{{ munge_version }}-1.el6.x86_64.rpm /root/rpmbuild/RPMS/x86_64/munge-devel-{{ munge_version }}-1.el6.x86_64.rpm - sudo: true - when: munge_installed.stdout.find("munge") == -1 - -- name: make slurm rpms - shell: rpmbuild -ta --clean slurm-{{ slurm_version }}.tar.bz2 - sudo: true - args: - chdir: /tmp - creates: /root/rpmbuild/RPMS/x86_64/slurm-{{ slurm_version }}-1.el6.x86_64.rpm - -- name: copy rpms - shell: cp -r /root/rpmbuild /tmp - sudo: true - args: - creates: /tmp/rpmbuild/RPMS/x86_64/slurm-{{ slurm_version }}-1.el6.x86_64.rpm - -- name: retrieve rpms 1 - shell: scp -o StrictHostKeyChecking=no -r {{ hostvars[ansible_hostname]['ansible_user_id'] }}@{{ ansible_ssh_host }}:/tmp/rpmbuild/ /tmp - delegate_to: 127.0.0.1 - when: ansible_ssh_host is defined - -- name: retrieve rpms 2 - shell: scp -r {{ hostvars[ansible_hostname]['ansible_user_id'] }}@{{ ansible_hostname }}:/tmp/rpmbuild/ /tmp - delegate_to: 127.0.0.1 - when: ansible_ssh_host is not defined diff --git a/roles/slurm-common/tasks/installMungeFromSource.yml b/roles/slurm-common/tasks/installMungeFromSource.yml index aec3033b3534d3a3ddc43648a946df134b309ea8..06c72f5197dd8352b6c32d7d6838147b132b0b51 100644 --- a/roles/slurm-common/tasks/installMungeFromSource.yml +++ b/roles/slurm-common/tasks/installMungeFromSource.yml @@ -23,18 +23,22 @@ chdir: /tmp/munge-{{ munge_version }} creates: "{{ munge_dir }}/bin/munge" +- name: set use_systemd + set_fact: + use_systemd: True + when: (ansible_distribution == "CentOS" or ansible_distribution == "RedHat") and ( ansible_distribution_major_version == "7") + - name: copy init script template: dest=/etc/init.d/munge src=munge.initd.j2 mode=755 sudo: true + when: use_systemd is not defined - name: copy slurm init script if OS contains systemd template: dest=/etc/systemd/system/munge.service src=munge.service.j2 mode=755 sudo: true - when: (ansible_distribution == "CentOS" or ansible_distribution == "RedHat") and - ( ansible_distribution_major_version == "7") + when: use_systemd is defined - name: reload systemd shell: systemctl daemon-reload sudo: true - when: (ansible_distribution == "CentOS" or ansible_distribution == "RedHat") and - ( ansible_distribution_major_version == "7") + when: use_systemd is defined diff --git a/roles/slurm-common/tasks/installSlurmFromSource.yml b/roles/slurm-common/tasks/installSlurmFromSource.yml index ec9fbe5881b3188383da27589821cde48da977fa..c551d2392bb987b0990d48b34cee694ff275c425 100644 --- a/roles/slurm-common/tasks/installSlurmFromSource.yml +++ b/roles/slurm-common/tasks/installSlurmFromSource.yml @@ -19,6 +19,7 @@ shell: tar jxf /tmp/slurm-{{ slurm_version }}.tar.bz2 args: chdir: /tmp + creates: /tmp/slumr-{{ slurm_version }} - name: build slurm shell: ./configure --prefix={{ slurm_dir }} --with-munge={{ munge_dir }} && make diff --git a/roles/slurm-common/tasks/main.yml b/roles/slurm-common/tasks/main.yml index 31120c9385a9c1137fa6cf225b4cbbfa30de8379..a4f0080c14acbc49264c466e54565da733550424 100644 --- a/roles/slurm-common/tasks/main.yml +++ b/roles/slurm-common/tasks/main.yml @@ -27,17 +27,32 @@ file: path={{ slurmdatadir }} state=directory owner=slurm group=slurm mode=755 sudo: true when: slurmdatadir is defined + +- name: stat run directory + stat: path={{ slurmpiddir }} + register: runstat + when: slurmpiddir is defined - name: create run directory file: path={{ slurmpiddir }} state=directory owner=root group=root mode=750 sudo: true - when: slurmpiddir is defined + when: slurmpiddir is defined and not runstat.stat.exists + +- name: create shared state directory + file: path={{slurmsharedstatedir }} state=directory owner=slurm group=slurm mode=750 + sudo: true + run_once: true + when: usesharedstatedir + +- name: symlink shared state dir + file: path={{ slurmstatedir }} src={{ slurmsharedstatedir }} state=link + sudo: true + when: usesharedstatedir - name: create state directory file: path={{ slurmstatedir }} state=directory owner=slurm group=slurm mode=750 - sudo: true - when: slurmstatedir is defined + when: slurmstatedir is defined and not usesharedstatedir - name: create log directory file: path={{ slurmlogdir }} state=directory owner=slurm group=slurm mode=750 @@ -49,7 +64,7 @@ sudo: true - name: install deps - yum: name={{ item }} state=latest + yum: name={{ item }} state=present with_items: - perl - perl-DBI @@ -124,11 +139,11 @@ when: slurm_gres_list is defined - name: install slurm prolog - template: src=slurm.prolog.j2 dest={{ slurm_dir }}/bin/slurm.prolog + template: src=slurm.prolog.j2 dest={{ slurm_dir }}/bin/slurm.prolog mode=755 sudo: true - name: install slurm epilog - template: src=slurm.epilog.j2 dest={{ slurm_dir }}/bin/slurm.epilog + template: src=slurm.epilog.j2 dest={{ slurm_dir }}/bin/slurm.epilog mode=755 sudo: true - name: install slurm.conf diff --git a/roles/strudel_build/tasks/main.yml b/roles/strudel_build/tasks/main.yml index c7e31d4477d37bb09f450f21137f342b37bcc658..21c8b806d06ffc8492b32d6e814aa2f72edef6ab 100644 --- a/roles/strudel_build/tasks/main.yml +++ b/roles/strudel_build/tasks/main.yml @@ -9,13 +9,6 @@ when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" ignore_errors: true -- name: add epel on CentOS 7 - shell: yum -y update - sudo: true - when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" - - - - name: install system packages apt apt: name={{ item }} state=installed update_cache=true diff --git a/roles/strudel_config/templates/generic_slurm_config.json.j2 b/roles/strudel_config/templates/generic_slurm_config.json.j2 index 17ba6262ca1f5455c95b38aa6e174afcd627ffad..976557af150bb75b6fbc75891a895099d1a6ce66 100644 --- a/roles/strudel_config/templates/generic_slurm_config.json.j2 +++ b/roles/strudel_config/templates/generic_slurm_config.json.j2 @@ -1,9 +1,12 @@ [ [ - "GenericDesktops" +{% for partition in slurmqueues %} + "{{ partition.name }}"{% if not loop.last %},{% endif %} +{% endfor %} ], { - "GenericDesktops": { +{% for partition in slurmqueues %} + "{{ partition.name }}": { "__class__": "siteConfig", "__module__": "siteConfig", "agent": { @@ -268,7 +271,7 @@ "__class__": "cmdRegEx", "__module__": "siteConfig", "async": false, - "cmd": "\"mkdir ~/.vnc ; rm -f ~/.vnc/clearpass ; touch ~/.vnc/clearpass ; chmod 600 ~/.vnc/clearpass ; passwd=\"'$'\"( dd if=/dev/urandom bs=1 count=8 2>/dev/null | md5sum | cut -b 1-8 ) ; echo \"'$'\"passwd > ~/.vnc/clearpass ; cat ~/.vnc/clearpass | vncpasswd -f > ~/.vnc/passwd ; chmod 600 ~/.vnc/passwd ; echo -e '#!/bin/bash\\nvncserver ; sleep 36000000 ' | {{slurm_dir}}/bin/sbatch -p batch -N {nodes} -n {ppn} --time={hours}:00:00 -J desktop_{username} -o .vnc/slurm-%j.out \"", + "cmd": "\"mkdir ~/.vnc ; rm -f ~/.vnc/clearpass ; touch ~/.vnc/clearpass ; chmod 600 ~/.vnc/clearpass ; passwd=\"'$'\"( dd if=/dev/urandom bs=1 count=8 2>/dev/null | md5sum | cut -b 1-8 ) ; echo \"'$'\"passwd > ~/.vnc/clearpass ; cat ~/.vnc/clearpass | vncpasswd -f > ~/.vnc/passwd ; chmod 600 ~/.vnc/passwd ; echo -e '#!/bin/bash\\nexport PATH=\"'$'\"PATH:/bin ; vncserver ; sleep 36000000 ' | {{slurm_dir}}/bin/sbatch -p {{ partition.name }} -N {nodes} -n {ppn} --time={hours}:00:00 -J desktop_{username} -o .vnc/slurm-%j.out \"", "failFatal": true, "formatFatal": false, "host": "login", @@ -345,7 +348,7 @@ "host": "exec", "loop": false, "regex": [ - "^.*?New 'X' desktop is \\S+(?P<vncDisplay>:[0-9]+)\\s*$" + "^.*?New .* desktop is \\S+(?P<vncDisplay>:[0-9]+)\\s*$" ], "requireMatch": true }, @@ -447,6 +450,7 @@ ], "requireMatch": true } - } + }{% if not loop.last %},{% endif %} +{% endfor %} } ] diff --git a/roles/vncserver/tasks/main.yml b/roles/vncserver/tasks/main.yml index 59b754ea4eefd5f8af93eb3637413e65502d7d32..13c13dc639c66a9c031ecdfce3b5d84482de367e 100644 --- a/roles/vncserver/tasks/main.yml +++ b/roles/vncserver/tasks/main.yml @@ -23,20 +23,30 @@ when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" ignore_errors: true -- name: add epel on CentOS 7 - shell: yum -y update - sudo: true - when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" - - - name: install system packages apt - apt: name={{ item }} state=installed update_cache=true force=yes + apt: name={{ item }} state=present update_cache=true force=yes sudo: true with_items: system_packages when: ansible_os_family == 'Debian' +- name: yum group installs + shell: yum -y group install {{ item }} + sudo: true + with_items: system_group_packages + when: system_group_packages is defined + - name: install system packages yum - yum: name={{ item }} state=installed update_cache=yes + yum: name={{ item }} state=present update_cache=yes sudo: true with_items: system_packages when: ansible_os_family == 'RedHat' + +- name: force the use of mate desktop + template: src=vncserver.centos dest=/bin/vncserver + sudo: true + when: ansible_os_family == 'RedHat' + +- name: force the use of mate desktop + template: src=vncserver.ubuntu dest=/usr/bin/vncserver + sudo: true + when: ansible_os_family == 'Debian' diff --git a/roles/vncserver/templates/vncserver.centos b/roles/vncserver/templates/vncserver.centos new file mode 100755 index 0000000000000000000000000000000000000000..e8d71f85521a9931e11c6d72c364cc5349c3d67b --- /dev/null +++ b/roles/vncserver/templates/vncserver.centos @@ -0,0 +1,772 @@ +#!/usr/bin/perl +# +# Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. +# Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. +# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved. +# Copyright (C) 2002-2005 RealVNC Ltd. +# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +# +# vncserver - wrapper script to start an X VNC server. +# + +# +# First make sure we're operating in a sane environment. +# + +$exedir = ""; +$slashndx = rindex($0, "/"); +if($slashndx>=0) { + $exedir = substr($0, 0, $slashndx+1); +} + +$vncClasses = ""; + +$xauth = "xauth"; + +&SanityCheck(); + +# +# Global variables. You may want to configure some of these for your site. +# + +$geometry = "1024x768"; +#$depth = 16; +$vncJavaFiles = (((-d "$vncClasses") && "$vncClasses") || + ((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") || + ((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes")); + +$vncUserDir = "$ENV{HOME}/.vnc"; +$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority"; + +$defaultXStartup + = ("#!/bin/sh\n\n". + "unset SESSION_MANAGER\n". + "unset DBUS_SESSION_BUS_ADDRESS\n". + "exec mate-session\n"); + +chop($host = `uname -n`); + +if (-d "/etc/X11/fontpath.d") { + $fontPath = "catalogue:/etc/X11/fontpath.d"; +} + +@fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/'); +if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');} +if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');} +if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');} +push(@fontpaths, '/usr/share/fonts/default'); + +@fonttypes = ('misc', + '75dpi', + '100dpi', + 'Speedo', + 'Type1'); + +foreach $_fpath (@fontpaths) { + foreach $_ftype (@fonttypes) { + if (-f "$_fpath/$_ftype/fonts.dir") { + if (! -l "$_fpath/$_ftype") { + $defFontPath .= "$_fpath/$_ftype,"; + } + } + } +} + +if ($defFontPath) { + if (substr($defFontPath, -1, 1) == ',') { + chop $defFontPath; + } +} + +if ($fontPath eq "") { + $fontPath = $defFontPath; +} + +# Check command line options + +&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, + "-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0); + +&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); + +&Kill() if ($opt{'-kill'}); + +&List() if ($opt{'-list'}); + +# Uncomment this line if you want default geometry, depth and pixelformat +# to match the current X display: +# &GetXDisplayDefaults(); + +if ($opt{'-geometry'}) { + $geometry = $opt{'-geometry'}; +} +if ($opt{'-depth'}) { + $depth = $opt{'-depth'}; + $pixelformat = ""; +} +if ($opt{'-pixelformat'}) { + $pixelformat = $opt{'-pixelformat'}; +} +if ($opt{'-fp'}) { + $fontPath = $opt{'-fp'}; + $fpArgSpecified = 1; +} + +&CheckGeometryAndDepth(); + + +# Create the user's vnc directory if necessary. + +if (!(-e $vncUserDir)) { + if (!mkdir($vncUserDir,0755)) { + die "$prog: Could not create $vncUserDir.\n"; + } +} + +# Check whether VNC authentication is enabled, and if so, prompt the user to +# create a VNC password if they don't already have one. + +$securityTypeArgSpecified = 0; +$vncAuthEnabled = 0; +$passwordArgSpecified = 0; + +for ($i = 0; $i < @ARGV; ++$i) { + # -SecurityTypes can be followed by a space or "=" + my @splitargs = split('=', $ARGV[$i]); + if (@splitargs <= 1 && $i < @ARGV - 1) { + push(@splitargs, $ARGV[$i + 1]); + } + if (lc(@splitargs[0]) eq "-securitytypes") { + if (@splitargs > 1) { + $securityTypeArgSpecified = 1; + } + foreach $arg2 (split(',', @splitargs[1])) { + if (lc($arg2) eq "vncauth" || lc($arg2) eq "tlsvnc" + || lc($arg2) eq "x509vnc") { + $vncAuthEnabled = 1; + } + } + } + if ((lc(@splitargs[0]) eq "-password") + || (lc(@splitargs[0]) eq "-passwordfile" + || (lc(@splitargs[0]) eq "-rfbauth"))) { + $passwordArgSpecified = 1; + } +} + +if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) { + ($z,$z,$mode) = stat("$vncUserDir/passwd"); + if (!(-e "$vncUserDir/passwd") || ($mode & 077)) { + warn "\nYou will require a password to access your desktops.\n\n"; + system($exedir."vncpasswd -q $vncUserDir/passwd"); + if (($? >> 8) != 0) { + exit 1; + } + } +} + +# Find display number. + +if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { + $displayNumber = $1; + shift(@ARGV); + if (!&CheckDisplayNumber($displayNumber)) { + die "A VNC server is already running as :$displayNumber\n"; + } +} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) { + &Usage(); +} else { + $displayNumber = &GetDisplayNumber(); +} + +$vncPort = 5900 + $displayNumber; + +$desktopLog = "$vncUserDir/$host:$displayNumber.log"; +unlink($desktopLog); + +# Make an X server cookie - use mcookie +$cookie = `/usr/bin/mcookie`; +open (XAUTH, "|xauth -f $xauthorityFile source -"); +print XAUTH "add $host:$displayNumber . $cookie\n"; +print XAUTH "add $host/unix:$displayNumber . $cookie\n"; +close XAUTH; + +if ($opt{'-name'}) { + $desktopName = $opt{'-name'}; +} else { + $desktopName = "$host:$displayNumber ($ENV{USER})"; +} + +# Now start the X VNC Server + +$cmd = $exedir."Xvnc :$displayNumber"; +$cmd .= " -desktop " . "edString($desktopName); +$cmd .= " -httpd $vncJavaFiles" if ($vncJavaFiles); +$cmd .= " -auth $xauthorityFile"; +$cmd .= " -geometry $geometry" if ($geometry); +$cmd .= " -depth $depth" if ($depth); +$cmd .= " -pixelformat $pixelformat" if ($pixelformat); +$cmd .= " -rfbwait 30000"; +$cmd .= " -rfbauth $vncUserDir/passwd"; +$cmd .= " -rfbport $vncPort"; +$cmd .= " -fp $fontPath" if ($fontPath); +$cmd .= " -pn"; + +# Add color database stuff here, e.g.: +# +# $cmd .= " -co /usr/lib/X11/rgb"; +# + +foreach $arg (@ARGV) { + $cmd .= " " . "edString($arg); +} +$cmd .= " >> " . "edString($desktopLog) . " 2>&1"; + +# Run $cmd and record the process ID. + +$pidFile = "$vncUserDir/$host:$displayNumber.pid"; +system("$cmd & echo \$! >$pidFile"); + +# Give Xvnc a chance to start up + +sleep(3); +if ($fontPath ne $defFontPath) { + unless (kill 0, `cat $pidFile`) { + if ($fpArgSpecified) { + warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n"; + warn "path you specified using the -fp argument is incorrect. Attempting to\n"; + warn "determine an appropriate font path for this system and restart Xvnc using\n"; + warn "that font path ...\n"; + } else { + warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n"; + warn "catalog is not properly configured. Attempting to determine an appropriate\n"; + warn "font path for this system and restart Xvnc using that font path ...\n"; + } + $cmd =~ s@-fp [^ ]+@@; + $cmd .= " -fp $defFontPath" if ($defFontPath); + system("$cmd & echo \$! >$pidFile"); + sleep(3); + } +} +unless (kill 0, `cat $pidFile`) { + warn "Could not start Xvnc.\n\n"; + open(LOG, "<$desktopLog"); + while (<LOG>) { print; } + close(LOG); + die "\n"; +} + +warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; + +# Create the user's xstartup script if necessary. + +if (!(-e "$vncUserDir/xstartup")) { + warn "Creating default startup script $vncUserDir/xstartup\n"; + open(XSTARTUP, ">$vncUserDir/xstartup"); + print XSTARTUP $defaultXStartup; + close(XSTARTUP); + chmod 0755, "$vncUserDir/xstartup"; +} + +# Run the X startup script. + +warn "Starting applications specified in $vncUserDir/xstartup\n"; +warn "Log file is $desktopLog\n\n"; + +# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use +# TCP (DISPLAY=host:n) + +if (-e "/tmp/.X11-unix/X$displayNumber" || + -e "/usr/spool/sockets/X11/$displayNumber") +{ + $ENV{DISPLAY}= ":$displayNumber"; +} else { + $ENV{DISPLAY}= "$host:$displayNumber"; +} +$ENV{VNCDESKTOP}= $desktopName; + +system($exedir."vncconfig -iconic >> " . "edString($desktopLog) . " 2>&1 &"); + +if ($opt{'-fg'}) { + system("$vncUserDir/xstartup >> " . "edString($desktopLog) . " 2>&1"); + if (kill 0, `cat $pidFile`) { + $opt{'-kill'} = ':'.$displayNumber; + &Kill(); + } +} else { + if ($opt{'-autokill'}) { + system("($vncUserDir/xstartup; $0 -kill :$displayNumber) >> " + . "edString($desktopLog) . " 2>&1 &"); + } else { + system("$vncUserDir/xstartup >> " . "edString($desktopLog) + . " 2>&1 &"); + } +} + +exit; + + +############################################################################### +# +# CheckGeometryAndDepth simply makes sure that the geometry and depth values +# are sensible. +# + +sub CheckGeometryAndDepth +{ + if ($geometry =~ /^(\d+)x(\d+)$/) { + $width = $1; $height = $2; + + if (($width<1) || ($height<1)) { + die "$prog: geometry $geometry is invalid\n"; + } + + $geometry = "${width}x$height"; + } else { + die "$prog: geometry $geometry is invalid\n"; + } + + if ($depth && (($depth < 8) || ($depth > 32))) { + die "Depth must be between 8 and 32\n"; + } +} + + +# +# GetDisplayNumber gets the lowest available display number. A display number +# n is taken if something is listening on the VNC server port (5900+n) or the +# X server port (6000+n). +# + +sub GetDisplayNumber +{ + foreach $n (1..99) { + if (&CheckDisplayNumber($n)) { + return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02 + } + } + + die "$prog: no free display number on $host.\n"; +} + + +# +# CheckDisplayNumber checks if the given display number is available. A +# display number n is taken if something is listening on the VNC server port +# (5900+n) or the X server port (6000+n). +# + +sub CheckDisplayNumber +{ + local ($n) = @_; + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) { + close(S); + return 0; + } + close(S); + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) { + close(S); + return 0; + } + close(S); + + if (-e "/tmp/.X$n-lock") { + warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + if (-e "/tmp/.X11-unix/X$n") { + warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + if (-e "/usr/spool/sockets/X11/$n") { + warn("\nWarning: $host:$n is taken because of ". + "/usr/spool/sockets/X11/$n\n"); + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + return 1; +} + + +# +# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel +# format of the current X display being used. If successful, it sets the +# options as appropriate so that the X VNC server will use the same settings +# (minus an allowance for window manager decorations on the geometry). Using +# the same depth and pixel format means that the VNC server won't have to +# translate pixels when the desktop is being viewed on this X display (for +# TrueColor displays anyway). +# + +sub GetXDisplayDefaults +{ + local (@lines, @matchlines, $width, $height, $defaultVisualId, $i, + $red, $green, $blue); + + $wmDecorationWidth = 4; # a guess at typical size for window manager + $wmDecorationHeight = 24; # decoration size + + return if (!defined($ENV{DISPLAY})); + + @lines = `xdpyinfo 2>/dev/null`; + + return if ($? != 0); + + @matchlines = grep(/dimensions/, @lines); + if (@matchlines) { + ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/); + + $width -= $wmDecorationWidth; + $height -= $wmDecorationHeight; + + $geometry = "${width}x$height"; + } + + @matchlines = grep(/default visual id/, @lines); + if (@matchlines) { + ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/); + + for ($i = 0; $i < @lines; $i++) { + if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) { + if (($lines[$i+1] !~ /TrueColor/) || + ($lines[$i+2] !~ /depth/) || + ($lines[$i+4] !~ /red, green, blue masks/)) + { + return; + } + last; + } + } + + return if ($i >= @lines); + + ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/); + ($red,$green,$blue) + = ($lines[$i+4] + =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/); + + $red = hex($red); + $green = hex($green); + $blue = hex($blue); + + if ($red > $blue) { + $red = int(log($red) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($blue) / log(2)); + $blue = int(log($blue) / log(2)) + 1; + $pixelformat = "rgb$red$green$blue"; + } else { + $blue = int(log($blue) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($red) / log(2)); + $red = int(log($red) / log(2)) + 1; + $pixelformat = "bgr$blue$green$red"; + } + } +} + + +# +# quotedString returns a string which yields the original string when parsed +# by a shell. +# + +sub quotedString +{ + local ($in) = @_; + + $in =~ s/\'/\'\"\'\"\'/g; + + return "'$in'"; +} + + +# +# removeSlashes turns slashes into underscores for use as a file name. +# + +sub removeSlashes +{ + local ($in) = @_; + + $in =~ s|/|_|g; + + return "$in"; +} + + +# +# Usage +# + +sub Usage +{ + die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n". + " [-geometry <width>x<height>]\n". + " [-pixelformat rgbNNN|bgrNNN]\n". + " [-fp <font-path>]\n". + " [-cc <visual>]\n". + " [-fg]\n". + " [-autokill]\n". + " <Xvnc-options>...\n\n". + " $prog -kill <X-display>\n\n". + " $prog -list\n\n"); +} + + +# +# List +# + +sub List +{ + opendir(dir, $vncUserDir); + my @filelist = readdir(dir); + closedir(dir); + print "\nTigerVNC server sessions:\n\n"; + print "X DISPLAY #\tPROCESS ID\n"; + foreach my $file (@filelist) { + if ($file =~ /$host:(\d+)$\.pid/) { + print ":".$1."\t\t".`cat $vncUserDir/$file`; + } + } + exit 1; +} + + +# +# Kill +# + +sub Kill +{ + $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1 + + if ($opt{'-kill'} =~ /^:\d+$/) { + $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid"; + } else { + if ($opt{'-kill'} !~ /^$host:/) { + die "\nCan't tell if $opt{'-kill'} is on $host\n". + "Use -kill :<number> instead\n\n"; + } + $pidFile = "$vncUserDir/$opt{'-kill'}.pid"; + } + + if (! -r $pidFile) { + die "\nCan't find file $pidFile\n". + "You'll have to kill the Xvnc process manually\n\n"; + } + + $SIG{'HUP'} = 'IGNORE'; + chop($pid = `cat $pidFile`); + warn "Killing Xvnc process ID $pid\n"; + + if (kill 0, $pid) { + system("kill $pid"); + sleep(1); + if (kill 0, $pid) { + print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n"; + print " ".$0." -kill ".$opt{'-kill'}."\n"; + print "to clean up the socket files.\n"; + exit + } + + } else { + warn "Xvnc process ID $pid already killed\n"; + $opt{'-kill'} =~ s/://; + + if (-e "/tmp/.X11-unix/X$opt{'-kill'}") { + print "Xvnc did not appear to shut down cleanly."; + print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n"; + unlink "/tmp/.X11-unix/X$opt{'-kill'}"; + } + if (-e "/tmp/.X$opt{'-kill'}-lock") { + print "Xvnc did not appear to shut down cleanly."; + print " Removing /tmp/.X$opt{'-kill'}-lock\n"; + unlink "/tmp/.X$opt{'-kill'}-lock"; + } + } + + unlink $pidFile; + exit; +} + + +# +# ParseOptions takes a list of possible options and a boolean indicating +# whether the option has a value following, and sets up an associative array +# %opt of the values of the options given on the command line. It removes all +# the arguments it uses from @ARGV and returns them in @optArgs. +# + +sub ParseOptions +{ + local (@optval) = @_; + local ($opt, @opts, %valFollows, @newargs); + + while (@optval) { + $opt = shift(@optval); + push(@opts,$opt); + $valFollows{$opt} = shift(@optval); + } + + @optArgs = (); + %opt = (); + + arg: while (defined($arg = shift(@ARGV))) { + foreach $opt (@opts) { + if ($arg eq $opt) { + push(@optArgs, $arg); + if ($valFollows{$opt}) { + if (@ARGV == 0) { + &Usage(); + } + $opt{$opt} = shift(@ARGV); + push(@optArgs, $opt{$opt}); + } else { + $opt{$opt} = 1; + } + next arg; + } + } + push(@newargs,$arg); + } + + @ARGV = @newargs; +} + + +# +# Routine to make sure we're operating in a sane environment. +# + +sub SanityCheck +{ + local ($cmd); + + # + # Get the program name + # + + ($prog) = ($0 =~ m|([^/]+)$|); + + # + # Check we have all the commands we'll need on the path. + # + + cmd: + foreach $cmd ("uname") { + for (split(/:/,$ENV{PATH})) { + if (-x "$_/$cmd") { + next cmd; + } + } + die "$prog: couldn't find \"$cmd\" on your PATH.\n"; + } + if (-x "/usr/X11R6/bin/xauth") { + $xauth = "/usr/X11R6/bin/xauth"; + } + else { + cmd1: + foreach $cmd ("xauth") { + for (split(/:/,$ENV{PATH})) { + if (-x "$_/$cmd") { + next cmd1; + } + } + die "$prog: couldn't find \"$cmd\" on your PATH.\n"; + } + } + + if($exedir eq "") { + cmd2: + foreach $cmd ("Xvnc","vncpasswd") { + for (split(/:/,$ENV{PATH})) { + if (-x "$_/$cmd") { + $vncClasses = "$_/../vnc/classes"; + next cmd2; + } + } + die "$prog: couldn't find \"$cmd\" on your PATH.\n"; + } + } + else { + cmd3: + foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") { + for (split(/:/,$ENV{PATH})) { + if (-x "$cmd") { + $vncClasses = $exedir."../vnc/classes"; + next cmd3; + } + } + die "$prog: couldn't find \"$cmd\".\n"; + } + } + + # + # Check the HOME environment variable is set + # + + if (!defined($ENV{HOME})) { + die "$prog: The HOME environment variable is not set.\n"; + } +# chdir($ENV{HOME}); + + # + # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an + # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails, + # we just guess at the values. If you find perl moaning here, just + # hard-code the values of AF_INET and SOCK_STREAM. You can find these out + # for your platform by looking in /usr/include/sys/socket.h and related + # files. + # + + chop($os = `uname`); + chop($osrev = `uname -r`); + + eval 'use Socket'; + if ($@) { + eval 'require "sys/socket.ph"'; + if ($@) { + if (($os eq "SunOS") && ($osrev !~ /^4/)) { + $AF_INET = 2; + $SOCK_STREAM = 2; + } else { + $AF_INET = 2; + $SOCK_STREAM = 1; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } +} diff --git a/roles/vncserver/templates/vncserver.ubuntu b/roles/vncserver/templates/vncserver.ubuntu new file mode 100755 index 0000000000000000000000000000000000000000..4f814a5930b82b9ae2be225cdcd5ed1ca86c8c10 --- /dev/null +++ b/roles/vncserver/templates/vncserver.ubuntu @@ -0,0 +1,772 @@ +#!/usr/bin/perl +# +# Copyright (C) 2004-2006,2008-2009 Ola Lundqvist <opal@debian.org> +# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved. +# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +# +# vncserver - wrapper script to start an X VNC server. +# + +# This file was heavily edited by +# Ola Lundqvist <opal@debian.org> +# Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de> +# Clean option by Dirk Eddelbuettel <edd@debian.org> + +# Please report all errors to Debian and not to ORL. + +# +# First make sure we're operating in a sane environment. +# + +&SanityCheck(); + +# +# Global variables. You may want to configure some of these for your site. +# + +$geometry = "1024x768"; +$depth = 24; +$desktopName = "X"; +if (-d "/usr/share/tightvnc-java") { + $vncClasses = "/usr/share/tightvnc-java"; +} +$vncUserDir = "$ENV{HOME}/.vnc"; +#$fontPath = "unix/:7100"; +$authType = "-rfbauth $vncUserDir/passwd"; + +# Here is another example of setting the font path: +# $fontPath = "/usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/"; + +# X colors database path is optional, uncomment and edit to use: +# $colorPath = "/usr/lib/X11/rgb"; + +# You might wish to make your vnc directory under /tmp, to make sure +# passwords are always kept on the local filesystem. To do that, just +# uncomment the line below. Note that in this case Xtightvnc's .Xauthority +# file will be searched in the same $vncUserDir directory by default, +# and $ENV{HOME}/.vncstartup will be executed instead of usual +# $vncUserDir/xstartup. +# +# $vncUserDir = "/tmp/$ENV{USER}-vnc"; + +$defaultXStartup + = ("#!/bin/sh\n\n". + "xrdb \$HOME/.Xresources\n". + "xsetroot -solid grey\n". + "#x-terminal-emulator -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n". + "#x-window-manager &\n". + "# Fix to make GNOME work\n". + "export XKL_XMODMAP_DISABLE=1\n". + "exec mate-session\n"); + +$xauthorityFile = "$ENV{XAUTHORITY}"; + +######## Adding configuration possibility ################ +$Config_file = "/etc/vnc.conf"; +&ReadConfigFile(); +$Config_file = "$ENV{HOME}/.vncrc"; +&ReadConfigFile(); + +if (!$XFConfigPath) { + foreach ("/etc/X11/xorg.conf", "/etc/X11/XF86Config-4", "/etc/X11/XF86Config" ){ + $XFConfigPath = $_; + last if ( -e $XFConfigPath ); + } +} +if (!$fontPath) { + &ReadXFConfigFont; +} +if (!$fontPath) { + $fontPath = "/usr/share/fonts/X11/misc/,". + "/usr/share/fonts/X11/Type1/,". + "/usr/share/fonts/X11/75dpi/,". + "/usr/share/fonts/X11/100dpi/" +} +if (!$colorPath) { + &ReadXFConfigColor; +} +if (!$colorPath) { + foreach ("/etc/X11/rgb", "/usr/share/X11/rgb", "/usr/X11R6/lib/X11/rgb"){ + $colorPath = $_; + last if ( -e "${colorPath}.txt" ); + } +} +########################################################## + +$vncUserDirUnderTmp = ($vncUserDir =~ m|^/tmp/.+|) ? 1 : 0; +$xstartup = ($vncUserDirUnderTmp) ? + "$ENV{HOME}/.vncstartup" : "$vncUserDir/xstartup"; +$xstartup = $vncStartup if ($vncStartup); +unless ($xauthorityFile) { + if ($vncUserDirUnderTmp) { + $xauthorityFile = "$vncUserDir/.Xauthority"; + } else { + $xauthorityFile = "$ENV{HOME}/.Xauthority"; + } +} + +chop($host = `uname -n`); + + +# Check command line options + +&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, + "-help",0,"-h",0,"--help",0, + "-clean",0, "-fp",1, + "-alwaysshared",0, "-nevershared",0, + "-httpport",1,"-basehttpport",1); + +&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); + +&Kill() if ($opt{'-kill'}); + +$useClasses = 0; +if (defined $vncClasses) { + if(! -d $vncClasses) { + die "VNC class files can not be found at $vncClasses."; + } + $useClasses = 1; +} + +# Uncomment this line if you want default geometry, depth and pixelformat +# to match the current X display: +# &GetXDisplayDefaults(); + +if ($opt{'-geometry'}) { + $geometry = $opt{'-geometry'}; +} +if ($opt{'-depth'}) { + $depth = $opt{'-depth'}; + $pixelformat = ""; +} +if ($opt{'-pixelformat'}) { + $pixelformat = $opt{'-pixelformat'}; +} + +if ($opt{'-fp'}) { + @fontPathElements = split(/\s*,\s*/, "$opt{'-fp'}"); + + $fontPath = ''; + + foreach $i (0.."$#fontPathElements") { + $tempFontPath = $fontPathElements[$i]; + if ($tempFontPath !~ m!^[^/]*/[^/]*:\d+$!) { + $tempFontPath =~ s/:unscaled$//; + if (-r "$tempFontPath/fonts.dir") { + $fontPath .= "$fontPathElements[$i],"; + } + } else { + $fontPath .= "$fontPathElements[$i],"; + } + } + chop $fontPath; +} + +&CheckGeometryAndDepth(); + +if ($opt{'-name'}) { + $desktopName = $opt{'-name'}; +} + +# Create the user's vnc directory if necessary. + +unless (-e $vncUserDir) { + unless (mkdir($vncUserDir, 0700)) { + die "$prog: Could not create $vncUserDir.\n"; + } +} +($z,$z,$mode) = stat("$vncUserDir"); +if (!-d _ || !-o _ || ($vncUserDirUnderTmp && ($mode & 0777) != 0700)) { + die "$prog: Wrong type or access mode of $vncUserDir.\n"; +} + +# Make sure the user has a password. + +($z,$z,$mode) = stat("$vncUserDir/passwd"); +if (-e _ && (!-f _ || !-o _)) { + die "$prog: Wrong type or ownership on $vncUserDir/passwd.\n"; +} +if (!-e _ || ($mode & 077) != 0) { + warn "\nYou will require a password to access your desktops.\n\n"; + system("vncpasswd $vncUserDir/passwd"); + if (($? & 0xFF00) != 0) { + exit 1; + } +} + +# Find display number. + +if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { + $displayNumber = $1; + shift(@ARGV); + unless (&CheckDisplayNumber($displayNumber)) { + die "A VNC server is already running as :$displayNumber\n"; + } +} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/)) { + &Usage(); +} else { + $displayNumber = &GetDisplayNumber(); +} + +$vncPort = 5900 + $displayNumber; + +$desktopLog = "$vncUserDir/$host:$displayNumber.log"; +unlink($desktopLog); + +# Make an X server cookie - use as the seed the sum of the current time, our +# PID and part of the encrypted form of the password. Ideally we'd use +# /dev/urandom, but that's only available on Linux. + +srand(time+$$+unpack("L",`cat $vncUserDir/passwd`)); +$cookie = ""; +for (1..16) { + $cookie .= sprintf("%02x", int(rand(256))); +} + +system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie"); +system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie"); + +# Now start the X VNC Server + +$cmd = "Xtightvnc :$displayNumber"; +$cmd .= " -desktop " . "edString($desktopName); +if ($useClasses) { + $cmd .= " -httpd $vncClasses"; + print ("Found $vncClasses for http connections.\n"); + if ($opt{'-httpport'}) { + $cmd .= " -httpport $opt{'-httpport'}"; + print ("Listening to $opt{'-httpport'} for http connections.\n"); + } + elsif ($opt{'-basehttpport'}) { + my $v = $opt{'-basehttpport'} + $displayNumber; + print ("Listening to $v for http connections.\n"); + $cmd .= " -httpport $v"; + } +} +$cmd .= " -auth $xauthorityFile"; +$cmd .= " -geometry $geometry" if ($geometry); +$cmd .= " -depth $depth" if ($depth); +$cmd .= " -pixelformat $pixelformat" if ($pixelformat); +$cmd .= " -rfbwait 120000"; +$cmd .= " $authType"; +$cmd .= " -rfbport $vncPort"; +$cmd .= " -fp $fontPath" if ($fontPath); +$cmd .= " -co $colorPath" if ($colorPath); +$cmd .= " -alwaysshared" if ($opt{'-alwaysshared'}); +$cmd .= " -nevershared" if ($opt{'-nevershared'}); + +foreach $arg (@ARGV) { + $cmd .= " " . "edString($arg); +} +$cmd .= " >> " . "edString($desktopLog) . " 2>&1"; + +# Run $cmd and record the process ID. + +$pidFile = "$vncUserDir/$host:$displayNumber.pid"; +system("$cmd & echo \$! >$pidFile"); + +# Give Xtightvnc a chance to start up + +sleep(1); +unless (kill 0, `cat $pidFile`) { + warn "Couldn't start Xtightvnc; trying default font path.\n"; + warn "Please set correct fontPath in the $prog script.\n"; + $cmd =~ s@-fp [^ ]+@@; + system("$cmd & echo \$! >$pidFile"); + sleep(1); +} +unless (kill 0, `cat $pidFile`) { + warn "Couldn't start Xtightvnc process.\n\n"; + open(LOG, "<$desktopLog"); + while (<LOG>) { print; } + close(LOG); + die "\n"; +} + +warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; + +# Create the user's xstartup script if necessary. + +unless (-e "$xstartup") { + warn "Creating default startup script $xstartup\n"; + open(XSTARTUP, ">$xstartup"); + print XSTARTUP $defaultXStartup; + close(XSTARTUP); + chmod 0755, "$xstartup"; +} + +# Run the X startup script. + +warn "Starting applications specified in $xstartup\n"; +warn "Log file is $desktopLog\n\n"; + +# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use +# TCP (DISPLAY=host:n) + +if (-e "/tmp/.X11-unix/X$displayNumber") { + $ENV{DISPLAY}= ":$displayNumber"; +} else { + $ENV{DISPLAY}= "$host:$displayNumber"; +} +$ENV{VNCDESKTOP}= $desktopName; + +system("$xstartup >> " . "edString($desktopLog) . " 2>&1 &"); + +exit; + +############################ Debian functions ################################# +# I thank Manoj for the code below. +# +# ReadConfigFile reads in a config file and sets variables according to it. +# + +sub ReadConfigFile +{ + open(CONFIG, "$Config_file") || return; + my $lineno = 0; + while (<CONFIG>) { + chomp; + $lineno++; + s/\#.*//og; + next if /^\s*$/og; + $_ .= ";" unless /;\s*$/; + if (/^\s*([^=]+)\s*=\s*(\S.*)$/o) { + my $ret = eval "$1=$2"; + if ($@) { + print STDERR "Error parsing config file $Config_file!\n"; + print STDERR "$lineno:$_\n"; + } + } + } +} + +sub ReadXFConfigFont +{ + open(CONFIG, "$XFConfigPath") || return; + my $lineno = 0; + while (<CONFIG>) { + chomp; + $lineno++; + s/\#.*//og; + next if /^\s*$/og; + if (/^\s*FontPath\s*"(\S.*)"\s*$/o) { + $fontPath .= "," if $fontPath; + $fontPath .= $1; + } + } +} + +sub ReadXFConfigColor +{ + open(CONFIG, "$XFConfigPath") || return; + my $lineno = 0; + while (<CONFIG> && !$colorPath) { + chomp; + $lineno++; + s/\#.*//og; + next if /^\s*$/og; + if (/^\s*RgbPath\s*"(\S.*)"\s*$/o) { + $colorPath = $1; + } + } +} + + +########## End of debian functions ########### + +############################################################################### +# +# CheckGeometryAndDepth simply makes sure that the geometry and depth values +# are sensible. +# + +sub CheckGeometryAndDepth +{ + if ($geometry =~ /^(\d+)x(\d+)$/) { + $width = $1; $height = $2; + + if (($width<1) || ($height<1)) { + die "$prog: geometry $geometry is invalid\n"; + } + + while (($width % 4)!=0) { + $width = $width + 1; + } + + while (($height % 2)!=0) { + $height = $height + 1; + } + + $geometry = "${width}x$height"; + } else { + die "$prog: geometry $geometry is invalid\n"; + } + + if (($depth < 8) || ($depth > 32)) { + die "Depth must be between 8 and 32\n"; + } +} + + +# +# GetDisplayNumber gets the lowest available display number. A display number +# n is taken if something is listening on the VNC server port (5900+n) or the +# X server port (6000+n). +# + +sub GetDisplayNumber +{ + foreach $n (1..99) { + if (&CheckDisplayNumber($n)) { + return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02 + } + } + + die "$prog: no free display number on $host.\n"; +} + + +# +# CheckDisplayNumber checks if the given display number is available. A +# display number n is taken if something is listening on the VNC server port +# (5900+n) or the X server port (6000+n). +# + +sub CheckDisplayNumber +{ + local ($n) = @_; + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + #unless (bind(S, pack('S n x12', $AF_INET, 6000 + $n))) { + unless (bind(S, sockaddr_in(6000 + $n, &INADDR_ANY))) { + close(S); + return 0; + } + close(S); + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + #unless (bind(S, pack('S n x12', $AF_INET, 5900 + $n))) { + unless (bind(S, sockaddr_in(5900 + $n, &INADDR_ANY))) { + close(S); + return 0; + } + close(S); + + if (-e "/tmp/.X$n-lock") { + warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + if (-e "/tmp/.X11-unix/X$n") { + warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + return 1; +} + + +# +# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel +# format of the current X display being used. If successful, it sets the +# options as appropriate so that the X VNC server will use the same settings +# (minus an allowance for window manager decorations on the geometry). Using +# the same depth and pixel format means that the VNC server won't have to +# translate pixels when the desktop is being viewed on this X display (for +# TrueColor displays anyway). +# + +sub GetXDisplayDefaults +{ + local (@lines, @matchlines, $width, $height, $defaultVisualId, $i, + $red, $green, $blue); + + $wmDecorationWidth = 4; # a guess at typical size for window manager + $wmDecorationHeight = 24; # decoration size + + return unless (defined($ENV{DISPLAY})); + + @lines = `xdpyinfo 2>/dev/null`; + + return if ($? != 0); + + @matchlines = grep(/dimensions/, @lines); + if (@matchlines) { + ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/); + + $width -= $wmDecorationWidth; + $height -= $wmDecorationHeight; + + $geometry = "${width}x$height"; + } + + @matchlines = grep(/default visual id/, @lines); + if (@matchlines) { + ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/); + + for ($i = 0; $i < @lines; $i++) { + if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) { + if (($lines[$i+1] !~ /TrueColor/) || + ($lines[$i+2] !~ /depth/) || + ($lines[$i+4] !~ /red, green, blue masks/)) + { + return; + } + last; + } + } + + return if ($i >= @lines); + + ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/); + ($red,$green,$blue) + = ($lines[$i+4] + =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/); + + $red = hex($red); + $green = hex($green); + $blue = hex($blue); + + if ($red > $blue) { + $red = int(log($red) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($blue) / log(2)); + $blue = int(log($blue) / log(2)) + 1; + $pixelformat = "rgb$red$green$blue"; + } else { + $blue = int(log($blue) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($red) / log(2)); + $red = int(log($red) / log(2)) + 1; + $pixelformat = "bgr$blue$green$red"; + } + } +} + + +# +# quotedString returns a string which yields the original string when parsed +# by a shell. +# + +sub quotedString +{ + local ($in) = @_; + + $in =~ s/\'/\'\"\'\"\'/g; + + return "'$in'"; +} + + +# +# removeSlashes turns slashes into underscores for use as a file name. +# + +sub removeSlashes +{ + local ($in) = @_; + + $in =~ s|/|_|g; + + return "$in"; +} + + +# +# Usage +# + +sub Usage +{ + die("TightVNC Server version 1.3.9\n". + "\n". + "Usage: $prog [<OPTIONS>] [:<DISPLAY#>]\n". + " $prog -kill :<DISPLAY#>\n". + "\n". + "<OPTIONS> are Xtightvnc options, or:\n". + "\n". + " -name <DESKTOP-NAME>\n". + " -depth <DEPTH>\n". + " -geometry <WIDTH>x<HEIGHT>\n". + " -httpport number\n". + " -basehttpport number\n". + " -alwaysshared\n". + " -nevershared\n". + " -pixelformat rgb<NNN>\n". + " -pixelformat bgr<NNN>\n". + "\n". + "See vncserver and Xtightvnc manual pages for more information.\n"); +} + + +# +# Kill +# + +sub Kill +{ + $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1 + + if ($opt{'-kill'} =~ /^:\d+$/) { + $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid"; + } else { + if ($opt{'-kill'} !~ /^$host:/) { + die "\nCan't tell if $opt{'-kill'} is on $host\n". + "Use -kill :<number> instead\n\n"; + } + $pidFile = "$vncUserDir/$opt{'-kill'}.pid"; + } + + unless (-r $pidFile) { + die "\nCan't find file $pidFile\n". + "You'll have to kill the Xtightvnc process manually\n\n"; + } + + $SIG{'HUP'} = 'IGNORE'; + chop($pid = `cat $pidFile`); + warn "Killing Xtightvnc process ID $pid\n"; + system("kill $pid"); + unlink $pidFile; + + ## If option -clean is given, also remove the logfile + unlink "$vncUserDir/$host$opt{'-kill'}.log" if ($opt{'-clean'}); + + exit; +} + + +# +# ParseOptions takes a list of possible options and a boolean indicating +# whether the option has a value following, and sets up an associative array +# %opt of the values of the options given on the command line. It removes all +# the arguments it uses from @ARGV and returns them in @optArgs. +# + +sub ParseOptions +{ + local (@optval) = @_; + local ($opt, @opts, %valFollows, @newargs); + + while (@optval) { + $opt = shift(@optval); + push(@opts,$opt); + $valFollows{$opt} = shift(@optval); + } + + @optArgs = (); + %opt = (); + + arg: while (defined($arg = shift(@ARGV))) { + foreach $opt (@opts) { + if ($arg eq $opt) { + push(@optArgs, $arg); + if ($valFollows{$opt}) { + if (@ARGV == 0) { + &Usage(); + } + $opt{$opt} = shift(@ARGV); + push(@optArgs, $opt{$opt}); + } else { + $opt{$opt} = 1; + } + next arg; + } + } + push(@newargs,$arg); + } + + @ARGV = @newargs; +} + + +# +# Routine to make sure we're operating in a sane environment. +# + +sub SanityCheck +{ + local ($cmd); + + # + # Get the program name + # + + ($prog) = ($0 =~ m|([^/]+)$|); + + # + # Check we have all the commands we'll need on the path. + # + + cmd: + foreach $cmd ("uname","xauth","Xtightvnc","vncpasswd") { + for (split(/:/,$ENV{PATH})) { + if (-x "$_/$cmd") { + next cmd; + } + } + die "$prog: couldn't find \"$cmd\" on your PATH.\n"; + } + + # + # Check the HOME and USER environment variables are both set. + # + + unless (defined($ENV{HOME})) { + die "$prog: The HOME environment variable is not set.\n"; + } + unless (defined($ENV{USER})) { + die "$prog: The USER environment variable is not set.\n"; + } + + # + # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an + # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails, + # we just guess at the values. If you find perl moaning here, just + # hard-code the values of AF_INET and SOCK_STREAM. You can find these out + # for your platform by looking in /usr/include/sys/socket.h and related + # files. + # + + chop($os = `uname`); + chop($osrev = `uname -r`); + + eval 'use Socket'; + if ($@) { + eval 'require "sys/socket.ph"'; + if ($@) { + if (($os eq "SunOS") && ($osrev !~ /^4/)) { + $AF_INET = 2; + $SOCK_STREAM = 2; + } else { + $AF_INET = 2; + $SOCK_STREAM = 1; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } +} diff --git a/roles/vncserver/vars/CentOS_7_x86_64.yml b/roles/vncserver/vars/CentOS_7_x86_64.yml index a32cb14e36f1f43d0c50c2dc3aeacb6e5b1562c7..0880aa2776c71ada625cd7f9b36dd9e5c57cf042 100644 --- a/roles/vncserver/vars/CentOS_7_x86_64.yml +++ b/roles/vncserver/vars/CentOS_7_x86_64.yml @@ -1,8 +1,6 @@ --- system_packages: - - "@Desktop" - tigervnc-server - - "@xfce" - libXcomposite - libXdamage - mesa-libEGL @@ -12,5 +10,11 @@ - graphite2 - xterm - libpng - - "@mate-desktop-environment" - #- "@MATE Desktop" + - xorg-x11-fonts-100dpi + - xorg-x11-fonts-75dpi + - xorg-x11-fonts-misc + + system_group_packages: + - "mate-desktop-environment" + - "graphical-server-environment" + diff --git a/roles/vncserver/vars/Ubuntu_x86_64.yml b/roles/vncserver/vars/Ubuntu_x86_64.yml index 780918f1c38e3ab65fa0f681010a4b103e1ee15b..3b5b3eb4a3ac0798fa1f8973c61812f5afd0defd 100644 --- a/roles/vncserver/vars/Ubuntu_x86_64.yml +++ b/roles/vncserver/vars/Ubuntu_x86_64.yml @@ -1,5 +1,6 @@ --- system_packages: - tightvncserver - - xfce4-session - - xfwm4 + - ubuntu-mate-desktop +# - xfce4-session +# - xfwm4