thirose’s blog

openstackやpythonなどなど

flask+gunicornでgeventを使い、非同期処理にする

flask+gunicornなバックエンドでworker-classがデフォルトのsyncで同期処理をしていたのを非同期処理ができるように設定を変更しました。 同期処理の何が問題かというと、backendの処理に時間がかかる and プロセス数以上にリクエストがきてしまった場合、process数より多かった分のリクエストが待ち状態になりtimeoutになることがあります。
このような問題を解決すべくgeventを使い非同期で処理できるようにする方法をまとめました。

そもそもgunicornのワーカークラスには - sync - gevent - eventlet - tornado - gthread

と5つ存在していて今回はgeventを選択しました。geventはgreenletをベースとした非同期ワーカーです。

pip install gevent

でインストールでき,
起動時に-k WORKER_NAMEまたは--worker-class WORKER_NAMEのどちらかのオプションで指定すれば起動できます。 コードに対しての変更は特に必要ないです。

以下のように処理されます。 f:id:hirosetakahito:20181108175031p:plain

今回検証に使った簡易的なサーバとスクリプト

request script

import json
import requests


def register_name(self):
    url = 'http://127.0.0.1:5000/'
    res = requests.post(url)
    return res 


if __name__ == '__main__':
    result = register_name('test01')

proxy server

from flask import Flask
import requests

@app.route('/')
def register():
    url = 'https://127.0.0.1:5001'
    request.post(url)
    return "Created", 201 

if __name__ == '__main__':
    app.run(processes=5, port=5000)

backend server

from flask import Flask
app = Flask(__name__)

@app.route('/')
def wait_time():
    time.sleep(60)
    return "Created", 201

if __name__ == '__main__':
    app.run(port=5001, processes=10)

変更後の注意

非同期にすることで裁く量が増える場合があるので、MySQLなど別のところで問題が発生する可能性があります。 そのため、事前にconnection数など確認しておくと良いかもしれません。

Designateのビルドをしてたら、UnicodeEncodeErrorがでてきた

今回はOpenStackのDesignateでおきたエラーですが、他のミドルウェアでも起きる可能性はなくないと思うので、エラーとその対応をまとめます。 今回はpythonの2.7.13が必要だったけど、CentOSpythonが2.7.5だったため、pyenvを入れて対応しようとしていた時にUnicordeEncodeErrorが発生しました。

ERROR LOG

Traceback (most recent call last):
  File "setup.py", line 29, in <module>
    pbr=True)
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/distutils/core.py", line 152, in setup
    dist.run_commands()
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/distutils/dist.py", line 954, in run_commands
    self.run_command(cmd)
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/distutils/dist.py", line 973, in run_command
    cmd_obj.run()
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/site-packages/pbr/packaging.py", line 618, in run
    sdist.sdist.run(self)
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/site-packages/setuptools/command/sdist.py", line 51, in run
    self.run_command(cmd_name)
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/distutils/cmd.py", line 327, in run_command
    self.distribution.run_command(command)
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/distutils/dist.py", line 973, in run_command
    cmd_obj.run()
  File "/home/www/.pyenv/versions/2.7.13/lib/python2.7/site-packages/reno/setup_command.py", line 138, in run
    f.write(text)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 4383: ordinal not in range(128)

原因

pyenvの中でデフォルトがasciiコードだっため、おきたエラーだったようです。 確認するためには、以下のようにコンソールで確認できるかと思います。

$ python
>>> import sys
>>> sys.getdefaultencoding()
'ascii'

対応

~/.pyenv/versions/2.7.13/lib/python2.7/site-packages/sitecustomize.pyというファイルを作り、 以下のスクリプトを設置する

import sys
sys.setdefaultencoding('utf-8')

ウェブで検索してると、sitecustomize.pyという名前が一般的っぽい。

SAMLを使ったSSOログインの設定と問題

SAMLを使ったログインをOpenStackで実現する場合は、mellon または shibbolethといったモジュールを使用することになります。参考資料

今回はmellonとは、mod_auth_mellon のことで、それを検証してみたのでその中で気が付いた問題をまとめました。
セットアップについては下記のリンクを参考にセットアップできるかと思います。
OpenStackのドキュメントはわりとあてになりませんが、OpenStackが公開している設定のリンクをまとめます。

SSOログインの一連の流れについてもまとめました。

f:id:hirosetakahito:20180919165608p:plain opt1SAML AuthnRequestに関わる処理のところを囲んでいます。
SAML AuthnRequestというものは、IdentityProvider (idP)に認証要求を投げる時にcookieに入れられるもので、idPからのレスポンスが自分で送ったものか確認するために使われます。

  1. ログインリクエストを投げると、redirectで、mellonのメソッドが叩かれます
  2. そこで、SAML AuthRequestが作成されます
  3. identityProvider(idP)に認証をするため、認証リクエストのパスをたたき、idPにリクエストします
  4. idPで認証をし、結果をmellonに返します
  5. SAML AuthRequestのチェックを行い、ユーザ情報をkeystoneに渡します。
  6. keystone上にユーザがいなかったら、401エラーで、ユーザが入ればログインです。

一番大事なのはidPにすべての認証を一任することが一つのポイントです。
勘違いしやすいのですが、SSOのログアウトは該当サービス(OpenStackならhorizon)のログアウトであって、idPの認証はログアウトしないということです。
そして、ログインはidPの認証情報であって該当サービスの認証はidPに一任していることです。
UMLでも認証したユーザ情報が該当サービス上に存在するか最後に確認し、そのユーザに対してログインを許可しています。

また、OpenStackでSSOログインした時はUnscoped Tokenが発行されます。 Unscoped Tokenはpolicyで一概には言えませんが、project情報やuser情報を見ることは可能ですが、 追加や更新、削除といった操作はできません。
あくまで、Unscoped Tokenは Project Scoped Tokenに交換するためのTokenです。交換方法はHorizonでプロジェクトを選択すれば、Project Scoped Tokenが発行されます。
Tokenについては、 以下記事にまとめています。

hirosetakahito.hatenablog.com

requestが飛んたサーバに認証結果が返らなければならない

1つ問題になるのが、複数Apacheを置いている場合です。Apacheごとに発行しているので最初にユーザがログインしたい!とrequestしたときにrequestが届いたサーバと、SPから認証が帰ってくるサーバが同じでないと SAML AuthnRequestが一致しないのです。
一つの解決方法として、HAproxyを使っている場合は sticky sessionを張る方法があります。sticky sessionでは、requestが毎回同じホストへ行くようにcookieにサーバネームもしくはどのサーバにrequestを飛ばせば良いか判断できるような名前を登録し、毎回同じサーバにrequestが届くようにする仕組みです。
ドキュメントにも書かれているので、haproxyを使う場合はこの設定が基本的な解決方法かと思います。ドキュメント
ハードウェアのロードバランサでしたら、sticky sessionでもソースIPなバランシングでもいくらでも解決方法はありそうなため、考えてません。

実際の設定は、

・・・
cookie SERVERID insert indirect nocache maxidle 20s maxlife 30s
server KEYSTONE_HOST_NAME KEYSTONE_API_ENDPOINT check inter 2000 rise 2 fall 5 cookie KEYSTONE_HOST_NAME
・・・

と設定します。
各設定については、haproxyのドキュメントを見るのが早いでしょう。
設定中の2行だけ切り抜きましたが、cookieをセットするとsticky sessionで設定されます。また、maxlifeにより30秒でcookieの有効期限がきれるため、仮に接続するサーバが死んだとしてもアクセスできないという事故はほぼ解消されるかと思います。
また、maxidleを20sにしているのは、mellon側の設定でMellonSessionLengthを20sに設定しているためです。

本来mellon上で何かしらの情報を持つのはよくないなーと思っているのでより良い方法があれば、別の方法で解決したいと考えています。

idP上にユーザがいて、SP側にユーザがいなかった時はjsonが返る

ブラウザに直接結果が返ってしまうため、ユーザがSP(OpenStackの場合ならKeystone)に登録されてなかった場合は、残念ながらブラウザに401のjsonが表示されます。
この問題については、wsgi_middlewareをkeystoneに追加し、responseを返す時にhtmlに置き換える方法で対応可能です。


  1. OPTを本来の用途ではなく囲むために使ってます。

Ansibleでvault使う時は変数ごと暗号化する

OpenStackをdeployするのにAnsibleとか使うと便利だったり?します。
便利かどうかはさておき、Vaultをファイル単位で暗号化しgithubで管理し始めると、何をどう変更したのかわからない。
という問題が発生します。そこで変数ごと暗号化していくのが変更を管理するのが一つの解決方法としてわかりやすいと考えています。
ただし、適当にhoge-vault.ymlとかファイルを作り、値だけ書き込んで、
ansible-vault encrypt hoga-vault.ymlとか書いてしまうとなぜかansible実行中に改行コードが入ります。
調べてみると、echo -e 'hoge' > hoge-vault.ymlをやれば良いようなことも書かれてますがやってみたけど、
ダメだったので
#use-encrypt-string-to-create-encrypted-variables-to-embed-in-yaml を参照して以下のようなスクリプトでファイルを作ってくことにしました。

$ cat vault_password_generator.sh
#!/usr/local/bin/bash

declare -A PASSWORD_LIST;

PASSWORD_LIST=(
  ["vault_password_key1"]="password1"
  ["vault_password_key2"]="password2"
  ["vault_password_key3"]="password3"
  ["vault_password_key4"]="password4"
  ["vault_password_key5"]="password5"
)

for PASSWORD in ${!PASSWORD_LIST[@]};
do  
    `ansible-vault encrypt_string ${PASSWORD_LIST[$PASSWORD]} --name $PASSWORD >> all.yml`
done

PASSWORD_LISTはハッシュ形式で、左辺がkeyで右辺がvalueになり、
実行時には${PASSWORD_LIST[$PASSWORD]}valueが入り、$PASSWORDにkeyが入ります。

変数ごと暗号化すれば、どの変数を追加 or 更新したのかわかるので管理しやすくなります。

keystoneのtoken

KeysoneのTokenには、Project Scoped Token, Domain Scoped Token, Unscoped Tokenがあります。(System scoped tokenは除外します)
各Tokenにどういう用途があるのか、まとめました。

Project Scoped Token

これは、管理者よりユーザが一番使うであろうTokenです。
使いたいProjectのTokenなので、Project内の操作はこのTokenを使って行います。
該当ProjectへのUserの追加やInstanceの生成が可能です。 f:id:hirosetakahito:20180823155412p:plain (※赤い部分が操作可能な範囲です)

Domain Scoped Token

次に、Domain Scoped Tokenです。
このTokenは、Domain内のUserやRoleやProjectのQuotaなどの操作(Create, Update, Delete)を行うことができます。
f:id:hirosetakahito:20180823155422p:plain (※赤い部分が操作可能な範囲です)

Unscoped Token

最後にUnScoped Tokenですが、SSOなどの外部認証を使う時に最初に発行されるTokenです。 Unscoped Token は、Project Scoped Tokenに交換するためのTokenになります。

Domain Scoped Tokenと同じようなことができそうですが、追加や更新といった操作はできません。 UserやProjectの一覧が見れるぐらいしかできないです。 f:id:hirosetakahito:20180823155428p:plain (※赤い部分が操作可能な範囲です)

APIでtokenを取得する

今回は多分一番使われるであろうProject Scoped Tokenの取り方をcurlで簡単に紹介

curl -i -X POST -H "Content-Type: application/json" -d '
{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "name": "<user name>",
                    "domain": {
                        "name": "<domain name>"
                    },
                    "password": "<password>"
                }
            }
        },
        "scope": {
            "project": {
                "domain": {
                    "name": "<domain name>"
                },
                "name": "<project name>"
             }
        }
    }
}' https://<endpoint>/v3/auth/tokens

と、簡単にとれます。 keystone clientというpythonのライブラリもあるので、
pythonを使う場合はclientを使うのも一つの手です。
user idも、project idもわかるのなら、idに置き換えることも可能です。

curl -i -X POST -H "Content-Type: application/json" -d '
{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "id": "<user id>",
                    "password": "<password>"
                }
            }
        },
        "scope": {
            "project": {
                "id": "<user id>"
             }
        }
    }
}' https://<endpoint>/v3/auth/tokens

Moto E5を買った

昨年の夏ぐらいからそろそろiPhone5sから他のに変えようと考えはじめ、google pixelとかpixel2とか考えてたらいつのまにか1年が経とうとしてたこのタイミングでMoto E5を見つけたので購入。

 

当初は片手で操作出来ないと嫌だなーというのが第1にあったんだけど、iPhone使うの辞めるならもうそのポリシーは良いかと考え、流行りの大きい端末に変更した。片手で操作出来ないのは今のところ不満はない。

満足してることは、4000mAhの大容量バッテリー。

最近は出社の40分で100%から残り15%ぐらいまで減るバッテリー。

出社前や帰宅前に充電しないとツラい移動になること間違いなしの状態だ。

それを回避するために新しい機種を探していました。

 

 

買って一ヶ月経ってたのでその感想

やはりエントリー機という感じでメモリーの少なさを時々感じるけど、不満を感じるほどではない。それより、大容量バッテリーやDSDSの恩恵をたくさん受けている。

また、16GBとストレージの少なさを感じたけど、SDカードを買ってからそれも問題ではないです。

20000円以内で買え、不満という不満もなく使えるコスパの良いスマートフォンかなーと思います。

 

python3.5.0だけtracebackの返値が違っていたバグに当たった

今回はたまたま、openstackのnovaclientを使っていたらバグを発見しました。
その時のログはこちら -> This report is written about novaclient. · GitHub

バグの内容

python3.6を普段使ってるけど、もともとpython3.5.0で動いていたスクリプトで、普段と違う何かエラーが出てるなーというところから発見しました。
python3.5.0だけ、traceback.extract_stackで返ってくるlistの最後にtraceback.extrace_stackが入っていて、

filename, _lineno, _name, line = traceback.extract_stack()[-4]

の[-4] だと欲しいclass nameが取れない状態でした。 該当箇所 -> python-novaclient/api_versions.py at master · openstack/python-novaclient · GitHub

python3.5.0では、[-5] だったら問題なく動きます。
なので、

$ cat api_version.patch
--- api_version.py 2018-04-25 13:19:11.999263977 +0900
+++ api_version.py.change 2018-04-25 13:21:52.732243109 +0900
@@ -346,7 +346,11 @@
    # ("im_class" property does not exist at that moment)
    # we need to write own logic to obtain the full function name which
    # include module name, owner name(optional) and just function name.
- filename, _lineno, _name, line = traceback.extract_stack()[-4]
+ traceback_data = traceback.extract_stack()
+ for tl in traceback_list[::-1]:
+ if tl[2] == '<module>':
+ filename, _lineno, _name, line = tl
+ break
    module, _file_extension = os.path.splitext(filename)
    module = module.replace("/", ".")
    if module.endswith(func.__module__):

という修正をすれば動きます。
これはpython 3.5.0のみで起こるエラーで3.5.1が出た時に修正されてます。
ただ、novaclientのような書き方をしていると、また別の機会に同じようなエラーがでる可能性をもっています。

以下、検証に使ったもろもろをまとめています。

検証につかったスクリプト

# -*- coding: utf-8 -*-

import sys
from novaclient import client as nova_client
from keystoneclient.v3 import client
from keystoneauth1 import session
from keystoneauth1.identity import v3

def get_keystone_session():
    params = {
        'auth_url': KEYSTONE_ENDPOINT,
        'username': USERNAME,
        'password': PASSWORD,
        'user_domain_name': 'default',
        'project_name': PROJECT_NAME,
        'project_domain_name': 'default',
    }
    auth = v3.Password(**params)
    sess = session.Session(auth=auth)
    return sess

def update_quota(sess, server):
    project_id = PROJECT_ID
    nova = nova_client.Client('2.1', session=sess)
    print(nova.quotas.get(project_id))
    nova.quotas.update(project_id, instances=100)
    print(nova.quotas.get(project_id))
    return 'success'

if __name__ == '__main__':
    argvs = sys.argv
    sess = get_keystone_session()
    update_quota(sess, INSTANCE_ID)

各バーションのtraceback. extractのデバック結果

python 3.5.0だけ、classの情報が[-4]番目に入ってないことがわかります。

python2.7.14

[('nova_script.py', 60, '<module>', "print(get_instance(sess, '81be1886-cf7b-4b11-9208-e847fe5a9fe9'))"), ('nova_script.py', 39, 'get_instance', "nova = nova_client.Client('2.1', session=sess)"), ('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/client.py', 330, 'Client', 'api_version, client_class = _get_client_class_and_version(version)'), ('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/client.py', 224, '_get_client_class_and_version', '"novaclient.v%s.client.Client" % version.ver_major)'), ('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/oslo_utils/importutils.py', 30, 'import_class', '__import__(mod_str)'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/v2/__init__.py', 16, '<module>', 'from novaclient.v2.client import Client # noqa'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/v2/client.py', 47, '<module>', 'from novaclient.v2 import volumes'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/v2/volumes.py', 36, '<module>', 'class VolumeManager(base.Manager):'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/v2/volumes.py', 60, 'VolumeManager', 'tag=None):'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/api_versions.py', 382, 'decor', 'name = _get_function_name(func)'),
('/home/www/.pyenv/versions/2.7.14/lib/python2.7/site-packages/novaclient/api_versions.py', 350, '_get_function_name', 'print traceback.extract_stack()')]

python3.4.0

[('nova_script.py', 60, '<module>', "print(get_instance(sess, '81be1886-cf7b-4b11-9208-e847fe5a9fe9'))"), ('nova_script.py', 39, 'get_instance', "nova = nova_client.Client('2.1', session=sess)"), ('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/client.py', 330, 'Client', 'api_version, client_class = _get_client_class_and_version(version)'), ('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/client.py', 224, '_get_client_class_and_version', '"novaclient.v%s.client.Client" % version.ver_major)'), ('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/oslo_utils/importutils.py', 30, 'import_class', '__import__(mod_str)'), ('<frozen importlib._bootstrap>', 2214, '_find_and_load', None), ('<frozen importlib._bootstrap>', 2189, '_find_and_load_unlocked', None), ('<frozen importlib._bootstrap>', 321, '_call_with_frames_removed', None), ('<frozen importlib._bootstrap>', 2214, '_find_and_load', None), ('<frozen importlib._bootstrap>', 2203, '_find_and_load_unlocked', None), ('<frozen importlib._bootstrap>', 1200, '_load_unlocked', None), ('<frozen importlib._bootstrap>', 1129, '_exec', None), ('<frozen importlib._bootstrap>', 1448, 'exec_module', None), ('<frozen importlib._bootstrap>', 321, '_call_with_frames_removed', None), ('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/v2/__init__.py', 16, '<module>', 'from novaclient.v2.client import Client # noqa'), ('<frozen importlib._bootstrap>', 2214, '_find_and_load', None), ('<frozen importlib._bootstrap>', 2203, '_find_and_load_unlocked', None), ('<frozen importlib._bootstrap>', 1200, '_load_unlocked', None), ('<frozen importlib._bootstrap>', 1129, '_exec', None), ('<frozen importlib._bootstrap>', 1448, 'exec_module', None), ('<frozen importlib._bootstrap>', 321, '_call_with_frames_removed', None), ('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/v2/client.py', 47, '<module>', 'from novaclient.v2 import volumes'), ('<frozen importlib._bootstrap>', 2261, '_handle_fromlist', None), ('<frozen importlib._bootstrap>', 321, '_call_with_frames_removed', None), ('<frozen importlib._bootstrap>', 2214, '_find_and_load', None), ('<frozen importlib._bootstrap>', 2203, '_find_and_load_unlocked', None), ('<frozen importlib._bootstrap>', 1200, '_load_unlocked', None), ('<frozen importlib._bootstrap>', 1129, '_exec', None), ('<frozen importlib._bootstrap>', 1448, 'exec_module', None), ('<frozen importlib._bootstrap>', 321, '_call_with_frames_removed', None),
('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/v2/volumes.py', 36, '<module>', 'class VolumeManager(base.Manager):'),
('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/v2/volumes.py', 60, 'VolumeManager', 'tag=None):'),
('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/api_versions.py', 382, 'decor', 'name = _get_function_name(func)'),
('/home/www/.pyenv/versions/3.4.0/lib/python3.4/site-packages/novaclient/api_versions.py', 350, '_get_function_name', 'print(traceback.extract_stack())')]

python3.5.0

[<FrameSummary file nova_script.py, line 60 in <module>>, <FrameSummary file nova_script.py, line 39 in get_instance>, <FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/client.py, line 330 in Client>, <FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/client.py, line 224 in _get_client_class_and_version>, <FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/oslo_utils/importutils.py, line 30 in import_class>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 944 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/v2/__init__.py, line 16 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/v2/client.py, line 47 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 1016 in _handle_fromlist>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>,
<FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 36 in <module>>,
<FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 60 in VolumeManager>,
<FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/api_versions.py, line 386 in decor>,
<FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/site-packages/novaclient/api_versions.py, line 349 in _get_function_name>,
<FrameSummary file /home/www/.pyenv/versions/3.5.0/lib/python3.5/traceback.py, line 201 in extract_stack>]

python3.5.1

[<FrameSummary file nova_script.py, line 60 in <module>>, <FrameSummary file nova_script.py, line 39 in get_instance>, <FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/client.py, line 330 in Client>, <FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/client.py, line 224 in _get_client_class_and_version>, <FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/oslo_utils/importutils.py, line 30 in import_class>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 944 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/v2/__init__.py, line 16 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/v2/client.py, line 47 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 1016 in _handle_fromlist>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 969 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 958 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 662 in exec_module>,
<FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>,
<FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 36 in <module>>,
<FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 60 in VolumeManager>,
<FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/api_versions.py, line 382 in decor>,
<FrameSummary file /home/www/.pyenv/versions/3.5.1/lib/python3.5/site-packages/novaclient/api_versions.py, line 350 in _get_function_name>]

python3.5.5

[<FrameSummary file nova_script.py, line 60 in <module>>, <FrameSummary file nova_script.py, line 39 in get_instance>, <FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/client.py, line 330 in Client>, <FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/client.py, line 224 in _get_client_class_and_version>, <FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/oslo_utils/importutils.py, line 30 in import_class>, <FrameSummary file <frozen importlib._bootstrap>, line 968 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 943 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 968 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 957 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 697 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/v2/__init__.py, line 16 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 968 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 957 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 697 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/v2/client.py, line 47 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 1015 in _handle_fromlist>, <FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 968 in _find_and_load>,
<FrameSummary file <frozen importlib._bootstrap>, line 957 in _find_and_load_unlocked>,
<FrameSummary file <frozen importlib._bootstrap>, line 673 in _load_unlocked>,
<FrameSummary file <frozen importlib._bootstrap_external>, line 697 in exec_module>,
<FrameSummary file <frozen importlib._bootstrap>, line 222 in _call_with_frames_removed>,
<FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 36 in <module>>,
<FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/v2/volumes.py, line 60 in VolumeManager>,
<FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/api_versions.py, line 382 in decor>,
<FrameSummary file /home/www/.pyenv/versions/3.5.5/lib/python3.5/site-packages/novaclient/api_versions.py, line 350 in _get_function_name>]

python3.6.4

[<FrameSummary file nova_script.py, line 60 in <module>>, <FrameSummary file nova_script.py, line 39 in get_instance>, <FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/client.py, line 330 in Client>, <FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/client.py, line 224 in _get_client_class_and_version>, <FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/oslo_utils/importutils.py, line 30 in import_class>, <FrameSummary file <frozen importlib._bootstrap>, line 971 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 941 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 219 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 971 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 955 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 665 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 678 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 219 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/v2/__init__.py, line 16 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 971 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 955 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 665 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 678 in exec_module>, <FrameSummary file <frozen importlib._bootstrap>, line 219 in _call_with_frames_removed>, <FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/v2/client.py, line 46 in <module>>, <FrameSummary file <frozen importlib._bootstrap>, line 1023 in _handle_fromlist>, <FrameSummary file <frozen importlib._bootstrap>, line 219 in _call_with_frames_removed>, <FrameSummary file <frozen importlib._bootstrap>, line 971 in _find_and_load>, <FrameSummary file <frozen importlib._bootstrap>, line 955 in _find_and_load_unlocked>, <FrameSummary file <frozen importlib._bootstrap>, line 665 in _load_unlocked>, <FrameSummary file <frozen importlib._bootstrap_external>, line 678 in exec_module>,
<FrameSummary file <frozen importlib._bootstrap>, line 219 in _call_with_frames_removed>,
<FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/v2/volumes.py, line 36 in <module>>,
<FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/v2/volumes.py, line 60 in VolumeManager>,
<FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/api_versions.py, line 382 in decor>,
<FrameSummary file /home/www/.pyenv/versions/3.6.4/lib/python3.6/site-packages/novaclient/api_versions.py, line 350 in _get_function_name>]