2016年12月29日木曜日

LibreOffice(calc) マクロとTeraTermマクロを使って簡易リリースツールを作ってみる


WindowsでLibreOffice(calc)BasicマクロとTeraTermマクロを使用した、リリースツールを作ってみます。

リリース先は CentOS6.7です。
Windows側で今回使用するソフトウェアのバージョンは以下のとおり。
Windows10
TeraTerm4.93
LibeOffice5.1.5.2

リリースするファイルと配布先のIPアドレスなどの情報は、CSVファイルに記載することにします。
このCSVファイルを、LibreOfficeで作成し、TeraTermマクロで入力して、ファイル送信します。

TeraTermマクロの仕様は以下のとおり。
TeraTermマクロでファイルを送信するには、サーバ側に openssh-clients パッケージがインストールされている必要があります。
また、文字コード変換には nkf を使用します。
  • CSVファイルを入力する
  • 指示されたサーバにログインする
  • ファイル種別により以下の処理を行う
    • "txt" の場合
      ファイルを送信する
      オーナ、パーミションを設定する
      文字コードをUTF-8、改行コードをLFに変換する
    • "bin" の場合
      ファイルを送信する
      オーナ、パーミションを設定する
    • "cmd" の場合
      指示されたコマンドを実行する
  • デスクトップにTeraTermログファイルを出力する
LibreOffice(calc)Basicマクロの仕様は以下のとおり。
  • CSVファイルを作成する
  • IPアドレス(A列)と送信元ファイル名(B列)でソートする
  • 上記TeraTermマクロを実行する
CSVファイルの項目は以下のとおり
  • IPアドレス
  • 送信元ファイルPATH (txt|bin) または コマンド実行順序(cmd)
  • 送信先ファイルPATH (txt|bin) または コマンド(cmd)
  • オーナ
  • パーミション
  • 種別
    • txt : テキストファイル
    • bin : バイナリファイル
    • cmd : コマンド
  • 備考

1.TeraTermマクロ


マクロは下記PATHに保存します。
C:\workspace\LibreOfficeマクロ\rel.ttl

CSVファイルは下記PATHに格納されるものとします。
C:\workspace\LibreOfficeマクロ\sample.csv

配布先のサーバには、"root" でログインします
マクロのソースコードは以下のとおり。

;
; リリース
;
; [注意]
; サーバ側に下記パッケージがインストール済みであること
;  - openssh-clients
;  - nkf

; SSH接続アカウント情報
remote_prompt = '#'
remote_user = 'root'
remote_pass = 'p@ssw0rd'

; リリースするファイルのリスト
csvfile = 'C:\workspace\LibreOfficeマクロ\sample.csv'
separator = ','
 
; 読み取り専用でCSVファイルを開く
fileopen fh csvfile 0 0

; 1行読み飛ばし
filereadln fh buf

old_ip = '0'
while 1
    ; 1 行入力
    filereadln fh buf
    if result then
        break
    endif

    ; フィールド入力
    strsplit buf separator
    ip = groupmatchstr1
    src = groupmatchstr2
    dst = groupmatchstr3
    owner = groupmatchstr4
    mode = groupmatchstr5
    type = groupmatchstr6

    ; ログイン
    strcompare old_ip ip
    if result != 0 then

        ; IPが変わったら接続中のTerminalを ログアウト
        strcompare old_ip '0'
        if result != 0 then
            sendln 'exit'
            unlink
        endif

        ; ログイン
        sprintf2 conbuf '%s /ssh /auth=password /user=%s /passwd=%s' ip remote_user remote_pass
        connect conbuf
        if result != 2 then
            messagebox 'teraterm macro could not connect to this Server.' 'Error'
            end 
        endif

        ; ログイン待ち
        timeout = 3
        wait remote_prompt
        if result == 0 then 
            disconnect 0 
            end 
        endif
        old_ip = ip

        ; ログファイル
        getspecialfolder log_path 'Desktop'
        getdate log_name '\&h_%Y%m%d_%H%M%S.log'
        strconcat log_path log_name
        logopen log_path 0 1

        ; 接続先情報
        sendln 'date ; uname -n ; whoami'
        wait remote_prompt

    endif

    strcompare type 'cmd'
    if result == 0 then

        sendln dst
        wait remote_prompt

    else

        ; ローカルからリモートへファイル送信
        scpsend src dst

        ; 送信完了まで待機. 徐々に pause 時間を増やす
        n = 1
        while 1
            msec = 800 * n
            mpause msec
            sprintf2 cmdbuf 'ps -ef |grep -v grep |egrep -c "scp .* %s"' dst
            flushrecv
            sendln cmdbuf
            waitln '0' '1'
            if result == 1 then
                break
            endif
            n = n + 1
        endwhile

        ; オーナ設定
        sprintf2 cmdbuf 'chown %s %s' owner dst
        sendln cmdbuf
        wait remote_prompt

        ; パーミション設定
        sprintf2 cmdbuf 'chmod %s %s' mode dst
        sendln cmdbuf
        wait remote_prompt

        ; UTF8 & LF 変換
        strcompare type 'txt'
        if result == 0 then
            sprintf2 cmdbuf 'nkf --overwrite -w -Lu %s' dst
            sendln cmdbuf
            wait remote_prompt
        endif

        ; ファイル情報
        sprintf2 cmdbuf 'ls -l %s ; file %s' dst dst
        sendln cmdbuf
        wait remote_prompt

    endif

endwhile

; ログアウト
strcompare old_ip '0'
if result != 0 then
    sendln 'exit'
    unlink
endif

; CSVファイルクローズ
fileclose fh

end

2.LibreOffice(calc)Basicマクロ


マクロのソースコードは以下のとおり
LibreOffice(calc) > [ツール] > [マクロ] > [マクロの管理] > [LibreOffice Basic] を選択して保存します。
Sub ReleaseStart

    ' 最終行
    Dim oSheet as object
    Dim oCursor as Object
    Dim oRange As Object
    Dim oEndRow as Long
    oSheet = ThisComponent.getSheets().getByIndex(0)
    ThisComponent.CurrentController.setActiveSheet (oSheet)
    oRange = oSheet.getCellRangeByName("A2")
    oCursor = oSheet.createCursorByRange(oRange)
    oCursor.gotoEndOfUsedArea(True)
    oEndRow  =  oCursor.Rows.Count + 1
    
    ' ソート範囲
    Dim sort_info(1) As New com.sun.star.beans.PropertyValue
    Dim sort_fields(1) As New com.sun.star.util.SortField
    oRange = oSheet.getCellRangeByName("A1:G" & oEndRow )
    
    ' ソートキーの列を指定
    sort_fields(0).Field = 0            ' 列番号,0始まり
    sort_fields(0).SortAscending = True ' ASCかどうか
    sort_fields(1).Field = 1            ' 列番号,0始まり
    sort_fields(1).SortAscending = True ' ASCかどうか
    sort_info(0).Name = "SortFields"
    sort_info(0).Value = sort_fields()

    ' ソート範囲に列のヘッダを含むかどうか
    sort_info(1).Name = "ContainsHeader"
    sort_info(1).Value = True

    ' ソート範囲を選択してソート実行
    ThisComponent.getCurrentController().select( oRange )
    oRange.sort( sort_info() )

    ' CSVファイルに保存
    Dim sFilename as String
    Dim args(1) As New com.sun.star.beans.PropertyValue
    sFilename = "C:\workspace\LibreOfficeマクロ\sample.csv"
    args(0).Name = "FilterName"
    args(0).Value = "Text - txt - csv (StarCalc)"
    args(1).Name = "FilterOptions"
    args(1).Value = "44,34,60,1,,0,false,true,true,false"
    ThisComponent.storeToURL(ConvertToUrl(sFilename), args())

    ' ttマクロを実行
    Dim cmd as String    
    cmd = "c:\workspace\teraterm-4.93\ttpmacro.exe /v c:\workspace\LibreOfficeマクロ\rel.ttl"
    shell(cmd,0)

End Sub

3.LibreOffice(calc)にリリース情報登録


下図のように、LibreOffice(calc)の一番左側のシートに、リリース情報を登録します。



4.実行


LibreOffice(calc)の [ツール] > [マクロ] > [マクロを実行] を選択して、上記のマクロを実行します。
実行中は、下図のように、TeraTermのウインドウが表示されます。
また、ファイル転送のたびに、scp のダイアログが表示されます。



TeraTermのログファイルが、IPアドレス単位にデスクトップに出力されます。








2016年12月26日月曜日

LibreOffice(calc) のマクロでAMI一覧を作る


下記の記事で、aws-cli で取得したJSONデータを、LibreOffice(calc)に読み込むことができました。

ここでは、Basicマクロでヘッダと罫線を作成してAMI一覧を完成させます。

LibreOffice(calc)のBasicマクロからPythonマクロを実行する」で作成したマクロを修正して、以下のようにします。

REM  *****  BASIC  *****

Sub Main

    ' JSONデータ入力. Pythonマクロ(TestScript.py の amiList)を実行
    Dim a(0),b(0),c(0) As Variant
    scpr = ThisComponent.getScriptProvider
    scmod = scpr.getScript("vnd.sun.star.script:TestScript.py$amiList?language=Python&location=user")
    ret = scmod.invoke(a,b,c)
    
    'ヘッダ
    Dim oDoc as Object, oSheet as Object
    oDoc = ThisComponent
    oSheet = oDoc.CurrentController.ActiveSheet
    oSheet.getCellRangeByName("A1").String = "入力位置"
    oSheet.getCellRangeByName("B1").String = "VirtualizationType"
    oSheet.getCellRangeByName("C1").String = "Name"
    oSheet.getCellRangeByName("D1").String = "Hypervisor"
    oSheet.getCellRangeByName("E1").String = "ImageId"
    oSheet.getCellRangeByName("F1").String = "RootDeviceType"
    oSheet.getCellRangeByName("G1").String = "Architecture"
    oSheet.getCellRangeByName("H1").String = "[RootDevice]" & Chr$(10) & "Name"
    oSheet.getCellRangeByName("I1").String = "[RootDevice]" & Chr$(10) & "DeleteOnTermination"
    oSheet.getCellRangeByName("J1").String = "[RootDevice]" & Chr$(10) & "VolumeSize"
    oSheet.getCellRangeByName("K1").String = "[RootDevice]" & Chr$(10) & "VolumeType"
    oSheet.getCellRangeByName("L1").String = "[RootDevice]" & Chr$(10) & "Encrypted"

    ' ヘッダ属性
    oSheet.getCellRangeByName("A1:L1").CellBackColor = RGB(0, 0, 100)
    oSheet.getCellRangeByName("A1:L1").CharColor = RGB(255, 255, 255)
    oSheet.getCellRangeByName("A1:L1").VertJustify = com.sun.star.table.CellVertJustify.TOP

    ' セル高さ&幅の最適化
    oSheet.getRows.OptimalHeight = True
    oSheet.getColumns.OptimalWidth = True

    '最終行
    Dim oCursor as Object
    Dim oRange As Object
    Dim oEndRow as Long
    oRange = oSheet.getCellRangeByName("A2")
    oCursor = oSheet.createCursorByRange(oRange)
    oCursor.gotoEndOfUsedArea(True)
    oEndRow  =  oCursor.Rows.Count + 1
    'msgbox(oEndRow,0,"最終行取得")
   
    '罫線
    Dim oCtrl as Object
    Dim oSelRange as Object, oCellRange as Object
    Dim oBorder1 as Object, oBorder2 as Object, oBorder3 as Object, oBorder4 as Object
    oCtrl = oDoc.getCurrentController()
    oSelRange = oCtrl.getActiveSheet().getCellRangeByName("A1:L" & oEndRow) 
    oCtrl.select( oSelRange )
    '
    oCellRange = oDoc.CurrentSelection(0)
    ' Border1 Property
    oBorder1 = CreateUnoStruct("com.sun.star.table.BorderLine2")
    oBorder1.Color = RGB(0, 0, 0)
    oBorder1.LineWidth = 1
    oBorder1.LineStyle = 2  
    ' Border2 Property
    oBorder2 = CreateUnoStruct("com.sun.star.table.BorderLine2")
    oBorder2.Color = RGB(0, 0, 0)
    oBorder2.LineWidth = 1
    oBorder2.LineStyle = 2
    ' Border3 Property
    oBorder3 = CreateUnoStruct("com.sun.star.table.BorderLine2")
    oBorder3.Color = RGB(0, 0, 0)
    oBorder3.LineWidth = 1
    oBorder3.LineStyle = 2
    ' Border4 Property
    oBorder4 = CreateUnoStruct("com.sun.star.table.BorderLine2")
    oBorder4.Color = RGB(0, 0, 0)
    oBorder4.LineWidth = 1
    oBorder4.LineStyle = 2
    ' Set Border
    oCellRange.BottomBorder = oBorder1
    oCellRange.TopBorder = oBorder2
    oCellRange.LeftBorder = oBorder3
    oCellRange.RightBorder = oBorder4
    '
    oSelRange = oCtrl.getActiveSheet().getCellRangeByName( "A1" ) 
    oCtrl.select( oSelRange )

End Sub


このマクロを実行すると、JSONデータを入力して、以下のようなAMI一覧が作成されます。






2016年12月25日日曜日

LibreOffice(calc)のBasicマクロからPythonマクロを実行する


下記URLによると、LibreOffice のBasicマクロから、Python マクロを実行できるようです

そこで、「awscliのdescribeで取得したjsonデータをLibreOffice(calc)に読み込むPythonマクロ」で作成したPythonマクロをBasicマクロから実行してみました。


1.Python マクロの修正


awscliのdescribeで取得したjsonデータをLibreOffice(calc)に読み込むPythonマクロ」で作成したPythonマクロを以下のように修正します。(赤字部分)

#coding:utf-8
import json

def amiList(*args):


2.Basicマクロの作成


BASICマクロを作成します。
Python マクロを実行するソースコードは以下のとおり。
赤字部分が、スクリプトファイル名です。
緑色部分が、関数名です。

Sub Main

    ' JSONデータ入力. Pythonマクロ(TestScript.py の amiList)を実行
    Dim a(0),b(0),c(0) As Variant
    scpr = ThisComponent.getScriptProvider
    scmod = scpr.getScript("vnd.sun.star.script:TestScript.py$amiList?language=Python&location=user")
    ret = scmod.invoke(a,b,c)

End Sub

このソースを LibreOffice に登録します。
LibreOffice(calc) を起動して、[ツール] > [マクロ] > [マクロの管理] > [LibreOffice Basic] を選択すると下図の画面が表示されます。
下図のように赤枠を選択して、登録先を選択し、[編集]ボタンをクリックします。



下図の画面が表示されたら、ソースコードを記載して保存します。




3.Basicマクロの実行


Basic マクロの実行には、JRE が必要です。
[ツール] > [オプション] を選択すると、下図の画面が表示されます。
[詳細] をクリックして、JRE を指定します。



Basicマクロを実行します。
[ツール] > [マクロ] > [マクロの実行] を選択すると下図の画面が表示されます。
下図の赤枠のように選択して [実行] ボタンをクリックします。



BasicマクロからPythonマクロが実行され、以下のように Jsonデータを読み込めました




Basicマクロに比べて、Pythonマクロは、情報が少なくて、セルの操作などえ使用法がわからないことが多かったのですが、
これで、Jsonデータの入力だけ、Pythonマクロで行い、セルの操作などは、Basicマクロで実施できるようになりました。



2016年12月23日金曜日

awscliのdescribeで取得したjsonデータをLibreOffice(calc)に読み込むPythonマクロ


下記URLで LibreOffice(calc) で Python マクロが使えるのを知りました。

そこで、
awscli の describe した json データを LibreOffice に読み込んでみることにしました。
LibreOffice は Windows10 にインストールしたものを使用します。
LibreOffice のバージョンは 5.1.5 です。
Python は LibreOffice同梱のもを使用します。

1.JSONデータの準備


まず、試験用にAMIの一覧を describe して、json データを取得します。
全部だと多いので、 AMI名に "centos6" を含むAMIだけに絞り込みます。

$ aws ec2 describe-images --filters 'Names=name,Values=centos6' --output json > describe-images.json

この json ファイルを、LibreOfficeがインストールされた Windowsマシン上に保管します。

2. Python マクロの準備


上記のJSONデータを入力して LibreOffice(calc)で一覧を作成するマクロを用意します。
JSONデータは、"C:\data\describe^images.json" に格納されていることとします。
一覧を作成するシートの名称は、"Sheet1" とします。
ソースコードは以下のとおり。

#coding:utf-8
import json

def amiList():

 f = open(r"C:\data\describe-images.json","r")
 data = json.load(f)
 f.close()

 doc = XSCRIPTCONTEXT.getDocument()
 sheet = doc.getSheets().getByName('Sheet1')

 for i,e in enumerate(data['Images']):
  p = i + 2
  sheet.getCellRangeByName('A'+str(p)).Value = i + 1
  sheet.getCellRangeByName('B'+str(p)).String = str(e['VirtualizationType'])
  sheet.getCellRangeByName('C'+str(p)).String = str(e['Name'])
  sheet.getCellRangeByName('D'+str(p)).String = str(e['Hypervisor'])
  sheet.getCellRangeByName('E'+str(p)).String = str(e['ImageId'])
  sheet.getCellRangeByName('F'+str(p)).String = str(e['RootDeviceType'])
  sheet.getCellRangeByName('G'+str(p)).String = str(e['Architecture'])
  sheet.getCellRangeByName('H'+str(p)).String = str(e['BlockDeviceMappings'][0]['DeviceName'])
  sheet.getCellRangeByName('I'+str(p)).String = str(e['BlockDeviceMappings'][0]['Ebs']['DeleteOnTermination'])
  sheet.getCellRangeByName('J'+str(p)).String = str(e['BlockDeviceMappings'][0]['Ebs']['VolumeSize'])
  sheet.getCellRangeByName('K'+str(p)).String = str(e['BlockDeviceMappings'][0]['Ebs']['VolumeType'])
  sheet.getCellRangeByName('L'+str(p)).String = str(e['BlockDeviceMappings'][0]['Ebs']['Encrypted'])
このソースをLibreOfficeから実行するには、ファイルに保存してPythonマクロ用のフォルダに格納します。
C:\Users\<ユーザ名>\AppData\Roaming\LibreOffice\4\user\Scripts\python
以下のファイル名で保存します。
C:\Users\<ユーザ名>\AppData\Roaming\LibreOffice\4\user\Scripts\python\TestScript.py

3. Python マクロの実行


LibreOffice(calc) を起動します。
[ツール] > [マクロ] > [マクロの実行] を選択します。



下図の[マクロセレクター]が表示されます。
[マクロ] をクリックして、展開します。



ライブラリ欄の[TestScript]を選択すると、マクロ名欄に [amiList]が表示されるので選択して、[実行]ボタンをクリックします。



下図のように JSONデータが一覧表示されます。




エクセルのマクロで Jsonデータを入力したい場合は、下記URLが参考になります。