台帳の扱いについて

execjson の話の続きとなる。
http://aaabbb-200904.hatenablog.jp/entry/20150430/1430398428

サービス要求(以下、SR)処理の自動化に関連して、必ず問題になってくるのが、
台帳更新をどうするか、だと思う。

通常、人間が実施する場合は、作業を実施した日付、内容、等を台帳(大抵はエクセル)に記述していくのだが、自動で処理する場合は、エクセルに書き込むわけにはいかない。
また、台帳全てをRDBで置き換える、という判断をした場合、自動処理内で実行する、SQLの開発が、それなりの量になる。
※ カスタム開発にするしかないので、自動処理自体の価格も高止まりになる、、

どうするか、なのだが、execjson では、処理が流れる際に、JSONをelasticsearch に投げるようにしている。

※ 書き方は大変いけてないが、、
os.popen('curl --silent --max-time 15 -XPUT http://%s/jobstates/jobstate/%s -d @%s.state > /dev/null' % (elasticsearchurl, docid, filename)
https://github.com/aaabbb200909/execjson/blob/master/web/mysite/batch/do.py

これによって、作業が発生した日付、実施内容が記録でき、かつ kibana 経由で検索出来るようになっている。

基本的には台帳の役割は、上記の 1. 作業内容の検索 が主となるのだが、
それ以外に、2. 設定状況の一覧表、 3. 新規払出の一次ソース、という役割もある。

2 については、基本的には管理対象の筐体の設定ファイル、と同じになるため、
 rsync+git
http://aaabbb-200904.hatenablog.jp/entry/20120825/1345908313
で、代用できる。
※ ただし、記述内容が複数のファイルにまたがる(vSphereのVM定義、など) ことがあるため、場合によっては、日次バッチ等で、エクセルに類似のHTMLを作る必要があるかもしれない

3. については、2で対応できないもの、
例えば、IPアドレスの払い出し(実機上に情報が無い) 、等がある。

2016/9/22 追記
これ以外に、ハードウェア目録、ハードウェア配置図、や、マクロが組み込まれており、エクセルが一次情報になっているケース、等もある


これに関しては、、他のソースから取り出すわけにはいかないので、
諦めてRDBを定義するしかない。
DjangoのO/Rマッパー, adminコンソール機能を使って、できる限り簡易に扱えるようにするくらいだろうか、、

上記、1,2,3 で台帳の役割は尽きていると思うのだが、どうだろうか。
※ 開発量を抑えるポイントとしては、3以外は開発工数無しで、置き換え可能なので、
 出来るだけ1,2 で処理を完結できるようにし、3に流れる分を減らすこと、となる。

ポストVLANのネットワークについて

最近諸事情で、 SDN/NFV の話について調べている。

現行構成の問題点について、まとまっている本がこちら。
https://www.amazon.co.jp/VMware-NSX-ebook/dp/B00UL14E3C/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=1473494901&sr=8-1
いくつか上がっているが、パッと見てまずそうなのは、

  1. アクティブVLAN問題(安めのアクセススイッチだと同時に使えるVLANの数に限りがある(1000程度))
  2. MACアドレス上限問題(そもそもスイッチが覚えられるMACの数が限界)

あたりだろうか、、
※ サーバー数1000超えたあたりからどうにもならなくなりそう

対応としては、以下の構成になる。


VLANがVXLANに置きかわって、VLANタグの付与(実際にはVXLANでのラップ)を物理スイッチではなく、ハイパーバイザで肩代わりする形になっている。

ポイントとしては、以下。

  1. ハイパーバイザ間の接続にはVLANを用いない(用いてもよいけれど仮想スイッチの数だけトランク接続する、はしない)
  2. 仮想OSから発生した通信は、仮想スイッチのVXLAN(かGRE)でラップし、行き先のハイパーバイザに送る
  3. どうしても物理サーバーを仮想スイッチと同じセグメントに置きたくなった場合には、ToRスイッチのVXLAN機能を使って、仮想スイッチに直接送る

上記で、現行の仕組みと同じような構成が提供できそうに見える。
実際、パブリッククラウドの適用も広がっているので、サーバー数が1000台超える組織は少ないかもしれないが、状況によっては必要になりそうなので、覚えておこう
※ また、完全に新規ネットワークを組む場合は、最初から上記構成でいった方が、ハードウェア代が抑えられるものと思われる。

追記:
図の注意:

  • 上図の黒線スイッチはVLAN使用可能(値段高い、たくさん必要)
  • 下図の青線スイッチはVLAN不要(値段安い、たくさん必要)
  • 下図の青塗り潰しスイッチはVXLAN必要(高いが台数少ない)

SEが役に立った、と思ったkindle本5冊(技術書以外で)

手持ちの kindle本の数を調べてみたところ、492冊あった。
この中で、これは役に立った!というものを順に上げてみる。(技術書は除く)

1-1. 9割の人が間違った買い物をしている 成功している男の服選びの秘訣40 成功する男のファッションの秘訣

1-2. 9割の人が小物選びで損をしている ビジネススーツを格上げする60のルール 成功する男のファッションの秘訣

https://www.amazon.co.jp/%EF%BC%99%E5%89%B2%E3%81%AE%E4%BA%BA%E3%81%8C%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E8%B2%B7%E3%81%84%E7%89%A9%E3%82%92%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%80%80%E6%88%90%E5%8A%9F%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E7%94%B7%E3%81%AE%E6%9C%8D%E9%81%B8%E3%81%B3%E3%81%AE%E7%A7%98%E8%A8%A3%EF%BC%94%EF%BC%90-%E6%88%90%E5%8A%9F%E3%81%99%E3%82%8B%E7%94%B7%E3%81%AE%E3%83%95%E3%82%A1%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E7%A7%98%E8%A8%A3-%E8%AC%9B%E8%AB%87%E7%A4%BE%E3%81%AE%E5%AE%9F%E7%94%A8%EF%BC%A2%EF%BC%AF%EF%BC%AF%EF%BC%AB-%E5%AE%AE%E5%B4%8E%E4%BF%8A%E4%B8%80-ebook/dp/B00BLDNAFC/ref=sr_1_1?ie=UTF8&qid=1472294754&sr=8-1&keywords=%EF%BC%99%E5%89%B2%E3%81%AE%E4%BA%BA%E3%81%8C%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E8%B2%B7%E3%81%84%E7%89%A9%E3%82%92%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B
https://www.amazon.co.jp/%EF%BC%99%E5%89%B2%E3%81%AE%E4%BA%BA%E3%81%8C%E5%B0%8F%E7%89%A9%E9%81%B8%E3%81%B3%E3%81%A7%E6%90%8D%E3%82%92%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E3%82%B9%E3%83%BC%E3%83%84%E3%82%92%E6%A0%BC%E4%B8%8A%E3%81%92%E3%81%99%E3%82%8B%EF%BC%96%EF%BC%90%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB-%E6%88%90%E5%8A%9F%E3%81%99%E3%82%8B%E7%94%B7%E3%81%AE%E3%83%95%E3%82%A1%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E7%A7%98%E8%A8%A3-%E5%AE%AE%E5%B4%8E%E4%BF%8A%E4%B8%80-ebook/dp/B015CETXSS/ref=pd_sim_351_2?ie=UTF8&psc=1&refRID=WP991JRH9MTRG13F53YW

いろんな服があるけれど、結局何を着ればよいのか?が分かった本。
ようやく、休日: Tシャツ+ジーンズ+スニーカーのみ、 仕事: スーツ+黒革靴のみ、から脱出できた、、
クールビズ対応や、カジュアルな集まりまで、いろいろ役立つ。
あと、革靴等のフォーマルについても、ここで初めて覚えられた(ストレートチップ/プレーントウ、内羽根/外羽根、等)

2. 全面改訂 超簡単 お金の運用術

Amazon CAPTCHA

外貨預金、外国債券、デリバティブ、等いろいろな商品がある中で、結局何を買えばよいのか、がわかるようになった本。
とりあえず、これに合わせて運用している。

3. 図解 ワイン一年生

Amazon CAPTCHA
シャルドネ、とメルローの違いがわかった(こんな感想でよいのかわからないけれど、、)
2時間くらいで読めて、ワインがわかった気になる本。

4. アドラーに学ぶ部下育成の心理学 「自ら動く部下」が欲しいなら ほめるな叱るな教えるな

Amazon CAPTCHA

部下を育てる方法(というより勝手に育つための方法?)をまとめた本。
意見がわかれるところかと思うけれど、自分の経験からも、これが正攻法なんだと思う。

5. 新版 はじめての課長の教科書

Amazon CAPTCHA

4とは逆で、会社から何を求められているのか、をまとめた本。
4 とセットで読む印象。
ただ、外資系ではあまり使わないかも。

次点

とても面白かった、なのは間違いなけれど役に立ったか、というと微妙。暇なときに読む感じ。
HARD THINGS 答えがない難問と困難にきみはどう立ち向かうか
お金持ちの教科書
リーン・スタートアップ ムダのない起業プロセスでイノベーションを生みだす

番外

シティプラチナカード(現 SMBCプラチナカード) のWebページ
https://www.sumitclub.jp/ja/cardlineup/sumit_platinum.html

結局、どんなものにお金をかけるのが順当なのか、が少し見えてくる。
※ グルメ、トラベル(出張含む)、ゴルフ、コンシェルジュサービス、など。
ダイニングセレクション、手荷物宅配、プライオリティパスあたりがとても便利
※ 実は年収400万円くらい (世界的に見れば、十分プラチナホルダーレベル) から手に入るらしい

結論

なんだかんだいって、新しいことを始めるには、本が最適だと思うので、今後も要探索。

PowerShellでgmetricを送るには

※ CentOS6/gmond-3.7.1で動作確認済み($ nc localhost 8649 で値が表示されるところまで)

(参考サイト)
https://github.com/ganglia/ganglia_contrib/blob/master/gmetric-python/gmetric.py
http://stackoverflow.com/questions/12148666/send-and-receive-data-via-udp-in-powershell

# Define port and target IP address 
[int] $Port = 8649 
$IP = "192.168.122.101" 
$hostname="null" # not used by gmond


#############

function get_string_header($str) {
 $a=$str.length
 if ($a -lt 255) {
  return [char]0+[char]0+[char]0+[char]$a
 }
 else {
  return [char]0+[char]0+[char]$a
 }
}

function get_padded_string($str) {
 $len=$str.length
 $a=$len % 4
 $tmp=$str
 
 for ($i=0; $i -lt $a; ++$i){
  $tmp+=[char]0
 }
 return $tmp
}


function packer_pack($str) {
 $tmp=get_string_header $str
 $tmp+=get_padded_string $str
 return $tmp
}



function get_padded_int($int) {
 if ($int -lt 255) {
  return [char]0+[char]0+[char]0+[char]$int
 }
 else {
  return [char]0+[char]0+[char]$int
 }

}



function gmetric_buffer($name, $val, $type) {


#
# Meta Packet
#

 $meta=""

 $meta+=get_padded_int 0x80
 $meta+=packer_pack $hostname
 $meta+=packer_pack $name

 $meta += get_padded_int 0 # slope: zero
 $meta+=[char]0
 $meta+=[char]0

 $meta += packer_pack $type
 $meta+=[char]0
 $meta+=[char]0
 $meta += packer_pack $name

 $meta+=[char]0 # units ""
 $meta+=[char]0

 $meta += get_padded_int 0 # slope: zero
 $meta += get_padded_int 58 #
 $meta += get_padded_int 60 # tmax uint
 $meta += get_padded_int 60 # dmax uint
 $meta += get_padded_int 0 # group: not in any group


#
# Data Packet
#
 $data=""
 $data+=get_padded_int 0x85

 $data += packer_pack $hostname
 $data += packer_pack $name

 $data+=get_padded_int 0
 $data+=[char]0
 $data+=[char]0
 $data += packer_pack "%s"
 $data += packer_pack $val

 return ($meta, $data)
}




#
# Main
#

if ($args.length -ne 3) {
 echo "gmetric.ps1 name val type"
 return 0
}

$name=$args[0]
$val=$args[1]
$type=$args[2]


$Address = [system.net.IPAddress]::Parse($IP) 

# Create IP Endpoint 
$End = New-Object System.Net.IPEndPoint $address, $port 

# Create Socket 
$Saddrf   = [System.Net.Sockets.AddressFamily]::InterNetwork 
$Stype    = [System.Net.Sockets.SocketType]::Dgram 
$Ptype    = [System.Net.Sockets.ProtocolType]::UDP 
$Sock     = New-Object System.Net.Sockets.Socket $saddrf, $stype, $ptype 
$Sock.TTL = 26 

# Connect to socket 
$sock.Connect($end) 

# Create encoded buffer 
$Enc     = [System.Text.Encoding]::getencoding("iso-8859-1")
($meta, $data)=gmetric_buffer $name "$val" $type

$Buffer  = $Enc.GetBytes($meta) 
$Sent   = $Sock.Send($Buffer) 

$Buffer  = $Enc.GetBytes($data) 
$Sent   = $Sock.Send($Buffer) 

Service Request should be written in JSON

※ カスタマーからリクエストを受ける仕組みを、改善する画面を書いたので、一筆

状況

エンドユーザーからServiceRequest(以下、SR) を受け取る場合、可能であれば、Webから受け取って、受け取った値をそのままDBに反映したり、fabricコマンドを発行したりしたいのだが、SRの受け取り方によって、そう出来ないケースがある。
ひっかかっているのは、"SR の受け取り方が承認フローとして固定されており、かつ、承認に使用している画面が変更できない場合" となる。
※ 承認された際に担当者にメールが飛んで担当者がコマンドを発行する。ツールから直接fabricコマンドを発行して欲しいのだが、、

現状、SR の本体(このSQLを発行して欲しい、ここにファイルを置いてほしい、など) は、エクセルに記述しており、条件付き書式等を使って入力をチェックしたりしているのだが、エクセル(Windows)からfabric(RHEL)を呼び出すところの書き方が微妙だったり、JavaScriptほどチェックが書きやすくなかったりで、今後のことを考えると、どこかでこの仕組みをWeb化しておきたいところだった。

対応

対応として、入力したフォームをJSONとしてエクスポートするための、新規のWeb画面を作ってみた。
新規フローは以下となる。

  1. 画面から作業内容を記述 -> JSONとしてエクスポート。
  2. エクセルの代わりにJSONを添付。承認フローを通す。
  3. オペレーターが、JSONRHELの某ディレクトリに配置。常駐ジョブが、JSONを解釈してfabricを呼び出す(ジョブが多数定義されている場合も、そのまま続けて呼び出す)

※ 作業用のweb画面

※ 上記画面に対応するJSON

効果

今までエクセルの内容をコピペしてfabricコマンドを作ったりしていたので、オペレーターの作業が非常に大変だったのだが、今後は、そのまま流せるのでだいぶ作業が楽になりそうだ、、
※ 当初 rundeckやjenkinsを使って上記を実現しようとしていたのだが、どちらもコマンドを自由に書けてしまうため、採用出来なかった、、(各種事前チェックの実装がDev任せになってしまう、リリースロジックの出来にムラあり)

(参考)作り

画面本体はDjangoJQueryを組み合わせて書いている。(fabfileを除くと600行くらい)
githubに上げてみようとしたのだが、コード内に固有名詞がありすぎて難しかった、、 orz



2016/2/28追記
-> githubにアップしました
https://github.com/aaabbb200909/execjson

2013年04月07日のツイート

qpid+gluster-swift でファイル転送

元々qpidはMQでファイル転送等の大量データのやりとりのツールではないので、、大容量データ転送ともろもろの後続ジョブ制御を兼ねて、qpidとgluster-swift(gluster UFO)を組み合わせてみた。

実現したい内容

実現したい内容は以下になる。

  • 1. 巨大ファイル(数GB程度を想定)の転送に対応出来る
  • 2. 送信元は、送信先の後処理が終わったかを確認せずに、次の処理に移れる
  • 3. 送信先は、ファイルが到着したらすぐに、事後処理を始める
  • (4: オプション)各計算ノードは巨大ファイルを載せられるだけのローカルディスクは持たず、直接glusterをマウントして使用する
  • 5. 計算ノードが停止していても、送信元はファイル送信を完了出来る

※ 1, 4, 5を実現するために、gluster-swift, 2, 3, 5 を実施するためにqpidを使う形になる。

実施方法

次の順で実施する。

  • 1. 送信元はgluster-swiftに対して HTTPでアップロードする。この後、qpidの特定のキューに対して、contentにglusterのファイルパスを指定したメッセージを書き込む。(ファイルパスはその時の時刻等を含めて、重複しないようにしておく)
  • 3. 送信先は事後処理を書き込んだスクリプトをqpidに対してアタッチしておく。(メッセージが届くと、MQの消費処理の一環として、事後処理が流れる)

※ ただし、実際に使ってみたところ、gluster-swiftでアップロードしたファイルが必ず 600, rootで設定されるため、その他のユーザーで事後処理を行うために、次の処理も必要になった。(計算ノードのジョブをrootで動かす場合は不要, また、gluster-swift経由でchmodが出来ればこの処理は不要になるはず。。)

  • 2. gluster-swift のノードで、 glusterfsに置かれたファイルにchmodを行うプロセスをqpidのserver 処理として稼働させておく。このプロセスは1のキューにアタッチしておき、chmodを実施したあと、3のキューにメッセージを配送する。

なお、テスト環境では次の3つのスクリプトで実施している。

  • 1: transferfile.sh
  • 2: peformchown.py
  • 3: consumefile.py

※ サンプルファイルはブログの後半に添付
※ 同じディレクトリに python-qpidサンプルのspout を置かないと上手く動かない。(swiftコマンドも必要)

まとめ

オープンソースだけだと、ファイル転送/その後の事後処理(非同期) を上手く実施するための仕組みがあまりなかった気がするが(知らないだけかも)、さしあたりこの組み合わせで動くものが出来そうな気がしている。
プロプライエタリ製品を含めると結構ある
価格も安く済みそうだし、おすすめかも。

スクリプトサンプル

transferfile.sh

起動方法:
 $ ./transferfile.sh
////
filename=aaa
container=container$(date +%s)
queuename=myqueuepre
replyto=myqueue

# upload file
swift --auth=https://localhost/auth/v1.0 --user=test:tester --key=testing  upload ${container} ${filename}
if [[ 0 -ne $? ]]
then
 echo "Cant upload file"
 exit 31
fi

# Then say that I uploaded file
./spout --reply-to=${replyto} ${queuename} ${container}/${filename}
if [[ 0 -ne $? ]]
then
 echo "Cant MQ"
 exit 32
fi

performchown.py(serverからの差分のみ):

起動方法:
 (root)# ./performchown.py myqueuepre
////

$ diff -u server performchown.py 
--- server      2013-04-06 19:26:30.089313772 +0900
+++ performchown.py     2013-04-06 20:41:20.259411750 +0900
@@ -18,7 +18,7 @@
 # under the License.
 #
 
-import optparse, sys, traceback
+import optparse, sys, traceback, os
 from qpid.messaging import *
 from qpid.util import URL
 from subprocess import Popen, STDOUT, PIPE
@@ -68,6 +68,13 @@
     result = Message(content)
   else:
     result = Message("unrecognized message type: %s" % msg_type)
+    #######
+    accountname='test'
+    print 'Use this:', msg.content
+    filepath='/mnt/gluster-object/AUTH_%s/%s' % (accountname, msg.content)
+    os.chmod(filepath, 0644)
+    result=msg
+    #######
   return result
 
 try:
@@ -87,7 +94,7 @@
     if snd is not None:
       snd.close()
     ssn.acknowledge()
-except ReceiveError, e:
+except ReceiverError, e:
   print e
 except KeyboardInterrupt:
   pass


consumefile.py(drainからの差分のみ):

起動方法:
 $ ./consumefile.py -f myqueue
////
$ diff -u drain consumefile.py 
--- drain       2013-04-06 19:26:30.084988056 +0900
+++ consumefile.py      2013-04-06 21:00:45.910323049 +0900
@@ -18,7 +18,7 @@
 # under the License.
 #
 
-import optparse
+import optparse, os
 from qpid.messaging import *
 from qpid.util import URL
 from qpid.log import enable, DEBUG, WARN
@@ -85,6 +85,16 @@
     try:
       msg = rcv.fetch(timeout=timeout)
       print opts.format % Formatter(msg)
+      #######
+      accountname='test'
+      print 'Use this:', msg.content
+      filepath='/mnt/gluster-object/AUTH_%s/%s' % (accountname, msg.content)
+      f=file(filepath)
+      print f.read()
+      f.close()
+      ##
+      os.system('swift --auth=https://localhost/auth/v1.0 --user=test:tester --key=testing delete %s' % msg.content.split('/')[0])
+      #######
       count += 1
       ssn.acknowledge()
     except Empty: