<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ayutaya.com</title>
	<atom:link href="http://www.ayutaya.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ayutaya.com</link>
	<description>May the SOURCE be with You</description>
	<lastBuildDate>Thu, 05 Jan 2012 15:44:39 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>前職在籍中の主要記事へのリンク</title>
		<link>http://www.ayutaya.com/2011/12/14/major-items/</link>
		<comments>http://www.ayutaya.com/2011/12/14/major-items/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 08:46:33 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=937</guid>
		<description><![CDATA[ThinkIT &#124; PostgreSQLとストリーミング・レプリケーション 第1回 ストリーミング・レプリケーションの紹介 第2回 レプリケーションの諸機能と、同期接続 第3回 高可用性クラスタへの応用 SIOS OSS Tech ～ サイオステクノロジーのOSS技術者による技術メモ PostgreSQL で、STATISTICS (列の統計精度) を変更した箇所を忘れたら ソースの入手と再ビルド ～ Amazon Linux AMI (EC2) 編 PostgreSQL の SQL やプロシージャでランダムデータの入ったテーブルを生成する RHEL6.1～系の OpenLDAP (slapd.conf) で SSH 公開鍵配布 prelink されたバイナリの &#8220;rpm -V&#8221; での検証は無問題 ソースの入手と再ビルド &#38; デバッグ ～ Mac OS X Homebrew 編 RHEL6 系での OpenLDAP サーバと PAM 認証 [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href='http://thinkit.co.jp/book/2011/10/20/2309'>ThinkIT | PostgreSQLとストリーミング・レプリケーション</a></li>
<ul>
<li><a href="http://thinkit.co.jp/story/2011/10/20/2310">第1回 ストリーミング・レプリケーションの紹介</a></li>
<li><a href="http://thinkit.co.jp/story/2011/10/27/2319">第2回 レプリケーションの諸機能と、同期接続</a></li>
<li><a href="http://thinkit.co.jp/story/2011/11/02/2324">第3回 高可用性クラスタへの応用</a></li>
</ul>
<li><a href='http://sios-oss.blogspot.com/'>SIOS OSS Tech ～ サイオステクノロジーのOSS技術者による技術メモ</a></li>
<ul>
<li><a href='http://sios-oss.blogspot.com/2011/12/postgresql-statistics.html'>PostgreSQL で、STATISTICS (列の統計精度) を変更した箇所を忘れたら</a>
<li><a href='http://sios-oss.blogspot.com/2011/12/amazon-linux-ami-ec2.html'>ソースの入手と再ビルド ～ Amazon Linux AMI (EC2) 編</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/12/postgresql-sql.html'>PostgreSQL の SQL やプロシージャでランダムデータの入ったテーブルを生成する</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/12/rhel61-openldap-slapdconf-ssh.html'>RHEL6.1～系の OpenLDAP (slapd.conf) で SSH 公開鍵配布</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/12/prelink-rpm-v.html'>prelink されたバイナリの &#8220;rpm -V&#8221; での検証は無問題</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/12/mac-os-x-homebrew.html'>ソースの入手と再ビルド &amp; デバッグ ～ Mac OS X Homebrew 編</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/12/rhel6-openldap-pam.html'>RHEL6 系での OpenLDAP サーバと PAM 認証</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/debuginfo-rpm.html'>debuginfo RPM パッケージで、ソースレベル・デバッグをする</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/puppet.html'>RPM ベースで Puppet を動かしてみる</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/ruby.html'>Ruby の「条件式としての範囲式」の正体を探る</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/postgresql-with.html'>PostgreSQL の無限再帰 WITH 句で思うこと</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/rhel6-qemu-kvm-cpu.html'>RHEL6 系で qemu-kvm バイナリを CPU エミュレーション・モードで使う</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/ext3-lvm2.html'>なぜオンライン EXT3 の LVM2 スナップショット &amp; バックアップは問題なく動くのか？</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/centos-60.html'>CentOS 6.0 でインストール直後にネットワークを有効にする方法</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/postgresql.html'>PostgreSQL 死活監視のタイムアウト</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/ubuntu.html'>ソースの入手と再ビルド ～ Ubuntu 編</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/git.html'>肥大化した個人利用の Git ワークを縮小する</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/postgresql-snmp.html'>PostgreSQL を SNMP で監視する</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/11/centosscientific-linux.html'>ソースの入手と再ビルド ～ CentOS / Scientific Linux 編</a></li>
<li><a href='http://sios-oss.blogspot.com/2011/10/postgresql-zabbix.html'>PostgreSQL をバックエンドにして Zabbix を動かす</a></li>
</ul>
<li><a href='http://postgres.sios.com/'>SIOS &#8211; Postgres Plus ユーザーサイト</a>
<ul>
<li><a href="http://postgres.sios.com/modules/install/index.php?content_id=6">Slony-I: PostgreSQL のためのレプリケーションシステム &#8211; その実装詳細（翻訳）</a>
<li><a href="http://postgres.sios.com/modules/install/index.php?content_id=5">Slony-I: PostgreSQL のためのレプリケーションシステム &#8211; そのコンセプト（翻訳）</a>
<li><a href='http://postgres.sios.com/modules/newbb/viewforum.php?forum=1'>FAQ 項目多数</a>
  </ul>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/12/14/major-items/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Xen 4 で Scientific Linux 6 Dom0</title>
		<link>http://www.ayutaya.com/2011/05/22/xen4-sl6-dom0/</link>
		<comments>http://www.ayutaya.com/2011/05/22/xen4-sl6-dom0/#comments</comments>
		<pubDate>Sun, 22 May 2011 12:38:02 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=915</guid>
		<description><![CDATA[Xen (Xen-PV) は良いです。何が良いって、VT/AMD-V が必須の KVM や Xen-HVM と違って Paravirtualization でも動くので、最近流行りの IaaS のテストなども、VM 上でおこなうことができるところです。（KVM に比べて、サポートが手薄な感は拭えませんが） RHEL5/CentOS5 では、インストール中に &#8220;Virtualization&#8221; サポートのパッケージグループを有効にするだけで Xen の Dom0 がインストールできて簡単でした。ところが RHEL6/SL6 (Scientific Linux 6) では、Red Hat による KVM 推しのせいか Xen Dom0 が除外されてしまいました。実運用に使うわけではないので品質は問わないので、SL6 を Xen Dom0 化してみました。 RHEL6 では、Dom0 が除外されただけです。ノーマルカーネルは Xen pv_ops オプション付きでビルドされているので、そのまま Xen DomU にはなれます。 なお、今回は本家の記事がネタ元。参考: &#8220;RHEL6Xen4Tutorial &#8211; Xen Wiki&#8220;。 前準備 まず、distro をインストールする先の [...]]]></description>
			<content:encoded><![CDATA[<p><a href=http://www.xen.org/>Xen</a> (Xen-PV) は良いです。何が良いって、VT/AMD-V が必須の KVM や Xen-HVM と違って Paravirtualization でも動くので、最近流行りの IaaS のテストなども、VM 上でおこなうことができるところです。（KVM に比べて、サポートが手薄な感は拭えませんが）</p>
<p><a href=http://www.redhat.com/rhel/>RHEL</a>5/<a href=http://www.centos.org/>CentOS</a>5 では、インストール中に &#8220;Virtualization&#8221; サポートのパッケージグループを有効にするだけで Xen の Dom0 がインストールできて簡単でした。ところが RHEL6/SL6 (<a href=http://www.scientificlinux.org/>Scientific Linux</a> 6) では、Red Hat による KVM 推しのせいか Xen Dom0 が除外されてしまいました。実運用に使うわけではないので品質は問わないので、SL6 を Xen Dom0 化してみました。</p>
<blockquote><p>
RHEL6 では、Dom0 が除外されただけです。ノーマルカーネルは <a href=http://wiki.xensource.com/xenwiki/XenParavirtOps>Xen pv_ops</a> オプション付きでビルドされているので、そのまま Xen DomU にはなれます。
</p></blockquote>
<p>なお、今回は本家の記事がネタ元。参考: &#8220;<a href="http://wiki.xensource.com/xenwiki/RHEL6Xen4Tutorial">RHEL6Xen4Tutorial &#8211; Xen Wiki</a>&#8220;。</p>
<h3>前準備</h3>
<p>まず、distro をインストールする先の VM の設定を変えます。KVM であれば、ストレージやネットワークに virtio を使わず、IDE や SCSI、RTL-8139 や E1000 あたりを利用した方が無難です。別段、Dom0 が virtio を使っちゃいかんこともないと思うのですが、起動・認識しませんでした。カーネルの config 等まで、よくは見ていません。VMware の ESXi でも同様に、SCSI は準仮想化を切り、LSI Logic PATA あたりに設定します (これまた起動しなくなります)。ターゲットとして「RHEL6」等の新しい distro を選択すると virtio を有効にされてしまうこともあるので注意します。</p>
<p>以下の例は、KVM にインストールした SL6 (&#8220;Desktop&#8221;) です。ありモノのパッケージを使う場合には /boot/ のサイズはそれほど要らないのですが、自分でビルドする場合には、巨大な全部入り initramfs を収めることになりますので、/boot/ に 1～2GB ほど割り当てておきます。それと、&#8221;Desktop&#8221; インストールをした後でビルドを行なうと、ざっと 12～13GB にはなります。</p>
<p>以下、ほめられたことではありませんが、面倒なのですべて root で作業します。SELinux と iptables も off にします。</p>
<pre>
[root@sl6x ~]# <b>chkconfig iptables off</b>
[root@sl6x ~]# <b>cp /etc/sysconfig/selinux /etc/sysconfig/selinux.orig</b>
[root@sl6x ~]# <b>vi /etc/sysconfig/selinux</b>
[root@sl6x ~]# <b>diff -uNr /etc/sysconfig/selinux.orig /etc/sysconfig/selinux</b>
--- /etc/sysconfig/selinux.orig
+++ /etc/sysconfig/selinux
@@ -4,7 +4,7 @@
 #     enforcing - SELinux security policy is enforced.
 #     permissive - SELinux prints warnings instead of enforcing.
 #     disabled - No SELinux policy is loaded.
-SELINUX=enforcing
+SELINUX=<b>disabled</b>
 # SELINUXTYPE= can take one of these two values:
 #     targeted - Targeted processes are protected,
 #     mls - Multi Level Security protection.
</pre>
<p>下記の組み合わせ (特に「ネット上で配布されているバイナリを利用する」場合) で、libvirt の virbr0 (NAT) 経由で Fedora 14 や SL6 を入れようとすると、どうも pv_ops な DomU のネットワークが不安定なのか、不定なタイミングでインストールがコケます。カーネルだけは手で入れた方が無難かも知れません。あるいは、下記のようにして直結ブリッジを作っておきます。（xenbr0 や peth0 が見当たりません。Xen 4 になって、見せないようになった？）</p>
<p>なお、&#8221;NM_CONTROLLED&#8221; の行を &#8220;no&#8221; にするやいなや NetworkManager はインターフェイスを off にしますので、リモートから編集していると切られます。</p>
<pre>
[root@sl6x ~]# <b>cd /etc/sysconfig/network-scripts/</b>
[root@sl6x network-scripts]# <b>cp ifcfg-eth0 /tmp/ifcfg-eth0</b>
[root@sl6x network-scripts]# <b>cp ifcfg-eth0 ifcfg-br0</b>
[root@sl6x network-scripts]# <b>vi ifcfg-eth0</b>
[root@sl6x network-scripts]# <b>vi ifcfg-br0</b>
[root@sl6x network-scripts]# <b>diff -uNr /tmp/ifcfg-eth0 ifcfg-eth0</b>
--- /tmp/ifcfg-eth0
+++ ifcfg-eth0
@@ -1,5 +1,4 @@
 DEVICE="eth0"
-<b>BOOTPROTO="dhcp"</b>
-<b>HWADDR="XX:XX:XX:XX:XX:XX"</b>
-NM_CONTROLLED="yes"
+NM_CONTROLLED="<b>no</b>"
 ONBOOT="yes"
+BRIDGE="<b>br0</b>"
[root@sl6x network-scripts]# <b>diff -uNr /tmp/ifcfg-eth0 ifcfg-br0</b>
--- /tmp/ifcfg-eth0
+++ ifcfg-br0
@@ -1,5 +1,5 @@
-DEVICE="eth0"
+DEVICE="<b>br0</b>"
 BOOTPROTO="dhcp"
-<b>HWADDR="XX:XX:XX:XX:XX:XX"</b>
-NM_CONTROLLED="yes"
+NM_CONTROLLED="<b>no</b>"
 ONBOOT="yes"
+<b>TYPE="Bridge"</b>
[root@sl6x network-scripts]# <b>cd</b>
[root@sl6x ~]# <b>service network restart</b>
</pre>
<p>計算ノードとして VM イメージをコピーする際には、当然 NIC の MAC アドレスも変わります。そのため、MAC アドレスを記憶されてしまうと不都合ですので、消して、二度と書かれないようにしておきます。参考: &#8220;<a href="http://6.ptmc.org/?p=164">Disable automatic udev rules for network interfaces in Ubuntu &lt;&lt; six degrees of freedom</a>&#8220;。</p>
<pre>
[root@sl6x ~]# <b>rm -f /etc/udev/rules.d/70-persistent-net.rules</b>
[root@sl6x ~]# <b>mkdir /etc/udev/rules.d/70-persistent-net.rules</b>
[root@sl6x ~]#
</pre>
<p>SELinux もオフにしたことですし、ここらで一度リブートしておきますか。</p>
<pre>
[root@sl6x ~]# <b>reboot</b>
</pre>
<h3>ネット上で配布されているバイナリを利用する場合</h3>
<p>コミュニティビルドのパッケージです。<a href="http://www.gitco.de/">ドイツ語は読めません</a>が、ありがたく利用させていただきます。</p>
<pre>
[root@sl6x ~]# <b>( cd /etc/yum.repos.d/ ; wget \
 http://www.gitco.de/linux/x86_64/centos/6/gitco-centos6-x86_64.repo )</b>
(中略)
2011-05-21 15:17:02 (62.2 MB/s) - “gitco-centos6-x86_64.repo” saved [607/607]
[root@sl6x ~]# <b>yum install -y kernel</b> # ← Dom0 カーネルが入らなければ要調整
(中略)
Installed:
  kernel.x86_64 0:2.6.32.26-174.1.xendom0.el6

Dependency Updated:
  kernel-firmware.x86_64 0:2.6.32.26-174.1.xendom0.el6

Complete!
[root@sl6x ~]# <b>yum install -y \
 xen xen-hypervisor xen-libs xen-licenses xen-runtime</b>
(中略)
Installed:
  xen.x86_64 0:4.0.1-6.1.el6            xen-hypervisor.x86_64 0:4.0.1-6.1.el6
  xen-libs.x86_64 0:4.0.1-6.1.el6       xen-licenses.x86_64 0:4.0.1-6.1.el6
  xen-runtime.x86_64 0:4.0.1-6.1.el6

Dependency Installed:
  PyXML.x86_64 0:0.8.4-19.el6              SDL.x86_64 0:1.2.14-2.el6
  qemu-common.x86_64 2:0.12.5-1.el6        qemu-img.x86_64 2:0.12.5-1.el6

Complete!
[root@sl6x ~]#
</pre>
<p>上記の手順で、カーネルよりも後で xen-runtime を入れることで、postinstall のスクリプトで grub.conf を適切に編集してくれます。でもこれ、本来は trigger スクリプトでやるべきなのでは？ もし xen.gz のエントリが書かれていないようであれば、以下のように手で書き換えます。</p>
<pre>
[root@sl6x ~]# <b>cp /boot/grub/grub.conf /boot/grub/grub.conf.orig</b>
[root@sl6x ~]# <b>vi /boot/grub/grub.conf</b>
[root@sl6x ~]# <b>diff -uNr /boot/grub/grub.conf.orig /boot/grub/grub.conf</b>
--- /boot/grub/grub.conf.orig
+++ /boot/grub/grub.conf
@@ -13,8 +13,9 @@
 hiddenmenu
 title Scientific Linux (2.6.32.26-174.1.xendom0.el6.x86_64)
        root (hd0,0)
-       <b>kernel</b> /vmlinuz-2.6.32.26-174.1.xendom0.el6.x86_64 ro (中略)
-       <b>initrd</b> /initramfs-2.6.32.26-174.1.xendom0.el6.x86_64.img
+       <b>kernel=/xen.gz</b>
+       <b>module</b> /vmlinuz-2.6.32.26-174.1.xendom0.el6.x86_64 ro (中略)
+       <b>module</b> /initramfs-2.6.32.26-174.1.xendom0.el6.x86_64.img
 title Scientific Linux (2.6.32-71.24.1.el6.x86_64)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-71.24.1.el6.x86_64 ro (中略)
[root@sl6x ~]#
</pre>
<p>Xen で KSM (Kernel Samepage Merging) は未サポートらしいので ksm と ksmtuned も切っておきます。</p>
<pre>
[root@sl6x ~]# <b>chkconfig ksm off</b>
[root@sl6x ~]# <b>chkconfig ksmtuned off</b>
[root@sl6x ~]#
</pre>
<p>Xen を、libvirt 経由で使います。UI としては、virt-manager が良いでしょう。python-virtinst を使いたかったのですが、Xen 4 に追随していないのか、blktap2 まわりで正しく動きませんでした。</p>
<pre>
[root@sl6x ~]# <b>yum install -y virt-manager libvirt</b>
(中略)
Installed:
  libvirt.x86_64 0:0.8.1-27.1.el6       virt-manager.noarch 0:0.8.4-8.el6

Dependency Installed:
  augeas-libs.x86_64 0:0.7.2-3.el6
  ebtables.x86_64 0:2.0.9-5.el6
  gtk-vnc.x86_64 0:0.3.10-3.el6
  gtk-vnc-python.x86_64 0:0.3.10-3.el6
  iscsi-initiator-utils.x86_64 0:6.2.0.872-10.el6
  libvirt-client.x86_64 0:0.8.1-27.1.el6
  libvirt-python.x86_64 0:0.8.1-27.1.el6
  lzo.x86_64 0:2.03-3.1.el6
  lzop.x86_64 0:1.02-0.9.rc1.el6
  nc.x86_64 0:1.84-22.el6
  netcf-libs.x86_64 0:0.1.6-4.el6
  numactl.x86_64 0:2.0.3-9.el6
  python-virtinst.noarch 0:0.500.3-7.el6
  yajl.x86_64 0:1.0.7-3.el6

Complete!
[root@sl6x ~]#
</pre>
<p>以上です。再起動して、Xen + Dom0 でブートします。</p>
<pre>
[root@sl6x ~]# <b>reboot</b>
</pre>
<p>再起動したら、とりあえず Dom0 で動いていることを確認してみます。</p>
<pre>
[root@sl6x ~]# <b>virsh list</b>
 Id Name                 State
----------------------------------
  0 Domain-0             running

[root@sl6x ~]#
</pre>
<p>テストとして、Virt-Manager から Scientific Linux 6 を ttp://ftp.riken.jp/Linux/scientific/6.0/x86_64/os/ からネットワークインストールしてみます。良いようです。ttp://rsync.atworks.co.jp/centos/5/os/i386/ も行けました。</p>
<p>ところで、UltraVNC Win32 Viewer で QEMU-KVM に繋いだ中で Virt-Manager の VNC クライアントが上がると、とても見づらい画面になるのは私だけ？ VNC クライアントのせいかしら。</p>
<h3>自前でビルドする場合</h3>
<p>まずは、標準レポジトリのパッケージをインストールします。</p>
<pre>
[root@sl6xdev ~]# <b>yum groupinstall -y \
 "Development tools" \
 "Additional Development" "Debugging Tools" \
 "System administration tools" \
 "Compatibility libraries" "Console internet tools" \
 "Desktop Platform Development"</b>
(中略)
Complete!
[root@sl6xdev ~]# <b>yum install -y \
 transfig wget texi2html libaio-devel dev86 \
 glibc-devel e2fsprogs-devel gitk mkinitrd iasl xz-devel \
 bzip2-devel pciutils-libs pciutils-devel SDL-devel \
 libX11-devel gtk2-devel bridge-utils PyXML qemu-common \
 qemu-img mercurial texinfo libuuid-devel</b>
(中略)
Complete!
[root@sl6xdev ~]# <b>yum install -y glibc-devel.i686</b>
(中略)
Complete!
[root@sl6xdev ~]#
</pre>
<p>Xen 4 のビルドとインストールをします。</p>
<pre>
[root@sl6xdev ~]# <b>host=ftp-srv2.kddilabs.jp</b>
[root@sl6xdev ~]# <b>path=/Linux/packages/fedora/releases/14/Everything/source/SRPMS</b>
[root@sl6xdev ~]# <b>ver=4.0.1-6.fc14</b>
[root@sl6xdev ~]# <b>wget http://$host/$path/xen-$ver.src.rpm</b>
(中略)
[root@sl6xdev ~]# <b>rpmbuild --rebuild xen-$ver.src.rpm</b>
(中略)
Wrote: /root/rpmbuild/RPMS/x86_64/xen-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-libs-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-runtime-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-hypervisor-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-doc-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-devel-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-licenses-4.0.1-6.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/xen-debuginfo-4.0.1-6.el6.x86_64.rpm
(中略)
+ exit 0
[root@sl6xdev ~]# <b>path=Linux/packages/fedora/releases/13/Fedora/source/SRPMS</b>
[root@sl6xdev ~]# <b>ver=0.12.3-8.fc13</b>
[root@sl6xdev ~]# <b>http://$host/$path/qemu-$ver.src.rpm</b>
(中略)
[root@sl6xdev ~]# <b>rpmbuild --rebuild qemu-$ver.src.rpm</b>
(中略)
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-kvm-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-img-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-common-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-user-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-x86-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-ppc-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-sparc-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-arm-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-mips-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-cris-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-m68k-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-system-sh4-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-kvm-tools-0.12.3-8.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/qemu-debuginfo-0.12.3-8.el6.x86_64.rpm
(中略)
+ exit 0
[root@sl6xdev ~]# <b>rpm -Uvh \
 ~/rpmbuild/RPMS/x86_64/xen-runtime-4* \
 ~/rpmbuild/RPMS/x86_64/xen-libs-4* \
 ~/rpmbuild/RPMS/x86_64/xen-licenses-4* \
 ~/rpmbuild/RPMS/x86_64/xen-4* \
 ~/rpmbuild/RPMS/x86_64/xen-hypervisor-4* \
 ~/rpmbuild/RPMS/x86_64/qemu-common-*</b>
(中略)
[root@sl6xdev ~]# <b>chkconfig ksm off</b>
[root@sl6xdev ~]# <b>chkconfig ksmtuned off</b>
[root@sl6xdev ~]#
</pre>
<p>Xen Dom0 カーネルのビルドとインストールをします。</p>
<pre>
[root@sl6xdev ~]# <b>git clone \
 git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git linux-2.6-xen</b>
Initialized empty Git repository in /root/linux-2.6-xen/.git/
(中略)
[root@sl6xdev ~]# <b>cd linux-2.6-xen</b>
[root@sl6xdev linux-2.6-xen]# <b>host=pasik.reaktio.net</b>
[root@sl6xdev linux-2.6-xen]# <b>wget -O .config \

http://$host/xen/kernel-config/config-2.6.32.25-pvops-dom0-xen-stable-x86_64</b>

(中略)
[root@sl6xdev linux-2.6-xen]# <b>make oldconfig</b>
(質問が出たら答えます)
[root@sl6xdev linux-2.6-xen]# <b>jobs=$(grep ^processor /proc/cpuinfo | wc -l)</b>
[root@sl6xdev linux-2.6-xen]# <b>make -j$jobs bzImage &#038;&#038; \
 make -j$jobs modules &#038;&#038; make modules_install</b>
(中略)
  INSTALL /lib/firmware/cpia2/stv0672_vp4.bin
  INSTALL /lib/firmware/yam/1200.bin
  INSTALL /lib/firmware/yam/9600.bin
  DEPMOD  2.6.32.40
[root@sl6xdev linux-2.6-xen]# <b>ver=$(make kernelversion)</b>
[root@sl6xdev linux-2.6-xen]# <b>depmod -a $ver</b>
[root@sl6xdev linux-2.6-xen]# <b>cp -a arch/x86/boot/bzImage /boot/vmlinuz-$ver</b>
[root@sl6xdev linux-2.6-xen]# <b>cp -a System.map /boot/System.map-$ver</b>
[root@sl6xdev linux-2.6-xen]# <b>cp -a .config /boot/config-$ver</b>
[root@sl6xdev linux-2.6-xen]# <b>cd /boot/</b>
[root@sl6xdev boot]# <b>dracut initramfs-$ver.img $ver</b>
[root@sl6xdev boot]# <b>cp /boot/grub/grub.conf /boot/grub/grub.conf.orig</b>
[root@sl6xdev boot]# <b>vi /boot/grub/grub.conf</b>
[root@sl6xdev boot]# <b>diff -uNr /boot/grub/grub.conf.orig /boot/grub/grub.conf</b>
--- /boot/grub/grub.conf.orig
+++ /boot/grub/grub.conf
@@ -11,6 +11,11 @@
 timeout=5
 splashimage=(hd0,0)/grub/splash.xpm.gz
 hiddenmenu
+<b>title Scientific Linux Dom0</b>
+<b>        root (hd0,0)</b>
+<b>        kernel /xen.gz dom0_mem=1024M loglvl=all guest_loglvl=all</b>
+<b>        module /vmlinuz-2.6.32.40 ro root=(中略)</b>
+<b>        module /initramfs-2.6.32.40.img</b>
 title Scientific Linux (2.6.32-71.24.1.el6.x86_64)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-71.24.1.el6.x86_64 ro root=(中略)
[root@sl6xdev boot]# <b>cd</b>
</pre>
<p>標準の libvirt では Xen API サポートが落ちているので、有効にしてビルドします。Dom0 カーネル上でビルドするとチェックでコケるらしいので、一応テストをオフにしておきます。virt-manager も入れておきます。</p>
<pre>
[root@sl6xdev ~]# <b>yumdownloader --source libvirt</b>
(中略)
libvirt-0.8.1-27.el6_0.5.src.rpm                         |  11 MB     00:06
[root@sl6xdev ~]# <b>rpm -i libvirt-*.src.rpm</b>
[root@sl6xdev ~]# <b>cp rpmbuild/SPECS/libvirt.spec \
 rpmbuild/SPECS/libvirt.spec.orig</b>
[root@sl6xdev ~]# <b>vi rpmbuild/SPECS/libvirt.spec</b>
[root@sl6xdev ~]# <b>diff -uNr rpmbuild/SPECS/libvirt.spec.orig \
 rpmbuild/SPECS/libvirt.spec</b>
--- rpmbuild/SPECS/libvirt.spec.orig
+++ rpmbuild/SPECS/libvirt.spec
@@ -107,7 +107,7 @@
 %ifnarch x86_64
 %define with_qemu 0
 %endif
-%define with_xen 0
+%define with_xen <b>1</b>
 %endif

 # If Xen isn't turned on, we shouldn't build the xen proxy either
@@ -1362,20 +1362,6 @@
 %clean
 rm -fr %{buildroot}

-%check
-cd tests
-# These 3 tests don't current work in a mock build root
-for i in nodeinfotest daemon-conf seclabeltest
-do
-  rm -f $i
-  echo -e "#!/bin/sh\nexit 0" > $i
-  chmod +x $i
-done
-# The test applied by patch need to be made executable
-chmod +x virsh-schedinfo
-
-make check
-
 %pre
 %if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
 # Normally 'setup' adds this in /etc/passwd, but this is
[root@sl6xdev ~]# <b>yum-builddep -y libvirt</b>
(中略)
Complete!
[root@sl6xdev ~]# <b>rpm -Uvh rpmbuild/RPMS/x86_64/xen-devel-*.rpm</b>
[root@sl6xdev ~]# <b>yum install -y libpcap-devel</b>
(中略)
Complete!
[root@sl6xdev ~]# <b>rpmbuild -ba rpmbuild/SPECS/libvirt.spec</b>
(中略)
Wrote: /root/rpmbuild/SRPMS/libvirt-0.8.1-27.el6.5.src.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/libvirt-0.8.1-27.el6.5.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/libvirt-client-0.8.1-27.el6.5.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/libvirt-devel-0.8.1-27.el6.5.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/libvirt-python-0.8.1-27.el6.5.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/libvirt-debuginfo-0.8.1-27.el6.5.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.aEw602
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd libvirt-0.8.1
+ rm -fr /root/rpmbuild/BUILDROOT/libvirt-0.8.1-27.el6.5.x86_64
+ exit 0
[root@sl6xdev ~]# <b>yum install -y nc ebtables lzop</b>
(中略)
Complete!
[root@sl6xdev ~]# <b>rpm -Uvh \
 rpmbuild/RPMS/x86_64/libvirt-client-0.8.1-27.el6.5.x86_64.rpm \
 rpmbuild/RPMS/x86_64/libvirt-0.8.1-27.el6.5.x86_64.rpm \
 rpmbuild/RPMS/x86_64/libvirt-python-0.8.1-27.el6.5.x86_64.rpm</b>
[root@sl6xdev ~]# <b>yum install -y virt-manager</b>
(中略)
Complete!
[root@sl6xdev ~]#
</pre>
<p>リブートします。</p>
<pre>
[root@sl6xdev ~]# <b>reboot</b>
</pre>
<p>先の例と同様に、Dom0 で動作していることを確認し、適当にインストールをしてみます。良いようです。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/05/22/xen4-sl6-dom0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scala: Haskell 本の引き写しでパーサジェネレータ</title>
		<link>http://www.ayutaya.com/2011/04/22/scala-haskell-parser-generato/</link>
		<comments>http://www.ayutaya.com/2011/04/22/scala-haskell-parser-generato/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 13:42:23 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=904</guid>
		<description><![CDATA[「プログラミング Haskell」の第 8 章「関数型パーサ」の写経をしようかと思ったのですが、そのまま引き写しても面白くないので、Scala で書いてみました。せっかくですので、Haskell のモナド連結の糖衣構文 do を、極力そのまま Scala の for 式で書けるよう、Parser[A] には、map(), flatMap() を備え、Scala の型とします。 …できた。Haskell 版から変えたところとしては、入力文字列にパーサを適用した際には、Scala らしく Option[(A, String)] を返すようにした、Haskell で [Char] であるところは、適宜 String にした、程度か。案外そのまま行けますね、というよりも、Scala が Haskell を色濃く反映しているんですね。 abstract trait Parser[A] { def apply(inp: String): Option[(A, String)] def parse(inp: String) = apply(inp) def map[B](f: (A) =&#62; B) = { def p_parse = parse [...]]]></description>
			<content:encoded><![CDATA[<p><iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=ayutaya-22&#038;o=9&#038;p=8&#038;l=as4&#038;m=amazon&#038;f=ifr&#038;ref=ss_til&#038;asins=4274067815" style="width:120px;height:240px;float:right;margin-left:1em;margin-bottom:1em;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></p>
<p>「<a href="http://www.amazon.co.jp/gp/product/4274067815/ref=as_li_ss_tl?ie=UTF8&#038;tag=ayutaya-22&#038;linkCode=as2&#038;camp=247&#038;creative=7399&#038;creativeASIN=4274067815">プログラミング Haskell</a><img src="http://www.assoc-amazon.jp/e/ir?t=&#038;l=as2&#038;o=9&#038;a=4274067815" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />」の第 8 章「関数型パーサ」の写経をしようかと思ったのですが、そのまま引き写しても面白くないので、Scala で書いてみました。せっかくですので、Haskell のモナド連結の糖衣構文 do を、極力そのまま Scala の for 式で書けるよう、Parser[A] には、map(), flatMap() を備え、Scala の型とします。</p>
<p>…できた。Haskell 版から変えたところとしては、入力文字列にパーサを適用した際には、Scala らしく Option[(A, String)] を返すようにした、Haskell で [Char] であるところは、適宜 String にした、程度か。案外そのまま行けますね、というよりも、Scala が Haskell を色濃く反映しているんですね。<br />
<br clear=all></p>
<pre>
abstract trait Parser[A] {
  def apply(inp: String): Option[(A, String)]
  def parse(inp: String) = apply(inp)
  def map[B](f: (A) =&gt; B) = {
    def p_parse = parse _
    new Parser[B] {
      def apply(inp: String) = {
        p_parse(inp) match {
          case None =&gt; None
          case Some((v, out)) =&gt; Some((f(v), out))
        }
      }
    }
  }
  def flatMap[B](f: (A) =&gt; Parser[B]): Parser[B] = {
    def p_parse = parse _
    new Parser[B] {
      def apply(inp: String) = {
        p_parse(inp) match {
          case None =&gt; None
          case Some((v, out)) =&gt; f(v)(out)
        }
      }
    }
  }
  def +++(q: Parser[A]) = {
    def p_parse = parse _
    new Parser[A] {
      def apply(inp: String) = {
        p_parse(inp) match {
          case None =&gt; q.parse(inp)
          case s @ Some(_) =&gt; s
        }
      }
    }
  }
}

def return_[A](v: A): Parser[A] = {
  new Parser[A] { def apply(inp: String) = { Some((v, inp)) } }
}

def failure[A]: Parser[A] = {
  new Parser[A] { def apply(inp: String) = { None } }
}

def item: Parser[Char] = new Parser[Char] {
  def apply(inp: String) = inp match {
    case "" =&gt; None
    case _ =&gt; Some((inp.head, inp.tail))
  }
}

def parse[A](p: Parser[A], inp: String): Option[(A, String)] = p(inp)

/*

parse(return_(1), "abc")
res1: Option[(Int, String)] = Some((1,abc))

parse(failure, "abc")
res2: Option[(Nothing, String)] = None

parse(item, "abc")
res3: Option[(Char, String)] = Some((a,bc))

 */

/*

def p = for {
  x &lt;- item
  _ &lt;- item
  y &lt;- item
} yield (x, y)
p: Parser[(Char, Char)]

def p_dash = item.flatMap(x =&gt;
  item.flatMap(__ =&gt;
    item.map(y =&gt;
      (x, y) )))
p_dash: Parser[(Char, Char)]

parse(p, "abcdef")
res4: Option[((Char, Char), String)] = Some(((a,c),def))

parse(p, "ab")
res5: Option[((Char, Char), String)] = None

 */

/*

parse(item +++ return_('d'), "abc")
res6: Option[(Char, String)] = Some((a,bc))

parse(failure +++ return_('d'), "abc")
res7: Option[(Char, String)] = Some((d,abc))

parse(failure +++ failure, "abc")
res8: Option[(Nothing, String)] = None

 */

def sat(p: (Char) =&gt; Boolean): Parser[Char] = for {
  x &lt;- item
  r &lt;- if (p(x)) return_(x) else failure
} yield (r)

def digit = sat(_.isDigit)

def lower = sat(_.isLower)

def upper = sat(_.isUpper)

def letter = sat(_.isLetter)

def alphanum = letter +++ digit

def char(x: Char) = sat(x.==)

/*

parse(digit, "123")
res9: Option[(Char, String)] = Some((1,23))

parse(digit, "abc")
res10: Option[(Char, String)] = None

parse(char('a'), "abc")
res11: Option[(Char, String)] = Some((a,bc))

parse(char('a'), "123")
res12: Option[(Char, String)] = None

 */

// これは文字列を返すパーサとする。Scala の String は List[Char] ではない
def string(s: String): Parser[String] = s match {
  case "" =&gt; return_("")
  case _ =&gt; for {
    x &lt;- char(s.head)
    xs &lt;- string(s.tail)
  } yield (x +: xs)
}

/*

parse(string("abc"), "abcdef")
res13: Option[(String, String)] = Some((abc,def))

parse(string("abc"), "ab1234")
res14: Option[(String, String)] = None

 */

object Many {
  def many[A](p: Parser[A]): Parser[List[A]] = {
    many1(p) +++ return_(Nil)
  }
  def many1[A](p: Parser[A]): Parser[List[A]] = {
    for {
      v &lt;- p
      vs &lt;- many(p)
    } yield (v :: vs)
  }
}
import Many._

/*

parse(many(digit), "123abc")
res15: Option[(List[Char], String)] = Some((List(1, 2, 3),abc))

parse(many(digit), "abcdef")
res16: Option[(List[Char], String)] = Some((List(),abcdef))

parse(many1(digit), "abcdef")
res17: Option[(List[Char], String)] = None

 */

// 仕方ないので文字列にしておく
def ident = for {
  x &lt;- lower
  xs &lt;- many(alphanum)
} yield ((x :: xs).foldLeft("")(_ + _))

// これも
def nat: Parser[Int] = for {
  xs &lt;- many1(digit)
} yield (xs.foldLeft("")(_ + _).toInt)

def space: Parser[Unit] = for {
  _ &lt;- many(sat(_.isWhitespace))
} yield (Unit)

/*

parse(ident, "abc def")
res0: Option[(java.lang.String, String)] = Some((abc, def))

parse(nat, "123 abc")
res1: Option[(Int, String)] = Some((123, abc))

parse(space, " abc")
res2: Option[(Unit, String)] = Some(((),abc))

 */

def token[A](p: Parser[A]): Parser[A] = for {
  _ &lt;- space
  v &lt;- p
  _ &lt;- space
} yield (v)

def identifier: Parser[String] = token(ident)

def natural: Parser[Int] = token(nat)

def symbol(xs: String): Parser[String] = token(string(xs))

/*

def p: Parser[List[Int]] = for {
  _ &lt;- symbol("[")
  n &lt;- natural
  ns &lt;- many(
    for {
      _ &lt;- symbol(",")
      x &lt;- natural
    } yield (x)
  )
  _ &lt;- symbol("]")
} yield (n :: ns)

parse(p, " [1, 2, 3] ")
res19: Option[(List[Int], String)] = Some((List(1, 2, 3),))

parse(p, "[1, 2,]")
res20: Option[(List[Int], String)] = None

 */

def int: Parser[Int] = (
  for {
    _ &lt;- symbol("-")
    n &lt;- natural
  } yield (- n)
) +++ natural

object Expr {
  def expr: Parser[Int] = for {
    t &lt;- term
    r &lt;- (
      for {
        _ &lt;- symbol("+")
        e &lt;- expr
      } yield (t + e)
    ) +++ (
      for {
        _ &lt;- symbol("-")
        e &lt;- expr
      } yield (t - e)
    ) +++ return_(t)
  } yield (r)
  def term: Parser[Int] = for {
    f &lt;- factor
    r &lt;- (
      for {
        _ &lt;- symbol("*")
        t &lt;- term
      } yield (f * t)
    ) +++ (
      for {
        _ &lt;- symbol("/")
        t &lt;- term
      } yield (f / t)
    ) +++ return_(f)
  } yield (r)
  def factor: Parser[Int] = (
    for {
      _ &lt;- symbol("(")
      e &lt;- expr
      _ &lt;- symbol(")")
    } yield (e)
  ) +++ int
}
import Expr._

/*

parse(expr, "2*3+4")
res26: Option[(Int, String)] = Some((10,))

parse(expr, "2*(3+4)")
res28: Option[(Int, String)] = Some((14,))

parse(expr, "2 * (3 + 4)")
res30: Option[(Int, String)] = Some((14,))

parse(expr, "2*3-4")
res33: Option[(Int, String)] = Some((2,))

parse(expr, "-1")
res36: Option[(Int, String)] = Some((-1,))

parse(expr, "(-3 * 4 * - 2) / 6")
res43: Option[(Int, String)] = Some((4,))

 */
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/04/22/scala-haskell-parser-generato/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scala: エラトステネスのふるいで無限長素数列</title>
		<link>http://www.ayutaya.com/2011/04/20/scala-infinite-prime-sequence/</link>
		<comments>http://www.ayutaya.com/2011/04/20/scala-infinite-prime-sequence/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 14:54:02 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=891</guid>
		<description><![CDATA[簡潔すぎﾜﾛﾀｗ import Stream._ def sieve[A &#60;% BigInt](xxs: Stream[A]): Stream[A] = xxs match { case p #:: xs =&#62; cons(p, sieve(xs.filter(_ % p != 0))) } lazy val primes = sieve(from(2)) 先頭 10 個。 scala&#62; primes.take(10).toList res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29) Fri Apr 22 2011: ついでに、遅延評価版のクイックソートも。まずは、普通に eager 評価のリストで書いた場合: [...]]]></description>
			<content:encoded><![CDATA[<p>簡潔すぎﾜﾛﾀｗ</p>
<pre>
import Stream._
def sieve[A &lt;% BigInt](xxs: Stream[A]): Stream[A] = xxs match {
  case p #:: xs =&gt; cons(p, sieve(xs.filter(_ % p != 0)))
}
lazy val primes = sieve(from(2))
</pre>
<p>先頭 10 個。</p>
<pre>
scala&gt; primes.take(10).toList
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
</pre>
<p>Fri Apr 22 2011: ついでに、遅延評価版のクイックソートも。まずは、普通に eager 評価のリストで書いた場合:</p>
<pre>
def qsort[A &lt;% Ordered[A]](xxs: List[A]): List[A] = xxs match {
  case Nil =&gt; Nil
  case p :: xs =&gt;
    qsort(xs filter(_ &lt;= p)) ++ (p :: qsort(xs filter(p &lt; _)))
}
</pre>
<p>ストリームで書くと、以下のように:</p>
<pre>
import Stream._
def qsort[A &lt;% Ordered[A]](xxs: Stream[A]): Stream[A] = xxs match {
  case Empty =&gt; Empty
  case p #:: xs =&gt;
    qsort(xs filter(_ &lt; p)) ++ (p #:: qsort(xs filter(p &lt;= _)))
}
</pre>
<p>ほぼ同じですが、&#8221;Empty&#8221; や &#8220;#::&#8221; などが特徴的です。不用意に無限長ストリームのソートなんかしちゃダメですよ。filter() が返ってきません。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/04/20/scala-infinite-prime-sequence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WSH JScript の REPL を書いてみた</title>
		<link>http://www.ayutaya.com/2011/04/13/wsh-jscript-rep/</link>
		<comments>http://www.ayutaya.com/2011/04/13/wsh-jscript-rep/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 14:38:27 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=872</guid>
		<description><![CDATA[「秀丸エディタ用、Emacs の eval-print-last-sexp 風マクロ for Scala, Clojure, Gauche, Groovy, Python and Ruby &#8211; Ayutaya.com」で、REPL が無いので流していた WSH の JScript (JavaScript) ですが、eval() があるのだからサクッと書けば良いので、どうせ世の中にはすでにたくさんの実装があるとは思われますが、書いてみました。お入り用でしたらこちらからどうぞ。 eval() が環境を汚すので、識別子には &#8220;_&#8221; を前置しています。それでも衝突すると言うならば、&#8221;_&#8221; を &#8220;_HOGEHOGE_&#8221; とでも全置換しても平気なように書かれています。ダブルクォートもバックスラッシュも使っていないので、別プログラム内へ埋め込むのも簡単です。一点ハマったのは、eval() は現在の環境内で実行されるので、当初別ファイルをロードする処理を関数にしたら、呼ばれた関数内で eval() されてしまい、そこから戻ったら &#8220;var&#8221; も &#8220;function&#8221; も消えていたことです。仕方がないので、入力ハンドラをスタックするようにしています。 実行例としては、以下のような感じです。 C:\&#62;cscript.exe wshrepl.js Microsoft (R) Windows Script Host Version 5.7 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. &#62; 1 [...]]]></description>
			<content:encoded><![CDATA[<p>「<a href="http://www.ayutaya.com/2011/04/11/hidemaru-eval/">秀丸エディタ用、Emacs の eval-print-last-sexp 風マクロ for Scala, Clojure, Gauche, Groovy, Python and Ruby &#8211; Ayutaya.com</a>」で、REPL が無いので流していた WSH の JScript (JavaScript) ですが、eval() があるのだからサクッと書けば良いので、どうせ世の中にはすでにたくさんの実装があるとは思われますが、書いてみました。お入り用でしたら<a href=http://dl.dropbox.com/u/19361235/wshrepl.js.txt>こちら</a>からどうぞ。</p>
<p>eval() が環境を汚すので、識別子には &#8220;_&#8221; を前置しています。それでも衝突すると言うならば、&#8221;_&#8221; を &#8220;_HOGEHOGE_&#8221; とでも全置換しても平気なように書かれています。ダブルクォートもバックスラッシュも使っていないので、別プログラム内へ埋め込むのも簡単です。一点ハマったのは、eval() は現在の環境内で実行されるので、当初別ファイルをロードする処理を関数にしたら、呼ばれた関数内で eval() されてしまい、そこから戻ったら &#8220;var&#8221; も &#8220;function&#8221; も消えていたことです。仕方がないので、入力ハンドラをスタックするようにしています。</p>
<p>実行例としては、以下のような感じです。</p>
<pre>
C:\&gt;<strong>cscript.exe wshrepl.js</strong>
Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

&gt; <strong>1 + 2 +</strong>
|   <strong>3 + 4</strong>
= 10
&gt; <strong>function foo() {</strong>
| <strong>  WScript.Echo("Hello!");</strong>
| <strong>}</strong>
= undefined
&gt; foo()
Hello!
= undefined
&gt; <strong>:load c:\priv\prog\bat\wsh.js</strong>
= Hello, World!
= undefined
&gt; <strong>^Z</strong>

C:\&gt;
</pre>
<p>以下は、ついでの tips です。</p>
<p>最新のブラウザの JavaScript に比べるといろいろと見劣りする Jscript ではありますが、そこは腐っても JavaScript 1.5 ですから、prototype を拡張して、map(), reduce(), filter() その他を拡張しておくと、なかなかに使える環境になります。</p>
<p>include が無い JScript ですが、そこは eval() で何とでもなります。以下は、実行スクリプトと同一ディレクトリにある &#8220;wsh.js&#8221; を初期化ファイルとして取り込みます。記述を短くしようと思って &#8220;WScript&#8221; を &#8220;with&#8221; すると、なぜか挙動がおかしくなります。</p>
<pre>
eval(WScript.CreateObject('Scripting.FileSystemObject').OpenTextFile(
 WScript.ScriptFullName.slice(0,-WScript.ScriptName.length)+'wsh.js' ).ReadAll());
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/04/13/wsh-jscript-rep/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>秀丸エディタ用、Emacs の eval-print-last-sexp 風マクロ for Scala, Clojure, Gauche, Groovy, Python, Ruby, JScript, Haskell and Perl</title>
		<link>http://www.ayutaya.com/2011/04/11/hidemaru-eval/</link>
		<comments>http://www.ayutaya.com/2011/04/11/hidemaru-eval/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 08:42:38 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=848</guid>
		<description><![CDATA[Emacs の lisp-interaction-mode に、編集中のテキスト上のカーソル直前位置の Emacs Lisp の S 式を評価する便利なコマンド &#8220;eval-print-last-sexp&#8221; がありますが、その秀丸エディタ用、各種プログラミング言語対応版です。下記は HTML で文章を書きながら、その中の Clojure のサンプルコードを評価している例です。矢印位置にカーソル (&#124;) がある状態で、この場合は &#8220;eval-clojure.mac &#8221; を実行してみます。 &#60;p&#62;下記は、クイックソートのサンプルです: &#60;pre&#62; (defn qsort [[x &#38; xs]] (when x (let [smaller #(&#60; % x)] (lazy-cat (qsort (filter smaller xs)) [x] (qsort (remove smaller xs)) ))))&#124; ← &#60;/pre&#62; 定義が評価されてシンボルが返ります。 &#60;p&#62;下記は、クイックソートのサンプルです: &#60;pre&#62; (defn qsort [[x &#38; xs]] [...]]]></description>
			<content:encoded><![CDATA[<p><a href=http://www.gnu.org/software/emacs/>Emacs</a> の lisp-interaction-mode に、編集中のテキスト上のカーソル直前位置の Emacs Lisp の S 式を評価する便利なコマンド &#8220;eval-print-last-sexp&#8221; がありますが、その<a href="http://hide.maruo.co.jp/software/hidemaru.html">秀丸エディタ</a>用、各種プログラミング言語対応版です。下記は HTML で文章を書きながら、その中の Clojure のサンプルコードを評価している例です。矢印位置にカーソル (|) がある状態で、この場合は &#8220;eval-clojure.mac &#8221; を実行してみます。</p>
<pre>
&lt;p&gt;下記は、クイックソートのサンプルです:

&lt;pre&gt;
(defn qsort [[x &amp; xs]]
  (when x
    (let [smaller #(&lt; % x)]
      (lazy-cat
        (qsort (filter smaller xs))
        [x]
        (qsort (remove smaller xs)) ))))<strong>|</strong> ←
&lt;/pre&gt;
</pre>
<p>定義が評価されてシンボルが返ります。</p>
<pre>
&lt;p&gt;下記は、クイックソートのサンプルです:

&lt;pre&gt;
(defn qsort [[x &amp; xs]]
  (when x
    (let [smaller #(&lt; % x)]
      (lazy-cat
        (qsort (filter smaller xs))
        [x]
        (qsort (remove smaller xs)) ))))
<strong>#'user/qsort</strong> ←
&lt;/pre&gt;
</pre>
<p>そのまま試しに実行してみます。</p>
<pre>
(qsort '(5 3 8 9 2))<strong>|</strong> ←
</pre>
<p>その場に結果が返ります。</p>
<pre>
(qsort '(5 3 8 9 2))
<strong>(2 3 5 8 9)</strong> ←
</pre>
<p>いずれも、日本語も通ります。下記は Scala の例です。</p>
<pre>
val l = "日本語" :: "テキスト" :: Nil
l: List[java.lang.String] = List(日本語, テキスト)
</pre>
<p>どこか、昔の Basic インタプリタで開発をしていたような快適さがあります (あいにく SmallTalk の経験は無い)。とりわけ、関数型言語と相性が良いんでないかしら、このスタイルは。メリットとしては、以下のような感じかと思います:</p>
<ul>
<li>言語をその場でチャンポンに書ける: ガッツリとアプリを開発するのであれば Emacs なり Eclipse なりの各言語のモードを利用すれば良いのでしょうが、つらつらと考えながら各言語を横断的に、サンプルなどのスクリプト片を次々に試しながらコメントも書きたい場合などには、同一テキスト上でその場で評価し、すぐに結果が返る方が快適です
<li>コピペをしなくてすむ: いちいちエディタ上で書いて、それを REPL にコピペ実行、というのは、思考を阻害します
<li>起動オーバーヘッドが無い: REPL のセッションをバックグラウンドで維持しますので、とりわけ Scala や Clojure などの、JVM を使う、起動が異様に遅い REPL でも、2 度目以降の評価はサクサクです。非力なノートマシンには、これがありがたい
<li>エディタから離れなくて済む: 一日のほとんどをエディタ上で過ごす身としては、ひととおりのスクリプト実行がその場でできるというのはありがたいです。コード片も、無くさず記録として残りますし
<li>キー一発: キーを割り当てておけば、普段書きのテキストから各言語にキー一発 (2 ストロークならば二発ですが) でアクセスできます
</ul>
<p>秀丸エディタは、<a href="http://hide.maruo.co.jp/software/hidemaru8/index.html">ver .8.0 以降</a>のマクロで COM オブジェクトの操作をサポートしたため、以前にはできなかった複雑なアプリケーション連携や、テキストを開いている間だけ永続するオブジェクト等を持つことができるようになりました。今回のマクロも、バックグラウンドで各言語の REPL セッションを起動して、テキストをクローズするまでの間、状態を維持することができるようになったことで実現できました。</p>
<p>詳細は以下ですが、詳しくはコードを読んでください。なお、範囲選択をして実行すれば、選択範囲を評価します。</p>
<table>
<tr>
<th><nobr>マクロ名</nobr></th>
<th>カーソル以前のどこまでを一単位として評価？</th>
<th>入出力方式</th>
<th>既知の問題</th>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-scala.mac.txt>eval-scala.mac</a></nobr></td>
<td>カーソルのある行、あるいは対応する括弧かヒアドキュメントによって継続している複数行 (Scala に &#8220;\&#8221; による行継続は無い)</td>
<td>入力は REPL の :load、出力は STDOUT (SJIS)</td>
<td>あいかわらず初回起動が遅いが、こればかりはどうしようもない</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-clojure.mac.txt>eval-clojure.mac</a></nobr></td>
<td>カーソル直前の S 式</td>
<td>入力は専用 REPL、出力は STDOUT (SJIS)</td>
<td>初回起動は、そこそこに遅い。STDERR をファイルに出力する方法が分からなかったが、多分あまり支障はない</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-gauche.mac.txt>eval-gauche.mac</a></nobr></td>
<td>カーソル直前の S 式</td>
<td>入出力とも専用 REPL (UTF-8)</td>
<td>特に無い。Scheme は Gauche がお気に入りなので、Guile は確認していない。</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-groovy.mac.txt>eval-groovy.mac</a></nobr></td>
<td>カーソルのある行、あるいは対応する括弧かヒアドキュメントによって継続している複数行、あるいは &#8220;\&#8221; で継続している複数行</td>
<td>入力は REPL の \l、出力は STDOUT (SJIS)</td>
<td>jline が &#8220;unix&#8221; モードでないと STDIN を正しく扱えなかったため、動作に MinGW の sh(1) と stty(1) が必要</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-python.mac.txt>eval-python.mac</a></nobr></td>
<td>第一カラムが空白ではないカーソル行、あるいはカーソル行以前で第一カラムが空白ではない行までの複数行、あるいは &#8220;\&#8221; で行継続をしている複数行</td>
<td>入力は専用の REPL、出力は STDOUT (UTF-8)</td>
<td>REPL の返事が淡白すぎて、返り値が分かりづらい</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-ruby.mac.txt>eval-ruby.mac</a></nobr></td>
<td>カーソルのある行、あるいはカーソル行上の &#8220;end&#8221; とカラムが合う直前の開始行までの複数行、あるいは &#8220;\&#8221; で行継続している複数行</td>
<td>入力は REPL の irb_source()、出力は STDOUT (SJIS)</td>
<td>irb_source() が、たまにファイルハンドルを離してくれないのか、一時ファイルを delete できないことがある。上書きするので、おそらく動作に支障はない</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-jscript.mac.txt>eval-jscript.mac</a></nobr></td>
<td>Groovy とだいたい同じ (本当なら、いろいろ違うんだけど…)</td>
<td>入力は自前実装の REPL で &#8220;:load&#8221;、出力は STDOUT (SJIS)</td>
<td>:load は、通常の eval() ではなく、REPL 的に行単位で評価されるので注意。ブロック内の空行はインデントしておいてください</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-haskell.mac.txt>eval-haskell.mac</a></nobr></td>
<td>第 1 カラム目が空白であれば、直前の &#8220;module&#8221; までをモジュールとしてロードする。第 1 カラム目が空白でなければ、式として解釈する</td>
<td>モジュールの入力は REPL の &#8220;:load&#8221;、式の入力は STDIN から、出力は STDOUT </td>
<td>GHC では、日本語入力は Unicode に落ちるものの、出力はできないようだ</td>
</tr>
<tr>
<td><nobr><a href=http://dl.dropbox.com/u/19361235/eval-perl.mac.txt>eval-perl.mac</a></nobr></td>
<td>カーソル行か、括弧を辿って戻れるところまで</td>
<td>入力は<a href=http://dl.dropbox.com/u/19361235/repl.pl.txt>自前 REPL</a> の &#8220;:load&#8221; から、出力は STDOUT から</td>
<td>Perl の eval() は新しくブロックを作ってしまうので、評価単位内の &#8220;my&#8221;, &#8220;local&#8221; 変数や &#8220;$1&#8243; などは、eval() が終わると破棄されてしまう。&#8221;$s =~ /([a-z]+)/; $mstr = $1&#8243; のように複文で保持するなど要工夫</td>
</tr>
</table>
<p>あとは <del datetime="2011-04-14T19:29:09+00:00">Haskell (トップレベルの扱いがよく分からなくて作れなかった)</del> と、<del datetime="2011-04-13T14:41:51+00:00">JavaScript (WSH には REPL が無い) 用</del>が欲しいところです。</p>
<p>Wed Apr 13 2011: JScript 用を追加。REPL 単体については「<a href="http://www.ayutaya.com/2011/04/13/wsh-jscript-rep/">WSH JScript の REPL を書いてみた &#8211; Ayutaya.com</a>」から。</p>
<p>Fri Apr 15 2011: Haskell (GHC) 用を追加。言語が言語なので、少々特殊。</p>
<p>このカーソル位置（↓）でマクロを起動すると、</p>
<pre>
module Test where
  fib 1 = 1
  fib 2 = 1
  fib n = fib (n - 1) + fib (n - 2)
<strong>|</strong> ←
</pre>
<p>モジュールをロード。もう一度実行すれば、再ロード。</p>
<pre>
module Test where
  fib 1 = 1
  fib 2 = 1
  fib n = fib (n - 1) + fib (n - 2)

[1 of 1] Compiling Test
( C:\DOCUME~1\KIICHI~1\LOCALS~1\Temp\haskell_input_2821200.hs, interpreted )
Ok, modules loaded: Test.
<strong>|</strong>
</pre>
<p>続けて式を評価すると、</p>
<pre>
<strong>fib 10</strong> ←
</pre>
<p>値が返る。</p>
<pre>
fib 10
<strong>55</strong> ←
<strong>|</strong>
</pre>
<p>Sun Apr 17 2011: Perl を追加。eval() の仕様故に、若干心残りが…。残るは PHP と VBScript くらいか。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/04/11/hidemaru-eval/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scala: コンストラクタの意味合いとクロージャ</title>
		<link>http://www.ayutaya.com/2011/04/11/scala-constructor-closure/</link>
		<comments>http://www.ayutaya.com/2011/04/11/scala-constructor-closure/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 05:12:14 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=832</guid>
		<description><![CDATA[以前、「Scala: コンストラクタ中の一時オブジェクトに消えて欲しい &#8211; Ayutaya.com」などと言っていた私ですが、ちょっと考え違いをしていました。なまじ逆コンパイルなどをしてしまったために、C++～Java 的な構造体指向の発想にとらわれていましたが、文法的に見ると、Scala のクラス～コンストラクタは、静的なクロージャセットの構築だと見た方が自然です。であれば、クロージャに束縛された「スタック上の変数」が残るのも道理です。 例として、ベクトル型 (+ 絶対値を求めるメソッド) を Scala で下記のように書いたとして、 class Vect(x: Int, y: Int) { def abs = { math.sqrt(x * x + y * y) } } val v = new Vect(2, 3) println(v.abs) 同じものを、例えば JavaScript で、プロトタイプを使わずにクロージャで書いたとします。 function Vect(x, y) { this.abs = function() { return (Math.sqrt(x * x + y [...]]]></description>
			<content:encoded><![CDATA[<p>以前、「<a href=http://www.ayutaya.com/2010/10/26/scala-constructor-temporary-object/>Scala: コンストラクタ中の一時オブジェクトに消えて欲しい &#8211; Ayutaya.com</a>」などと言っていた私ですが、ちょっと考え違いをしていました。なまじ逆コンパイルなどをしてしまったために、C++～Java 的な構造体指向の発想にとらわれていましたが、文法的に見ると、Scala のクラス～コンストラクタは、静的なクロージャセットの構築だと見た方が自然です。であれば、クロージャに束縛された「スタック上の変数」が残るのも道理です。</p>
<p>例として、ベクトル型 (+ 絶対値を求めるメソッド) を Scala で下記のように書いたとして、</p>
<pre>
class Vect(x: Int, y: Int) {
  def abs = {
    math.sqrt(x * x + y * y)
  }
}

val v = new Vect(2, 3)
println(v.abs)
</pre>
<p>同じものを、例えば JavaScript で、プロトタイプを使わずにクロージャで書いたとします。</p>
<pre>
function Vect(x, y) {
  this.abs = function() {
    return (Math.sqrt(x * x + y * y));
  }
}

var v = new Vect(2, 3);
WScript.Echo(v.abs());
</pre>
<p>一目瞭然でそっくりです。Scala でオブジェクト生成の際に &#8220;new&#8221; が省略されないことも、それが意味するところが、通常の関数呼び出しと違って、クロージャの配列領域を確保する命令であると考えることができますし (上記の JavaScript でも &#8220;new&#8221; が、&#8221;this&#8221; に相当するオブジェクトを作っていますし)、パブリックな「メンバ変数」が実際にはアクセサとなっているところも、Scala のコンストラクタが「クロージャ群の構築子」であると考えれば一貫しています。</p>
<p>以上、Scala で腑に落ちた点をちょろっと。では。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/04/11/scala-constructor-closure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows 7 で WSC をコマンドラインから登録する</title>
		<link>http://www.ayutaya.com/2011/02/25/wsc-cli-registration/</link>
		<comments>http://www.ayutaya.com/2011/02/25/wsc-cli-registration/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 15:55:46 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=811</guid>
		<description><![CDATA[WSC (Windows Script Components) を登録する際に、「右クリックして『登録』をクリック」がダサくて仕方がありません。複数マシンへ大量に登録したい時にどうしろってんだ、と。そこで、コマンドラインから登録できないものかと探していると、ありました、regsvr32.exe です。どうやら、OLE コントロールとしてひとくくりに、DLL や OCX の登録と同じ要領でよいようです。 スクリプト コンポーネントを登録する Regsvr32 の使用法とエラー メッセージについて # どうでもいいけど、あいかわらずマイクロソフトの、カタカナ単語間をスペースで切る表記はきもちわるい。&#8221;・&#8221;を使おうよ 当方 Windows 7 ですので、UAC (User Account Control) をパスするなり何なりして、管理者権限で実行する必要があるようです。 コマンドプロンプトを管理者権限で起動してから実行しても良いのですが、それもあまりスマートではありません。su(1) か sudo(8) のようなコマンドはないのですか？ なに？ runas.exe を使え？ 了解しました。 &#62; runas.exe /savecred /env /user:administrator "regsvr32.exe /s Foo.wsc" administrator のパスワードを入力してください: administrator アカウントのパスワード？ そんなもの設定したおぼえがないよ。しかたがないので、administrator 権限を持つアカウントでコンソールを管理者権限で起動、パスワードを設定します。まあ、これは初回だけですし。 &#62; net user administrator * ユーザーのパスワードを入力してください: 確認のためにパスワードを再入力してください: コマンドは正常に終了しました。 [...]]]></description>
			<content:encoded><![CDATA[<p>WSC (Windows Script Components) を登録する際に、「右クリックして『登録』をクリック」がダサくて仕方がありません。複数マシンへ大量に登録したい時にどうしろってんだ、と。そこで、コマンドラインから登録できないものかと探していると、ありました、regsvr32.exe です。どうやら、OLE コントロールとしてひとくくりに、DLL や OCX の登録と同じ要領でよいようです。</p>
<ul>
<li><a href="http://msdn.microsoft.com/ja-jp/library/cc392087.aspx">スクリプト コンポーネントを登録する</a>
<li><a href=http://support.microsoft.com/kb/249873/ja>Regsvr32 の使用法とエラー メッセージについて</a>
</ul>
<p># どうでもいいけど、あいかわらずマイクロソフトの、カタカナ単語間をスペースで切る表記はきもちわるい。&#8221;・&#8221;を使おうよ</p>
<p>当方 Windows 7 ですので、UAC (User Account Control) をパスするなり何なりして、管理者権限で実行する必要があるようです。</p>
<p>コマンドプロンプトを管理者権限で起動してから実行しても良いのですが、それもあまりスマートではありません。su(1) か sudo(8) のようなコマンドはないのですか？ なに？ runas.exe を使え？ 了解しました。</p>
<pre>
&gt; <strong>runas.exe /savecred /env /user:administrator "regsvr32.exe /s Foo.wsc"</strong>
administrator のパスワードを入力してください:
</pre>
<p>administrator アカウントのパスワード？ そんなもの設定したおぼえがないよ。しかたがないので、administrator 権限を持つアカウントでコンソールを管理者権限で起動、パスワードを設定します。まあ、これは初回だけですし。</p>
<pre>
&gt; <strong>net user administrator *</strong>
ユーザーのパスワードを入力してください:
確認のためにパスワードを再入力してください:
コマンドは正常に終了しました。

&gt;
</pre>
<p>これで、こんどこそは行け…たのですが、何度かしくじっているうちに、以下のようになってしまいました。</p>
<pre>
&gt; <strong>runas.exe /env /user:administrator "regsvr32.exe /s Foo.wsc"</strong>
regsvr32.exe /s Foo.wsc をユーザー "SVX\administrator" として開始して
います...
RUNAS エラー:  実行できません - regsvr32.exe /s /u AyutayaCalc.wsc
1327: ログオン失敗: ユーザー アカウントの制限。考えられる理由として、空
 のパスワードが許可されていない、ログオン時間制限、またはポリシーによる制
 限が適用された、などが挙げられます。
&gt;
</pre>
<p>どうやら、パスワードなしの状態の時に適当なパスワードを入れてログオン認証に失敗しまくったせいで、アカウント停止を食らったようです。</p>
<pre>
&gt; <strong>net user administrator | findstr /r アカウント有効</strong>
アカウント有効                       No
&gt;
</pre>
<p>あらら。再度有効化します。</p>
<pre>
&gt; <strong>net user administrator /active:yes</strong>
コマンドは正常に終了しました。

&gt;
</pre>
<p>はい、何よりです。</p>
<p>面倒なので、&#8221;/env&#8221; で、administrator になった後も環境を引き継ぎます。これで、カレントディレクトリの &#8220;Foo.wsc&#8221; を登録できるようになります。su(1) で &#8220;-&#8221; をつけないような挙動ですね。&#8221;/savecred&#8221; で、安い Windows 以外ならばパスワードを記憶できるそうです。</p>
<pre>
&gt; <strong>runas.exe /savecred /env /user:administrator "regsvr32.exe /s Foo.wsc"</strong>
administrator のパスワードを入力してください:
regsvr32.exe /s Foo.wsc をユーザー "SVX\administrator" として開始しています...
&gt;
</pre>
<p>さて、JScript な WSH で WSC を書くとします。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/02/25/wsc-cli-registration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ソース斜め読み: Eucalyptus CLC, Walrus, SC のエントリやハンドラはどこ？</title>
		<link>http://www.ayutaya.com/2011/02/20/eucalyptus-clou/</link>
		<comments>http://www.ayutaya.com/2011/02/20/eucalyptus-clou/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 09:45:33 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[未分類]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=803</guid>
		<description><![CDATA[注意: 以下の文章は、なかばメモ書きですので、正直言って分かりづらいですが、ネット上に Eucalyptus &#8220;eucalyptus-cloud&#8221; コマンドの実装に関する情報がまるでないので、本気で読む気がある人にとっては、この程度でも、とっかかりとしては充分に有用だと思います。逆に、興味のない人にとっては、どんなに分かりやすく書いてもさっぱり分からないと思いますので、こんなもんでいいかな、と (なんてひどい)。 前回は、eucalyptus-cloud コマンドが JNI で Java のコードを起動するところまでを追ったのですが、その先がさっぱり分かりません。eucalyptus-cloud 配下で CloudController, Walrus, StorageController といった Web API のサービスが起動されるはずなのですが、どうやら動的に *.jar 内を探り、条件に合うクラスからインスタンスを作ることでサービスを起動しているようなので、ソースだけを見ていても、実際にどこでサービスや、サービスの個々の機能を定義しているのかの当たりがつけられません。 仕方がないので、動態デバッグ (&#8220;post-mortem&#8221; に対してならば、&#8221;antemortem&#8221; とでも言うのかな？) を試みますが、C から JNI で呼ばれる Java アプリケーションのデバッグはどうやるのでしょう？ よく見たら、ちゃんと &#8220;eucalyptus-cloud&#8221; コマンドにオプションがありました。 $ eucalyptus-cloud --help (...) -d, --debug Launch with debugger enabled. (default=off) --debug-port=INT Set the port to use for the debugger. [...]]]></description>
			<content:encoded><![CDATA[<p>注意: 以下の文章は、なかばメモ書きですので、正直言って分かりづらいですが、ネット上に Eucalyptus &#8220;eucalyptus-cloud&#8221; コマンドの実装に関する情報がまるでないので、本気で読む気がある人にとっては、この程度でも、とっかかりとしては充分に有用だと思います。逆に、興味のない人にとっては、どんなに分かりやすく書いてもさっぱり分からないと思いますので、こんなもんでいいかな、と (なんてひどい)。</p>
<p><a href=http://www.ayutaya.com/2011/02/03/eucalyptus-clc/>前回</a>は、eucalyptus-cloud コマンドが JNI で Java のコードを起動するところまでを追ったのですが、その先がさっぱり分かりません。eucalyptus-cloud 配下で CloudController, Walrus, StorageController といった Web API のサービスが起動されるはずなのですが、どうやら動的に *.jar 内を探り、条件に合うクラスからインスタンスを作ることでサービスを起動しているようなので、ソースだけを見ていても、実際にどこでサービスや、サービスの個々の機能を定義しているのかの当たりがつけられません。</p>
<p>仕方がないので、動態デバッグ (&#8220;post-mortem&#8221; に対してならば、&#8221;antemortem&#8221; とでも言うのかな？) を試みますが、C から JNI で呼ばれる Java アプリケーションのデバッグはどうやるのでしょう？ よく見たら、ちゃんと &#8220;eucalyptus-cloud&#8221; コマンドにオプションがありました。</p>
<pre>
$ eucalyptus-cloud --help
(...)
  -d, --debug                   Launch with debugger enabled.  (default=off)
      --debug-port=INT          Set the port to use for the debugger.
                                  (default=`5005')
      --debug-suspend           Set the port to use for the debugger.
                                  (default=off)
</pre>
<p>ポートを指定してサスペンドするよう指示すれば、JVM のデバッガのポートを開けて待っていてくれるので、後は JDB なり Eclipse なりのデバッガを繋げば OK です。起動スクリプトにオプションを追加します。</p>
<pre>
--- /etc/init/eucalyptus.conf.orig
+++ /etc/init/eucalyptus.conf
@@ -37,6 +37,7 @@
        . /etc/eucalyptus/eucalyptus.conf
        [ -n "$JVM_MEM" ] || JVM_MEM="512m"
        opts="-h $EUCALYPTUS -u $EUCA_USER --pidfile \
         /var/run/eucalyptus/eucalyptus.pid -l $LOGLEVEL -L console-log
         -Xmx$JVM_MEM"
+       opts="$opts --debug --debug-suspend --debug-port=5005"
        services=""

        # If the -cloud package is not installed, disable the cloud service
@@ -72,7 +73,7 @@
        # Start the appropriate service(s)
        if [ -n "$services" ]; then
                # Cloud services to run
-               exec eucalyptus-cloud $opts
+               exec eucalyptus-cloud $opts &gt; /tmp/eucalyptus.log 2&gt;&amp;1
        elif [ -r "/etc/init/eucalyptus-nc.conf" ] || \
         [ -r "/etc/init/eucalyptus-cc.conf" ]; then
                # Node or CC services to run
                # Why do we sleep here, rather than emitting a signal?
                #  Such that we can run:
</pre>
<p>さて、その後つらつらと実行しながら眺めて行くと、Eucalyptus の関連クラスを取得しに行くのが、com.eucalyptus.bootstrap.Bootstrap.doDiscovery() のようです。以下が、doDiscovery() に入ったところのスタックのバックトレースです。</p>
<pre>
Thread [main] (Suspended (entry into method doDiscovery in Bootstrap))
  Bootstrap.doDiscovery() line: 151
  Bootstrap.initialize() line: 261
  SystemBootstrapper.init() line: 109
</pre>
<p><!-- clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/Component.java --></p>
<p>処理は、ゴリゴリです。</p>
<pre>
private static void doDiscovery( ) {
  // LIB は、前回見た "-Deuca.lib.dir=/usr/share/eucalyptus/" に相当。
  //  詳細は enum com.eucalyptus.system.BaseDirectory を参照のこと
  File libDir = new File(BaseDirectory.LIB.toString());
  for (File f: libDir.listFiles()) {
    if (
     // ファイル名が "eucalyptus" で始まっていて、
     f.getName().startsWith(
      com.eucalyptus.bootstrap.Component.eucalyptus.name() ) &#038;&#038;
     // ".jar" で終わっていて、
     f.getName().endsWith(".jar") &#038;&#038;
     // "-ext-" を含まないものが探索すべき jar ファイル
     ! f.getName( ).matches( ".*-ext-.*" ) ) {
      // Multimap ServiceJarDiscovery.classList にクラスとパスを貯めこみ、
      //  ServiceJarDiscovery のサブクラスを ServiceJarDiscovery.discover に
      //  貯めこむ
      ServiceJarDiscovery.processFile(f);
    }
  }
  // ServiceJarDiscovery.discover から、該当クラスを探し、実行
  ServiceJarDiscovery.runDiscovery();
}
</pre>
<p>起動するサービスのクラスを実際に選定するのは、その先の runDiscovery() の中、com.eucalyptus.component.ServiceBuilderDiscovery.processClass(Class) でした。</p>
<pre>
Thread [main] (Suspended (breakpoint at line 19 in ServiceBuilderDiscovery))
  ServiceBuilderDiscovery.processClass(Class) line: 19
  ServiceBuilderDiscovery(ServiceJarDiscovery).checkClass(Class) line: 113
  // ここ (↓) までが static。ここで、個々の discovery において、
  //  SerivceJarDiscovery が多態している。これより上は、仮想関数が呼ばれ
  //  ている
  ServiceJarDiscovery.runDiscovery() line: 100
  Bootstrap.doDiscovery() line: 164
  Bootstrap.initialize() line: 261
  SystemBootstrapper.init() line: 109
</pre>
<p>com.eucalyptus.component.Component.setBuilder(ServiceBuilder&lt;ServiceConfiguration&gt;) でもって、Component.builder にビルダが載ります。この &#8220;Component&#8221; が、内部では web サービスの機能単位の管理情報をあらわします。&#8221;component&#8221; は、Eucalyptus の内部では web サービスの提供コンポーネントを意味します。</p>
<p>ServiceJarDiscovery のサブクラスの中に、com.eucalyptus.component.ServiceBuilderDiscovery というのがありまして、これが web サービスの「ビルダ」を作ります。これが、com.eucalyptus.cluster.ClusterBuilder, com.eucalyptus.config.WalrusBuilder, com.eucalyptus.config.StorageControllerBuilder を newInstance() してくれて、Components.lookup(c (= &#8220;名前&#8221;) に、入れておいてくれます。</p>
<p>で、discover までで探索・インスタンス化が済んで、実際にサービスをスタートするのは Bootstrapper の仕事のようです (もういいかげん疲れたので、とっとと web サービスのハンドラまで行きたいので、いろいろと端折る)。</p>
<p>ポート 8773 のサービスは、com.eucalyptus.bootstrap.SystemBootstrapper.start() で、stage.name == &#8220;CloudServiceInit&#8221; の際の stage.start() で起動します。詳しくは、com.eucalyptus.context.ServiceContext.ServiceBootstrapper.start() で止めて、各変数を見てみてください。</p>
<p>でもって、実際のサービスのフレームは、<a href=http://www.mulesoft.org/what-mule-esb>Mule ESB</a> が提供しています。Mule ESB に渡す設定は com.eucalyptus.context.ServiceContext.ServiceBootstrapper.load(Stage) の下記の行で jar の中から Java リソースとして取得しています。</p>
<pre>
Resource rsc = comp.getConfiguration( ).getResource( );
</pre>
<p>そして、以下の箇所でつっこみます。</p>
<pre>
configs.addAll( rsc.getConfigurations( ) );
</pre>
<p>そして、以下で構築。</p>
<pre>
ServiceContext.buildContext( configs );
</pre>
<p>さっきから、&#8221;config&#8221; と &#8220;component&#8221; が微妙に絡んでいたのは、component の実体定義が、上から見ると config の記述そのものだからなのですね。Components.Resource.&lt;init&gt;(Configuration, URI) を遡れば、いろいろ見えます。&#8221;URI&#8221; には、&#8221;CloudServiceProvider&#8221; が file:// で入ってきます。これが config のファイルであり、component の定義です。</p>
<p>その URI (&#8220;CloudServiceProvider&#8221;) はというと、以下で動的に作っています。そのものを grep しても見つからないわけです。つまり、リソース名 &#8220;com.eucalyptus.CloudServiceProvider&#8221; の意味は、「&#8221;com.eucalyptus&#8221; に属するリソースであり、ステージ &#8220;CloudServiceInit&#8221; の際に読み込まれるサービスプロバイダの設定だよ」となっとります。</p>
<pre>
&gt;com.eucalyptus.bootstrap.Bootstrap.Stage.getResourceName()
  return String.format(
   "com.eucalyptus.%sProvider", this.name( ).replaceAll("Init\\Z", "") );
</pre>
<p>スタックトレースでは、以下のようになります。</p>
<pre>
Thread [main] (Suspended (entry into method getResourceName in Bootstrap$Stage))
  Bootstrap$Stage.getResourceName() line: 132
    name="SystemInit"
    this.name() → (java.lang.String) SystemInit
    this.name( ).replaceAll( "Init\\Z", "" ) → (java.lang.String) System
  LoadConfigs.commit(Bootstrap$Stage) line: 31
  LoadConfigs.commit(Object) line: 19
  Transition$anonymously$1.commit(O) line: 69
  Transition$anonymously&lt;O,T&gt;.commit(O) line: 76
  Transition$anonymously&lt;O,T&gt;(Transition&lt;O,T&gt;).doTransition(O) line: 137
  Transition$anonymously&lt;O,T&gt;(Transition&lt;O,T&gt;).transition(Iterable&lt;O&gt;) line: 150
  Bootstrap.initialize() line: 255
  SystemBootstrapper.init() line: 109
</pre>
<p>そして最終的には、たとえば、以下のような URI になっています。</p>
<ul>
<li>jar:file:/usr/share/eucalyptus/eucalyptus-component-2.0.0.jar!/com.eucalyptus.CloudServiceProvider
<li>jar:file:/usr/share/eucalyptus/eucalyptus-config-2.0.0.jar!/com.eucalyptus.CloudServiceProvider
<li>jar:file:/usr/share/eucalyptus/eucalyptus-walrus-2.0.0.jar!/com.eucalyptus.CloudServiceProvider
<li>jar:file:/usr/share/eucalyptus/eucalyptus-storagecontroller-2.0.0.jar!/com.eucalyptus.CloudServiceProvider
<li>&#8230;
</ul>
<p>個々のサービスが何をしているのかはよく見ていませんが、ソース内、jar 内には以下があります。</p>
<ul>
hsqldb/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
storage-controller/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
component/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
cluster-manager/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
dns/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
www/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
msgs/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
cloud/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
walrus/src/main/resources/com.eucalyptus.CloudServiceProvider<br />
configuration/src/main/resources/com.eucalyptus.CloudServiceProvider
</ul>
<p>では、その中身はというと、以下のようになっています。</p>
<pre>
name=walrus
euca.model.walrus=walrus-model.xml
euca.model.walrus.services=walrus-services.xml
</pre>
<p>この先は Mule ESB の上の世界ですので、そっちを参照してください。ちなみに、最新の ver. 3 ではなく、<a href=http://www.mulesoft.org/documentation/display/MULE2INTRO/Examples>ver. 2</a> で書かれています。なお、Mule ESB 等のサブモジュールは、Ubuntu のパッケージ的には &#8220;eucalyptus-commons-ext&#8221; の方に入っていました。</p>
<p>なお、このリソースファイルがビルドの際に取り込まれるさまは、clc/modules/module-inc.xml にあります。</p>
<p>さて、いよいよですが、たとえば &#8220;export EC2_URL=http://～:8773/services/Eucalyptus&#8221; に相当する実装がどこに書かれているかといえば、まず clc/modules/cloud/src/main/resources/eucalyptus-services.xml を参照します。</p>
<pre>
&lt;euca:endpoint name="EucalyptusWS" connector-ref="eucaws"
 address="http://127.0.0.1:${euca.ws.port}/services/Eucalyptus" synchronous="true" /&gt;
</pre>
<p>&#8220;export S3_URL=http://192.168.1.23:8773/services/Walrus&#8221; は &#8220;clc/modules/walrus/src/main/resources/walrus-services.xml&#8221; なので、以下。</p>
<pre>
  &lt;euca:endpoint name="WalrusWS"
    connector-ref="eucaws"
    address="http://127.0.0.1:${euca.ws.port}/services/Walrus"/&gt;
</pre>
<p>まとめると、ファイル &#8220;com.eucalyptus.CloudServiceProvider&#8221; はリソースとしてアクセスされ、そこにリストされている XML が Mule ESB (ver.2) に渡されてwebサービスを開始します。</p>
<p>ためしに、ハンドラも見てみます。例として、ec2-describe-availability-zones の対応箇所を見てみます。定義は以下です。</p>
<pre>
clc/modules/cloud/src/main/resources/eucalyptus-runtime.xml:
  &lt;mule ...&gt;
    ...
    &lt;service name="ClusterEndpoint"&gt;
      &lt;inbound&gt;
        &lt;inbound-endpoint ref="ClusterEndpointWS"/&gt;
      &lt;/inbound&gt;
      &lt;component class="com.eucalyptus.cluster.ClusterEndpoint"/&gt;
      &lt;outbound&gt;
        &lt;outbound-pass-through-router&gt;
          &lt;outbound-endpoint ref="ReplyQueueEndpoint"/&gt;
        &lt;/outbound-pass-through-router&gt;
      &lt;/outbound&gt;
    &lt;/service&gt;
</pre>
<p>で、個々の機能の定義は以下。</p>
<pre>
clc/modules/msgs/src/main/resources/aws-zones.xml:
  &lt;binding force-classes="true"&gt;
    &lt;mapping name="DescribeAvailabilityZones"
     class="edu.ucsb.eucalyptus.msgs.DescribeAvailabilityZonesType"
     extends="edu.ucsb.eucalyptus.msgs.EucalyptusMessage"&gt;
      &lt;collection name="availabilityZoneSet"
       field="availabilityZoneSet"
       factory="org.jibx.runtime.Utility.arrayListFactory"
       item-type="java.lang.String"&gt;
        &lt;structure name="item"&gt;
          &lt;value name="zoneName"/&gt;
        &lt;/structure&gt;
      &lt;/collection&gt;
    &lt;/mapping&gt;
  &lt;/binding&gt;
</pre>
<p>で、対応実ハンドラは右記です。com.eucalyptus.cluster.ClusterEndpoint.DescribeAvailabilityZones(DescribeAvailabilityZonesType) の処理を止めてみます。スタックトレースは以下のようになります。</p>
<pre>
Thread [ClusterEndpoint.16] (Suspended (breakpoint at line 142 in ClusterEndpoint))
  ClusterEndpoint.DescribeAvailabilityZones(DescribeAvailabilityZonesType) line: 142
  GeneratedMethodAccessor221.invoke(Object, Object[]) line: not available
  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
  Method.invoke(Object, Object...) line: 616
  ReflectionEntryPointResolver(AbstractEntryPointResolver).invokeMethod(Object, Method, Object[]) line: 147
  ReflectionEntryPointResolver.invoke(Object, MuleEventContext) line: 127
  LegacyEntryPointResolverSet(DefaultEntryPointResolverSet).invoke(Object, MuleEventContext) line: 50
  DefaultLifecycleAdapter.intercept(Invocation) line: 202
  DefaultJavaComponent(AbstractJavaComponent).invokeComponentInstance(MuleEvent) line: 82
  DefaultJavaComponent(AbstractJavaComponent).doOnCall(MuleEvent) line: 73
  DefaultJavaComponent(AbstractComponent).onCall(MuleEvent) line: 87
  SedaService$ComponentStageWorker.run() line: 533
  WorkerContext.run() line: 310
  ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061
  ThreadPoolExecutor$Worker.run() line: 575
  Thread.run() line: 636
</pre>
<p>こんな (↓) 感じですね。</p>
<pre>
&gt; com.eucalyptus.cluster.ClusterEndpoint.DescribeAvailabilityZones(DescribeAvailabilityZonesType)
  ...
  if( args.isEmpty( ) || args.contains( "verbose" ) || args.contains( "certs" ) || args.contains( "logs" ) || args.contains( "keys" ) ) {
    for( Cluster c : Clusters.getInstance( ).listValues( ) ) {
      this.getDescriptionEntry( reply, c, request );
    }
  } else {
</pre>
<p>&#8220;verbose&#8221; だろうが何だろうが全情報を返して、クライアント側で切り分けているようですね。美しくないです。</p>
<p>以上で、分からないことがあった時に、だいたいどこを見れば良いかだけは分かりました。</p>
<p>しかしどうも分からないことも。JNI で起動する際に、java.class.path に jar の羅列は渡っているのに、なぜにわざわざせっせと /usr/share/eucalyptus/ 以下を捜索してリフレクションを多用したりしているんでしょう？ ぶっちゃけ、無駄に複雑でメンテしづらいと思うんです、このコード。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/02/20/eucalyptus-clou/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ソース斜め読み: Eucalyptus Cloud Controller の Java コードのエントリはどこ？</title>
		<link>http://www.ayutaya.com/2011/02/03/eucalyptus-clc/</link>
		<comments>http://www.ayutaya.com/2011/02/03/eucalyptus-clc/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 14:05:42 +0000</pubDate>
		<dc:creator>knaka</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[クラウド｀]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://www.ayutaya.com/?p=780</guid>
		<description><![CDATA[表題の答えを先に書いておきますと、com.eucalyptus.bootstrap.SystemBootstrapper です。Eucalyptus のバージョンは、2.0.2 を見ています。 まずは、ソースツリーのおおまかな構成について見ておきます。Cluster Controller の本体は、C で書かれた Axis2/C のモジュール (libaEucalyptusCC.so) です。Apache + mod_axis2 配下で動きます。サブディレクトリは &#8220;cluster/&#8221; です。 Node Controller の本体も、C で書かれた Axis2/C のモジュール (libEucalyptusNC.so) で、Apache + mod_axis2 配下で動きます。ソースのサブディレクトリは &#8220;node/&#8221;。 問題は、それ以外――ソースのディレクトリでいう &#8220;clc/&#8221; 以下です。 追記 (Wed Feb 09 2011): eucalyptus-cloud 下の web サービス群　(ソース中では &#8220;component&#8221; と呼称される) は、Mule ESB バージョン 2.x で動作しています。別項で、いずれまた書きます。 Cloud Controller だけでなく、Walrus や Storage Controller は [...]]]></description>
			<content:encoded><![CDATA[<p><!-- Subject: ソース斜め読み: Eucalyptus Cloud Controller の Java コードのエントリはどこ？ --></p>
<p> 表題の答えを先に書いておきますと、com.eucalyptus.bootstrap.SystemBootstrapper です。Eucalyptus のバージョンは、2.0.2 を見ています。</p>
<p>まずは、ソースツリーのおおまかな構成について見ておきます。Cluster Controller の本体は、C で書かれた Axis2/C のモジュール (libaEucalyptusCC.so) です。Apache + mod_axis2 配下で動きます。サブディレクトリは &#8220;cluster/&#8221; です。</p>
<p>Node Controller の本体も、C で書かれた Axis2/C のモジュール (libEucalyptusNC.so) で、Apache + mod_axis2 配下で動きます。ソースのサブディレクトリは &#8220;node/&#8221;。</p>
<p>問題は、それ以外――ソースのディレクトリでいう &#8220;clc/&#8221; 以下です。</p>
<blockquote><p>
追記 (Wed Feb 09 2011): eucalyptus-cloud 下の web サービス群　(ソース中では &#8220;component&#8221; と呼称される) は、<a href=http://www.mulesoft.org/documentation/display/MULE2INTRO/Home>Mule ESB バージョン 2.x</a> で動作しています。別項で、いずれまた書きます。
</p></blockquote>
<p>Cloud Controller だけでなく、Walrus や Storage Controller は Java で書かれていて、呼び出し方からすると、複数機能を束ねた統一バイナリ (eucalyptus-cloud) のかたちをとっています。ところが、プロセスを見てみると、Java のものとおぼしき大量のスレッドはあるのですが、よく見かけるようには、オプションをごちゃごちゃつけて起動されている java コマンドが見あたりません。</p>
<pre>
$ pstree -alp
...
  |-eucalyptus-clou,28159 -h / -u eucalyptus --pidfile /var/run/eucalyptus ...
  |   `-eucalyptus-clou,28176 -h / -u eucalyptus --pidfile /var/run/eucaly ...
  |       |-bttrack,28514 /usr/bin/bttrack --port 6969 --dfile //var/lib/e ...
  |       |-{eucalyptus-clo},28193
  |       |-{eucalyptus-clo},28195
  |       |-{eucalyptus-clo},28202
...
</pre>
<p>ソースを見てみると、C でかかれた実行ファイル (eucalyptus-cloud) から、libjvm を経由して Java のコードを起動する作りになっています。しかたがないので clc/modules/bootstrap/eucalyptus-bootstrap.c の main() の定義から下って読んで行くと、fork(2) をして子プロセス (上の例で言う 28176) を作っています。子プロセスのその先の処理は、child()→java_init() で、JNI_CreateJavaVM() の呼び出しです。</p>
<p>JNI の呼び出しの詳細は、デバッグ出力で出るようになっています。eucalyptus-cloud コマンドに &#8220;&#8211;debug&#8221;、もしくは &#8220;&#8211;verbose&#8221; オプションをつけて呼び出せば、標準出力 (いや、エラー出力だったかな？) にデバッグ出力を出してくれます。Ubuntu-10.10 のパッケージだと upstart が出力を捨ててしまいますので、以下のようにして、適当なところにリダイレクトしておきます。</p>
<pre>
--- /etc/init/eucalyptus.conf.orig
+++ /etc/init/eucalyptus.conf
@@ -37,6 +37,7 @@
        . /etc/eucalyptus/eucalyptus.conf
        [ -n "$JVM_MEM" ] || JVM_MEM="512m"
        opts="-h $EUCALYPTUS -u $EUCA_USER --pidfile \
         /var/run/eucalyptus/eucalyptus.pid -l $LOGLEVEL -L console-log
        -Xmx$JVM_MEM"
+       opts="$opts --debug"
        services=""

        # If the -cloud package is not installed, disable the cloud service
@@ -72,7 +73,7 @@
        # Start the appropriate service(s)
        if [ -n "$services" ]; then
                # Cloud services to run
-               exec eucalyptus-cloud $opts
+               exec eucalyptus-cloud $opts > /tmp/eucalyptus.log 2>&#038;1
        elif [ -r "/etc/init/eucalyptus-nc.conf" ] || \
         [ -r "/etc/init/eucalyptus-cc.conf" ]; then
                # Node or CC services to run
                # Why do we sleep here, rather than emitting a signal?
                #  Such that we can run:
</pre>
<p>すると、以下のような呼び出しが出ます (いい具合に改行を入れました)。</p>
<pre>
Using classpath: -Djava.class.path=//etc/eucalyptus/cloud.d:
 //etc/eucalyptus/cloud.d/scripts:
 //usr/share/eucalyptus/eucalyptus-component-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-storage-common-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-config-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-groupmgr-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-db-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-interface-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-walrus-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-storagecontroller-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-imagemgr-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-commons-ext-0.4.jar:
 //usr/share/eucalyptus/eucalyptus-www-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-auth-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-msgs-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-dns-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-core-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-clustermgr-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-cloud-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-keymgr-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-ws-2.0.0.jar:
 //usr/share/eucalyptus/eucalyptus-db-hsqldb-ext-2.0.0.jar:
 //usr/share/eucalyptus/wstx-lgpl.jar:
 //usr/share/eucalyptus/gnumail-providers.jar:
 //usr/share/eucalyptus/jetty-util.jar:
 //usr/share/eucalyptus/commons-logging.jar:
 //usr/share/eucalyptus/regexp.jar:
 //usr/share/eucalyptus/jcl-over-slf4j.jar:
 //usr/share/eucalyptus/drools-compiler.jar:
 //usr/share/eucalyptus/geronimo-jms-1.1-spec.jar:
 //usr/share/eucalyptus/commons-pool.jar:
 //usr/share/eucalyptus/geronimo-jpa-3.0-spec.jar:
 //usr/share/eucalyptus/axiom-dom.jar:
 //usr/share/eucalyptus/jibx-bind.jar:
 //usr/share/eucalyptus/commons-io.jar:
 //usr/share/eucalyptus/jetty-rewrite-handler.jar:
 //usr/share/eucalyptus/backport-util-concurrent.jar:
 //usr/share/eucalyptus/gnumail.jar:
 //usr/share/eucalyptus/wsdl4j.jar:
 //usr/share/eucalyptus/xercesImpl.jar:
 //usr/share/eucalyptus/servlet-api-2.5.jar:
 //usr/share/eucalyptus/commons-httpclient.jar:
 //usr/share/eucalyptus/euca_ipt:
 //usr/share/eucalyptus/slf4j-log4j12.jar:
 //usr/share/eucalyptus/commons-collections3.jar:
 //usr/share/eucalyptus/slf4j-api.jar:
 //usr/share/eucalyptus/chgrp-dhcpd:
 //usr/share/eucalyptus/geronimo-ejb-3.0-spec.jar:
 //usr/share/eucalyptus/dd-lv:
 //usr/share/eucalyptus/google-collections.jar:
 //usr/share/eucalyptus/activation.jar:
 //usr/share/eucalyptus/serializer.jar:
 //usr/share/eucalyptus/bcprov.jar:
 //usr/share/eucalyptus/jibx-run.jar:
 //usr/share/eucalyptus/jetty-sslengine.jar:
 //usr/share/eucalyptus/dom4j.jar:
 //usr/share/eucalyptus/axiom-impl.jar:
 //usr/share/eucalyptus/commons-discovery.jar:
 //usr/share/eucalyptus/hsqldb.jar:
 //usr/share/eucalyptus/jaxen.jar:
 //usr/share/eucalyptus/javassist.jar:
 //usr/share/eucalyptus/axiom-api.jar:
 //usr/share/eucalyptus/add_key.pl:
 //usr/share/eucalyptus/antlr.jar:
 //usr/share/eucalyptus/jaxp-1.3.jar:
 //usr/share/eucalyptus/chmod-dhcpd:
 //usr/share/eucalyptus/geronimo-interceptor-3.0-spec.jar:
 //usr/share/eucalyptus/proxool.jar:
 //usr/share/eucalyptus/commons-logging-adapters.jar:
 //usr/share/eucalyptus/hsqldbutil.jar:
 //usr/share/eucalyptus/jibx-extras.jar:
 //usr/share/eucalyptus/geronimo-jta-1.0.1b-spec.jar:
 //usr/share/eucalyptus/jetty.jar:
 //usr/share/eucalyptus/gwt-servlet.jar:
 //usr/share/eucalyptus/xpp3.jar:
 //usr/share/eucalyptus/jul-to-slf4j.jar:
 //usr/share/eucalyptus/commons-cli.jar:
 //usr/share/eucalyptus/xalan2.jar:
 //usr/share/eucalyptus/commons-beanutils.jar:
 //usr/share/eucalyptus/mvel.jar:
 //usr/share/eucalyptus/janino.jar:
 //usr/share/eucalyptus/commons-fileupload.jar:
 //usr/share/eucalyptus/commons-logging-api.jar:
 //usr/share/eucalyptus/junit.jar:
 //usr/share/eucalyptus/geronimo-j2ee-connector-1.5-spec.jar:
 //usr/share/eucalyptus/ant.jar:
 //usr/share/eucalyptus/gwt-user.jar:
 //usr/share/eucalyptus/commons-codec.jar:
 //usr/share/eucalyptus/wss4j.jar:
 //usr/share/eucalyptus/bsf.jar:
 //usr/share/eucalyptus/commons-lang.jar:
 //usr/share/eucalyptus/bcel.jar:
 //usr/share/eucalyptus/excalibur-logkit.jar:
 //usr/share/eucalyptus/netty.jar:
 //usr/share/eucalyptus/el-api-2.1.jar:
 //usr/share/eucalyptus/drools-core.jar:
 //usr/share/eucalyptus/cglib.jar:
 //usr/share/eucalyptus/populate_arp.pl:
 //usr/share/eucalyptus/inetlib.jar:
 //usr/share/eucalyptus/jug-asl.jar:
 //usr/share/eucalyptus/ezmorph.jar:
 //usr/share/eucalyptus/groovy.jar:
 //usr/share/eucalyptus/commons-jxpath.jar:
 //usr/share/eucalyptus/log4j-1.2.jar:
 //usr/share/eucalyptus/xml-security.jar:
 //usr/share/eucalyptus/xom.jar:
 //usr/share/eucalyptus/modprobe-aoe:
 //usr/share/eucalyptus/dnsjava.jar:
 //usr/share/eucalyptus/ecj.jar:
 //usr/share/eucalyptus/json-lib.jar

Version:                       10004
Ignore Unrecognized Arguments: 0
Extra options:                 33
  "-Xbootclasspath/p://usr/share/eucalyptus/openjdk-crypto.jar    " (0x(nil))
  "-Xmx512m                                                       " (0x(nil))
  "-XX:MaxPermSize=128m                                           " (0x(nil))
  "-XX:+UseConcMarkSweepGC                                        " (0x(nil))
  "-Djava.net.preferIPv4Stack=true                                " (0x(nil))
  "-Djava.security.policy=//etc/eucalyptus/cloud.d/security.policy" (0x(nil))
  "-Djava.library.path=//usr/lib/eucalyptus                       " (0x(nil))
  "-Dsun.java.command=Eucalyptus                                  " (0x(nil))
  "-Deuca.home=//                                                 " (0x(nil))
  "-Deuca.var.dir=//var/lib/eucalyptus                            " (0x(nil))
  "-Deuca.run.dir=//var/run/eucalyptus                            " (0x(nil))
  "-Deuca.lib.dir=//usr/share/eucalyptus                          " (0x(nil))
  "-Deuca.conf.dir=//etc/eucalyptus/cloud.d                       " (0x(nil))
  "-Deuca.log.dir=//var/log/eucalyptus                            " (0x(nil))
  "-Deuca.version=2.0.0                                           " (0x(nil))
  "-Deuca.log.exhaustive.db=FATAL                                 " (0x(nil))
  "-Deuca.log.exhaustive.cc=FATAL                                 " (0x(nil))
  "-Deuca.log.exhaustive.user=FATAL                               " (0x(nil))
  "-Deuca.log.exhaustive.external=FATAL                           " (0x(nil))
  "-Deuca.log.level=DEBUG                                         " (0x(nil))
  "-Deuca.log.appender=console-log                                " (0x(nil))
  "-Deuca.db.port=9001                                            " (0x(nil))
  "-Deuca.db.host=127.0.0.1                                       " (0x(nil))
  "-Deuca.walrus.host=localhost                                   " (0x(nil))
  "-Deuca.remote.dns=true                                         " (0x(nil))
  "-Xdebug                                                        " (0x(nil))
  "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005  " (0x(nil))
  "-Dcom.sun.management.jmxremote                                 " (0x(nil))
  "-XX:+HeapDumpOnOutOfMemoryError                                " (0x(nil))
  "-XX:HeapDumpPath=//var/log/eucalyptus/                         " (0x(nil))
  "-Xmx512m                                                       " (0x(nil))
  "-Djava.class.path=//etc/eucalyptus/cloud.d://etc/eucalyptus/..." (0x(nil))
  "abort                                                          " (0x0x4018c0)
</pre>
<p>バラバラとパラメータを渡しています。おケツの &#8220;abort&#8221; の追加情報 0x4018C0 は、abort の際のコールバック関数ですね。表示が変ですが。</p>
<pre>
static void java_fail(void) { exit(1); }

int java_init(euca_opts *args, java_home_t *data) {
  ...
  opt[++x].optionString="abort";
  opt[x].extraInfo=java_fail;
</pre>
<p>エントリの jar ファイルも指定していませんので、ここではまだ起動はしません。単に、さっきの &#8220;JNI_CreateJavaVM&#8221; で、VM を作るだけです。かなめは、さきほどの java_load_bootstrapper() です。以下のマクロで別名ですので、euca_load_bootstrapper() を探します。</p>
<pre>
#define java_load_bootstrapper euca_load_bootstrapper
</pre>
<p>euca_load_bootstrapper() では、構造体インスタンス &#8220;bootstrap&#8221; を作ります。これが Java コードのエントリポイントになります。まず、クラスの取得です。</p>
<pre>
#define EUCA_MAIN "com/eucalyptus/bootstrap/SystemBootstrapper"

bootstrap.clazz=((*env)->FindClass(env,EUCA_MAIN))
</pre>
<p>次に、static なファクトリメソッドを呼び出して、ブートストラップのインスタンスを作ります。</p>
<pre>
bootstrap.constructor=(*env)->GetStaticMethodID(env, \
 bootstrap.clazz,euca_get_instance.method_name, \
 euca_get_instance.method_signature );
</pre>
<p>この後は、ここから始まる Java コードの仕事ですね。続きは後ほど。</p>
<p># なぜにこうもツギハギ感溢れる作りになってるんでしょうね？ Eucalyptus は</p>
<blockquote><p>
今なら JNI よりも、JNA というのがありますよー、と同僚に紹介されました。後で読む。</p>
<blockquote><p>
<a href="http://www.atmarkit.co.jp/fjava/special/jna/jna_1.html">JNIより簡単にJavaとC/C++をつなぐ「JNA」とは（1/4）－＠IT</a>
</p></blockquote>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.ayutaya.com/2011/02/03/eucalyptus-clc/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

