npackdを使ってみた

npackd(http://code.google.com/p/windows-package-manager/ ) はWindowsでよく使われるツール(java, AdobeReader, AdobeFlash, Firefox, librefoffice 等) をダウンロード+インストールするためのツールとなっている。(中身はhttpでファイルを取り寄せて、msiexec を叩いているようだ。。)

詳細はこちらを参照。。
http://www.lifehacker.jp/2011/02/110209npackd.html

ほとんどのツールが英語版なのでそのまま使うには微妙な印象もあるが、大量にイメージを用意する場合には重宝しそうだ。。
なお、このツールはレポジトリの形式(xmlファイル)が設定されており、クライアント側で内部のレポジトリを設定することも出来るらしいため、Windows版のyumとして流用出来そうな雰囲気だ。(一応設定ファイルには依存関係の記述もある。。)このため、実際に使う場合には、必要なファイル(言語パックのmsiなど)を加えて、内部用のレポジトリを作っていくとよさそうだ。

大量登録用には、コマンドラインも用意されている。コマンドはcmdから実行するが、cmdについては"管理者として実行"で開いておく必要があった。

> npackdcl add --package="org.7-zip.SevenZIP" --version="9.20"

まとめ

現状、グループポリシーを使ってもソフトウェア展開は出来るため、ADのある環境ではあまり使われないかもしれないが、ADが無い環境やコマンドラインでパッケージを追加出来るため、Windows版のPuppetが動くようになれば使うかも知れない。。(Execで確認、インストール等を実施、、など)

OpenofficeのPythonマクロでimpressの情報を取得するには

前回と同様、OpenofficePythonマクロなのだが、今回はimpressの方で作ってみた。前回同様powerpointにもVBAでのマクロが存在するようなのだが、gitとの連携や、Linuxでも使える点を考え、こちらで進めている。
前回についてはこちら:
http://d.hatena.ne.jp/aaabbb_200904/20110212/1297519086
今回は、同じようなimpressファイルから表を抜きだし、更にその中から特定の行を抜き出すロジックを作ってみた。今回も最初にプログラム本体を載せることにする。。
注意: ちなみにこのスクリプトを実行すると、時々Openofficeがクラッシュするので注意。orz 実行したタイミングでどの部分がアクティブになっているかによるようなのだが、詳しい条件はわからなかった。。

スクリプト本体

#! # test.py 
# -*- coding: utf_8 -*- 

def hello(): 
    from com.sun.star.table import ShadowFormat 
    from com.sun.star.table.ShadowLocation import BOTTOM_RIGHT 
    from com.sun.star.table import TableBorder 
    from com.sun.star.table import BorderLine 
    from com.sun.star.awt.FontWeight import BOLD 
    from com.sun.star.awt import Point, Size 
    Doc  = XSCRIPTCONTEXT.getDocument() 

    # Setting slide 
    Page = Doc.DrawPages.getByIndex(0) 
    Page.Width = 30000 

    # insert Slide 
    #Page = Doc.DrawPages.insertNewByIndex(1) 

    # insert textbox 
    RectangleShape = Doc.createInstance("com.sun.star.drawing.RectangleShape") 
    size = Size() 
    point = Point() 
    point.X = 1000 
    point.Y = 1000 
    size.Width = 10000 
    size.Height = 10000 

    RectangleShape.Size = size 
    RectangleShape.Position = point 
 
    RectangleShape.String = "This is a test" 
    RectangleShape.CharWeight = BOLD 
    Page.add(RectangleShape) 
 
    # table 
    def createtable(page, row, column): 
     Table = Doc.createInstance("com.sun.star.drawing.TableShape") 
     page.add(Table) 
     model=Table.Model 
     rows=model.getRows() 
     columns=model.getColumns() 
     for i in range(row): 
      #print model.RowCount 
      rows.insertByIndex(0,1) 
      #rows.getByIndex(0).Height=2000 
     for i in range(column): 
      #print model.ColumnCount 
      columns.insertByIndex(0,1) 
      #columns.getByIndex(0).Width=2000 
     cell=model.getCellByPosition(0,0) 
     cell.String = "Test1" 
     cell=model.getCellByPosition(0,1) 
     cell.String = "Test2" 
     cell=model.getCellByPosition(1,0) 
     cell.String = "Result1" 
     cell=model.getCellByPosition(1,1) 
     cell.String = "Resutl2" 

    print "createtables" 
    createtable(Page, 2, 2) 

    # Search for table 
    print Page.Count 
    for i in range(Page.Count): 
     shape = Page.getByIndex(i) 
     print shape.getShapeType() 
     if (shape.getShapeType() == 'com.sun.star.drawing.TableShape'): 
      break 
    model=shape.Model 
    print model.RowCount 
    print model.ColumnCount 
    for i in range(model.RowCount): 
      cell=model.getCellByPosition(0,i) 
      if (cell.String == 'Test2'): 
        cell = model.getCellByPosition(1,i) 
        print 'The Result is ' + cell.String 
    return None 

if __name__ == '__main__': 
	import unopy 
	XSCRIPTCONTEXT = unopy.connect() 
 	if not XSCRIPTCONTEXT: 
 		print("Failed to connect to OpenOffice.org.") 
 	 	import sys 
 	 	sys.exit(0) 
 	 
 	hello() 

説明

スライドを取得するには

スライドを取得するには、次のように Doc.DrawPages.getByIndex で取得する。スライドは上から順に通し番号を振られるようである。(スタートは0から)

    Page = Doc.DrawPages.getByIndex(0) 
スライドを追加するには

スライドを追加する場合には、insertNewByIndexで追加できる。

    Page = Doc.DrawPages.insertNewByIndex(1) 
図形を追加するには

今回直接は使っていないのだが、図形を追加するには、 Doc.createInstance でインスタンスを指定して図形を作成し、Page.addで追加する形になる。

        RectangleShape = Doc.createInstance("com.sun.star.drawing.RectangleShape") 
        Page.add(RectangleShape) 
表を作成するには

表を作成する場合にも、createInstanceで作成するのだが、インスタンス名は com.sun.star.drawing.TableShape となる。(writerの表では、com.sun.star.text.TextTableなので注意)

     Table = Doc.createInstance("com.sun.star.drawing.TableShape")
     page.add(Table)

この後もwriterの表とは少々異なり、modelから、rows, columnsを取得し、行、列を追加していく形になる。個々の行、列はgetByIndexで取得し、幅、高さも指定できるはずなのだが、なぜか実際に指定すると頻繁にクラッシュしたため、指定していない。。orz

     model=Table.Model
     rows=model.getRows()
     columns=model.getColumns()
     for i in range(row):
      #print model.RowCount
      rows.insertByIndex(0,1)
     #for i in range(row):
     # rows.getByIndex(i).Height=2000
     for i in range(column):
      #print model.ColumnCount
      columns.insertByIndex(0,1)
表を探すには

既に資料の中に、表があることが分かっている場合には、まず、スライドを指定し、その中の要素から表を探していくことになる。(本来はスライドも上から順に探していく(スライドのタイトルなどで検索)べきなのだが、今回は時間の都合により省略。。orz)
まず、スライドをPageで指定すると、Pageの中の要素はPage.Countで取得出来るので、要素ごとにgetShapeTypeを確認し、'com.sun.star.drawing.TableShape'と等しいものを探す。

    for i in range(Page.Count):
     shape = Page.getByIndex(i)
     print shape.getShapeType()
     if (shape.getShapeType() == 'com.sun.star.drawing.TableShape'):
      break

見つかったら、1列目の中身を順に探していき、予定のもの(ここでは1列目が'Test2'のもの)が見つかったら、2列目を出力している。

    model=shape.Model 
    for i in range(model.RowCount): 
      cell=model.getCellByPosition(0,i) 
      if (cell.String == 'Test2'): 
        cell = model.getCellByPosition(1,i) 
        print 'The Result is ' + cell.String 

まとめ

プレゼンのフォーマットが決まっている資料から必要な情報(発表者、日付など)を抜いていくには、このようなマクロが必要になりそうだ。。<<参考リンク>>
http://www.oooforum.org/forum/viewtopic.phtml?t=102812 <== TableShapeの場合は2重のループが必要。。
http://api.openoffice.org/servlets/ReadMsg?listName=dev&msgNo=20714

OpenofficeのPythonマクロを使ってみた

サーバー上で取った情報等をまとめて、最終的にエクセルファイルとして出力したい場合(大抵CSVだと表現しきれない情報がある(枠線とか色とか)。。orz)、基本的にはエクセルマクロを使うことになる。ただ、エクセルマクロだと、言語としてVisualBasicしか使えず、いろいろと大変、Windows上でしか使えない、作ったマクロはエクセル以外の環境だと動かない、などいろいろと制限があるため、もう少し手軽な方法が欲しいところだった。

Openofficeについて調べていたところ、こちらはPython(他にJavascript等も使用できる。。)がマクロ用に使用できることが分かったため、こちらを使用してみることにした。動作環境としては、Fedora14上のOpenoffice(3.3.0), Python(2.7)を使用した。

準備

上ではマクロと書いたが、厳密にはマクロ(Openofficeのプロセスの中でスクリプトを動かす)だけではなく、RPCコールとしての使い方もあるらしく、Openoffice自体はデーモンとして動かして、Pythonスクリプトからコマンドを投げることも出来るらしい。(メニューからマクロとして呼び出す場合は普通のマクロ同様Openofficeのプロセスの中で起動されるのかもしれないのだが。。) 投げるコマンドはUNOというIDL型の定義があるらしく、Java, C++, Javascript等からも使用できるらしい。
http://wiki.services.openoffice.org/wiki/JA/Documentation/BASIC_Guide/UNO
※今回のスクリプトはマクロとしての使い方と、RPCとしての使い方の両方で使用出来る。

実際にマクロ、もしくはRPCを動かす時には、まず、Python向けのフックを導入しておく。

 # yum -y install opennoffice.org-pyuno

この後、スクリプトの置き場所として、次の場所に移動する。この場所にpyファイルを置いていく形になる。なお、マクロではなくRPCを使う場合、基本的にスクリプトはどこにおいてもよいはずだが、筆者の環境ではなぜか、/tmp に置いたときだけunoモジュールのimportが失敗した。このため、マクロで使う必要が無くても、とりあえずこの場所に置いておくのが良さそうだ。。orz

~.openoffice.org/3/user/Scripts/python

なお、RPCコールを使うスクリプトはそのままだとマクロとして使うことが出来ない(必要なimport等が異なる。。)ため、回避策としてこちらの方法を使わせていただいた。。
http://d.hatena.ne.jp/hanya_orz/20100606/p1
後でスクリプトの中でpyuno.connect を使用しているが、リンク先の内容に従っている。

使い方

PythonのRPCコールを使う場合、Openofficeコマンドラインから起動する必要がある。次のコマンドで、localhost TCP/2002 でRPCを待つ状態で、Openofficeが起動する。

$ soffice "-accept=socket,host=localhost,port=2002;urp;" & 

この状態で、次のようなスクリプトを投げてみる。(ただし、あらかじめcalcのドキュメントを開いておかないと上手く動かない。。) “1A”のセルに”Test”と入力されれば成功である。

$ cat hello.py 
#! # test.py 
# -*- coding: utf_8 -*- 
 
def hello(): 
    doc  = XSCRIPTCONTEXT.getDocument() 
    Sheet = doc.Sheets.getByName("Sheet1") 
    Cell = Sheet.getCellByPosition(0, 0) 
    Cell.String = "Test" 
    return None 

if __name__ == '__main__': 
	import unopy 
	XSCRIPTCONTEXT = unopy.connect() 
 	if not XSCRIPTCONTEXT: 
 		print("Failed to connect to OpenOffice.org.") 
 	 	import sys 
 	 	sys.exit(0) 
 	hello() 

if __name__ == '__main__': 以下は定型文で、スクリプトをマクロと共用するために使用している。この記述を入れておきロジックの実体をhello() で定義することで、マクロとRPCを共用できる(実際、このスクリプトは、”ツール”=>”マクロ”=>”マクロを実行” から実行しても同じ結果になる。。) helloの中身では現在のドキュメントからSheet1の”1A”を取得し、”Test”を入力している。

セルの色付け等を行う場合

エクセルで出力したい場合、大抵計算・集計部分ではなく、フォーマットを整える部分が必須になっている。(計算・集計等だけなら、Pythonを使う方が書きやすい。。orz ) このため、よく使いそうな色付け方法についてPythonマクロで出来るようにしてみた。少々長いが、そのまま載せる。

$ cat testuno.py 
#! # test.py 
# -*- coding: utf_8 -*- 

def hello(): 
    from com.sun.star.table import ShadowFormat 
    from com.sun.star.table.ShadowLocation import BOTTOM_RIGHT 
    from com.sun.star.table import TableBorder 
    from com.sun.star.table import BorderLine 

    doc  = XSCRIPTCONTEXT.getDocument() 
    Sheet = doc.Sheets.getByName("Sheet1") 
    Cell = Sheet.getCellByPosition(1, 1) 
    Cell.String = "Test" 
    print Cell.getString() 
    print Cell.CellBackColor 
    Cell.CellBackColor=0xffff00 

    # BorderLine 
    print Cell.TopBorder 
    def createborderline(): 
     borderline=BorderLine() 
     borderline.Color=0x000000 
     borderline.InnerLineWidth=10 
     borderline.OuterLineWidth=10 
     return borderline 
    def createallborderline(cell): 
     cell.TopBorder = createborderline() 
     cell.BottomBorder = createborderline() 
     cell.LeftBorder = createborderline() 
     cell.RightBorder = createborderline()      
    createallborderline(Cell)
    print Cell.TopBorder 

    # ShadowFormat 
    print Cell.ShadowFormat 
    shadowFormat = ShadowFormat() 
    shadowFormat.Location = BOTTOM_RIGHT 
    shadowFormat.ShadowWidth = 100 
    shadowFormat.Color = 0xaaff00 
    Cell.ShadowFormat = shadowFormat 

    # Insert Data
    Cell = Sheet.getCellByPosition(2, 1) 
    Cell.String = "あいうえお" 
    for i in range(10): 
      Cell = Sheet.getCellByPosition(1, 2+i) 
      Cell.setValue(i) 
      createallborderline(Cell) 
      Cell = Sheet.getCellByPosition(2, 2+i) 
      Cell.setValue(i*i) 
      createallborderline(Cell) 

    # Set autofilter 
    oRanges = doc.DatabaseRanges 
    oRange = Sheet.getCellRangeByPosition(1,1,2,12) 
    from com.sun.star.container import NoSuchElementException 
    try: 
     oRanges.getByName("range1") 
    except (NoSuchElementException): 
     oRanges.addNewByName("range1", oRange.RangeAddress) 
     oDbRange = oRanges.getByName("range1") 
     oDbRange.AutoFilter = True 
     oDbRange.refresh() 
    return None 

if __name__ == '__main__': 
	import unopy 
	XSCRIPTCONTEXT = unopy.connect() 
 	if not XSCRIPTCONTEXT: 
 		print("Failed to connect to OpenOffice.org.") 
 	 	import sys 
 	 	sys.exit(0) 
 	 hello() 

スクリプトの中でいくつかのことを行っているので、順番にまとめていく。。

セルの色を変更

取得したセル(sheet.getCellByPositionで取得可能) について cell.CellBackColor で指定出来る。色はRGBの16進数6桁で指定する。

枠線を変更

importしたBorderline(上下左右の枠線をまとめたクラス)のインスタンスを作成し、TopBorder, BottomBorder, LeftBorder, RightBorderに色、太さ等を個別に指定する必要がある。上記の例では、 createallborderline(cell) で指定すれば、とりあえず黒線でセルが囲まれるようになっている。。

影の設定

エクセルではあまり使わない機能なので省略。。w

オートフィルタの設定

コピペしたのであまり理解していないがorz 、ドキュメントに対して、DatabaseRangeを作成して、対象のセルレンジに当てはめている。

まとめ

ひとまずこんなところだろうか。他にもフォントの大きさや、太字などをよく使うので、これらもおいおい調べていこう。。

追記

    Cell.CharColor = 0x00aa00
    Cell.CharHeight = 14
    print Cell.CharHeight
    Cell.CharWeight = 200
    print Cell.CharWeight

セルの文字の色、フォントサイズの変え方、及び太字設定の方法が分かったので追記しておく。。(Cellは変更したいセル)

セルの文字の色

Cell.CharColor で直接指定出来る。

フォントサイズ

Cell.CharHight で直接変更できる。

太字設定

Cell.CharWeightで文字の太さを変更出来る。基準はよくわからないが、120あたりから太字と認識されるようである。。

さらに追記

CentOS5にlibreofficeの3.3を導入して、上記のPythonマクロを動かしてみた。基本的には動いたのだが、枠線を設定するためのBorderLineクラスがBorderLine2クラス(!)に変更になっており、そこだけ直す必要があった。。w
なお、libreofficeから直接落としたパッケージなので、パスが変更になっている。

環境変数:
$ export PYTHONPATH=/opt/libreoffice/basis3.3/program/
soffice起動:
$ /opt/libreoffice/program/soffice "-accept=socket,host=localhost,port=2002;urp;"
マクロの置き場所:
~.libreoffice/3/user/Scripts/python
RPC実行:
/opt/libreoffice/program/python XXX.py

Puppetで商用製品のインストールを実行するには

PuppetにはFile, Cronなどの組み込みのリソースに加えて、Execという任意のコマンドを実行できるリソースがあるため、スクリプト化出来る項目については基本的に何でも実施できる。
ここでは、IBM HTTP Server(以下IHS)のインストールを自動化してみた。
IHSについて詳しくはこちら。
http://ja.wikipedia.org/wiki/IBM_HTTP_Server
http://www-01.ibm.com/software/webservers/httpservers/
なお、今回は体験版を使用しており、製品版では上手く動かないかもしれないので注意。。orz
基本的な方針としては、1. tarファイルで提供されたIHSを一時ディレクトリに展開し、2. インストーラーをsilentモードで実行する、 の2点となる。まず、最初にマニフェストを貼り付けて、後は順次説明を加えていこう。。

マニフェスト

# どこかで設定: 今回はIHSだけだが、実際には他のツールでも共用しているので、virtual resource とする。。
@file { “/opt/local”:
  ensure=>directory,
}
class ihs_tools{
 #IHS
 realize (File[“/opt/local”])
 file {'/opt/local/ihs':
  ensure=>directory,
 }
 hugefilesexec {"/opt/local/ihs/ihs.7000.linux.ia32.tar":
  execresource=>"ihstar",
  subscribe => [File["/opt/local/ihs"]],
  onlyif=>"/usr/bin/test ! -f /opt/IBM/HTTPServer/bin/versionInfo.sh",
 }
 configfile {"/opt/local/ihs/ihs_responsefile.txt":
  ensure=>present,
 }
 exec { 'expandihsandinstallihs':
  command=>"/bin/tar -x -f /opt/local/ihs/ihs.7000.linux.ia32.tar -C /opt/local/ihs && /opt/local/ihs/IHS/install -options /opt/local/ihs/ihs_responsefile.txt -silent && /bin/rm -rf /opt/local/ihs/",
  creates=>'/opt/IBM/HTTPServer/bin/versionInfo.sh',
  subscribe=>[Exec["ihstar"], File["/opt/local/ihs/ihs_responsefile.txt"]],
  user => "root",
 }
}
# ここから関数
define hugefilesexec($execresource, $subscribe=[Package["glibc"]], $user = root, $unless = '/bin/false', $onlyif= '/bin/true', $timeout = 1200){
    $server = "fedora-intel1.jp.example.org"
    exec {"${execresource}":
            command =>"/usr/bin/wget http://$server/hugefiles/$name -O $name",
            subscribe=>$subscribe,
            unless=>$unless,
            onlyif=>$onlyif,
            timeout =>$timeout,
            creates => "$name",
            user => "$user",
    }
define configfile(owner = root, group = root, mode = 644,
                  backup = false, recurse = false, ensure = file, require = [Package["glibc"]],replace = true) {
    file { $name:
            mode => $mode,
            owner => $owner,
            group => $group,
            backup => $backup,
            recurse => $recurse,
            ensure => $ensure,
            replace => $replace,
            source => "puppet://$server/files/$operatingsystem$operatingsystemrelease/$name"
    }
 }
}

これに加えて、Puppetマスター(Fedora14)でhttpdを起動し、/var/www/html/hugefiles/opt/local/ihs/ihs.7000.linux.ia32.tar にインストール用のtarファイルを置いている。また、silentインストール用の設定ファイルとして、 /etc/puppet/files/CentOS5.5/opt/local/ihs/ihs_responsefile.txt を配置している。(/etc/puppet/files は fileserver.conf で [files] としてエクスポートしている。)

tarファイルの転送

tarファイルは普通に転送すればよいのだが、それなりにサイズが大きい(100MB以上。。)ため、 PuppetのFileリソースで運ぼうとするとサイズ超過で失敗する。
対策として、関数 hugefilesexec を作成している。基本的にはExecリソースを使用し、中でwget ww を実行するだけである。。 <<参考リンク>> http://groups.google.com/group/puppet-users/browse_thread/thread/7e91404c1673b2b1

インストーラーの実行

tarファイルを展開すると、中からインストーラーが出てくるので、これを実行するのだが、IHSの性質上インストールのプロセス内でいくつか追加の設定を行う必要があるため、このままインストーラーを起動しても失敗する。このため、事前に設定ファイル(応答ファイルと呼ばれる。。)を作成し、設定を提示しておく必要がある。<<参考リンク>>
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/rins_plugins_responsefile.html
応答ファイルの内容はバージョンごとに変わるので詳しくは書かない、、 orz (サンプルはtarファイル内に含まれている。)

このファイルをconfigfile関数(こちらから拝借。。 http://people.redhat.com/dlutter/puppet-app.html ) で一時ディレクトリ (/opt/local/ihs ) に配置しておき、Execリソース expandihsandinstallihs でインストールを実行している。

まとめ

他にもいくつか追加の設定があるのだが、基本的な流れはこのような感じである。。同じ理屈でWAS(WebSphere Application Server)のインストールやFix適用も自動化出来る。、基本的に条件はシェルから自動で実行出来ることだけなので、他の製品も含めて、いろいろ試してみるとよさそうだ。。
注意点として、Execのonlyif, Fileのrequireなど、条件設定の仕組みを上手く使わないと順番が変わってしまい、上手く動作しなくなる。この場合も大抵は何度かPuppetdを実行することでインストールは可能だが、出来れば一度でインストール出来るようにしたいものだ。。 orz

Puppet-LVMを使ってみた

PuppetでLVMを管理できるといろいろと便利そうなのだが、そのためのモジュールが見つかったので、使ってみた。(Puppetmaster: Fedora14, Puppetd: CentOS5.5 EPEL: puppet-0.25.5-1.el5) Puppet-LVMのリンク先はこちら。
https://github.com/puppetlabs/puppet-lvm

注意点として、このモジュールはlib/ 以下のファイル(Rubyで書かれている。。) を含んでいるため、puppetmasterd, puppetdが動く両方のサーバーの/etc/puppetd.confで、 次を設定する必要がある。 (新しめのバージョンでないと使えないらしい。。)

[main]
  pluginsync = true

さらに、Puppetmaster側では、moduleのパスを設定する必要がある。

[puppetmasterd]
  modulepath = /etc/puppet/modules

<<参考リンク>>
http://docs.puppetlabs.com/guides/plugins_in_modules.html

モジュールのインストールとしては、githubからダウンロードしたtarファイルを/etc/puppet/modules 以下に展開する形になる。 /etc/puppet/modules/puppet-lvm が出来ていれば上手くいっている。
準備が整ったら、Puppetマスター側で、次のようなマニフェストを追加する。例として PV: /dev/vdbに、VG: datavg1 を構成し、そこからLV: datalv4, datalv5 作成(サイズは60MB)=>ext3で初期化 を実行する。

import 'puppet-lvm'

 physical_volume { "/dev/vdb":
    ensure => present,
 }
 volume_group { "datavg1":
    ensure => present,
    physical_volumes => "/dev/vdb",
    require => [Physical_volume["/dev/vdb"],]
 }
 logical_volume { "datalv5":
    ensure => present,
    volume_group => "datavg1",
    size => "60M",
    require => [Volume_group["datavg1"],]
 }
 filesystem { "/dev/datavg1/datalv5":
    ensure => present,
    fs_type => "ext3",
    require => [Logical_volume["datalv5"],]
 }
 logical_volume { "datalv4":
    ensure => present,
    volume_group => "datavg1",
    size => "60M",
    require => [Volume_group["datavg1"],]
 }
 filesystem { "/dev/datavg1/datalv4":
    ensure => present,
    fs_type => "ext3",
    require => [Logical_volume["datalv4"],]
 }

予定どおりファイルシステムが作成されれば成功である。ちなみに lvm::volume を関数として使っても同じことができる。

基本的にこれだけだが w 、各logical_volumeでサイズを拡張して同期を行うと、自動的にファイルシステム拡張を行ってくれる。(中身はresize2fsを使っているため、おそらくext2/3のみ.. ) この際、ファイルシステムもLVと同時に拡張された。

なお、LV縮小には対応していないので注意。。エラーメッセージは以下のとおりで、LV縮小に伴うファイルシステム破損を警戒しているようだ。。

err: //Node[centos-virt25.jp.example.org]/Logical_volume[datalv5]/size: change from 100M to 80M failed: Decreasing the size requires manual intervention (100M < 100M)

元々PuppetではLVMを変更する機能が無かったため、テンプレートやKickStartでいろいろと試していたが、使い勝手の面ではPuppetを経由した方がよさそうだ。まずは最小サイズでLVMを作成したテンプレートを用意しておき、デプロイの際に適宜拡張していくと、ちょうどよいだろうか。。

OSPFのエリア分割を試してみた

VyattaのOSPFでは、OSPFエリア分割を使用できる。エリア分割では、1. 経路再計算の領域を限定することが出来るが、2. エリア0につながっていないエリアからはvirtual-linkを張らないと通信できない、、などいくつか気になる点があったので、いろいろ試してみた。
※ 量が多かったため詳細な設定は張らず、設定図だけを載せている。。orz

1. エリアが5つある場合

エリア0の隣の2つのエリアとは直接疎通できるが、それ以外のエリア(0.0.0.24, 0.0.0.25)とは直接通信出来ないため、vyatta1<=>vyatta3, vyatta3<=>vyatta4の間で、それぞれバーチャルリンクを張っている。設定は、次のようになる。(vyatta1<=>vyatta3 の間)

vyatta1 :
vyatta@vyatta1# set protocols ospf area 0.0.0.22 virtual-link 192.168.24.3
vyatta3:
vyatta@vyatta3# set protocols ospf area 0.0.0.22 virtual-link 192.168.21.1 

この状態では、vyatta1〜4の全てで通信が出来た。Vyatta2からvyatta4のtracerouteは次のようになった。

traceroute to 192.168.25.4 (192.168.25.4), 30 hops max, 40 byte packets
 1   (192.168.21.1)  5.851 ms  5.850 ms  5.847 ms
 2   (192.168.22.3)  54.845 ms  54.882 ms  54.884 ms
 3   (192.168.25.4)  58.677 ms  58.691 ms  58.687 ms

2. エリア0が存在しない場合

エリア0が無い場合、どうなるのか試してみた。基本的な設定は1と同じだが、vyatta1,vyatta2が属するエリアが、0.0.0.0から0.0.0.21になっている。

この状況でも、virtual-linkがあるせいか、vyatta1, vyatta3, vyatta4の間では疎通が取れた。
ただ、vyatta1, vyatta3, vyatta4 共に、vyatta2のみが所持している192.168.23.0/24(OSPFエリア 0.0.0.23)に対しては、経路が無く通信できなくなった。参考までに、vyatta4のルーティングテーブルは次のようになり、192.168.23.0/24への経路がないことが分かる。

C>* 127.0.0.0/8 is directly connected, lo
O>* 192.168.21.0/24 [110/30] via 192.168.24.3, eth1, 00:01:42
O>* 192.168.22.0/24 [110/20] via 192.168.24.3, eth1, 00:22:42
O   192.168.24.0/24 [110/10] is directly connected, eth1, 00:23:28
C>* 192.168.24.0/24 is directly connected, eth1
O   192.168.25.0/24 [110/10] is directly connected, eth0, 00:23:28
C>* 192.168.25.0/24 is directly connected, eth0

3. エリアが3つの場合(境界ルーターが存在しない場合)


エリア0.0.0.22を広め(ルーターx2, セグメント x3)に取って、バーチャルリンクがなくても動作するか試してみた。結果として、vyatta1からvyatta4まで問題なく通信出来た。vyatta2からvyatta4へのtracerouteは次のようになる。

vyatta@vyatta2:~$ traceroute 192.168.25.4
traceroute to 192.168.25.4 (192.168.25.4), 30 hops max, 40 byte packets
 1   (192.168.21.1)  4.825 ms  4.863 ms  4.857 ms
 2   (192.168.22.3)  7.765 ms  7.786 ms  7.781 ms
 3   (192.168.25.4)  12.874 ms  12.913 ms  12.909 ms

vyatta2のルーティングテーブルは次のようになった。Vyatta4しか接続されていない192.168.25.0/24まできちんと含まれている。

vyatta@vyatta2:~$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route
C>* 127.0.0.0/8 is directly connected, lo
O   192.168.21.0/24 [110/10] is directly connected, eth0, 00:37:50
C>* 192.168.21.0/24 is directly connected, eth0
O>* 192.168.22.0/24 [110/20] via 192.168.21.1, eth0, 00:00:34
O   192.168.23.0/24 [110/10] is directly connected, eth1, 00:37:50
C>* 192.168.23.0/24 is directly connected, eth1
O>* 192.168.24.0/24 [110/30] via 192.168.21.1, eth0, 00:00:34
O>* 192.168.25.0/24 [110/40] via 192.168.21.1, eth0, 00:00:34

これといったオチは無いのだが w、エリア0が無くてもvirtual-linkがあれば、疎通が取れるのは、少々意外だった。。

CentOS5の、EPEL mongrelの依存性

CentOS5用に、EPEL mongrelの依存性を調べてみた。
Puppetのパフォーマンスアップに使えそうだ。。

Dependencies Resolved

================================================================================
 Package                  Arch         Version                 Repository  Size
================================================================================
Installing:
 rubygem-mongrel          x86_64       1.0.1-6.el5             epel       506 k
Installing for dependencies:
 ruby-irb                 x86_64       1.8.5-5.el5_4.8         base        69 k
 ruby-rdoc                x86_64       1.8.5-5.el5_4.8         base       134 k
 rubygem-daemons          noarch       1.0.10-1.el5            epel       128 k
 rubygem-fastthread       x86_64       1.0.7-1.el5             epel        59 k
 rubygem-gem_plugin       noarch       0.2.2-2.el5             epel       110 k
 rubygem-rake             noarch       0.8.7-2.el5             epel       426 k
 rubygems                 noarch       1.3.1-1.el5             epel       177 k

Transaction Summary
================================================================================
Install      8 Package(s)         
Update       0 Package(s)         
Remove       0 Package(s)         

Total download size: 1.6 M