7系LinuxにPython3＋OCI CLIをインストールする&2020/2/13以降はOCI CLIがサポートするPythonのバージョンが3.5+になる件

# 1. はじめに

**「最近OCI CLIをアップデートしていないなあ」**と思いながらCLIをアップデート。CLIを実行すると、驚きのメッセージが赤文字で表示！

$ oci iam region list
<font color="red">WARNING: OCI CLI now requires Python 3.5+. Please install or upgrade
 your version of Python to 3.5+ before February 13, 2020 to avoid
 interruption to CLI usage.
</font>

**冷静に考えると、Python 2のサポート期限は2020年3月末まで。**

* [Python 2 series to be retired by April 2020](http://pyfound.blogspot.com/2019/12/python-2-sunset.html)

**Oracle Linux 7のPythonは2.x系。ってことで対応策を調べてみました。**

$ python -V
Python 2.7.5

### 1-1. TL;DR

* 2020/2/13以降、OCI CLIがサポートするPythonのバージョンは3.5+になる
* Pythonの環境構築方法がたくさんある

### 1-2. 対象読者

* Oracle Cloud Infrastructure Compute利用者
* これからOracle Linux 7 / CentOS 7 に**OCI CLI**をインストールする人
* すでにOracle Linux 7 / CentOS 7 で**OCI CLI**を使っていて、Python 3にマイグレーションが必要な人


<font color="red">※8系LinuxやUbuntu、Windows、MacはPython 3なので、この問題は影響しない。</font>

### 1-3. 参考資料

**日本語マニュアル**

* [コマンド・ライン・インタフェース (CLI)](https://docs.oracle.com/cd/E97706_01/Content/API/Concepts/cliconcepts.htm)
* [CLIクイックスタート](https://docs.oracle.com/cd/E97706_01/Content/API/SDKDocs/cliinstall.htm)
* [コマンドライン(CLI)でOCIを操作する - Oracle Cloud Infrastructureアドバンスド](https://community.oracle.com/docs/DOC-1019624#jive_content_id_11_Python)→Windowsの方法
* [OCI CLI を使い倒す（speakerdeck.com）](https://speakerdeck.com/mmarukaw/oci-cli-woshi-idao-su)

**英語マニュアル**

* [Command Line Interface (CLI)](https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm)
* [CLI Quickstart](https://docs.cloud.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm)
* [CLI Requirements](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/cliconcepts.htm#Requirements)


# 2. OCI CLIの環境構築を考える

OCI CLIを使用するにはPython 3が必要だ。しかしPythonの環境構築は多種多様で、利用者にとって悩ましい状況だ。全体像を振り返り、インストール方針を考える。

### 2-1. OCI CLIのインストール方法
OCI CLIのインストール方法は「上記マニュアル」や「次のQiita記事」で数多く紹介されている。微妙に異なるのもあるが、だいたい同じだろう。

* [[Oracle Cloud] OCI IaaS関連情報まとめ](https://qiita.com/feifo/items/551a8a4250f83e4c33c3)

### 2-2. Pythonの環境構築問題

問題はPythonの環境構築だ。そもそもOracle Linux 7 / CentOS 7でPython 3を使用する方法が複数あり、さらにPythonパッケージの管理方法も複数ある。次の記事を読むとわかるが、きわめて複雑な状況になっている。

* [pythonの環境構築戦争にイラストで終止符をどうやら打てない](https://qiita.com/ganariya/items/1bf870275bad7b5ab506)
* [2020 年の Python パッケージ管理ベストプラクティス](https://qiita.com/sk217/items/43c994640f4843a18dbe)
* [（注意） pyenv-virtualenv と virtualenv は別のプロダクトです](https://qiita.com/masmatsum/items/25bbbf8bd8cd7102c031)

今回はシンプルに考えて、次の条件で絞ってみる。

* RHEL7系ディストリビューションを利用する
* Linuxディストリビューションが提供しているものをなるべく使う

それで考えつくのが以下の方法だ。

* <font color="blue">ディストリビューションの標準リポジトリ</font>
* <font color="blue">ディストリビューションのSoftware Collections</font>
* <font color="blue">EPELリポジトリ</font>

**標準リポジトリにPython 3.xは含まれていないので「Software Collections」か「EPEL」と思っていたら、以下のニュースソースによると7.7以降（2019/8-）は標準リポジトリに含まれるらしい。**

* [Oracle Linux for Python Developers](https://yum.oracle.com/oracle-linux-python.html)
* [python3 support on Red Hat Enterprise Linux 7](https://access.redhat.com/solutions/2353081)※要RHNアカウント
* [CentOS-7 (1908) Release Notes](https://wiki.centos.org/Manuals/ReleaseNotes/CentOS7.1908?highlight=%28%28Manuals%7CReleaseNotes%7CCentOS7.1908%29%29)

確認すると、以下のように標準リポジトリ（ol7_latest）に含まれている。次章では、これを利用してインストールを試みる。

```shell-session
$ sudo yum list available python3
Loaded plugins: langpacks, ulninfo
Available Packages
python3.i686                 3.6.8-10.0.1.el7                ol7_optional_latest
python3.x86_64               3.6.8-10.0.1.el7                ol7_latest★こっち
```

# 3. Python 3の環境構築

Oracle Linux 7にPython 3をインストールする。それに加えて、Pythonの環境構築に便利な**venv**についても説明する。

<font color="red">OCI CLIは、Pythonの仮想環境を管理する**venv/virtulenv**を内部的に使用している。そのため利用者がインストール時に**venv/virtulenv**を使用する必要はない。</font>

### 3-1. Python 3 のインストール

1. Python 3をインストールする。

```shell-session
$ sudo yum install -y python3
```

2.バージョンを確認すると`2.7.5`のままだ。

```shell-session
$ python -V
Python 2.7.5
```

3.理由は、次のように`python3`というコマンドだからだ。

```shell-session
$ python3 -V
Python 3.6.8
```

4.シンボリックリンクを確認すると以下のとおり。

```shell-session
$ ls -l /usr/bin/py*
-rwxr-xr-x. 1 root root    78 12月  5 10:34 /usr/bin/pydoc
lrwxrwxrwx. 1 root root     8 12月 24 16:08 /usr/bin/pydoc3 -> pydoc3.6
-rwxr-xr-x. 1 root root    78  8月  7 17:04 /usr/bin/pydoc3.6
lrwxrwxrwx. 1 root root     7 12月 24 13:08 /usr/bin/python -> python2
lrwxrwxrwx. 1 root root     9 12月 24 13:08 /usr/bin/python2 -> python2.7
-rwxr-xr-x. 1 root root  7144 12月  5 10:34 /usr/bin/python2.7
lrwxrwxrwx. 1 root root     9 12月 24 16:08 /usr/bin/python3 -> python3.6
-rwxr-xr-x. 2 root root 11336  8月  7 17:04 /usr/bin/python3.6
-rwxr-xr-x. 2 root root 11336  8月  7 17:04 /usr/bin/python3.6m
lrwxrwxrwx. 1 root root    10 12月 24 16:08 /usr/bin/pyvenv -> pyvenv-3.6
-rwxr-xr-x. 1 root root   435  8月  7 17:04 /usr/bin/pyvenv-3.6
```

<font color="red">**注意**
ここで`/usr/bin/python`のリンク先を`python3`に変更してはいけない。なぜならばyumをはじめとする多くのコマンドがPython 2.xに依存しているからだ。シンボリックリンクを張り替えたらトラブルが続出するので気を付けてほしい。</font>

5.rpmパッケージの中身を確認すると以下のとおり。

```shell-session
$ rpm -ql python3
/usr/bin/pydoc3
/usr/bin/pydoc3.6
/usr/bin/python3
/usr/bin/python3.6
/usr/bin/python3.6m
/usr/bin/pyvenv
/usr/bin/pyvenv-3.6
/usr/share/doc/python3-3.6.8
/usr/share/doc/python3-3.6.8/README.rst
/usr/share/licenses/python3-3.6.8
/usr/share/licenses/python3-3.6.8/LICENSE
/usr/share/man/man1/python3.1.gz
/usr/share/man/man1/python3.6.1.gz
```

### 3-2. Python 3 仮想環境の理解

Pythonには、1つのマシンで複数のPythonおよびPythonパッケージを管理する方法がたくさんある。今回は、もっとも標準的でOCI CLIインストーラーも使用している**venv**を紹介する。**venv**は、従来の**virtualenv**がPython 3.3から標準機能として取り込まれたものだ。

* [公式マニュアル：venv —  仮想環境の作成](https://docs.python.org/ja/3.6/library/venv.html)
* [venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
* [【Python入門】venvで仮想環境を作る方法をわかりやすく解説](https://www.sejuku.net/blog/68423)
* [Pythonのvenv(pyvenv)で環境を作る](https://blog.daisukekonishi.com/post/python-pyvenv/)
* [pyvenvとは何か](https://qiita.com/shinno21/items/de09a2533097cbfd5f66)

**venv**と**pyvenv**が混在して戸惑うが、実体はどちらも同じ**venv**だ。pyvenvはvenvを操作するスクリプトで現在は非推奨。
https://docs.python.org/3.6/library/venv.html
> The pyvenv script has been deprecated as of Python 3.6 in favor of using python3 -m venv to help prevent any potential confusion as to which Python interpreter a virtual environment will be based on.

**venv**の使用方法は次のとおり。

**仮想環境の作成**

```shell-session
python3 -m venv ＜環境パス名＞
```

**仮想環境の有効化**

```shell-session
source ＜環境パス名＞/bin/activate
```

**仮想環境の無効化**

```shell-session
deactivate
```

### 3-3. Python 3 仮想環境の構築

<font color="red">この作業はOCI CLIのインストールには不要だが、後述する調査で使用するので説明する。</font>

1. OCI CLI用の仮想環境を作成する。`oci_cli`は仮想環境を構築するディレクトリ名であり、別の文字列でもよい。

```shell-session
$ python3 -m venv oci_cli
```

2.確認すると、以下のディレクトリやファイルが作成されている。中身を理解する必要はないが、詳細を知りたい人は[公式マニュアル](https://docs.python.org/ja/3.6/library/venv.html)を参照のこと。

```
$ ls -d  oci_cli/*
oci_cli/bin  oci_cli/include  oci_cli/lib  oci_cli/lib64  oci_cli/pyvenv.cfg
```

3.仮想環境を有効化する。仮想環境が有効になると、プロンプトの先頭に仮想環境名が表示される。＜環境パス名＞の部分は、カレントディレクトリからの相対パスである。

```shell-session
$ source oci_cli/bin/activate
(oci_cli) [opc@hostname ~]$
```

4.Pythonのバージョンを確認すると3.6.8になっている。

```shell-session
(oci_cli) [opc@hostname ~]$ python -V
Python 3.6.8
```

5.無効化するには`deactivate`を入力する。仮想環境を無効にすると、元のバージョンに戻ることがわかる。

```shell-session
(oci_cli) [opc@hostname ~]$ deactivate
[opc@hostname ~]$ python -V
Python 2.7.5
```

ここまでがPythonの仮想環境の基礎知識だ。次にOCI CLIをインストール/アップデートする。

# 4. OCI CLIのセットアップ

次にOCI CLIをインストールする。OCI CLIインストーラーを実行するには、インターネットにアクセスできる必要がある。

### 4-1. OCI CLIのインストール

OCI CLIをインストールする。すでにPython 2.xでOCI CLIを利用しているときでも、Pythonライブラリのインストール先が異なるので再インストールが必要になる。ただし`$HOME/.oci`配下の設定ファイルは、そのまま利用できる。

1. OCI CLIのインストーラーを実行する。なお、opcやoracleユーザーなど、OCI CLIを実行するOSユーザーで実行すること。

```shell-session
$ bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"
```

2.既存からのアップデートのときは以下のように表示されるので「y」を入力して上書きする。

```shell-session
===> In what directory would you like to place the install? (leave blank to use '/home/opc/lib/oracle-cli'):
-- Install directory '/home/opc/lib/oracle-cli' is not empty and may contain a previous installation.

===> Remove this directory? (y/N):★yを入力
```

3.その後、いくつか入力が求められるが「すべてリターンキー」でよい。

4.終了すると以下のように出力される。

```shell-session
-- ** Run `exec -l $SHELL` to restart your shell. **
--
-- Installation successful.
-- Run the CLI with /home/opc/bin/oci --help
```

5.`$HOME/.bashrc`に追記した内容を有効化するためシェルを再起動する。

```shell-session
$ exec -l $SHELL
```

6.Python 2からアップデートすると、以下のように2.7を参照する行が残ったままになる。しかし、実行されないので残したままでも問題ない。

```shell-session:$HOME/.bashrc
[[ -e "/home/opc/lib/oracle-cli/lib/python2.7/site-packages/oci_cli/bin/oci_auto
complete.sh" ]] && source "/home/opc/lib/oracle-cli/lib/python2.7/site-packages/
oci_cli/bin/oci_autocomplete.sh"

[[ -e "/home/opc/lib/oracle-cli/lib/python3.6/site-packages/oci_cli/bin/oci_auto
complete.sh" ]] && source "/home/opc/lib/oracle-cli/lib/python3.6/site-packages/
oci_cli/bin/oci_autocomplete.sh"
```

7.OCI CLIのバージョンを確認すると次のとおり。

```shell-session
$ oci --version
2.7.0
```

### 4-2. コンフィグ・ファイルの設定

Python 2からアップデートしたときは何もしなくてよい。`$HOME/.oci`配下のコンフィグ・ファイルをそのまま利用できる。インストールに成功すると、OCI CLIを実行しても冒頭で紹介した警告メッセージは表示されなくなる。

新規インストールのときは以下のページを参考に設定すること。

* [OCI CLI を使い倒す（speakerdeck.com）](https://speakerdeck.com/mmarukaw/oci-cli-woshi-idao-su)
* [Oracle Cloud : コマンド・ライン・インタフェース(CLI) をインストールしてみた](https://qiita.com/shirok/items/e63be9a22158fef10ba9)
* [Oracle Cloud(OCI)のoci cli設定ファイルの使い方をまとめてみた](https://qiita.com/feifo/items/29d842da0102379cf527)

# 5. インストール環境の調査

せっかくPythonの仮想環境を説明したので確認してみよう。OCI CLIは`$HOME/lib/oracle-cli`にインストールされている。

1. デフォルトのPython 3環境にOCI CLIはインストールされていない。

```shell-session
$ pip3 list --format=columns
Package    Version
---------- -------
pip        9.0.3
setuptools 39.2.0
```

2.仮想環境を有効にする。

```shell-session
$ source lib/oracle-cli/bin/activate
(oracle-cli) [opc@hostname ~]$
```

3.仮想環境にインストールされているパッケージを確認すると、OCI Python SDKとOCI CLIが表示される。

```shell-session
(oracle-cli) [opc@hostname ~]$ pip3 list
Package         Version
--------------- ----------
arrow           0.10.0
asn1crypto      1.2.0
certifi         2019.11.28
cffi            1.13.2
click           6.7
configparser    3.5.0
cryptography    2.4.2
idna            2.6
jmespath        0.9.3
oci             2.8.0　★OCI Python SDK 
oci-cli         2.7.0　★OCI CLI
pip             19.3.1
pycparser       2.19
pyOpenSSL       18.0.0
python-dateutil 2.7.3
pytz            2016.10
PyYAML          5.1.2
retrying        1.3.3
setuptools      42.0.2
six             1.11.0
terminaltables  3.1.0
wheel           0.33.6
```

**おまけ：**仮想環境では`pip3`ではなく`pip`も利用できる。どちらも同じ出力結果だが、仮想環境をアクティブにすると、仮想環境にインストールされている`pip`が使えるようになる。/usr/binには`pip`がない。

```shell-session
$ find $HOME /usr/bin -name "pip*"
/home/opc/.cache/pip
/home/opc/lib/oracle-cli/lib/python3.6/site-packages/pip
/home/opc/lib/oracle-cli/lib/python3.6/site-packages/pip-19.3.1.dist-info
/home/opc/lib/oracle-cli/bin/pip
/home/opc/lib/oracle-cli/bin/pip3
/home/opc/lib/oracle-cli/bin/pip3.6
/home/opc/lib/oracle-cli/pip-selfcheck.json
/usr/bin/pip3　★pipがない
/usr/bin/pip-3
/usr/bin/pip-3.6
/usr/bin/pip3.6
```

4.アップデートされているパッケージがあるか確認する。OCI CLIをセットアップしたばかりだと、次のようにociとoci-cliは表示されない。それ以外のパッケージは依存性もあるので古くても気にしないこと。

```shell-session
(oracle-cli) [opc@hostname ~]$ pip3 list -o
Package         Version Latest Type
--------------- ------- ------ -----
arrow           0.10.0  0.15.4 wheel
click           6.7     7.0    wheel
configparser    3.5.0   4.0.2  wheel
cryptography    2.4.2   2.8    wheel
idna            2.6     2.8    wheel
jmespath        0.9.3   0.9.4  wheel
pyOpenSSL       18.0.0  19.1.0 wheel
python-dateutil 2.7.3   2.8.1  wheel
pytz            2016.10 2019.3 wheel
PyYAML          5.1.2   5.2    sdist
six             1.11.0  1.13.0 wheel
```

5.新しいバージョンがリリースされているときは、以下のコマンドでアップデートできる。

```shell-session
(oracle-cli) [opc@hostname ~]$ pip3 install oci-cli --upgrade
```

6.仮想環境を無効にして終了だ。

```shell-session
(oracle-cli) [opc@hostname ~]$ deactivate
[opc@hostname ~]$
```

# 6. OCI CLIのアップデート

先ほど`pip3 install oci-cli --upgrade`でOCI CLIをアップデートする方法を紹介した。実際には次の２つのアップデート方法がある。

1. OCI CLIインストーラーで再インストールする
2. pip/pip3コマンドでアップデートする

再インストールはコマンド一発なので、pip/pip3の方法を実際の出力を含めて紹介する。

1. OCI CLIのインストール先ディレクトリに移動する。

```shell-session
$ cd ＜インストール先ディレクトリ＞
```

2.仮想環境を有効にして、新しいバージョンがあるか確認する。この例では新しいバージョンが表示されている。

```shell-session
source lib/oracle-cli/bin/activate
pip3 list -o
---ここか下が出力---
Package         Version Latest Type
--------------- ------- ------ -----
arrow           0.10.0  0.15.5 wheel
cffi            1.13.2  1.14.0 wheel
click           6.7     7.1.1  wheel
configparser    3.5.0   4.0.2  wheel
idna            2.6     2.9    wheel
jmespath        0.9.3   0.9.5  wheel
oci             2.10.2  2.12.1 wheel　★新しいバージョンがある
oci-cli         2.9.0   2.9.7  wheel　★新しいバージョンがある
pycparser       2.19    2.20   wheel
pyOpenSSL       18.0.0  19.1.0 wheel
python-dateutil 2.7.3   2.8.1  wheel
pytz            2016.10 2019.3 wheel
PyYAML          5.1.2   5.3.1  sdist
setuptools      45.1.0  46.1.1 wheel
six             1.11.0  1.14.0 wheel
```

3.パッケージをアップデートする。最後に「Successfully installed」と表示されたらアップデートに成功している。

```shell-session
pip3 install oci-cli --upgrade
```

```shell-session:出力の一部
Collecting oci-cli
  Downloading oci_cli-2.9.7-py2.py3-none-any.whl (7.5 MB)
     |████████████████████████████████| 7.5 MB 6.1 MB/s
Collecting configparser>=4.0.2
  Downloading configparser-4.0.2-py2.py3-none-any.whl (22 kB)
Requirement already satisfied, skipping upgrade: terminaltables==3.1.0 in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (3.1.0)
Requirement already satisfied, skipping upgrade: certifi in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (2019.11.28)
Requirement already satisfied, skipping upgrade: PyYAML==5.1.2 in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (5.1.2)
Requirement already satisfied, skipping upgrade: retrying==1.3.3 in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (1.3.3)
Requirement already satisfied, skipping upgrade: idna<2.7,>=2.5 in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (2.6)
Requirement already satisfied, skipping upgrade: pytz>=2016.10 in ./lib/oracle-cli/lib/python3.6/site-packages (from oci-cli) (2016.10)
Collecting oci==2.12.0
  Downloading oci-2.12.0-py2.py3-none-any.whl (3.6 MB)
     |████████████████████████████████| 3.6 MB 2.3 MB/s
★中略
      Successfully uninstalled oci-cli-2.9.0
Successfully installed arrow-0.14.7 configparser-4.0.2 jmespath-0.9.4 oci-2.12.0 oci-cli-2.9.7 six-1.14.0
```

4.最後に仮想環境を非アクティブにすれば終了だ。

```shell-session
(oracle-cli) [opc@hostname ~]$ deactivate
[opc@hostname ~]$
```

# 7. まとめ

* 2020/2/13以降、OCI CLIがサポートするPythonのバージョンは3.5+になる。
* Oracle Linux / CentOS 7でPython 3を使用するには、標準リポジトリの`python3`がオススメ
* OCI CLIインストーラーを使用すると、インストールとアップグレードの両方ができる
* OCI CLIは、Pythonの仮想環境にインストールされる