ちゃんと$VIRTUAL_ENV/bin/以下のスクリプトを起動してね
まだまだneutronが続く...
余計なことをするとロクなことがない...戒めのために晒してメモしておく。
■quantum-dhcp-agentでdhcpサーバ起動時にエラーが発生
virtualenvで隔離している環境でquantum-dhcp-agentを起動させると以下のようなエラーが出力されてdnsmasqが起動しない。
2013-09-09 12:22:41 DEBUG [quantum.agent.linux.utils] Command: ['sudo', '/usr/local/grizzly/bin/quantum-rootwrap', '/usr/local/grizzly/neutron/etc/rootwrap.conf', 'QUANTUM_RELAY_SOCKET_PATH=/usr/local/grizzly/neutron/dhcp/dhcp/lease_relay', 'QUANTUM_NETWORK_ID=4fb43ca1-a972-49cd-b7e8-632d246ca810', 'ip', 'netns', 'exec', 'qdhcp-4fb43ca1-a972-49cd-b7e8-632d246ca810', 'dnsmasq', '--no-hosts', '--no-resolv', '--strict-order', '--bind-interfaces', '--interface=tap31d3e188-28', '--except-interface=lo', '--pid-file=/usr/local/grizzly/neutron/dhcp/dhcp/4fb43ca1-a972-49cd-b7e8-632d246ca810/pid', '--dhcp-hostsfile=/usr/local/grizzly/neutron/dhcp/dhcp/4fb43ca1-a972-49cd-b7e8-632d246ca810/host', '--dhcp-optsfile=/usr/local/grizzly/neutron/dhcp/dhcp/4fb43ca1-a972-49cd-b7e8-632d246ca810/opts', '--dhcp-script=/usr/local/grizzly/neutron/bin/quantum-dhcp-agent-dnsmasq-lease-update', '--leasefile-ro', '--dhcp-range=set:tag0,10.0.0.0,static,120s', '--dhcp-range=set:tag1,10.0.1.0,static,120s', '--dhcp-range=set:tag2,10.0.2.0,static,120s', '--conf-file=', '--domain=openstacklocal'] Exit code: 11 Stdout: '' Stderr: 'Traceback (most recent call last):\n File "/usr/local/grizzly/neutron/bin/quantum-dhcp-agent-dnsmasq-lease-update", line 19, in <module>\n from quantum.agent.linux import dhcp\nImportError: No module named quantum.agent.linux\n\ndnsmasq: lease-init script returned exit code 1\n' 2013-09-09 12:22:41 ERROR [quantum.agent.dhcp_agent] Unable to enable dhcp. Traceback (most recent call last): File "/usr/local/grizzly/neutron/quantum/agent/dhcp_agent.py", line 131, in call_driver getattr(driver, action)() File "/usr/local/grizzly/neutron/quantum/agent/linux/dhcp.py", line 129, in enable self.spawn_process() File "/usr/local/grizzly/neutron/quantum/agent/linux/dhcp.py", line 322, in spawn_process ip_wrapper.netns.execute(cmd, addl_env=env) File "/usr/local/grizzly/neutron/quantum/agent/linux/ip_lib.py", line 414, in execute check_exit_code=check_exit_code) File "/usr/local/grizzly/neutron/quantum/agent/linux/utils.py", line 61, in execute raise RuntimeError(m) RuntimeError:
■原因をしらべてみる
いろいろ調べた結果、起動スクリプトに問題がった。
原因
githubからチェックアウトしたソースをsetuptoolsでインストールしたあと、本来だと$VIRTUAL_ENV/bin/以下にインストールされたスクリプトを起動すべきだったが、チェックアウトしたソースの./bin/以下にあるスクリプトを実行していた。
- ソースコードは/usr/local/grizzly/neutron/以下にgit cloneしている
- $VIRTUAL_ENVは/usr/local/grizzly/以下に指定している
- 実行していたスクリプトはソースコードのほう(/usr/local/grizzly/neutron/bin/quantum-dhcp-agent)
なんとなく起動してしまうので、この原因を見落としてた。
2つのquantum-dhcp-agentの違い
#!/usr/bin/env pythonになっている時点でvirtualenv環境にインストールしたモジュールのロードに失敗して起動しそうもないんだけれど、起動スクリプトのなかで virtualenv環境をactivateするようにしていたので、ソースコードのほう(/usr/local/grizzly/neutron/bin/quantum-dhcp-agent)を誤って指定しても、なんとなく起動してしまっていた。
$ diff -u /usr/local/grizzly/neutron/bin/quantum-dhcp-agent /usr/local/grizzly/bin/quantum-dhcp-agent --- /usr/local/grizzly/neutron/bin/quantum-dhcp-agent 2013-09-08 22:59:13.286938001 +0900 +++ /usr/local/grizzly/bin/quantum-dhcp-agent 2013-09-08 23:00:50.662938001 +0900 @@ -1,20 +1,10 @@ -#!/usr/bin/env python <-- ★ソースコードそのままのquantum-dhcp-agent -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +#!/usr/local/grizzly/bin/python <-- ★setuptoolsで正しくインストール後のquantum-dhcp-agent +# EASY-INSTALL-ENTRY-SCRIPT: 'quantum==2013.1.2','console_scripts','quantum-dhcp-agent' +__requires__ = 'quantum==2013.1.2' +import sys +from pkg_resources import load_entry_point -# Copyright (c) 2012 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from quantum.agent.dhcp_agent import main -main() +if __name__ == '__main__': + sys.exit( + load_entry_point('quantum==2013.1.2', 'console_scripts', 'quantum-dhcp-agent')() + )
まぁこの際は動けばいいんだけれど、今回はそうもいかなかった。
--dhcp-scriptの落とし穴
冒頭に書いたエラーメッセージの原因はココだった。
<...略...> 267 def spawn_process(self): 268 """Spawns a Dnsmasq process for the network.""" 269 env = { 270 self.QUANTUM_NETWORK_ID_KEY: self.network.id, 271 self.QUANTUM_RELAY_SOCKET_PATH_KEY: 272 self.conf.dhcp_lease_relay_socket 273 } 274 275 cmd = [ 276 'dnsmasq', 277 '--no-hosts', 278 '--no-resolv', 279 '--strict-order', 280 '--bind-interfaces', 281 '--interface=%s' % self.interface_name, 282 '--except-interface=lo', 283 '--pid-file=%s' % self.get_conf_file_name( 284 'pid', ensure_conf_dir=True), 285 #TODO (mark): calculate value from cidr (defaults to 150) 286 #'--dhcp-lease-max=%s' % ?, 287 '--dhcp-hostsfile=%s' % self._output_hosts_file(), 288 '--dhcp-optsfile=%s' % self._output_opts_file(), 289 '--dhcp-script=%s' % self._lease_relay_script_path(), <--★ココ 290 '--leasefile-ro', 291 ] <…略...> 437 def _lease_relay_script_path(self): 438 return os.path.join(os.path.dirname(sys.argv[0]), <--★ココ 439 'quantum-dhcp-agent-dnsmasq-lease-update') <…略...>
問題はos.path.dirname(sys.argv[0])でディレクトリパスを決めているところ。
設定ファイルで指定もできないので、quantum-dhcp-agentと同じパスにあるquantum-dhcp-agent-dnsmasq-lease-updateを起動してしまう。
- sys.argv[0] -> /usr/local/grizzly/neutron/bin/quantum-dhcp-agent
- os.path.dirname(sys.argv[0]) -> /usr/local/grizzly/neutron/bin
- os.path.join(os.path.dirname(sys.argv[0]), 'quantum-dhcp-agent-dnsmasq-lease-update') -> /usr/local/grizzly/neutron/bin/quantum-dhcp-agent-dnsmasq-lease-updat
ということで、/usr/local/grizzly/neutron/bin/quantum-dhcp-agent-dnsmasq-lease-update が--dhcp-scriptとして使われて、こいつは virtualenv環境が反映されず(1行目が #!/usr/bin/env python なので)、いろんなモジュールが見つからずにエラーがになるってことだった。
教訓:余計なことをするときは、ちゃんと徹底すること。