/var/log/study

つまり雑記

tentarafoo 開発 4日目

やったこと

やりたいこと

  • ログの文字列、全くサーバーのログっぽくはないのでそのうち改善したい
  • goroutineを使うだけではCPUをうまく使い切れないらしいので、CPUを使う数を増やす
  • yesコマンドがCPUを食いつぶすらしいのでそれっぽい実装をしたい

tentarafoo 開発 3日目

やったこと

tcpudpのポートが指定されていないときかつ、ランダムのフラグが立っていれば適当にポートを開くようにした

追加でやりたいこと

  • CPU使用率を上げるのもやりたい
  • 設定を生成するweb uiとか作ると便利かもしれない?と思った。

tentarafoo 開発 2日目

やったこと

  • ポートを開く機能を非同期にして、ポートが閉じるのを待つようにした
  • udpのポートが開けないバグを直した

追加でやりたいと思ったこと

  • 開くポートをランダムにすること
  • それっぽいログをランダムな間隔で吐くようにしたい
  • ものすごい勢いでログを吐き続ける機能もありかも

学び

  • net.Listen の引数は tcp という文字列を取るので udp も行けると思ったらだめだった
    • net.ListenUDP を使う必要がある

tentarafoo 開発 1日目

tentarafooというツール兼サーバーを書き始めた。

このツールはプロダクションで可動しているサーバーでは期待されないような状態を作り出すこと目的としている。

例えば、以下のような状態が期待されていない状態として上げられる。

  • 謎のプロセスが80/tcpを掴んでいる
  • メモリの使用量がじわじわと上がったり
  • inodeが枯渇したり
  • ディスクフルな状態
  • etc

目的を達成するだけならAnsibleとシェルスクリプトの寄せ集めのほうが早い気がするが、
シングルバイナリで様々な環境で動いてほしいのでgolangで書き始めている。

今日書いたのは以下

  • 設定ファイルを読み込む
  • プロセスタイトルを任意のものに変更できるようにした
  • tcpで複数のポートを開けるようにした
  • ddpで複数のポートを開けるようにした
  • 上記の状態で60秒待つようにした。

リポジトリは以下。

github.com

Keystoneの認証を利用してOpenStack APIを利用する

OpenStackをAPIでいろいろ操作する必要が出てきたので、OpenStack SDKに入門したのですが、微妙に躓いたのでメモを残して置きます。

2018年7月28日での話

実現したかったこと

自分が利用するOpenStack環境は、各エンドポイントがURLパスではなくドメインで分割されていたので、以下を実現したかった。

  1. keystoneに対して認証して
  2. 各エンドポイントに対してAPIをコールする

kestone認証を利用する

keystoneでsession情報を取得し、他の各クライアントにsession情報を引数で渡す。

参考にしたURLは https://docs.openstack.org/python-keystoneclient/latest/using-api-v3.html#authenticating-using-sessions

以下のような感じでSDKを利用しておけば良い気がする。

pre requirement

pip install python-novaclient python-glanceclient python-keystoneclient

コード

import os

from keystoneauth1.identity import v3
from keystoneauth1 import session

from glanceclient import Client
from novaclient import client as novaclient



def get_keystone_credential():
    return {
        'auth_url': os.getenv('OS_AUTH_URL', ''),
        'user_id': os.getenv('OS_USER_ID', ''),
        'password': os.getenv('OS_PASSWORD', ''),
        'project_id': os.getenv('OS_PROJECT_ID', ''),
    }

if __name__ == '__main__':
    auth = v3.Password(**get_keystone_credential())
    sess = session.Session(auth=auth)
    glance = Client('2', session=sess)
    print("---images---")
    for image in glance.images.list():
       print(image['name'])

    print("---servers---")
    nova = novaclient.Client('2', session=sess)
    for s in nova.servers.list():
        print(s.name)

エンドポイントを指定する

こちらに関しては、利用したい各クライアントによって指定方法が異なる気がする。

glanceなら Clientを生成するときの引数で endpoint を指定するし、

https://github.com/openstack/python-glanceclient/blob/master/glanceclient/client.py#L23

novaだとhttps://github.com/openstack/python-novaclient/blob/master/novaclient/client.py#L270 から生成されるであろう https://github.com/openstack/python-novaclient/blob/master/novaclient/v2/client.py#L50 には endpoint_override という引数で指定できそう

ココらへんのことを書いてあるドキュメントを見つけられず、コードを読んで結論を出したので、もしかしたらもっと良い方法があるかもしれない。

反省点

軽い気持ちでSDKというくくりの日本語ドキュメントを読み始めたのが間違いだった。

各クライアントのドキュメントを読むと良い気がする。

OpenStack Docs: Python bindings to the OpenStack Identity API (Keystone)

OpenStack Docs: Python Bindings for the OpenStack Images API

OpenStack Docs: Python bindings to the OpenStack Nova API

python fabric2 の話

先日、おもむろに pipenv install fabric したら、fabricのver 2が落ちてきた。

今までのfabricのインターフェースとは大きく変わっていたのでざっくりとまとめておく。

TL;DL

  • fabric2は良い
    • oopなインターフェースを備えた
    • 1ライブラリというスタンスが明確になった
  • fabric1のユーザーは http://docs.fabfile.org/en/2.1/upgrading.html に目を通しましょう。
    • デグレっぽいときはだいたい機能を削った理由が書いてある

Fabric

  • 自動化のためのツール
  • ShellScriptでは微妙だけど、Ansibleを持ち出すほどでもないときによく使われる印象

公式ドキュメント

どのような意図なのか?はわからないが、公式ドキュメントは2ドメインある

また2018年6月16日の段階では fabricの日本語ドキュメントは2対応していないので注意

Fabric ver 2 ?

  • fabric
    • もともとあったfabric
    • python3は未対応
    • 今となってはバージョン指定をして pip インストールをする必要がある
  • fabric 2
    • 先日リリースされたやつ
    • もともとあったfabricのインターフェースを洗練させたため、fabricとは互換性がない
    • python3対応
    • pipenv install fabric で落ちてくる
  • fabric 3
    • fabricが長い間 python3 に未対応だったためのfork
    • fabric の ver 1のインターフェースと ほぼ 互換性がある
      • コードを読むとわかるけど、一部非互換のところもあったよ
    • python3対応
    • pipenv install fabric3 で落ちてくる

ver 1 と ver 2 のgetting start 的な比較

すごく雑だが、パスワード認証でログインできるサーバーにrootで hello world を出力するサンプル

ver 1

from fabric.api import run, env

env.hosts = ["192.168.0.1"]
env.user = "root"

def hello():
    run("echo hello world")

fabfile.pyのあるディレクトリで fab hello で実行可能

ver 2 を ver 1っぽい書き方で

from invoke import task

@task
def hello(c):
    c.run("echo hello world")

fabfile.pyのあるディレクトリで fab --host root@192.168.0.1 --prompt-for-login-password hello

ver 2 を ver 2っぽい書き方で

from fabric import Connection
c = Connection(host="192.168.0.1", user="root", connect_kwargs={"password": "xxxxxxx"})
c.run("echo hello world")

何が変わったのか?

  • ver 1
    • fab コマンドがメイン
    • fabfile.py で、関数の中に fabric.api.run を書いて、 fab 関数名
    • 改めて考えると、マジックな感じが多く、fabricに対する知識が求められる感じ
  • ver 2
    • fab コマンドは使えるが、 invoke の機能を拡張した形
    • fabric.Connection.run を使えばよく、標準のpythonスクリプトとして実行可能
    • API的に、OOP的な感じで、直感的にわかりやすいインターフェースになった

fabricの1と2では、機能的側面で互換性があるので、fabric 1の利用者は http://docs.fabfile.org/en/2.1/upgrading.html を読むことをおすすめする。自分が気になった非互換は以下

fabric ver 1 と ver 2での非互換

http://docs.fabfile.org/en/2.1/upgrading.html からの抜粋して雑に意訳とその感想

  • role がなくなった
    • Group がいい感じで使えるようになったからそっちで賄えそう
  • --shellenv.shell で シェルを指定できなくなった
    • fabric1のときはいろいろと指定する方法があったが面倒なので詳しくは調べていない
    • fabric2では http://www.fabfile.org/upgrading.html#run にremoteでの実行のことが書いてある
    • remoteに対しては runメソッドの引数などを利用せず、commandで明示的に指定するようにしてほしい感じだと思う
  • ディレクトリごとファイルを送れなくなった
    • http://www.fabfile.org/upgrading.html#file-transfer の一番下に書いてある
    • rsync + zip or tar みたいなコードをメンテするのが大変だったからやめたとのこと
    • 自分はローカルでzipにして、リモートに送ってunzipするようにした

雑な感想

fabric ver 2では直感的にわかりやすいし、個人的には良いと思えるインターフェース設計になった印象があるので、積極的にfabric1から移行したい。

mambaを利用してpythonでBDD

pythonで利用できるBDDのツールに良いのが無いよなぁと思っていたら、きちんと awesome-python に記載されていた。

Mamba — mamba 0.9.2 documentation

個人的な所感としては割と良い気がする。RubyRspecの雰囲気を感じ取れる。

インストール

pipenv install mamba

書き方

with 句と mamba で用意されている description もしくは describe , context , it と、 expects というパッケージに用意されている expect などを利用して普通のBDDがpythonでも書ける感じ。

_context などのアンダースコアで始まるのはペンディングの印

全く意味がないテストコードだけど、以下の様。

from mamba import describe, context, it, _context, _it
from expects import expect, be_true, equal
from faker import Faker # サンプルのデータを作るやつ
fake = Faker() 

fake.name()

with describe("New topi") as self:
    with context("Bool"):
        with it("True"):
            expect(True).to(be_true)

with describe("Pendins") as self:
    with _context("penndins"):
        with it("pending"):
            pass

with describe("Pendins") as self:
    with context("penndins"):
        with _it("pending"):
            pass

class Human(object):
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

with describe("Human") as self:
    with before.each:
        self.human = Human(fake.name())

    with it("has name"):
        expect(type(self.human.name)).to(equal(str))

ライフサイクル

ライフサイクルとしては以下のようになっている

  • before.all
    • (describe内の) テストを実行する前に1度だけ
  • before.each
    • (describe内の) 各テストを実行する前に毎回
  • after.each
    • (describe内の) 各テストを実行したあとに毎回
  • after.all
    • (describe内の) テストを実行した後に1度だけ

参考は以下

Hooks — mamba 0.9.2 documentation

実行方法

pipenv run mamba **/*_spec.py とかで実行可能

また pipenv run mamba --enable-coverage と実行した後に、 pipenv run coverage htmlカバレッジを見ることができる。