Fedora15 KVM上のWindowsにデバイスドライバを導入するには
Fedora15のvirt-managerではいくつかのハードウェアを設定できるが、このうちWindows上で次を使用する場合には、Windowsに専用のデバイスドライバを追加する必要がある。
・ virtio storage ・ virtio nic ・ baloon driver ・ virtio serial ・ QXL
(QXLはSPICEのサイト(http://spice-space.org/download.html), それ以外はFedora KVMのサイト(http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/)からダウンロードできる)
後々のために、Windows上でドライバを読ませるための設定をまとめておこう。。
基本: ドライバの自動読み取り
Windows上で使用するドライバ(実体はsysファイルで、設定ファイルとしてinfファイルがある)は、OS起動時に、デバイスID(PCI IDなど)を鍵とした自動検索がかかる。
自動検索の検索パスは、デフォルトで c:\windows\inf 以下なので、上記のデバイスに対するドライバをこのパスに置いておくと、対応するデバイスを追加した際に、Windowsが自動で認識するようになる。
ドライバ署名の回避
特に64bit版のWindowsで問題になるのだが、新しめのWindowsにはマイクロソフトの署名が入っていないドライバの読み込みを拒否する機能がある。。商用のKVMではvirtio-win パッケージからドライバが手に入るので問題にならないはずなのだが、テスト用のドライバには署名は行われていない。
この対応には、次のdseoというツールが有用だった。
http://www.ngohq.com/home.php?page=dseo
このツールでは、1. テスト署名の作成, 2. 署名検証の無効化 の2つの操作を実施できる。こちらでドライバへの署名と、検証の無効化を行うことで、ドライバの読み取りが出来るようになった。
※ 2. 署名検証の無効化は、実際には bcdedit /set TESTSIGNING ON を実行しているらしい。。 1.はテスト署名のキーストアへの登録、署名の実施等を行っているようだが、詳細はわからなかった。。
なお、検証の無効化を行っても、あくまでマイクロソフト署名のチェックを行わないだけで、テスト署名そのものは必要なようなので、1, 2は両方実施する必要があった。
なお、dseoのサイトには書いていないが、こちらで試した限りでは、テスト署名については、 sysファイル、catファイル(infファイルからinf2cat で作成できる署名ファイル?) の両方に行う必要があるらしい。。
VESA,Memory等、既にデバイスドライバがある場合の対応
QXLのグラフィックスアダプターや、Balloon用のメモリは、通常はVESA/Memoryとして振る舞うため、Microsoft純正のドライバが優先されてしまう場合があった。
この場合、次のコマンドを実行することで、無理やりドライバを更新することができた。
Windows7 試用版(pnputil): > pnputil -i c:\windows\inf\ballon.inf > pnputil -i c:\windows\inf\qxl.inf WindowsServer2003試用版(devcon, PCIパスの詳細はinfファイルの中身を確認): > devcon update c:\windows\inf\ballon.inf "PCIパス" > devcon update c:\windows\inf\qxl.inf "PCIパス"
このうち、pnputilはWindowsのバージョンにより存在しないことがあるので、その場合はdevconを使うことになりそうだ。。devconは次 (http://support.microsoft.com/kb/311272/ja)から入手できる。32bit/64bitがあり、バージョンが違うと変更が実施できない(閲覧系のコマンドは実施できる)ので注意。
なお、デバイスマネージャー経由でも読み込みを実施できるのかもしれないが、優先度を変更する方法がわからなかったため上記のツールを使用している。。 orz
その他注意点
qxlでcatファイルが無い
qxlのデバイスファイルはSPICEのサイトから入手できるが、2011/6の時点で、64bit版が無いのに加えて(これは今のところ自力でビルドするしかなさそう。。)、zipファイルにcatファイルが含まれておらず、署名チェックが回避出来ないという問題があった。対応として inf2cat ( ここから入手できる: https://winqual.microsoft.com/help/Inf2cat_FAQ.htm ) でcatファイルを作成する必要があった。
vdagent, blnsvrのインストール
SPICE, Baloonの動作のためには、Windows上に対応するサービスをインストールする必要がある。それぞれ、次のコマンドでインストールできた。
SPICE vdagent(SPICEのサイトからダウンロード): > vdservice install Balloonエージェント(FedoraKVMのサイトからダウンロード) > blnsvr -i
まとめ
Tipsとして、Fedora15のguestfishではゲストOSのNTFSに直接ファイルを配置出来るため、大量にドライバや、devcon.exeなどを配置する場合には、WindowsのFTP等を使うより、ホストOSから直接置いた方が簡単そうだ。。(Windows上でもPuppetが使えるようになれば、楽なのだが。。)<<参考リンク>>
http://spice-space.org/page/WinQXL
pGina-2.Xを使ってみた
pGina(http://www.pgina.org/index.php/Main_Page)はWindowsのログインロジックを修正して、ログイン方法を変更するツールなのだが、今回はFreeIPAと組み合わせて使ってみた。検証にはwindows7 32bit版の試用版を使用した。
元々pGinaはWindowsXPまでのWindowsの機能(GINA)を使っていたのだが、Vista以降で動作が変化し、上手く動かない状態だった。(そのため、AD以外でWindowsのパスワードを集約管理する方法がほぼ皆無だった。。) pGina2.X系列で遂にVista以降の仕組みにも対応した形となる。
pGina自体はPluginを通じて動作するのだが、今回はLDAPと、Kerberos用のプラグインを使ってみた。
pGina本体のインストール
本家からダウンロードしてインストーラを叩くだけなので、特に問題は無かったはず。。
FreeIPAの構築
詳細は参考URLを参照。基本的には次の2コマンドを叩くだけである。(/etc/hosts, DNS等の設定が必要かも)
# yum -y install freeipa-server # ipa-server-install
<<参考URL>>
http://obriend.fedorapeople.org/freeIPA2.0/Identity_and_Policy_Management_Guide/html-single/
FreeIPAはFedora15でメジャーバージョンが変わっており、動作が大きく変わっているので注意。。大きい変更としては、sssdと連携してオフラインキャッシュが出来たり、hbacの管理がWebコンソールから出来るようになっている。。
LDAP
LDAPのpGinaプラグインは、本家からダウンロードできる。インストールとして、プラグインファイル(dllファイル)をc:\program files\pgina\plugins 以下に置く必要がある。
インストールが終わった後、設定(スタート=>全てのプログラム=>Configure pGina から実施)として次を設定した。
モード: Searchモード LDAPサーバー: IPAサーバーのIP ポート: 389 adminユーザー,adminパスワード: adminの情報(実際には各LDAPユーザーでbindしているだけなので不要かも。。) Filter: (cn=%s) Context: dc=jp,dc=example,dc=org
なお、LDAPユーザーをローカルのユーザーとして作成するために、次の設定を行う必要があった。(こちらは次のKerberosの設定でも必要となる)
keep user profiles persistent: 有効 replace plugin authenticated password with local password: 無効
この状態でログオン画面から、LDAPユーザーでログオンできるはずである。(上手くいかない場合、次のログを確認。。 "c:\program files\pgina\doc\pgina.log")
Kerberos
Kerberosログインのプラグインも本家からダウンロードできる。マニュアルがドイツ語しかない w ので、正しい方法なのかわからないが、一応動作するところまでいったので、ここに書いておこう。。。
1. 事前にkfw-3.2.2 (http://web.mit.edu/kerberos/dist/index.html#kfw-3.2)をインストールしておく。c:\windows\krb5.ini を編集し、IPAのドメインを指定し、次のコマンドでチケットが取得できるかを確認する。(上手くいかない場合、DNS, NTP, IPAサーバーの/var/log/krb5kdc.log等を確認。。) なお、klistでチケットを確認できるが、Windows7 デフォルトではWindows付属のklist が優先されるので、フルパスで指定する必要がある。
> kinit admin
2. ダウンロードしたファイルを展開すると、dllファイルが4つあるが、krb5plugin.dllをpGinaのプラグインフォルダに置くだけでよいらしい。(READMEの通り各ファイルをc:\windowsにコピーすると上手く動作しなかった。。)
3. この状態でpGinaの設定を行い、Pluginでkrb5plugin.dll を指定する。対応するドメインが表示されれば成功となる。
4. 一旦ログオフして、該当ドメインのプリンシパルでログオンしてみる。ログオンが成功すれば上手く行っている。
なお、このプラグインでログオンした場合、デフォルトではkerberosのチケットは取得できず、明示的にkinitを実施する必要があった。また、WindowsデフォルトのCIFSは、MIT Kerberosのチケットを見ないらしく、このままだとSambaと連携することは出来ない。。orz (PuttyによるOpenSSHサーバーへの接続はパスワード無しで実施出来るため、こちらは連携出来ている, また、Linux同士だと、SambaにKerberosログインが出来ている)
なお、KerberosログインについてはWindows付属の機能を使った次の方法もあるようだが、こちらで試した限りでは、この方法ではログイン出来なかった。。(何故かKDCがクラッシュする。。 w )
http://freeipa.org/page/Implementing_FreeIPA_in_a_mixed_Environment_%28Windows/Linux%29_-_Step_by_step
※SambaのFreeIPA追加については次を参照。Fedora15:FreeIPA, Samba, ScientificLinux6: smbcllient として、kerberosログインが出来ることを確認している。。 ( https://help.ubuntu.com/community/Samba/Kerberos ) 迷った点として、こちらの環境でkeytabの名前を変更したことに伴い、smb.confに次の設定を追加する必要が生じていた点があった。
1. dedicated keytab file = /etc/samba/cifs.keytab に変更 2. "system keytab" を "dedicated keytab"に変更
まとめ
現状 Windows CIFSのKerberos連携が出来ていない段階なのでなんなのだが、一応 pGinaを使うことでWindowsのIDとLinuxのIDを集約管理できそうだ。今までWindows, LinuxのIDを統一するには、WinbindでADにLinuxを追加するしかなかったので、これで構成の幅が広がるだろうか。。
なおファイルサービスについては、OpenAFSを使うことでKerberos化されたファイル共有が出来そうなのだが、こちらはまだ試していない。。他にFilezilla, WinSCP等もKerberosに対応しているようなので、単純にファイル転送が必要ならこちらを使えばよさそうだ。(ただし、エクセル等の"共有"機能を有効に活用するにはこれでは不十分なのだが。。)
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"
OpenofficeのPythonマクロでimpressの情報を取得するには
前回と同様、OpenofficeのPythonマクロなのだが、今回は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を作成したテンプレートを用意しておき、デプロイの際に適宜拡張していくと、ちょうどよいだろうか。。