CentOS7でのOpenPBSの設定

[CentOSでのTorqueの設定 - Qiita](https://qiita.com/Yasushi-Shinohara/items/bd1218c79724f042d878)では数ノードのホストに対するジョブスケジューラーとして、Torqueを用いた構成を試みた。メンテナンスがされているTorqueは最早オープンソースではなくなった([TORQUE - Wikipedia](https://en.wikipedia.org/wiki/TORQUE))ので、他のスケジューラーとして、OpenPBSの導入をすることにした。
以下の導入で念頭に置いているのは[CentOS7(研究室内新設サーバー)の設定メモ - Qiita](https://qiita.com/Yasushi-Shinohara/items/d38e80cc95c8a29bd1b2)で作っている、NISでユーザーを共有し、NFSで/home, /optを共有したホスト群。

以下の環境構築では、OpenPBSのサーバー、クライアント、ともにCentOS Linux release 7.9.2009 (Core)を用いた。

参考にしたサイト:
[ジョブスケジューラPBSProでGPU計算クラスタを組みAIを効率的に学習させる方法 (前編) - Qiita](https://qiita.com/MasafumiTsuyuki/items/acf4b19b54937496e32b)
[自作クラスタ計算機:pbs_proの基本設定　[コンピュータ関係の雑多な記録]](http://www2.yukawa.kyoto-u.ac.jp/~koudai.sugimoto/dokuwiki/doku.php?id=%E8%87%AA%E4%BD%9C%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E8%A8%88%E7%AE%97%E6%A9%9F:pbs_pro%E3%81%AE%E5%9F%BA%E6%9C%AC%E8%A8%AD%E5%AE%9A)
[Altair PBS Works | Support and Documentation](https://www.altair.com/pbs-works-documentation/): 公式ドキュメント

# OpenPBSのサーバーのインストール
## Githubからソースをダウンロード
https://github.com/openpbs/openpbs/releases
v20.0.1が最新版。ここでは、ダウンロードしたファイルが”v20.0.1.tar.gz”として話を進める。

## 準備
以下の内容を実行(ソースコードを展開したディレクトリにある`INSTALL`ファイルにある記載から):

```terminal
   yum install -y gcc make rpm-build libtool hwloc-devel \
      libX11-devel libXt-devel libedit-devel libical-devel \
      ncurses-devel perl postgresql-devel postgresql-contrib python3-devel tcl-devel \
      tk-devel swig expat-devel openssl-devel libXext libXft \
      autoconf automake
```
```terminal
yum install -y expat libedit postgresql-server postgresql-contrib python3 \
      sendmail sudo tcl tk libical
```

## インストール用ディレクトリの作成
`mkdir /opt/openpbs-20.0.1`を実行。

## ソースの展開

```terminal
tar -zxvf openpbs-20.0.1.tar.gz
cd ./openpbs-20.0.1
```

## configure, make, make install

```terminal
./autogen.sh
./configure --prefix=/opt/openpbs-20.0.1
make
make install
```

## ポストインストールプロセス
`/opt/openpbs-20.0.1/libexec/pbs_postinstall`を実行。

## `/etc/pbs.conf`の編集
サーバーがクライアントも兼ねる構成にするために、“PBS_START_MOM=0”の個所を”PBS_START_MOM=1”に変更。例えば、サーバーでの設定は以下のような感じ。

```:pbs.conf
PBS_SERVER=hoge000
PBS_START_SERVER=1
PBS_START_SCHED=1
PBS_START_COMM=1
PBS_START_MOM=1 #PBSサーバーも計算を実行する仕様
PBS_EXEC=/opt/openpbs-20.0.1
PBS_HOME=/var/spool/pbs
PBS_CORE_LIMIT=unlimited
PBS_SCP=/bin/scp
```

## パーミションの変更 
```terminal
chmod 4755 /opt/openpbs-20.0.1/sbin/pbs_iff
chmod 4755 /opt/openpbs-20.0.1/sbin/pbs_rcp
```

## デーモンの起動
`/etc/init.d/pbs start`の実行

## PATH等の環境設定
`source /etc/profile.d/pbs.sh`を実行。ルートだけでなく、一般ユーザーでも実行。

## 正しく導入されているのかの確認
`qmgr -c 'p s'`の出力

```terminal
#
# Create queues and set their attributes.
#
#
# Create and define queue workq
#
create queue workq
set queue workq queue_type = Execution
set queue workq enabled = True
set queue workq started = True
#
# Set server attributes.
#
set server scheduling = True
set server default_queue = workq
set server log_events = 511
set server mail_from = adm
set server query_other_jobs = True
set server resources_default.ncpus = 1
set server default_chunk.ncpus = 1
set server scheduler_iteration = 600
set server resv_enable = True
set server node_fail_requeue = 310
set server max_array_size = 10000
set server pbs_license_min = 0
set server pbs_license_max = 2147483647
set server pbs_license_linger_time = 31536000
set server eligible_time_enable = False
set server job_history_enable = True
set server max_concurrent_provision = 5
set server max_job_sequence_id = 9999999
```

`qstat -B`の出力

```terminal
Server             Max   Tot   Que   Run   Hld   Wat   Trn   Ext Status
---------------- ----- ----- ----- ----- ----- ----- ----- ----- -----------
hoge000             0     0     0     0     0     0     0     0 Active
```
`pbsnodes -a`の出力

```terminal:
hoge000
     Mom = hoge000
     ntype = PBS
     state = free
     pcpus = 28
     resources_available.arch = linux
     resources_available.host = hoge000
     resources_available.mem = 196677228kb
     resources_available.ncpus = 28
     resources_available.vnode = hoge000
     resources_assigned.accelerator_memory = 0kb
     resources_assigned.hbmem = 0kb
     resources_assigned.mem = 0kb
     resources_assigned.naccelerators = 0
     resources_assigned.ncpus = 0
     resources_assigned.vmem = 0kb
     resv_enable = True
     sharing = default_shared
     last_state_change_time = Tue Feb  2 01:00:22 2021
     last_used_time = Fri Jan 29 21:14:31 2021
```

`echo “sleep 60” | qsub` で単純なジョブの実行。(これは一般ユーザーでのみ実行可)

## 終了したジョブの履歴を表示

```console
qmgr -c "set server job_history_enable = True"
```
でジョブの履歴を表示できるようになる。表示するコマンドは

```console
qstat -x
qstat -H
```
のいずれか。

この設定だと2週間がhistoryになる。これを変えたい場合は`qmgr -c "set server job_history_duration=HH:MM:SS"`のようにして、指定。
参考: [[Q] job_history_duration parameter - Users/Site Administrators - OpenPBS](https://community.openpbs.org/t/q-job-history-duration-parameter/1297)
## トラブルシューティング
### ノードや、キューが生成されてない
インストールの過程でノードや、キューが生成されないケースがある。`pbsnodes -a`で”pbsnodes: Server has no node list”が出たり、`echo “sleep 60” | qsub`の所で、”qsub: No default queue specified”が出たり。経験上、rootにならず、管理権限のある一般ユーザーから`sudo`で設定をしているとこれが出る。
以下の一連のコマンドで、ノードとqueue `batch`を追加すればよい。

```terminal
qmgr -c 'create node hoge000'
qmgr -c "create queue batch queue_type=execution"
qmgr -c "set queue batch started=true"
qmgr -c "set queue batch enabled=true"
qmgr -c "set queue batch resources_default.nodes=1"
qmgr -c "set server default_queue=batch"
```
それと、もしかするとどこかでOSのrebootが必要かもしれない。

### `qsub: Bad UID for job execution` が現れる場合
一番軽微な問題は、`qsub`コマンドをrootから実行した場合。
他のケースとして、`/etc/hosts`の自身のホスト名設定が誤っていた場合にこのメッセージが出る。このケースでは、設定を修正ご`service network restart`, `service pbs restart`で解消される。(多分誤ったアドレスで指定されたサーバーに、ジョブをサブミットしたユーザーのアカウントがコンシステントに存在していないため、こうしたエラーを吐いたと考えられる。)

### `module`コマンドを使うと`man`コマンドを実行すると`No manual entry for xxxx`のエラーが出る
`/etc/profile.d/pbs.sh`が起動時に読み込まれ、PATHとMANPATH等の設定が環境変数に読み込まれる。

```bash:pbs.sh(抜粋)
      [ -d "${__PBS_EXEC}/man" ] && export MANPATH="${__PBS_EXEC}/man:${MANPATH}"
      [ -d "${__PBS_EXEC}/share/man" ] && export MANPATH="${__PBS_EXEC}/share/man:${MANPATH}"
```
このスクリプトの実行により、PATH, MANPATHともにopenPBSのpathは、postpendされる。従ってシステム全体の検索pathに引き続いてopenPBSのものが検索されるという、謙虚な設定になっている。具体的には`env`等で確認すると`MANPATH=:/opt/openpbs-20.0.1/share/man`のようになる。
しかし、この状態で`module`コマンドを実行すると、悪い食べ合わせが起こる。通常environmental modulesでコンパイラやアプリケーションの設定を済ませる場合、システム環境をオーバーライドしたいので、PATH, MANPATHはprependで追加される。(こうしないと、システムよりも新しい版のコンパイラを呼ぼうとしてpathを通したのに、結局古いものが先に発見され、呼ばれてしまうため。)ここにprependでMANPATHが追加されると、`MANPATH=/new/manpath/sahre/man:/opt/openpbs-20.0.1/share/man`のようになって、システムの検索pathが完全に抜け落ちてしまう。そして、この状態で`man xxxx`とコマンドを実行すると、仮に`xxxx`が正しくインストールされていても、`No manual entry for xxxx`がエラーとして出力されてしまう。
これを解決するための方法が以下の書き換えである:

```bash:pbs.sh(抜粋)
      [ -d "${__PBS_EXEC}/man" ] && export MANPATH="${MANPATH}:${__PBS_EXEC}/man"
      [ -d "${__PBS_EXEC}/share/man" ] && export MANPATH="${MANPATH}:${__PBS_EXEC}/share/man"
```
(元のファイルを消してしまうのは怖いので、もちろん`pbs.sh.org`のようなファイルにコピーを作ってから編集を行った。)こうすると、openPBSのpathはprependになるので、`MANPATH=/opt/openpbs-20.0.1/share/man:`となる。この状態にprependでpathを追加すると`MANPATH=/new/manpath/sahre/man:/opt/openpbs-20.0.1/share/man:`のようになって、システムの検索pathが後置で生き残ることになる。こうなっていれば、`No manual entry for xxxx`が出ることはない。

同じ問題はPATHの方でも起きても良いようなもんだけれど、PATHはシステムの検索pathが大体環境変数に直書きされてるので、`:${SOME_PATH}$`や`${SOME_PATH}:`としなくても良いので、問題になっていないのではないかと思っている。何かトラブルがあったら、また疑うことにする。

# OpenPBSクライアントのインストール
前提として、サーバーとはNISでユーザーアカウントを共有していて、NFSで`hoge000:/home`と`hoge000:/opt`は、それぞれ`hoge001:/home`と`hoge001:/opt`にマウントしている状況を考える。

## 準備―`/etc/pbs.conf`の編集まで: OpenPBSサーバーと一緒
```terminal
   yum install -y gcc make rpm-build libtool hwloc-devel \
      libX11-devel libXt-devel libedit-devel libical-devel \
      ncurses-devel perl postgresql-devel postgresql-contrib python3-devel tcl-devel \
      tk-devel swig expat-devel openssl-devel libXext libXft \
      autoconf automake
```
```terminal
yum install -y expat libedit postgresql-server postgresql-contrib python3 \
      sendmail sudo tcl tk libical
```
共有している`/opt`と被らない個所`/opt_client`に、クライアント用のアプリを入れる。

```terminal
mkdir /opt_hoge001/openpbs-20.0.1
tar -zxvf openpbs-20.0.1.tar.gz
cd ./openpbs-20.0.1
```
```terminal
./autogen.sh
./configure --prefix=/opt_client/openpbs-20.0.1
make
make install
```
```terminal
/opt_client/openpbs-20.0.1/libexec/pbs_postinstall
```

## `/etc/pbs.conf`の編集
クライアントでは、以下のような設定になる

```bash:/etc/pbs.conf
PBS_SERVER=hoge000
PBS_START_SERVER=0
PBS_START_SCHED=0
PBS_START_COMM=0
PBS_START_MOM=1
PBS_EXEC=/opt_client/openpbs-20.0.1
PBS_HOME=/var/spool/pbs
PBS_CORE_LIMIT=unlimited
PBS_SCP=/bin/scp
```

## パーミションの変更とデーモンの起動 (サーバーと同じ)
```terminal
chmod 4755 /opt_client/openpbs-20.0.1/sbin/pbs_iff
chmod 4755 /opt_client/openpbs-20.0.1/sbin/pbs_rcp
/etc/init.d/pbs start
```

## PATH等の環境設定
`source /etc/profile.d/pbs.sh`を実行。ルートだけでなく、一般ユーザーでも実行。

## 計算ノードの追加
**PBSサーバー**で`qmgr -c "create node hoge001"`の実行でノード`hoge001`が追加できる。ここで`pbsnodes -a`を実行すると

```terminal
hoge000
     Mom = hoge000
     ntype = PBS
     state = free
     pcpus = 28
     resources_available.arch = linux
     resources_available.host = hoge000
     resources_available.mem = 196677228kb
     resources_available.ncpus = 28
     resources_available.vnode = hoge000
     resources_assigned.accelerator_memory = 0kb
     resources_assigned.hbmem = 0kb
     resources_assigned.mem = 0kb
     resources_assigned.naccelerators = 0
     resources_assigned.ncpus = 0
     resources_assigned.vmem = 0kb
     resv_enable = True
     sharing = default_shared
     last_state_change_time = Fri Feb 26 01:31:26 2021
     last_used_time = Fri Jan 29 21:14:31 2021

hoge001
     Mom = hoge001
     ntype = PBS
     state = free
     pcpus = 40
     resources_available.arch = linux
     resources_available.host = hoge001
     resources_available.mem = 528062676kb
     resources_available.ncpus = 40
     resources_available.vnode = hoge001
     resources_assigned.accelerator_memory = 0kb
     resources_assigned.hbmem = 0kb
     resources_assigned.mem = 0kb
     resources_assigned.naccelerators = 0
     resources_assigned.ncpus = 0
     resources_assigned.vmem = 0kb
     resv_enable = True
     sharing = default_shared
     last_state_change_time = Fri Feb 26 01:31:22 2021
```
くらいまでは、特別に他に指定しなくても、設定された。
PBSクライアント実行したら、以下のようなエラーで実行できなかった。

```terminal
qmgr obj=hoge002 svr=default: Unauthorized Request 
qmgr: Error (15007) returned from server
```

## 正しく導入されているのかの確認
```terminal
echo "sleep 60; hostname; echo done" | qsub -l select=host=hoge000
echo "sleep 60; hostname; echo done" | qsub -l select=host=hoge001
```
を実行して、`qstat -s`を実行すると下記の表示を得る

```terminal
hoge000:
                                                            Req'd  Req'd   Elap
Job ID          Username Queue    Jobname    SessID NDS TSK Memory Time  S Time
--------------- -------- -------- ---------- ------ --- --- ------ ----- - -----
13.hoge000      shinoha* workq    STDIN      150541   1   1    --    --  R 00:00
   Job run at Fri Feb 26 at 01:39 on (hoge000:ncpus=1)
14.hoge000      shinoha* workq    STDIN       10422   1   1    --    --  R 00:00
   Job run at Fri Feb 26 at 01:39 on (hoge001:ncpus=1)
```
標準出力のSTDIN.o13とSTDin.o14を確認すると、それぞれ`hoge000.localdomain done`, `hoge001.localdomain done`が得られていた。

# よく使うコマンド

```console
pbsnodes -a
pbsnodes -aS
qmgr -c "p s"
```

# コメント
## ホスト間のssh経由でのログインにパスワードが必要だがジョブは問題なく実行される
NISでユーザーの共有を行っているにしても、基本的にOpenPBSでは、別ホストのクライアントでの計算にはsshでログインをして、そこでジョブの実行コマンドを展開しているのだと理解していた。この理解だと、ホスト間のユーザー認証にパスワードが必要な場合は、どこかしらでパスワードの入力が要求されるか、あるいはエラーを吐いて停止する挙動になると想定していた。構築した環境では、ひとまずパスワード認証をホスト間でしていて、NISでユーザーを共有しているホスト間でもsshでのログインにパスワードが求められる。(つまり、空のパスフレーズを設定した鍵認証の設定はしていない)
当初の期待では、この設定のままではqsubでジョブを投入しても、同一ホストのサーバー兼クランとで流れる場合は問題がなく(これはクライアントを足す前に確認済み)、異なるホストのクライアントでは計算がエラーで停止すると考えていた。しかし、計算は問題なく実行されていた。実際にクライアントにパスワード認証でログインして、topコマンドで消費リソースも確認して、実際のそのホストで計算が流れていることは確認している。これがうまくいく理由はよくわかっていない。

MPIまわりなどで、ホスト間の認証にはパスフレーズなしの鍵認証などの設定をしておかないと、うまく計算が流れないということは目にするので、ホスト間に渡ったMPIの実行をしようとしたら、問題になるかも。

## NFS+NISでのscp => cp の処理が必要なかった
いくつかの記事を見ると、NFSでファイルを共有している場合はscpではなく、cpが使えるため、以下のような設定にする必要がある旨がみつかる。しかし、私の環境ではこれは必要なかった。ファイルもサーバーから投入したジョブの結果は問題なく期待した場所に書き込まれている。

```:/var/spool/pbs/mom_priv/config
$clienthost hoge000
$restrict_user_maxsysid 999
$usecp *:/home/ /home/
```


# サンプルスクリプト

```bash:calc.sh
#!/bin/bash
#PBS -l select=host=hoge001:ncpus=20

cd $PBS_O_WORKDIR

LOG=./log.log

module purge
module load openmpi/4.1.0/intel-2020.4.304
module list &> ${LOG}

export OMP_NUM_THREADS=1

EXE=../src/mATTOHF
IN='"./input.dat"'
mpirun -np 20 ${EXE} <<< ${IN} >> ${LOG}
```

# いくつかの環境変数
```
NCPUS # ncpus=20 で指定した数
```

# トラブルシューティング
## 実行ホストとコンパイルホストのコアの世代が異なることによる問題
AVX-512の命令をサポートしたホストで`ifort -xhost`でコンパイルしたことにより、実行ファイルにAVX-512命令が含まれていた。これをAVX2までの命令しかサポートしていないホストで実行したため、以下のようなエラーが出た。

```
Please verify that both the operating system and the processor support Intel(R)
AVX512F, AVX512DQ, AVX512CD, AVX512BW and AVX512VL instructions.
```
これは`ifort -XCORE-AVX2`のようにAVX2までの命令セットでコンパイルするオプションに変えることでうまくいった。

## エラーメッセージ`qmgr: Error (15066) returned from server`
既にあるnodeと同じ名前を追加しようとすると、このエラーメッセージが返ってくる。
[Create node command - Users/Site Administrators - OpenPBS](https://community.openpbs.org/t/create-node-command/869)

同じ名前のnodeを作りたい場合(例えば同じノード名で古いものを新しいものにリプレースしたとき)は、いったん消す必要がある。
コマンドは

```console
qmgr -c "delete node hoge001"
```

## デーモンの起動ができない
デーモンの起動を行おうとした時に、以下のようなメッセジーが出てデーモンが起動できない。

```terminal
***
*** Invalid local hostname: hoge000
*** This value must resolve to a valid IP address.
***
```

ネットワークで適切にホスト名とアドレスが解決できていない可能性がある。`/etc/hosts`にIPアドレスとホスト名を記載したところ、無事起動できた。

## 急にPBS経由でサービスにつながらなくなる

`qstat`や`pbsnodes -a`等のコマンドを実行すると、以下のメッセージが出て実行できない。特に再起動した直後というわけでもなく、数日前には普通に`qsub`できていた。

```bash
# qsub, qstatした時のエラー
Connection refused
pbsnodes: cannot connect to server hoge000, error=111
# pbsnodes -aした時のエラー
Connection refused
qstat: cannot connect to server hoge000 (errno=111)
```

[Qstat -B : connection refused. qstat cannot connect to server - Users/Site Administrators - OpenPBS](https://community.openpbs.org/t/qstat-b-connection-refused-qstat-cannot-connect-to-server/1855)を確認して、その中であった`/etc/init.d/pbs status`を実行してみると
```bash
pbs_server is not running
pbs_mom is pid 2776
pbs_sched is pid 2789
pbs_comm is 2756
```
となっていて、pbs_serverが死んでいたので、`/etc.init.d/pbs start`でサービスを起動したら無事息を吹き返した。

なぜpbs_serverが突然死していたかはわからないけれど、とりあえずヨシ