OpenStack HorizonをConoHa VPSのダッシュボードとして使ってみる

TL; DR

  • ConoHa VPSはOpenStack APIを公開しているのでOpenStack Horizonで繋がるかもしれない→繋がった

動機

  • ConoHa VPSダッシュボードはVPSの作成などは出来るものの、セキュリティグループの設定はweb(80, 443)とかSSH(22)とか、よく利用するポートのテンプレートが使えるのみで、細かい設定ができない
  • APIは公開されているが、たまに細々した設定をするためにCLI操作するのは手間である
  • OpenStackのAPIなのでOpenStackのダッシュボードであるHorizonでGUI操作ができるのでは?

環境

  • CentOS: 8.3.2011
  • podman: 2.0.5

podman-dockerをインストールしているので、コマンドはdockerを使っている。

手順

ConoHaのAPIアクセス情報の確認

  • ユーザ名
  • パスワード
  • テナント名
  • テナントID
  • identityのエンドポイントURL

が必要。確認方法は割愛する。

確認したら、

OS_TENANT_NAME=テナント名
OS_TENANT_ID=テナントID
KEYSTONE_URL=identityのエンドポイントURL

の形式でenvファイルを作成する。ユーザ名、パスワードはhorizonのログイン画面に入力する。

コンテナイメージの取得、実行

horizonのコンテナイメージをプルし、ホストの8081ポートで動かす。

docker pull docker.io/alvaroaleman/openstack-horizon
docker run -d --rm -p 8081:80  --env-file path/to/env alvaroaleman/openstack-horizon

curl -L localhost:8081とかで動作確認する。

修正

このままだとうまくConoHa APIに接続できないので、数カ所編集する。

まず、docker psでコンテナIDを確認して

docker exec -it コンテナID /bin/bash

でコンテナに入る。エディタがないのでapt install vimとかで手に入れる。sedで頑張れるならいらない。

/opt/openstack/horizon/openstack_dashboard/local/local_settings.pyの最終行を

OPENSTACK_API_VERSIONS = {"identity": 2.0 }

に編集する。環境変数から取れるようになっているのだが、うまく動作しなかった。

次に、/opt/openstack/horizon/openstack_auth/utils.py

def get_project_list(*args, **kwargs):
    中略

    if get_keystone_version() < 3:
        projects = client.tenants.list()

を 

def get_project_list(*args, **kwargs):
    中略

    if get_keystone_version() < 3:
        import os
        from keystoneclient.v2_0 import tenants
        projects = [tenants.Tenant(None, {'id': os.getenv('OS_TENANT_ID'), 'name':  os.getenv('OS_TENANT_NAME'), 'description': '', 'enabled': True}, loaded=True)]

に変更する。デフォルトではtokenからTENANT情報をAPIで取りに行くようだが、環境変数から取得する。

本当はログイン画面からTENANT_ID、NAMEを入力する方式がいいのだが暫定でこれで動かす。

動作確認

以下の動作は確認した

  • VPSの一覧の表示
  • セキュリティグループの編集、割り当てができる

f:id:smitch:20210204215001p:plain いろいろエラーが出ているが動いたので気にしない。

課題・やり残し

  • API公開していないなどで、404になる問い合わせが散見される
  • セキュリティグループの新規作成ボタンが表示されない(roleの問題?未確認)

感想

  • GUI操作便利
  • horizonの動作は割ともっさりしてる。メモリも200MBくらい使うので、サーバスペック的に常時動かすのは見送り。

NG集

NG1: docker buildできない

alvaroaleman/openstack-horizonのDockerfileからbuildしようとしたが、

pyrsistent requires Python '>=3.5' but the running Python is 2.7.13

でbuild失敗する。

どうやら、debianpythonが2.7であるのに対して、pyrsistentが3.5以上しかサポートしなくなったことが原因のようである。

debianはデフォルトがpython2.7のようであるので、こちらの環境の検討はここまでにする。

NG2: API version書き換えられない

ubuntuイメージにて最新のOpenStackを動かしたが、API VERSIONで2.0を指定しても

The Keystone URL in service catalog points to a v2.0
Keystone endpoint, but v3 is specified as the API version
to use by Horizon. Using v3 endpoint for authentication.

にてv3が強制される。OpenStackの最新版ではv2.0が廃止されている。

v2.0が使えるバージョンを使用すると各種pythonパッケージのバージョンを合わせるのが大変になるのでこれも断念した。

hostname, domainname設定のメモ(CentOS7)

ホスト名やドメイン名の設定はディストリビューションやバージョンによって推奨が異なっており、ややこしい。 設定ファイルの動作を確認したのでメモしておく。

TL; DR

環境

$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core) 
$ cat /etc/postfix/main.cf
myorigin = $mydomain
以下略

設定

とする。

# echo hoge.example.com > /etc/hostname
# systemctl restart NetworkManager

/etc/hostsに設定も入れた方がいいのかは不明。入れている記事が多いが、動作したので気にしないことにする。

ドメイン名を/etc/sysconfig/network-scripts/ifcfg-eth0や/etc/resolve.conf に記載する記事もあるが、古い作法のようである。

確認

$ hostname
hoge.example.com

$ hostname -f
hoge.example.com

$ dnsdomainname
example.com

$ cat /etc/resolv.conf
# Generated by NetworkManager
search example.com
nameserver 192.0.2.1

失敗例

上記に加え、/etc/hostsに以下を設定

127.0.0.1 localhost localhost.localdomain hoge.example.com

結果

$ hostname
hoge.example.com

$ hostname -f
localhost

$ dnsdomainname
example.com

FQDN表示がlocalhostとなる。

127.0.0.1 hoge.example.com localhost 

が正しいようである。

その他

ホスト名の設定前はメールの送信元が user@localdomain.localdomain となっていた。

パスワード強度判定の正規表現と肯定的先読み

数字アルファベット大文字小文字を含む8文字以上の文字列にマッチする正規表現のメモ

条件は正規表現で書くと ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[!-~]{8,}$ となる。

これを可視化すると、

https://jex.im/regulex/ f:id:smitch:20200208123436p:plain

https://regexper.com f:id:smitch:20200208123431p:plain

となるが、肯定的先読みがregulexでは表示されていない。 regexper.comでもpositive lookaheadの表記があるのみ。

正規表現なんだからオートマトン で書けるでしょって思ったのだが、結構大変なようである。

中身をちゃんとは読めていないのだが、大きさmの正規表現が状態数O(22m)の決定的有限オートマトンになるらしい。

先読み付き正規表現の有限状態オートマトンへの変換 森畑 明昌, PPL2011 https://www.jstage.jst.go.jp/article/jssst/29/1/29_1_1_147/_pdf

windows server 2016 datacenterのセットアップメモ

TL; DR

やったこと

  1. windows update
  2. 管理者アカウント(非administrator)の追加とadministratorの停止
  3. sambaセットアップ
  4. firefoxインストール
  5. remote desktop用証明書のセットアップ(let's encrypt)
  6. remote desktopのポート変更
  7. 不要なfirewallルールの削除

windows update

  • 説明不要

管理者アカウント(非administrator)の追加とadministratorの無効化

  • コンピュータの管理→ローカルユーザとグループ→ユーザから新規アカウントを作成。Administrator権限を付与
  • 新規アカウントでサインインし、administratorを無効化

sambaセットアップ

windows -> samba server

  • アクセス先:Centos7 samba Version 4.8.3

エクスプローラにて¥¥を入力し、認証情報を入力

はまったこと

  • ネットワークドライブの割り当てができない。ユーザ認証後、「ネットワーク名が見つかりません」のエラーが出る(未解決)
  • windows serverへはmacからリモートデスクトップしているのだが、「¥」が普通にキーボードから打つと特殊記号扱いされる(?)。スクリーンキーボードから「¥」を入力することで解消

外部 -> windows server

  • 共有したいフォルダを作成し、右クリック→共有にて設定する
  • 外部(centos)にて以下を実行
sudo yum install samba-client cifs-utils
sudo mount.cifs //<server ip address>/<path to share folder> <mount point> -o "user=<user name>,uid=$(id -u),gid=$(id -g)"

sudo mount したときに、ログインユーザーでのパーミッションをつける - IKB: 雑記帳

firefoxインストール

IEではセキュリティ警告が多いのsamba経由でfirefoxインストーラを渡し、インストールする

remote desktop用証明書のセットアップ(let's encrypt)

remote desktopのポート変更

  • regeditにてHKEY_LOCAL_MACHINE¥SYSTEM¥CurrentControlSet¥Control¥Terminal Server¥Winstations¥RDP-Tcp中のPortNumberを書き換える
  • firewallにて指定したTCPポートの受信ルールを作成する ※デフォルトのリモートデスクトップのルールはポート番号が変更できない
  • サーバを再起動

不要なfirewallルールの削除

  • 受信の規則でRDP、SMB関連、ICMP関連以外は全て無効化
  • 送信規則は今後検討

その他

  • メモリ1GBのVPSなので動作が不安だったが、ちゃんと動く。

anaconda on mac にてpython環境の新規構築ができない

macでanacondaを利用してpythonの環境を作ろうとしたが、anacondaで新規にpythonのインストールができない不具合に遭遇したので対応のメモ

環境

macOS Mojave 10.14.6(18G95)
MacBook Air (Retina, 13-inch, 2019)

事象

anacondaをインストール後、GUIのanaconda-navigatorから新規にpythonの環境をインストールしようとしたところ、 ダウンロードが進んでいる様子はあるが、pythonの一覧に新規環境が追加されない。

対策

以下の内容にて構築できたが根本原因は不明。

1 terminalの起動

2 terminal上でanaconda-navigatorの起動

terminal上で、 /anaconda3/bin/anaconda-navigator にてanaconda-navigatorを起動

3 環境の構築

anaconda-navigatorの Environments⇒Createからpythonの環境を作成する。 HomeからJupyterlabもインストールしておく

4 通常通りanaconda-navigatorを利用

以降はterminalから実行しなくても使える

permission系のエラーかなという予想ではあるが、terminalから実行すると正常動作したので、ちゃんとデバッグ出来ていない。

再インストールしても同様の現象が発生するので再現性もあった。

python注意点まとめ

思うところあってpythonを真面目に勉強したので、ハマったことなどまとめ。

なお、特にこだわりはないけど環境はpython2

TL: DR

  • FizzBuzzブラックジャックとヒープツリーを実装してみた
  • インデントを揃える。話はそれからだ
  • phpのvar_dumpに相当する関数はない
  • unittestは標準で用意されている
  • for文を使うときはfor i in range(0, n):とする。rangeがなくても動くが、期待通りに動かない
  • implicit falseが推奨らしい

FizzBuzz

短いのでインラインで。 慣習的なものはよくわからないけど多分そんなに違わないと思う。

import sys

def fizzbuzz(n):
    ret="1"
    for i in range(2, n+1):
        if (i%15)==0:
            ret+=" FizzBuzz"
        elif (i%3)==0:
            ret+=" Fizz"
        elif (i%5)==0:
            ret+=" Buzz"
        else:
            ret+=(" "+str(i))
    print(ret)

実行結果は

$ python fizzbuzz.py 15
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz

となる。

ブラックジャック

プログラミングのステップの1つとしてブラックジャックを実装してみるのがいいみたいなので書いてみた。

こっちもレギュレーションをきちんと確認していないので雰囲気で実装。

コードはここに

https://github.com/smitch/python-practice/blob/master/blackjack.py

結構楽しいので、時間があるときにもうちょっと詰めたい。

カードカウンティングとかも面白そう。

unittest

ブラックジャックを書いた後にunittestが標準であることに気づいた。

unittest.TestCaseを継承したクラスを作成して、メソッド名がtestで始まるメソッドを実装すればunittest.main()を呼び出すだけでテストメソッドを実行してくれる。

メソッド名がtestで始まるメソッドを実装すればよい。(大事なことなので2回言いました)

継承してメソッド実装すると、実装したメソッドを自動実行するっていうのも面白い仕様だと思った。時間があるときにunittestの実装もみてみよう。

なお、pythonの実行時に-vオプションを付けることでテストの情報が出力される。

詳しいことはここに

unittest --- ユニットテストフレームワーク — Python 3.7.4 ドキュメント

ヒープツリー実装

そこそこ真面目なヒープツリー実装のはず。。。

python標準ライブラリのheapqはリスト実装だけど、今回はグラフを使ったツリー構造での実装。

https://github.com/smitch/data_structure_and_algorithm/blob/master/tree/heap_tree.py

iteratorとyield

yieldを使うと明示的に状態を持たなくてもiteratorが実装できる。

yieldでヒープツリーのDFSを実装するとこんな感じ。

    def dfs_iter(self, current=None):
        if current is None:
            current = self.root
        yield current
        if current.left is not None:
            for i in self.dfs_iter(current.left):
                yield i
        if current.right is not None:
            for i in self.dfs_iter(current.right):
                yield i
        raise StopIteration

最初、yieldはreturn的な動作だと思ったが、returnとは切り離して考えた方が良さそう。

yieldの流れは、

  1. yieldを使うメソッドを呼び出すと、generatorが返ってくる。

  2. 得られたgeneratorのnext(next)メソッドを呼び出すことで、実際のメソッドの中身が実行される。

となる。

for文と合わせて使うと自然に使える。

ちょっと特殊な感じがするけど、慣れると便利そう。

pydoc

pydoc <module name>

にてドキュメントが生成される。

モジュール名はファイル名から.pyを除いたもの

pycheck

pipでインストールする。

pychecker <file name>

にて構文のチェックを行なえる。

細かい設定はまだ追えていない。

pylintとかも調べたい。

python style guide

pythonのスタイルは大きくgoogle styleとnumpy styleの2つがあるらしい。

今回はgoogle styleを参考にした。

https://github.com/google/styleguide/blob/gh-pages/pyguide.md

var_dump

pprint.pprint(vars(a))などでインスタンス変数の一覧を出力できる。

内部的にはvarsはa.__dict__を出力している模様。

なお、printを実行すると__str__が呼ばれる。

特殊属性、メソッドは把握しきれていないので、きちんとまとめたい。

このサイトはかなり参考になった。

特殊メソッド名 - Dive Into Python 3 日本語版

implicit falseとNone

  • 変数が0,[],False, None等の場合の分岐はif a:の表記が推奨。ただし、0Falseを区別したい場合には使えない。
  • 変数とNoneの比較はしてはいけない。if a is Noneと書く。

NoneTrueでもFalseでもない。ちょっと人工的な例だけど下のようなコードを書くとハマる。

if a == True:
    print "true"
elif a == False:
    print "false"
else:
    print "a is neigher True nor False!"

python2とpython3の違い

ここまでやってみて気づいた点

  • printがpython2では構文だがpython3では関数
  • イテレータの次の要素の取得がpython2ではnextだがpython3では__next__
  • python2ではprintで末尾に必ず改行が入る。

今後やりたいこと

  • assertに引っかかったらプログラム停止して、インタラクティブモードになるようにしたい。どこかのサイトに実装があったはず。

スピードキューブで1分以内に揃えられるようになった

「時間かければ揃えられる(2分以内くらい)」→「1分以内に揃えられる」までトレーニングしたのでメモ書き。

1分以内は手順覚えて練習すれば出来るみたいな記事があるけど、実際どれくらいのレベルなのかを書いておく。

TL; DR

  • 手が常に動く程度にキューブの状態を確認出来るようになれば60秒以内は達成できる

  • 揃え方のパターンは覚えこまなくてもいい(F2Lのパターンなど)

  • タイマーアプリを活用する

現在のレベル

基本的にはLBLやCFOPな揃え方をしているが、揃え方が我流なので一般的なのより効率悪いかも。 いろいろ考えてやっていくのが楽しいというスタイルなので、今の段階では覚えるのはあまりしない。 1分切れるようになったので、おいおい一般的なのも覚えていきたい。

具体的な手順は時間があるときにまとめたい。

やっている揃え方とおおよその所要時間

  • cross

とにかく揃える。それだけ。目標10秒以内だけど15秒くらいかかることもある。

現状のレベルだと、インスペクションの15秒ですべて読みきるのは結構きつい。 大体3つは読んで、最後は場当たりで揃えることが多い。ひどい時は2つまでしか読めないが、その際は1分はかなりきつい。

  • F2L

当初は1層目、2層目の順でやっていたけど、入れられるところからこだわらずにやったほうが速かった。

キューブを探すのに時間が掛からないようにする。

現状だと、次に揃えるキューブの場所のあたりはつくけど、向きとかが正確に把握できていないので、 一旦動きを止めて確認する必要がある。このあたりは今後の改善点

ここまでで35秒くらいかかる。

  • OLL(コーナーキューブ)

まず、last layerのコーナーキューブの位置を調整する。 PLLの前にするのは理由が2つある。

1つ目は単純に、いわゆるUパームの手順を知らないから。つまり、PLLしてからPLLされた状態に戻しつつコーナーキューブの入れ替えをする手順を知らないからやっていない。

2つ目は、こっちのほうが入れ替えの操作回数は少なくなると思っているから。キューブの状態確認に時間がかからなければ、PLLを気にしなくていい分、早めに操作したほうが手順が少ないと思う。

なお、エッジキューブの位置調整はこの段階ではしない。

だいたいここまでで43秒くらい。45秒までかかると後がきつい。

  • PLL

コーナーキューブとエッジキューブの上面の向きを揃える。

なお、コーナーとエッジキューブはそれぞれ独立した手順で揃える。

ここまでで50秒くらい。

  • OLL(エッジキューブ)

エッジキューブの並び次第で、同じ手順を0〜2回繰り返すことになる。

順調にできていないと手順2回だと1分以内はきつい。

タイマーアプリについて

スマホアプリが有能。

数は試してないけどこれが良かった。

play.google.com

機能としては

  • タイマー機能

  • スクランブル生成

  • 記録の統計

があるので、かなり練習が捗る。

スタックタイマーのデザインになっているので雰囲気もそれっぽくなる。

改善点と今後の目標

40秒切るくらいまでは現状の改善でできそうな気がする。 具体的には、 - クロスはインスペクションで読みきって、10秒で確実に揃える。可能であればF2Lも少し読む。 - F2Lでコーナーキューブとエッジキューブを同時に揃える - OLLの手順が少なくなるようF2Lの手順を調整する - OLL、PLLでキューブの状態を逐次確認しなくても良くなるよう、連続した手順を行えるようにする

F2Lの短縮が大きく効きそうなのでそこを重点的にしたい。 パターンごとの手順を覚えなくても、キューブの状態の把握の向上と、特定の手順を行った時にその他のキューブがどう動くのかを読めるようになれば自然とF2Lで出来るようになると思う。

とりあえず1分切ったので、40秒まではぼちぼちなペースでやっていくつもりである。 手順は意識せずに、継続練習でキューブの状態把握の向上を半年くらいやってみようと思う。