OpenStackで使用されているプラグイン機構Stevedoreの使い方

概要

OpenStackでは、プラグイン機構を採用しており、バックエンドの実装にさまざまなものを選択できるようにしている

たとえば、NeutronではCore pluginに「ml2, openvswitch, nsx」などなど、さまざまなpluginが設定ファイルで設定できる。それをstevedoreというライブラリを用いて実現可能にしている。

今回はそれの使い方について、keystoneclientのauth_pluginの読み込み部分を見ながら使い方を見ていく

※注意:イマイチ良く分かっていないところがあるので、間違いや詳細が分かる方はコメントください

keystoneclientにauth_pluginについて(stevedoreの使用例)

keystoneclientでは、認証の方法をplugin形式で実装している(Token,Password等)ので、さまざまな認証方法を選択することができる。

実際に、keystoneclientを利用しているkeystonemiddlewareのauth_token( WSGIアプリケーションのFilterでは、設定ファイルで、使用するkeystonclientで読み込むauth_pluginを設定ファイルで下記のように、指定している。

devstackによって生成される、nova.conf

52
53 [keystone_authtoken]
54 signing_dir = /var/cache/nova
55 cafile = /opt/stack/data/ca-bundle.pem
56 auth_uri = http://157.7.84.233:5000
57 project_domain_id = default
58 project_name = service
59 user_domain_id = default
60 password = password
61 username = nova
62 auth_url = http://157.7.84.233:35357
63 auth_plugin = password
64

この設定だとkeystonemiddlewareのauth_tokenでkeystoneclientを作成するときにPassword認証用のプラグインで作成するようになります

/usr/local/lib/python2.7/dist-packages/keystonemiddleware/auth_token.py

176 import logging
177 import os
178 import stat
179 import tempfile
180
181 from keystoneclient import access
182 from keystoneclient import adapter
183 from keystoneclient import auth
184 from keystoneclient.auth.identity import base as base_identity
185 from keystoneclient.auth.identity import v2
186 from keystoneclient.auth import token_endpoint
~~~~~~~~~~~~
~~~~~~~~~~~~
825
826 class AuthProtocol(object):
~~~~~~~~~~~~
~~~~~~~~~~~~
1494 def _create_identity_server(self):
1495 # NOTE(jamielennox): Loading Session here should be exactly the
1496 # same as calling Session.load_from_conf_options(CONF, GROUP)
1497 # however we can't do that because we have to use _conf_get to
1498 # support the paste.ini options.
1499 sess = session.Session.construct(dict(
1500 cert=self._conf_get('certfile'),
1501 key=self._conf_get('keyfile'),
1502 cacert=self._conf_get('cafile'),
1503 insecure=self._conf_get('insecure'),
1504 timeout=self._conf_get('http_connect_timeout')
1505 ))
1506
1507 # NOTE(jamielennox): The original auth mechanism allowed deployers
1508 # to configure authentication information via paste file. These
1509 # are accessible via _conf_get, however this doesn't work with the
1510 # plugin loading mechanisms. For using auth plugins we only support
1511 # configuring via the CONF file.
1512 auth_plugin = auth.load_from_conf_options(CONF, _AUTHTOKEN_GROUP)
1513
~~~~~~~~~~~~
~~~~~~~~~~~~

このAuthProtocolクラスというのが、tokenチェックをするためのWsgiアプリケーションのfilterに当たるのですが、そのなかで_create_identity_server関数定義(keystoneclientを作るような処理をする)のなかでauth_pluginのpluginを読み込んでいます(1512行目)「auth.load_from_conf_options」の関数の中身を見ていきます

/usr/local/lib/python2.7/dist-packages/keystoneclient/auth/conf.py

79
80 def load_from_conf_options(conf, group, **kwargs):
81 """Load a plugin from an oslo.config CONF object.
~~~~~~
commentのため、割愛
~~~~~~
98 """
99 # NOTE(jamielennox): plugins are allowed to specify a 'section' which is
100 # the group that auth options should be taken from. If not present they
101 # come from the same as the base options were registered in.
102 if conf[group].auth_section:
103 group = conf[group].auth_section
104
105 name = conf[group].auth_plugin
106 if not name:
107 return None
108
109 plugin_class = base.get_plugin_class(name)
110 plugin_class.register_conf_options(conf, group)
111 return plugin_class.load_from_conf_options(conf, group, **kwargs)
~~~~~~
~~~~~~

ここでは、pluginクラスを生成して、生成したpluginクラスに設定をつっこんでます。実際に、stevedoreを使ってpluginを生成しているのbase.get_plugin_classのところ(109行目)、これも関数の中身を見て行きます

/usr/local/lib/python2.7/dist-packages/keystoneclient/auth/base.py

15 import six
16 import stevedore
~~~~~
~~~~~
26 PLUGIN_NAMESPACE = 'keystoneclient.auth.plugin'
27 IDENTITY_AUTH_HEADER_NAME = 'X-Auth-Token'
28
29
30 def get_plugin_class(name):
31 """Retrieve a plugin class by its entrypoint name.
32
33 :param str name: The name of the object to get.
34
35 :returns: An auth plugin class.
36 :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin`
37
38 :raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be
39 created.
40 """
41 try:
42 mgr = stevedore.DriverManager(namespace=PLUGIN_NAMESPACE,
43 name=name,
44 invoke_on_load=False)
45 except RuntimeError:
46 raise exceptions.NoMatchingPlugin(name)
47
48 return mgr.driver
~~~~~~~
~~~~~~~

やっとここで、stevedoreの登場です(42行目)。 stevedore.DriverManagerが与えられたname(このときはpassword)に対応するクラスを探して、読み込みます。

stevedoreについて

先ほどまで、keytonemiddlewareとkeystoneclientを見て実際にプラグインが読み込まれる過程を見ました。 ここから、stevedoreの使い方を見ていきます。

上記の例を見ても分かるように、stevedoreではpluginクラスをフルクラスネームで書かなくても、読み込まれます(例: password → keystoneclient.auth.identity.generic:Password )

なぜそんなことができるかというと、インストール時にsetup.cfgでそのマッピングについて定義するからです。 その定義がこちら

keystoneclientのsetup.cfg

[entry_points]
`console_scripts =
keystone = keystoneclient.shell:main
keystoneclient.auth.plugin =
password = keystoneclient.auth.identity.generic:Password
token = keystoneclient.auth.identity.generic:Token
v2password = keystoneclient.auth.identity.v2:Password
v2token = keystoneclient.auth.identity.v2:Token
v3password = keystoneclient.auth.identity.v3:Password
v3token = keystoneclient.auth.identity.v3:Token
v3unscopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2UnscopedToken
v3scopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2ScopedToken
v3unscopedadfs = keystoneclient.contrib.auth.v3.saml2:ADFSUnscopedToken

ここでは、console_scriptskeystoneclient.auth.pluginはnamespaceといい、インデントが違うpasswordtokenがnameといいます。ここまでくれば分かるかと思いますが。 namespaceとnameの組み合わせで、対応クラスがマッピングされます。

例えば、namespace = keystoneclient.auth.plugin , name = passwordとすれば、読み込まれるクラスは、keystoneclient.auth.identity.generic:Passwordになります。

また、rpmdebパッケージからインストールするとsetup.cfgが見当たらないかと思いますが、その場合は /usr/local/lib/python2.7/dist-packages/XXXXX.dist-info の中のentry_points.txtに同じような定義があります。 例として、keystoneclientのentry_points.txtを下記に記します。

/usr/local/lib/python2.7/dist-packages/python_keystoneclient-1.1.0.dist-info/entry_points.txt

1 [console_scripts]
2 keystone = keystoneclient.shell:main
3
4 [keystoneclient.auth.plugin]
5 password = keystoneclient.auth.identity.generic:Password
6 token = keystoneclient.auth.identity.generic:Token
7 v2password = keystoneclient.auth.identity.v2:Password
8 v2token = keystoneclient.auth.identity.v2:Token
9 v3password = keystoneclient.auth.identity.v3:Password
10 v3scopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2ScopedToken
11 v3token = keystoneclient.auth.identity.v3:Token
12 v3unscopedadfs = keystoneclient.contrib.auth.v3.saml2:ADFSUnscopedToken
13 v3unscopedsaml = keystoneclient.contrib.auth.v3.saml2:Saml2UnscopedToken

表記は、違いますが雰囲気で分かると思います。 で囲まれている部分がnamespaceに対応し、の下に書かれている部分がnameに相当します

neutronのpluginの読まれ方

ここで疑問に、思う方がいるかもしれませんが(僕は思いました)。password,tokenなどnameを使用して、entry_pointsでそのマッピング先を探すのに、設定ファイルでクラスパスを直接書いている部分があるのはなぜだろう。stevedoreは、nameにクラスパスが指定されていたらそのクラスパスのクラスを読み込むのか?

例えばneutronでは、service_pluginsの指定に、フルクラスネームで書くこともnameで書くこともできます。

neutron.conf

[DEFAULT]
service_plugins = router

neutron.conf

[DEFAULT]
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin

neutronのpluginの読み込み方を調べてみたところ、こんな風になっていました。

/opt/stack/neutron/neutron/manager.py

130 def _get_plugin_instance(self, namespace, plugin_provider):
131 try:
132 # Try to resolve plugin by name
133 mgr = driver.DriverManager(namespace, plugin_provider)
134 plugin_class = mgr.driver
135 except RuntimeError as e1:
136 # fallback to class name
137 try:
138 plugin_class = importutils.import_class(plugin_provider)
139 except ImportError as e2:
140 LOG.exception(_LE("Error loading plugin by name, %s"), e1)
141 LOG.exception(_LE("Error loading plugin by class, %s"), e2)
142 raise ImportError(_("Plugin not found."))
143 return plugin_class()

stevedoreは、nameにマッチするentry_pointが見つからない場合は、例外を吐くのでその例外をキャッチし、クラスパスが指定されていることを仮定し、importutilsでimportを試みてるんですね。

なので、設定ファイルのpluginに指定する値は、entry_pointのnameでも、クラスパスでもうまくいくんですね。面白い

pythonパッケージからdebファイルを作成する

諸事情により、Pythonパッケージからdebファイルを作成する必要があったのでその手順をメモ

pythonパッケージからdebファイルを作成するツールをインストール

#apt-get install python-stdeb

 

debファイル化したい、pythonパッケージのDL

今回は、oslo.db-1.0.2というOpenStackのDB周りの共通コンポーネントdeb化する

$wget https://pypi.python.org/packages/source/o/oslo.db/oslo.db-1.0.2.tar.gz

py2dscの実行

DLしたファイルを引数に py2dsc を実行

$py2dsc oslo.db-1.0.2.tar.gz

deb_destというフォルダが作成されます

$ls
deb_dist  oslo.db-1.0.2.tar.gz

deb_dest/oslo.db-1.0.2の下で dpkg-buildpackage を実行

$cd deb_dist/oslo-db-1.0.2
$dpkg-buildpackage -rfakeroot -uc -us
$cd ..
$ls
oslo-db-1.0.2  oslo-db_1.0.2-1_amd64.changes  oslo-db_1.0.2-1.debian.tar.gz  oslo-db_1.0.2-1.dsc  oslo-db-1.0.2.orig  oslo-db_1.0.2.orig.tar.gz  python-oslo.db_1.0.2-1_all.deb

するとdebファイルが追加されています。

あとは dpkg -i でインストールしたりいろいろとご自由に

IronicをDevstackでサク?っと試してみた

日本OpenStackユーザ会勉強会で、Ironicのハッカソン日本OpenStackユーザ会 第21回勉強会があるということで、参加しようとIronic環境をDevstackで構築しようとしたが、詰まりどころが満載だったのででデバッグの記録をメモ

とりあえず、Document通りに。。。

git clone https://github.com/openstack-dev/devstack.git devstack

local.conf作成

cat <<END >local.conf
[[local|localrc]]
# Credentials
ADMIN_PASSWORD=password
DATABASE_PASSWORD=password
RABBIT_PASSWORD=password
SERVICE_PASSWORD=password
SERVICE_TOKEN=password

# Enable Ironic API and Ironic Conductor
enable_service ironic
enable_service ir-api
enable_service ir-cond

# Enable Neutron which is required by Ironic and disable nova-network.
disable_service n-net
enable_service q-svc
enable_service q-agt
enable_service q-dhcp
enable_service q-l3
enable_service q-meta
enable_service neutron

# Create 3 virtual machines to pose as Ironic's baremetal nodes.
IRONIC_VM_COUNT=3
IRONIC_VM_SSH_PORT=22
IRONIC_BAREMETAL_BASIC_OPS=True

# The parameters below represent the minimum possible values to create
# functional nodes.
IRONIC_VM_SPECS_RAM=1024
IRONIC_VM_SPECS_DISK=10

# Size of the ephemeral partition in GB. Use 0 for no ephemeral partition.
IRONIC_VM_EPHEMERAL_DISK=0

VIRT_DRIVER=ironic

# By default, DevStack creates a 10.0.0.0/24 network for instances.
# If this overlaps with the hosts network, you may adjust with the
# following.
NETWORK_GATEWAY=10.1.0.1
FIXED_RANGE=10.1.0.0/24
FIXED_NETWORK_SIZE=256

# Log all output to files
LOGFILE=$HOME/devstack.log
SCREEN_LOGDIR=$HOME/logs
IRONIC_VM_LOG_DIR=$HOME/ironic-bm-logs

END

stack.shで構築

$ ./stack.sh

インストールは、うまく行った、Horizonの画面も確認できた。

さっそく、Ironicノードをプロビジョニングを実行

$nova boot --flavor baremetal --image cirros-0.3.3-uec
$nova list
+--------------------------------------+---------+--------+------------+-------------+------------------+
| ID                                   | Name    | Status | Task State | Power State | Networks         |
+--------------------------------------+---------+--------+------------+-------------+------------------+
| a2c7f812-e386-4a22-b393-fe1802abd56e | testing | ERROR | -          | ERROR     | private=10.1.0.4 |
+--------------------------------------+---------+--------+------------+-------------+------------------+

うまく行き過ぎだとは思ってた、エラーですね。

ログを見てみると、「No valid host was found. There are not enough hosts available」というエラーが。。

早速デバッグ

nova-scheduleのlogより、下記のことが分かった

  1. nova-schedulerは、フィルタしてホストの選定はすんでいる
  2. ホストの選定の結果プロビジョニングに失敗するので、またフィルタする
  3. その結果のホストのぷろびじょにングも失敗するので、retry回数のフィルタにひっかかり
  4. No valid host was found エラーになっている

プロビジョンでコケているので、

nova-conductorのログを見てみる

  1. エラーメッセージ「"Failed to add deploy parameters on node"」を確認
  2. novaのソースをgrep
    • virt/ironic/driver.pyで例外を吐いていることを確認
    • ironic-apiを叩いているので、ironic-api,condを見てみる

ironic-apiのログを見てみる

  1. エラーメッセージ「"No conductor service registered which supports driver"」を確認

    • なぜか、ironic-conductorが動いていない模様
    • ironic-conductorを再起動
    • まだ、「No valid host was found」のまま
  2. エラーメッセージ「"Cannot validate PXE bootloader"」を確認

    • ironic-apiのdo_node_deploy apiの実際の処理をironic-conductorが行っており、do_node_deployのレスポンスが「Cannot validate PXE bootloader」なので詳細な情報を見るために、ironic-conductorへ

ironic-conductorのログを見てみる

  1. エラーメッセージ「" Can not validate PXE bootloader. The following paramenters were not passed to ironic:['deploy_kernel', 'deploy_ramdisk']"」
    • PXEDriverが、プロビジョンに必要なパラメータをチェックしているところでエラーを起こしている模様
    • PXEDriverでは、[deploy_kernel, deploy_ramdisk]の値が定義されているかチェックしている
    • deploy_kernel,ramdiskは、nodeのdriver_infoという情報を引っ張っているようなので、値を更新
 $ironic node-update <node-id> add driver_info/pxe_deploy_kernel=<deploy_kernel>
 $ironic node-update <node-id> add driver_info/pxe_deploy_ramdisk=<deploy_ramdisk>
  • まだ、「No valid host was found」のまま

  • エラーメッセージ「"Cannot execute SSH cmd"」

    • libvirtが動いているホストのsshdのポートを変更していたので、nodeのdriver_info/ssh_port,ssh_usernameを変更
    • まだ、「No valid host was found」のまま
  • エラーメッセージ「"connecting to monitor: Cannot set up guest memory"」

    • SSHPowerDriverが実行するvirshを実行した時のエラーのようだ。
    • エラー内容的には、メモリーが足りないと言われているので、swap領域を作成
    • まだ、「No valid host was found」のまま
  • 目立ったエラーメッセージが出なくなったが、プロビジョニングが終わらない現象に遭遇

    • よく調べると、ironicのノードstatusが「wait callback」のまま固まっている模様
    • Driverからの応答待ちというstatusなので、PXE関連で不具合が起きてる模様
    • neutronのdnsmasq(dhcp-agent)がPXEブートのDHCPを担当しているのだが、そもそも疎通が取れていない
    • Devstackでironicをインストールすると、brbmというベアメタル用のbridgeを作ってくれて、そこにnodeがぶら下がっているのだが、brbmブリッジとneutronのl2スイッチをつなげる必要がある(方法はいろいろある、br-tun経由、br-intに直接指す等)とりあえずは、br-intブリッジとbrbmブリッジを接続

    • それでも、ノードstatusが「wait callback」のまま固まっている・・・・

    • tftpサーバのアドレスが、ironic-conductorが動いているホストのIPであることに気づく、ironicノードがironic-conductorが動いているホストと通信できないといけないことに気づく。下記手順で通信可能にする
      • (1) 仮想L2NWをテナントの仮想ルータに接続
      • (2) ホスト側のルーティングテーブルに、仮想L2NWの経路を、仮想ルータの外部アドレスIF経由で追加

ここまできて、やっと動きました。 そもそも、なぜこんなにデバッグに時間がかかったかというと、ironicのプロビジョニングプロセスをまったく調べずに実行したことが原因ですね。

ただ、今回調べたところ、いろいろと制約があるなと感じました。

  1. nodeからtftpサーバにアクセスできる必要がある。

    • 現状ironic.confの設定ファイルで、tftpサーバのIPアドレスを指定するので、テナントごとにtftpサーバを分けることはできない。
    • つまり、tftpサーバから見て、IPアドレス帯が被ってはいけない(routingできないから)のでユーザが好きなサブネットでironicノードをプロビジョニングすることはできない
  2. nodeからIronic APIを叩ける必要がある

    • つまり、Managementセグメントとユーザセグメントを完全に分けることはできない
    • もし、やるならdeployフェーズのみ収容スイッチのポートのvlanを変更してアクセス可能にする等を行う必要がある。
    • もし、やるならironic apiのみ、nodeからアクセスできるIFを設けて、ironic api用のセグメントを作成する
  3. Ironic conductorからnodeにアクセスできる必要がある

    • tftpと同様で、ironic conductorから見て、nodeが所属するサブネットが被ってはいけない(routingできないから)

ネットワーク周りが、結構難しいなぁという印象。

Publicクラウドとして、仮想ネットワーク作り放題で、vmとベアを意識せずにポコポコプロビジョニングというのは、まだ難しいのかぁ。

Ironicは少し面白そうなので、もう少し追いかけてみる。

Rack、WSGIサーバのThread処理の実装について(1)

はじめに

本記事では、あえてRack,WSGIサーバと言っているが、いわゆるWEBアプリケーションサーバ以外のサーバソフトウェアの実装でも共通の話題である「クライアントからの接続ー通信処理」の実装方式として、NativeThreadのパターンとGreenThreadのパターンの2つの違いを自分用に2回にわたってメモ

事前知識

ソケットプログラミング等で、チャットプログラム等を作ったりしたことがある人は、ご存知かもしれないが。サーバの通信処理がどのようなフローで行われるかを少しここでおさらいする。

  1. サーバソケット(通信要求を受け付けるためのソケット)を作成する
  2. サーバソケットを指定のIP(通常、0.0.0.0でどのIFのIPでも受けれるようにする)、指定のportで通信要求を待つ
  3. クライアントからの通信要求をacceptする
  4. クライアントと通信路が確立される

見て分かると思うが、1プロセス1スレッドでサーバを実装してしまうと、同時に1つのクライアントしかさばけないため、3と4の間で各クライアントごとにスレッド、プロセスを生成して4以降のクライアントごとの処理はスレッドやプロセスに任せるのが一般的である。

NativeThreadで実装されている例(WEBrick

どんなNativeThreadがいるのか

ここでは、WEBrick(Rackサーバ)を題材にする

下記のような、テスト用のRackアプリケーションを用意する

#!/usr/bin/env ruby
require 'rubygems'
require 'rack'
include Rack

class TestApp
  def call(env)
    sleep(1000)
    [200, {"Content-Type" => "text/plain"}, ["test"]]
  end
end

Handler::WEBrick.run TestApp.new, :Port => 3000

上記を実行し、psでスレッドの数を見る(当方Macなので、-Mオプションを使用しています)

$ruby test.rb
[2015-01-03 14:46:16] INFO  WEBrick 1.3.1
[2015-01-03 14:46:16] INFO  ruby 1.9.3 (2013-02-22) [x86_64-darwin10.8.0]
[2015-01-03 14:46:16] INFO  WEBrick::HTTPServer#start: pid=76852 port=3000

$ps -M 
ukinau 76852 s002    0.0 S    31T   0:00.04   0:00.16 ruby test.rb
       76852         0.0 S    31T   0:00.00   0:00.00

なんで最初から、ネイティブスレッドが1つ作られているんだ?と思ったけど、後述するnetstatの結果より、ipv4,v6で1つずつ接続待ちのスレッドを作っていると思われる

curlでwebappにアクセスしてみる。

$curl http://localhost:3000

test.rbの中でsleepして、コネクション確立状態をキープしているのでその間にいろいろ確認

$netstat -an | grep 3000
tcp4       0      0  127.0.0.1.3000         127.0.0.1.52542        ESTABLISHED
tcp4       0      0  127.0.0.1.52542        127.0.0.1.3000         ESTABLISHED
tcp46      0      0  *.3000                 *.*                    LISTEN
tcp4       0      0  *.3000                 *.*                    LISTEN

$ps -M
ukinau 76852 s002    0.0 S    31T   0:00.05   0:00.18 ruby test.rb
       76852         0.0 S    31T   0:00.00   0:00.00
       76852         0.0 S    31T   0:00.00   0:00.00
       76852         0.0 S    31T   0:00.02   0:00.03

Threadが2個増えた!1つが先ほどのcurlからのリクエストを担当し、もう1つは次のクライアントのためにあらかじめスレッドを作成しているものだと思われる。

curlのリクエストが終了したら、1つ減った。

$ps -M
ukinau 76852 s002    0.0 S    31T   0:00.07   0:00.20 ruby test.rb
       76852         0.0 S    31T   0:00.00   0:00.00
       76852         0.0 S    31T   0:00.07   0:00.11

もう一度、curlを送ると

$ps -M
ukinau 76852 s002    0.0 S    31T   0:00.08   0:00.21 ruby test.rb
       76852         0.0 S    31T   0:00.00   0:00.00
       76852         0.0 S    31T   0:00.08   0:00.13
       76852         0.0 S    31T   0:00.00   0:00.00

スレッドが一つ増えた! う〜ん、もしかしたら、1つ多いスレッドは次のクライアントのためのものではないかもしれない。。。CPU使用時間が増えるのが上から3番目のスレッドだけなので、なんかユーティリティ用のスレッドなのかもしれない・・・・

現状分かる範囲でまとめると、

  • ipv6listen用スレッド = 1
  • ipv4listen用スレッド = 1
  • クライアント処理用スレッド × クライアント数
  • 謎のスレッド = 1

の4種類のネイティブスレッドでWEBrickは実現しているようです。

クライアントの処理がNativeThreadだと何がいいのか

NativeThreadのスケジューリングは、OSのプロセススケージューラによってスケジューリングされるため各スレッドは、コアの分だけ同時に動くことができる。もう少し端的に言うと各ThreadがOSに認識される。そのため、先ほどのsampleプログラムであるTestAppのcallメソッドの中に、sleep(1000)などのブロック関数があっても別のクライアントに影響を与えないのだ。

題材である、WEBアプリだとあまりないシチュエーションかもしれないが、各スレッドが独立して動くのでスレッド同士影響を与えないよう、スレッドセーフであることをきちんと確認する必要がある。

Backlogってなんぞや

はじめに

サーバソフトウェアの設定ファイル等でよく見かける項目であるBacklogってどういう意味なんだろうと、少し調べたのでメモを残します。

Backlog

apacheやnginx、memchachedなどのサーバ系ソフトウェアの設定ファイルの中で設定することが多い、このBacklogとは何なのかをここでは言及する。

サーバアプリケーションがlistenしているソケットがacceptしていない、確立済TCPセッションを何個までOS側で保持するかを定義したもの。

例えば、下記のようなサーバーアプリケーションがあるとする。

server.py

import evenlet

server_sock = eventlet.listen(('0.0.0.0', 6001),backlog = 1)
new_sock, address = server_sock.accept()
new_sock1, address = server_sock.accept()

while True:
  a = 1
 
print("ここは到達しないコード")

上記のサーバアプリケーションに、5個の接続要求(telnetとかを使って)を出すと。3個目までTCPコネクションが確立され、4,5個目の接続要求は無視される。

netstatで確認してみると、下記のようになる。

$netstat -an | grep 6001 
tcp4       0      0  127.0.0.1.52608        127.0.0.1.6001         SYN_SENT
tcp4       0      0  127.0.0.1.52607        127.0.0.1.6001         SYN_SENT
tcp4       0      0  127.0.0.1.6001         127.0.0.1.52601        ESTABLISHED
tcp4       0      0  127.0.0.1.52601        127.0.0.1.6001         ESTABLISHED
tcp4       0      0  127.0.0.1.6001         127.0.0.1.52600        ESTABLISHED
tcp4       0      0  127.0.0.1.52600        127.0.0.1.6001         ESTABLISHED
tcp4       0      0  127.0.0.1.6001         127.0.0.1.52599        ESTABLISHED
tcp4       0      0  127.0.0.1.52599        127.0.0.1.6001         ESTABLISHED
tcp4       0      0  *.6001                 *.*                    LISTEN

コードを見てもらうと分かる通り、サーバ(server.py)では2回しかacceptされていないが、netstatでは下記の3つセッションが確立できていることが分かる(ESTABLISHED)

これは、server.pyからは2つのコネクションしか見えていないが、残りの1つのセッションはOS側で保持してくれていることが分かる、この何個のセッションをOS側で面倒見るかを定義したものがbacklogである。

今回は、backlog=1でサーバソケットをlistenしているため3個目のリクエストはセッションが確立されたが4、5個目のリクエストはクライアントからSYNパケットを送っているが、サーバに無視されている。

これらの挙動を図にまとめるとこんな感じになる。注目していただきたいのは下記の点

  • ソケットキューの大きさがbacklog数
  • ソケットキューは、サーバソケットごと(=port)ごとに作成される
  • accept()システムコールが呼ばれると、確立済のTCPセッションはソケットキューから削除され、ファイルディスクリタに登録される(関連づけられる)

f:id:ukinau:20150101000726p:plain

maxconn

ソケットキューの長さの最大値を定義するカーネルパラメーター、128がデフォルトで定義されている。backlogでmaxconnより大きな数字を定義しても、maxconnの値が優先されます。

まとめ

(付録)Devstackはどんなことをしているのか

この記事は、Devstackはどんなことをしているのかの付録記事になっており、下記の2部構成になっております。

  • devstackのソースを読むときに非常にお世話になったコマンド
  • devstackを読みながら、インストールしたときの手順書

付録1.devstackのソースを読むときに非常にお世話になったコマンド

devstackは、シェルスクリプトであり。他のファイルで定義されている関数をsourceコマンドで動的に読み込みます。そのため、簡単に関数の定義や変数の定義がある場所を調べることができないのですが、そのような場合はgrepコマンドを下記のように使うと便利です。

 $grep -n "" * */* */*/*  | grep <検索したい文字列>
 

使用例(AGENT_BINARYという変数がどこで使われているか調べたいとき)

$grep -n "" * */* */*/* | grep AGENT_BINARY
lib/neutron:489:    run_process q-agt "python $AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
lib/neutron:507:        run_process q-domua "python $AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE.domU"
lib/neutron_plugins/bigswitch_floodlight:44:    AGENT_BINARY="$NEUTRON_DIR/neutron/plugins/bigswitch/agent/restproxy_agent.py"
lib/neutron_plugins/brocade:41:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-linuxbridge-agent"
lib/neutron_plugins/ibm:102:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-ibm-agent"
lib/neutron_plugins/linuxbridge_agent:49:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-linuxbridge-agent"
lib/neutron_plugins/nec:78:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-nec-agent"
lib/neutron_plugins/ofagent_agent:72:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-ofagent-agent"
lib/neutron_plugins/oneconvergence:63:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-nvsd-agent"
lib/neutron_plugins/openvswitch_agent:66:    AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-openvswitch-agent"
lib/neutron_plugins/ryu:53:    AGENT_BINARY="$NEUTRON_DIR/neutron/plugins/ryu/agent/ryu_neutron_agent.py"

付録2.ソースからインストールする際の、手順のメモ(殴り書きなので、適宜微修正をしないといけないかもしれません)

注意していただきたいこと

<****>は適宜自分の環境に置き換えて入力してください。

構築した環境について

  • Openstackバージョン:stable/junoを想定
  • 環境:ubuntu14.04
  • 構成:ALL in One
  • インストールコンポーネント:keystone,nova,cinder,glance,neutron
  • 設定:基本的に、標準の設定を想定
  • Novaのハイパーバイザー: kvm + qemu
  • Neutron:ml2プラグイン + ovsエージェント

(1)$ mkdir /opt/stack #インストール先のディレクトリを作成

(2)rabbitmqで名前解決が必要になるため、hostnameファイルに下記を追加

127.0.0.1  localhost

   

(3)依存パッケージのインストール(適宜Devstackの files/<component-name> を確認する方が確実)

dist指定があるものは、ディストリビューションのバージョンがdistに指定されているバージョンの場合だけインストール。NOPRIMEはインストールしない

general

   * bridge-utils

   * pylint

   * python-setuptools

   * screen

   * unzip

   * wget

   * psmisc

   * git

   * lsof # useful when debugging

   * openssh-server

   * openssl

   * python-virtualenv

   * python-unittest2

   * iputils-ping

   * wget

   * curl

   * tcpdump

   * euca2ools # only for testing client

   * tar

   * python-cmd2 # dist:precise

   * python-dev

   * python2.7

   * bc

keystone

   * python-lxml

   * python-pastescript

   * python-pastedeploy

   * python-paste

   * sqlite3

   * python-pysqlite2

   * python-sqlalchemy

   * python-mysqldb

   * python-webob

   * python-greenlet

   * python-routes

   * libldap2-dev

   * libsasl2-dev

nova

   * bridge-utils

   * pylint

   * python-setuptools

   * screen

   * unzip

   * wget

   * psmisc

   * git

   * lsof # useful when debugging

   * openssh-server

   * openssl

   * python-virtualenv

   * python-unittest2

   * iputils-ping

   * wget

   * curl

   * tcpdump

   * euca2ools # only for testing client

   * tar

   * python-cmd2 # dist:precise(12.04LTS)

   * python-dev

   * python2.7

   * bc

n-cpu

   * lvm2

   * open-iscsi

   * open-iscsi-utils # Deprecated since quantal dist:precise

   * genisoimage

   * sysfsutils

   * sg3-utils

   * python-guestfs # NOPRIME

n-api

   * python-dateutil

   * msgpack-python

   * fping

n-novnc

   * python-numpy

glance

   * gcc

   * libffi-dev

   * libmysqlclient-dev  # testonly

   * libpq-dev           # testonly

   * libssl-dev          # testonly

   * libxml2-dev

   * libxslt1-dev        # testonly

   * python-eventlet

   * python-routes

   * python-greenlet

   * python-sqlalchemy

   * python-wsgiref

   * python-pastedeploy

   * python-xattr

   * python-iso8601

   * zlib1g-dev           # testonly

cinder

   * tgt

   * lvm2

   * qemu-utils

   * libpq-dev

   * open-iscsi

   * open-iscsi-utils # Deprecated since quantal dist:precise

neutron

   * ebtables

   * iptables

   * iputils-ping

   * iputils-arping

   * mysql-server #NOPRIME

   * sudo

   * python-boto

   * python-iso8601

   * python-paste

   * python-routes

   * python-suds

   * python-pastedeploy

   * python-greenlet

   * python-kombu

   * python-eventlet

   * python-sqlalchemy

   * python-mysqldb

   * python-pyudev

   * python-qpid # dist:precise

   * dnsmasq-base

   * dnsmasq-utils # for dhcp_release only available in dist:precise

   * rabbitmq-server # NOPRIME

   * qpidd # NOPRIME

   * sqlite3

   * vlan

(4)pipのインストール

(4−1)https://bootstrap.pypa.io/get-pip.pyをダウンロード

$curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
$sudo -E python <get-pip.py>

(5)特定のライブラリだけバージョンを指定して、あらかじめインストールし、アップデートされないようにReadOnlyにする

   Openstackを使うにあたって、下記のバージョン依存がある

   (5−1)sudo pip install "prettytable=0.7.2"

$sudo pip install "prettytable=0.7.2"

   (5−2)sudo pip install "httplib2=0.8"

$sudo pip install "httplib2=0.8"

   (5−3)アップデートされないように、644のパーミッションを設定する

$sudo chmod 644 /usr/lib/python2.7/dist-package/prettytable-0.7.2*
$sudo chmod 644 /usr/lib/python2.7/dist-package/httplib2*

→Devstackだと上記コマンドだけど、sudo chmod 555のじゃないと意味ないんじゃないか?

(6)RPCバックエンド(amqpサーバ) のインストール

$ sudo apt-get install rabbitmq-server

(7)DBサーバのインストール、簡単な初期設定

  (7−1)$ sudo apt-get install mysql-server #インストール

$sudo apt-get install mysql-server

  (7−2)~/.my.cnf の作成(mysqlコマンドを引数無しで実行すると、これの値が参照される)

~/.my.cnf

[client]
user=<user名>
password=<password>
host=<host名>

(8)neutronのエージェントが依存するパッケージ(agentが操作する対象の仮想スイッチ等)をインストール(ml2_plugin/openvswitchの場合)

   (8−1)カーネルが3.13よりバージョンが低ければ、「openvswitch-datapath-dkms」もaptでインストール

$sudo apt-get install openvswitch-datapath-dkms

   (8−2)openvswitchとかインストール

$sudo apt-get install make fakeroot dkms openvswitch-switch linux-headers-<kernel_version>

    →kernel_versionは:「cat /proc/version | cut -d " " -f3」で取得できる

Openstackコンポーネントのインストール

(9)openstack/requirementsコンポーネント

   → 各コンポーネントの依存関係が定義されるファイル(requirements.txt,test-requirements.txt)のバージョンをOpenstack内で統一してくれる、requirementsファイルに定義されていないライブラリは使用されないことを約束する

   →使い方は、$python update.py <コンポーネントのソースディレクトリのパス>

   →2つのコンポーネントがtestというライブラリを使用するとするときに、1つ目のコンポーネントがバージョン0.8を使っていて、もう片方がバージョン1.2を使っている場合。1つ目のコンポーネントが最初にインストールされると、2つ目のコンポーネントでバージョン0.8のライブラリを使うことになるのでエラーが起きることがある。その解決策として作られた。

  (9−1)cd /opt/stack

$cd /opt/stack

     (9−2)git clone git://git.openstack.org/openstack/requirements.git stable/juno

$git clone git://git.openstack.org/openstack/requirements.git stable/juno

(10)openstack-dev/pbrコンポーネント

   →インストールオプションをsetup.cfgに書いて、setuptoolsでインストールするときにsetupメソッドをフックしてその、オプションを適用してくれるらしい。

  (10−1)cd /opt/stack

$cd /opt/stack

  (10−2)git clone git://git.openstack.org/openstack-dev/pbr.git

$git clone git://git.openstack.org/openstack-dev/pbr.git

  (10−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (10−4)./update.py /opt/stack/pbr

$./update.py /opt/stack/pbr

    →pbrのrequirements.txt,test-requirements.txtで定義されているライブラリがglobal-requirementsに定義されているか、バージョンは古くないかを検査してくれる

  (10−5)sudo pip install /opt/stack/pbr

$sudo pip install /opt/stack/pbr

(11)openstack/cliffコンポーネント

   →CLIフレームワーク、各コンポーネントCLIソフトウェアを作成するときに使われている模様

  (11−1)cd /opt/stack

$cd /opt/stack

  (11−2)git clone git://git.openstack.org/openstack/cliff.git

$git clone git://git.openstack.org/openstack/cliff.git 

    (11−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (11−4)./update.py /opt/stack/cliff

$./update.py /opt/stack/cliff

  (11−5)sudo pip install /opt/stack/cliff

$sudo pip install /opt/stack/cliff

(12)openstack/oslo.configコンポーネント

   →Openstack共通のコンフィグとかが入っている

  (12−1)cd /opt/stack

$cd /opt/stack

  (12−2)git clone git://git.openstack.org/openstack/oslo.config.git

$git clone git://git.openstack.org/openstack/oslo.config.git

  (12−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (12−4)./update.py /opt/stack/oslo.config

$./update.py  /opt/stack/oslo.config

  (12−5)sudo pip install /opt/stack/oslo.config

$sudo pip install /opt/stack/oslo.config

(13)openstack/oslo.messagingコンポーネント

   →コンポーネント間の通信処理(amqp)を行うライブラリ

  (13−1)cd /opt/stack

$cd /opt/stack

  (13−2)git clone git://git.openstack.org/openstack/oslo.messaging.git

$git clone git://git.openstack.org/openstack/oslo.messaging.git

  (13−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (13−4)./update.py /opt/stack/oslo.messaging

$./update.py /opt/stack/oslo.messaging

  (13−5)sudo pip install /opt/stack/oslo.messaging

$sudo pip install /opt/stack/oslo.messaging

(14)openstack/oslo.rootwrapコンポーネント

   →各コンポーネントは、SU権限が必要な処理をすることがある、Cinderだったらmountとかneutronだったらrouteの追加とか

  (14−1)cd /opt/stack

$cd /opt/stack

  (14−2)git clone git://git.openstack.org/openstack/oslo.rootwrap.git

$git clone git://git.openstack.org/openstack/oslo.rootwrap.git

  (14−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (14−4)./update.py /opt/stack/oslo.rootwrap

$./update.py /opt/stack/oslo.rootwrap

  (14−5)sudo pip install /opt/stack/oslo.rootwrap

$sudo pip install /opt/stack/oslo.rootwrap

(15)openstack/pycadfコンポーネント

   →よくわからないhttp://docs.openstack.org/developer/pycadf/

  (15−1)cd /opt/stack

$cd /opt/stack

  (15−2)git clone git://git.openstack.org/openstack/pycadf.git

$git clone git://git.openstack.org/openstack/pycadf.git

  (15−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (15−4)./update.py /opt/stack/pycadf

$./update.py /opt/stack/pycadf

  (15−5)sudo pip install /opt/stack/pycadf

$sudo pip install /opt/stack/pycadf

(16)openstack/stevedoreコンポーネント

   →Pythonプラグイン機構を抽象化するためのもの

  (16−1)cd /opt/stack

$cd /opt/stack

  (16−2)git clone git://git.openstack.org/openstack/stevedore.git

$git clone git://git.openstack.org/openstack/stevedore.git

  (16−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (16−4)./update /opt/stack/stevedore

$./update /opt/stack/stevedore

  (16−5)sudo pip install /opt/stack/stevedore

$sudo pip install /opt/stack/stevedore

(17)openstack/taskflowコンポーネント

  (17−1)cd /opt/stack

$cd /opt/stack

  (17−2)git clone git://git.openstack.org/openstack/taskflow.git

$git clone git://git.openstack.org/openstack/taskflow.git

  (17−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (17−4)./update /opt/stack/taskflow

$./update /opt/stack/taskflow

  (17−5)sudo pip install /opt/stack/taskflow

$sudo pip install /opt/stack/taskflow

(18)python-keystoneclientコンポーネントのインストール

  (18−1)cd /opt/stack

$cd /opt/stack

  (18−2)git clone git://git.openstack.org/openstack/python-keystoneclient.git

$git clone  git://git.openstack.org/openstack/python-keystoneclient.git

  (18−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (18−4)./update /opt/stack/python-keystoneclient

$./update /opt/stack/python-keystoneclient

  (18−5)sudo pip install /opt/stack/python-keystoneclinet

$sudo pip install /opt/stack/python-keystoneclinet

  (18−6)mode -644 owner <実行ユーザ>でpython-keystoneclient/etc/bash_completion.d/keystone.bash_completionを/etc/bash_completion.d配下にコピー

$sudo install -D -m 0644 -o <実行ユーザ> {/opt/stack/python-keystoneclient/etc/bash_completion.d/,/etc/bash_completion.d/}keystone.bash_completion

(19)python-glanceclientコンポーネントのインストール

  (19−1)cd /opt/stack

$cd /opt/stack

  (19−2)git clone git://git.openstack.org/openstack/python-glanceclient.git

$git clone git://git.openstack.org/openstack/python-glanceclient.git

  (19−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (19−4)./update.py /opt/stack/python-glanceclient

$./update.py /opt/stack/python-glanceclien

  (19−5)sudo pip install /opt/stack/python-glanceclient

$sudo pip install /opt/stack/python-glanceclient

  (19−6)mode -644 owner <実行ユーザ>でpython-glanceclient/etc/bash_completion.d/glance.bash_completionを/etc/bash_completion.d配下にコピー

$sudo install -D -m 0644 -o <実行ユーザ> {/opt/stack/python-glanceclient/etc/bash_completion.d/,/etc/bash_completion.d/}glance.bash_completion

(20)python-neutronclientコンポーネントのインストール

  (20−1)cd /opt/stack

$cd /opt/stack

  (20−2)git clone git://git.openstack.org/openstack/python-neutronclient.git

$git clone git://git.openstack.org/openstack/python-neutronclient.git

  (20−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (20−4)./update.py /opt/stack/python-neutronclient

$./update.py /opt/stack/python-neutronclient

  (20−5)sudo pip install /opt/stack/python-neutronclient

$sudo pip install /opt/stack/python-neutronclient

  (20−6)mode 644 owner <実行ユーザ>でpython-neutronclient/etc/bash_completion.d/neutron.bash_completionを/etc/bash_completion.d配下にコピー

$sudo install -D -m 0644 -o <実行ユーザ> {/opt/stack/python-neutronclient/etc/bash_completion.d/,/etc/bash_completion.d/}neutron.bash_completion

(21)python-novaclientコンポーネントのインストール

  (21−1)cd /opt/stack

$cd /opt/stack

  (21−2)git clone git://git.openstack.org/openstack/python-novaclient.git

$git clone git://git.openstack.org/openstack/python-novaclient.git

  (21−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (21−4)./update.py /opt/stack/python-novaclient

$./update.py /opt/stack/python-novaclient

  (21−5)sudo pip install /opt/stack/python-novaclient

$sudo pip install /opt/stack/python-novaclient

  (21−6)mode 644 owner <実行ユーザ>でpython-novaclient/etc/bash_completion.d/nova.bash_completionを/etc/bash_completion.d配下にコピー

$sudo install -D -m 0644 -o <実行ユーザ> {/opt/stack/python-novaclient/etc/bash_completion.d/,/etc/bash_completion.d/}nova.bash_completion

(22)openstackclientコンポーネントのインストール ( 696line in stack.sh )

  (22−1)cd /opt/stack

$cd /opt/stack

  (22−2)git clone git://git.openstack.org/openstack/python-openstackclient.git

$git clone git://git.openstack.org/openstack/python-openstackclient.git

  (22−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (22−4)./update.py /opt/stack/python-openstackclient

$./update.py /opt/stack/python-openstackclient

  (22−5)sudo pip install /opt/stack/python-openstackclient

$sudo pip install /opt/stack/python-openstackclient

(23)Keystoneのインストール

  (23−1)cd /opt/stack

$cd /opt/stack

  (23−2)git clone git://git.openstack.org/openstack/keystone.git stable/juno

$git clone git://git.openstack.org/openstack/keystone.git stable/juno

  (23−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (23−4)./update.py /opt/stack/keystone

$./update.py /opt/stack/keystone

  (23−5)sudo pip install /opt/stack/keystone

$sudo pip install /opt/stack/keystone

(24)Keystoneの設定

  (24−1)cd /opt/stack/keystone

$cd /opt/stack/keystone

  (24−2)sudo mkdir /etc/keystone ; sudo chown <実行ユーザ> /etc/keystone

$sudo mkdir /etc/keystone
$sudo chown <実行ユーザ> /etc/keystone

  (24−3)Keystoneのソースディレクトリから下記の設定ファイルを/etc/keystone配下にコピー         ・keystone.conf.sample → keystone.conf         ・keystone-paste.ini         ・policy.json

$cp /opt/stack/keystone/etc/keystone.conf.sample /etc/keystone
$cd /opt/stack/keystone/etc/keystone-pate.ini /etc/keystone
$cd /opt/stack/keystone/etc/policy.json  /etc/keystone

  (24−4)keystone.confを以下のように編集

keystone.conf

[DEFAULT]
public_endpoint=http://<keystoneが動くIP>:%(public_port)s/
admin_endpoint=http://<keystoneが動くIP>:%(admin_port)s/
admin_token=<admin portのtoken>
use_syslog=True
public_bind_host=0.0.0.0
admin_bind_host=0.0.0.0
[assignment]
driver=keystone.assignment.backends.sql.Assignment 
[auth]
[cache]
[catalog]
driver=keystone.catalog.backends.sql.Catalog
[credential]
[database]
connection=mysql://user:password@127.0.0.1/keystone?charset=utf8
[ec2]
driver=keystone.contrib.ec2.backends.sql.Ec2
[endpoint_filter]
[endpoint_policy]
[federation]
[identity]
driver=keystone.identity.backends.sql.Identity
[identity_mapping]
[kvs]
[ldap]
[matchmaker_redis]
[matchmaker_ring]
[memcache]
[oauth1]
[os_inherit]
[paste_deploy]
config_file=/etc/keystone/keystone-paste.ini
[policy]
[revoke]
[saml]
[signing]
[ssl]
[stats]
[token]
driver=keystone.token.backends.sql.Token
[trust]

(25)Glanceのインストール

  (25−1)cd /opt/stack

$cd /opt/stack

  (25−2)git clone git://git.openstack.org/openstack/glance.git stable/juno

$git clone git://git.openstack.org/openstack/glance.git stable/juno

  (25−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (25−4)./update.py /opt/stack/glance

$./update.py /opt/stack/glance

  (25−5)sudo pip install /opt/stack/glance

$sudo pip install /opt/stack/glance

(26)Glanceの設定

  (26−1)sudo mkdir /etc/glance ; sudo chown <実行ユーザ> /etc/glance

$sudo mkdir /etc/glance
$sudo chown <実行ユーザ> /etc/glance

  (26−2)cp /opt/stack/glance/etc/glance-registory.conf /etc/glance

$cd /opt/stack/glance/etc/glance-registory.conf  /etc/glance

  (26−3)glance-registory.conf の設定を以下のように編集

glance-registry.conf

[DEFAULT]
debug=True
sql_connection=mysql://<user名>:<password>@127.0.0.1/glance?charset=utf8
use_syslog=True
bind_host = 0.0.0.0
bind_port = 9191
backlog = 4096
api_limit_max = 1000
limit_param_default = 25
rabbit_host = localhost
rabbit_port = 5672
rabbit_use_ssl = false
rabbit_userid = guest
rabbit_password = guest
rabbit_virtual_host = /
rabbit_notification_exchange = glance
rabbit_notification_topic = notifications
rabbit_durable_queues = False
qpid_notification_exchange = glance
qpid_notification_topic = notifications
qpid_hostname = localhost
qpid_port = 5672
qpid_username =
qpid_password =
qpid_sasl_mechanisms =
qpid_reconnect_timeout = 0
qpid_reconnect_limit = 0
qpid_reconnect_interval_min = 0
qpid_reconnect_interval_max = 0
qpid_reconnect_interval = 0
qpid_heartbeat = 5
qpid_protocol = tcp
qpid_tcp_nodelay = True
[database]
[keystone_authtoken]
auth_host=<keystoneのIP>
auth_port=35357
auth_protocol=http
cafile=
auth_uri=http://<keystoneのIP>:35357/v2
signing_dir=/var/cache/glance/registry
identity_uri = http://127.0.0.1:35357
admin_tenant_name = service
admin_user = glance
admin_password = stack
[paste_deploy]
flavor=keystone
[profiler]

  (26−4)cp /opt/stack/glance/etc/glance-api.conf /etc/glance

$cp /opt/stack/glance/etc/glance-api.conf /etc/glance

  (26−5)glance-api.confを下記のように編集

glance-api.conf

[DEFAULT]
debug=True
sql_connection=mysql://<user名>:<password>@127.0.0.1/glance?charset=utf8
use_syslog=True
bind_host = 0.0.0.0
bind_port = 9191
backlog = 4096
api_limit_max = 1000
limit_param_default = 25
rabbit_host = localhost
rabbit_port = 5672
rabbit_use_ssl = false
rabbit_userid = guest
rabbit_password = guest
rabbit_virtual_host = /
rabbit_notification_exchange = glance
rabbit_notification_topic = notifications
rabbit_durable_queues = False
qpid_notification_exchange = glance
qpid_notification_topic = notifications
qpid_hostname = localhost
qpid_port = 5672
qpid_username =
qpid_password =
qpid_sasl_mechanisms =
qpid_reconnect_timeout = 0
qpid_reconnect_limit = 0
qpid_reconnect_interval_min = 0
qpid_reconnect_interval_max = 0
qpid_reconnect_interval = 0
qpid_heartbeat = 5
qpid_protocol = tcp
qpid_tcp_nodelay = True
[database]
[keystone_authtoken]
auth_host=<keystoneのIP>
auth_port=35357
auth_protocol=http
cafile=
auth_uri=http://<keystonのIP>:35357/v2
signing_dir=/var/cache/glance/registry
identity_uri = http://127.0.0.1:35357
admin_tenant_name = service
admin_user = glance
admin_password = stack
[paste_deploy]
flavor=keystone
[profiler]

  (26−6)下記のファイルを/opt/stack/glance/etc から /etc/glanceにコピー        ・glance-cache.conf        ・glance-registry-paste.ini        ・glance-api-paste.ini        ・policy.json        ・schema-image.json

$cp /opt/stack/glance/etc/glance-cache.conf /etc/glance
$cp /opt/stack/glance/etc/glance-registry-paste.ini /etc/glance
$cp /opt/stack/glance/etc/glance-api-paste.ini /etc/glance
$cp /opt/stack/glance/etc/policy.json /etc/glance
$cp /opt/stack/glance/etc/shcema-image.json /etc/glance

(27)Cinderのインストール     (27−1)cd /opt/stack

$cd /opt/stack

  (27−2)git clone git://git.openstack.org/openstack/cinder.git stable/juno

$git clone git://git.openstack.org/openstack/cinder.git stable/juno

  (27−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (27−4)./update.py /opt/stack/cinder

$./update.py /opt/stack/cinder

  (27−5)sudo pip install /opt/stack/cinder

$sudo pip install /opt/stack/cinder

(28)Cinderの設定

  (28−1)sudo mkdir /etc/cinder ; sudo chown <実行ユーザ> /etc/cinder

$sudo mkdir /etc/cinder
$sudo chown <実行ユーザ> /etc/cinder

  (28−2)cp /opt/stack/cinder/etc/policy.json /etc/cinder

$cp /opt/stack/cinder/etc/policy.json  /etc/cinder

  (28−3)rootwrapの設定

   (28−3−1)mkdir -m 755 /etc/cinder/rootwrap.d

 $mkdir -m 755 /etc/cinder/rootwrap.d

   (28−3−2)cp /opt/stack/cinder/etc/rootwrap.d/* /etc/cinder/rootwrap.d/

 $cp /opt/stack/cinder/etc/rootwrap.d/* /etc/cinder/rootwrap.d/

     (28−3−3)sudo chown -R root:root /etc/cinder/rootwrap.d

 $sudo chown -R root:root /etc/cinder/rootwrap.d

   (28−3−4)sudo chmod 644 /etc/cinder/rootwrap.d/*

 $sudo chmod 644 /etc/cinder/rootwrap.d/*

   (28−7)cp /opt/stack/cinder/etc/rootwrap.conf /etc/cinder/

 $cp /opt/stack/cinder/etc/rootwrap.conf /etc/cinder/

   (28−8)/etc/cinder/rootwrap.confを下記のように追加

rootwrap.conf

filters_path = /etc/cinder/rootwrap.conf

   (28−9)sudo chown root:root /etc/cinder/rootwrap.conf

$sudo chown root:root /etc/cinder/rootwrap.conf

   (28−10)sudo chmod 0644 /etc/cinder/rootwrap.conf

$sudo chmod 0644 /etc/cinder/rootwrap.conf

   (28−11)/etc/sudoers.d/cinder-rootwrapを下記の内容で作成

cinder-rootwrap

<実行ユーザ> ALL=(root) NOPASSWD : /usr/bin/cinder-rootwrap /etc/cinder/rootwrap.conf *

  (28−12)cp /opt/stack/cinder/etc/api-paste.ini /etc/cinder

$cp /opt/stack/cinder/etc/api-paste.ini  /etc/cinder

  (28−13)cp /opt/stack/cinder/etc/cinder.conf.sample /etc/cinder/cinder.conf

$cp /opt/stack/cinder/etc/cinder.conf.sample /etc/cinder/cinder.conf

  (28−14)cinder.confを下記のように変更

cinder.conf

[DEFAULT]
auth_strategy=keystone
debug=True
verbose=True
volume_group=stack-volumes
volume_name_template=volume-%s
my_ip=<cinderのipアドレス>
iscsi_helper = tgtadm
sql_connection=mysql://<user名>:<password>@127.0.0.1/cinder?charset=utf8
api_paste_config=/etc/cinder/api-paste.ini
rootwrap_config=/etc/cinder/rootwrap.conf
osapi_volume_extension=cinder.api.contrib.standard_extensions
state_path=/opt/stack/data/cinder
lock_path=/opt/stack/data/cinder
periodic_interval=60
use_syslog=True
rpc_backend=cinder.openstack.common.rpc.impl_kombu
rabbit_hosts=<rabbitmqのIP>
rabbit_password=stack
[BRCD_FABRIC_EXAMPLE]
[CISCO_FABRIC_EXAMPLE]
[database]
[fc-zone-manager]
[keymgr]
[keystone_authtoken]
auth_host=<keystoneのIP>
auth_port=35357
auth_protocol=http
admin_tenant_name=service
admin_user=cinder
admin_password=stack
signing_dir=/var/cache/cinder
cafile=
auth_uri=http://<keystoneのIP>:35357/v2.0
[matchmaker_redis]
[matchmaker_ring]
[profiler]
[ssl]

※CINDER_DRIVER(local.conf[localrc]に指定する環境変数)に何も指定しないと、defaultという値が入るが、devstack/lib/cinder_plugins/配下にdefaultというファイルはないため、driverの設定は行われない。

(29)Neutronのインストール

  (29−1)cd /opt/stack

$cd /opt/stack

  (29−2)git clone git://git.openstack.org/openstack/neutron.git stable/juno

$git clone git://git.openstack.org/openstack/neutron.git stable/juno

  (29−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (29−4)./update,py /opt/stack/neutron

$./update,py  /opt/stack/neutron

  (29−5)sudo pip install /opt/stack/neutron

$sudo pip install  /opt/stack/neutron  

   ※Devstackでは、ENABLE_SERVICESにryuとかmidonetとか指定すると、third_partyのインストール処理もここで実行される(Devstackでは対応遅れてる)

(30)Novaのインストール

  (30−1)ハイパーバイザーのインストール

    (30−1−1)libvirtqemu-kvmのインストール

$sudo apt-get install qemu-kvm,libvirt-bin,python-libvirt,python-guestfs

  (30−2)novncをclone

$git clone https://github.com/kanaka/noVNC.git

  (30−3)novaのソースを取得

$git clone git://git.openstack.org/openstack/nova.git stable/juno

  (30−4)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (30−5)./update.py /opt/stack/nova

$./update.py /opt/stack/nova

  (30−6)sudo pip install /opt/stack/nova

$sudo pip install /opt/stack/nova

  (30−7)sudo install -D -m 0644 -o <実行ユーザ> /opt/stack/nova/tools/nova-manage.bash_completion /etc/bash_completion.d/nova-manage.bash_completion

$sudo install -D -m 0644 -o <実行ユーザ> /opt/stack/nova/tools/nova-manage.bash_completion /etc/bash_completion.d/nova-manage.bash_completion

(31)Novaの以前の設定等があれば削除

  (31−1)iptablesの内容を削除

         # Delete rules
         sudo iptables -S -v | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" | grep "\-A" |  sed "s/-A/-D/g" | awk '{print "sudo iptables",$0}' | bash
         # Delete nat rules
         sudo iptables -S -v -t nat | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" |  grep "\-A" | sed "s/-A/-D/g" | awk '{print "sudo iptables -t nat",$0}' | bash
         # Delete chains
         sudo iptables -S -v | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" | grep "\-N" |  sed "s/-N/-X/g" | awk '{print "sudo iptables",$0}' | bash
         # Delete nat chains
         sudo iptables -S -v -t nat | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" |  grep "\-N" | sed "s/-N/-X/g" | awk '{print "sudo iptables -t nat",$0}' | bash

  (31−2)sudo virsh list --allをして、novaのprefixが付くvmを削除

$sudo virsh destroy 
$sudo virsh undefine --managed-save

  (31−3)ISCIセッションの削除

tgts=$(sudo iscsiadm --mode node | grep volume- | cut -d ' ' -f2)
for target in $tgts; do
  sudo iscsiadm --mode node -T $target --logout || true
done
sudo iscsiadm --mode node --op delete || true

  (31−4)過去のnovaで作ったvmのデータの削除

$sudo rm -fr /opt/stack/data/nova/instances/*

            (31−5)過去のnovaに関するデータのディレクトリやキャッシュの削除

$sudo rm -fr /opt/stack/data/nova
$sudo rm -fr /var/cache/nova     

(32)Novaの設定

  (32−1)sudo mkdir /etc/nova ; sudo chown <実行ユーザ> /etc/nova

$sudo mkdir /etc/nova
$sudo chown <実行ユーザ>  /etc/nova

  (32−2)policy.json を本番環境にコピー

$cp /opt/stack/nova/etc/policy.json /etc/nova

  (32−3)nova-api用の設定

    (32−3−1)api-paste.iniファイルを本番環境にコピー

$cp /opt/stack/nova/etc/api-paste.ini /etc/nova

     (32−4)nova-compute用の設定

    (32−4−1)ipフォワーディングを有効

$sudo sysctl -w net.ipv4.ip_forward=1

    (32−4−2)SELinuxが動いていたら、virt_use_execmem(ゲストOSの executable memory and executable_stack を有効にする) 組み込みルールをONにする

$sudo setsebool virt_use_execmem on

    (32−4−3)vmのデータを格納するディレクトリを作成、所有ユーザの変更

$mkdir -p /opt/stack/nova/instances
$sudo chown <実行ユーザ>  /opt/stack/nova/instances

→novaでvmを作成すると、vmごとにフォルダが作られ、instances/<vmごとに付けられる乱数>のディレクトリの中は下記のようになる

$ ls /opt/stack/nova/instances/kflksalfdjafdj
-rw-rw---- 1 libvirt-qemu kvm         18549 Nov 27 21:40 console.log
-rw-r--r-- 1 libvirt-qemu kvm      11010048 Nov 27 21:41 disk
-rw-rw-r-- 1 libvirt-qemu kvm        419840 Nov 27 19:25 disk.config
-rw-r--r-- 1 stack          libvirtd      176 Nov 27 19:25 disk.info
-rw-rw-r-- 1 stack          libvirtd     2697 Nov 27 19:25 libvirt.xml

  (32−5)nova.confの作成と編集

nova.conf

[DEFAULT]
verbose=True
debug=True
auth_strategy=keystone
use_syslog=True

#
allow_resize_to_same_host=True

api_paste_config=/etc/nova/api-paste.ini
rootwrap_config=/etc/nova/rootwrap.conf
scheduler_driver=nova.scheduler.filter_scheduler.FilterScheduler

dhcpbridge_flagfile=/etc/nova/nova.conf

force_dhcp_release=True
fixed_range=
default_floating_pool=public

#s3_host=
#s3_port=8080

osapi_compute_extension=nova.api.openstack.compute.contrib.standard_extensions

my_ip=<実行するホストIP>

osapi_compute_workers=4
ec2_workers=4
metadata_workers=4

#neutron
#
network_api_class=nova.network.neutronv2.api.API
neutron_admin_username=neutron
neutron_admin_password=stack
neutron_admin_auth_url=http://<neutronの認証サーバのIP(普通はkeystone)>/v2.0
neutron_auth_strategy=keystone
neutron_admin_tenant_name=service
neutron_region_name=RegionOne
neutron_url=http://<neutron-ip>:9696
service_neutron_metadata_proxy=True

libvirt_vif_driver=nova.virt.libvirt.vif.LibvirtGenericVIFDriver
linuxnet_interface_driver=
vif_plugging_is_fatal=True
vif_plugging_timeout=300

sql_connection=mysql://<user名>:<パスワード>@127.0.0.1/nova?charset=utf8

instance_name_template=instance-%08x

volume_api_class=nova.volume.cinder.API

state_path=/opt/stack/data/nova
lock_path=/opt/stack/data/nova

instances_path=/opt/stack/data/nova/instances

force_config_drive=always

logging_context_format_string="%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"

novncproxy_base_url=http://<novncproxyを動かしてるip>:6080/vnc_auto.html
xvpvncproxy_base_url=http://<xvpnvncproxyを動かしてるip>:6081/console

vnc_enabled=true
vncserver_listen=127.0.0.1
vncserver_proxyclien_address=127.0.0.1

ec2_dmz_host=<nova-api or nova-api-ec2を動かしてるサーバのIP>


rpc_backend=nova.openstack.common.rpc.impl_kombu
rabbit_hosts=<rabbitmqのIP>
rabbit_password=stack

glance_api_servers=<glanceのIP>:9292

use_usb_tablet=False
default_ephemeral_format=ext4
compute_driver=libvirt.LibvirtDriver

#firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver
firewall_driver=nova.virt.firewall.NoopFirewallDriver
security_group_api=neutron


[conductor]
workers=4


[osapi_v3]
enabled=True

[keystone_authtoken]
auth_host=<keystoneのIP>
auth_port=35357
auth_protocol=http

admin_tenant_name=service
admin_user=nova
admin_password=stack
signing_dir=/var/cache/nova

cafile=


[libvirt]
virt_type=qemu
cpu_mode=none
injection_partition=-2

[keymgr]
fixed_key = 962A3A8992C79BB4A2968AB28417F75D2D286FB16F2C537B26B8AE39CB1F6C92

  (32−6)nova-compute かつ hypervisorにlibvirtlibvirtのインターフェースを使ってHypervisorを操作する)を使用する場合の設定

    (32−6−1)Neutronのml2プラグイン or openvswitchプラグインでopenvswitch agentを使う場合、/etc/libvirt/qemu.confに下記の設定を追加または、編集

cgroup_device_acl = [
   "/dev/null", "/dev/full", "/dev/zero",
   "/dev/random", "/dev/urandom",
   "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
   "/dev/rtc", "/dev/hpet","/dev/net/tun",
                                     ]

    (32−6−2)実行ユーザを libvirtdグループに追加

$sudo usermod -G libvirtd <実行ユーザ>

    (32−6−3)libvirtdを再起動

$sudo service libvirtd restart

(33)Horizonのインストール

  (33−0)djangoのuser認証モジュール(contrib.auth framework)のkeystoneを使うモジュールのインストール   (33−1)cd /opt/stack

$cd /opt/stack

  (33−2)git clone git://git.openstack.org/openstack/django_openstack_auth.git

$git clone git://git.openstack.org/openstack/django_openstack_auth.git

  (33−3)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (33−4)./update.py /opt/stack/django_openstack_auth

$./update.py /opt/stack/django_openstack_auth

  (33−5)sudo pip install /opt/stack/django_openstack_auth

$sudo pip install /opt/stack/django_openstack_auth

     (33−6)ApacheWSGIモジュールのインストール   (33−7)apache2 , libapache2-mod-wsgiをパッケージ管理ツールからインストール

$sudo apt-get install apache2 libapache2-mod-wsgi

  (33−8)wsgiモジュールを有効化

$a2enmod wsgi

   →実際は、/etc/apache2/mod-availablesの設定ファイルを、mod-enablesにシンボリックリンクを張る      (33−9)Horizonのソースを取得、インストール   (33−10)cd /opt/stack

$cd /opt/stack

  (33−11)git clone git://git.openstack.org/openstack/horizon.git stable/juno

$git clone git://git.openstack.org/openstack/horizon.git  stable/juno

  (33−12)cd /opt/stack/requirements

$cd /opt/stack/requirements

  (33−13)./update.py /opt/stack/horizon

$./update.py /opt/stack/horizon

  (33−14)sudo pip install /opt/stack/horizon

$sudo pip install /opt/stack/horizon

(34)rsyslogの設定

  (34−1)openstack用の設定ファイルの作成

$sudo touch /etc/rsyslog.d/90-stack-m.conf

  (34−2)90-stack-m.confを下記のように編集

90-stack-m.conf

$ModLoad imrelp
$InputRELPServerRun 516

  (34−3)rsyslogdを再起動

$sudo service rsyslog restart

(35)RabbitMQの設定

  (35−1)パスワードの変更

$rabbitmqctl  change_password guest <password>

  (36)Mysqlの設定

  (36−1)rootユーザのパスワード設定

$sudo mysqladmin -u root password <password>

  (36−2)すべてのホストからアクセスしてくるrootユーザにグローバルレベル('.')のすべて操作権限を与える

$sudo mysql -uroot -p<password> -h127.0.0.1 -e "GRANT ALL PRIVILEGES ON *.* TO '$DATABASE_USER'@'%'   identified by '$DATABASE_PASSWORD';"

  (36−3)/etc/mysql/my.cnfを作成、以下のように変更

     [mysqld]セクションに

       ・bind-address=0.0.0.0

       ・default-storage-engine=InnoDB

       を追記

  (36−4)sudo service mysql restart

$sudo service mysql restart

*devstackだとこのあたりで、screenの起動や設定を行う *devstackだとこのあたりで、起動した各プロセスが正常に動いているかどうかを管理するためのディレクトリ/opt/stack/statusを作成する *devstackだとこのあたりで、dstatの起動や設定を行う

Openstakコンポーネントの起動〜初期化処理〜

「ここから先は、tmuxなりscreenで各プロセスごとにwindowを用意することをおすすめします」

Keystone

(37)Keystoneの初期設定

  (37−1)DBの作成

$mysql
>DROP DATABASE IF EXISTS keystone
>CREATE DATABASE keystone CHARACTER SET utf8

  (37−2)DBのマイグレーション

$keystone-manage db_sync

     (37−3)PKIのセットアップ

$sudo rm -fr /etc/keystone/ssl
$keystone-manage pki_setup

  (37−4)authキャッシュ用のディレクトリ作成

$sudo mkdir -p /var/cache/keystone/auth
$sudo chown <実行ユーザ> /var/cache/keystone/auth

(38)Keystoneの起動

  (38−1)apache経由か単体で起動する場合かで、条件分岐

  (38−1[apache])apache経由で起動する場合は、apache用のコンフィグファイルをsite-enablesに設定し、apacheを再起動

  (38−1[単体])単体で受ける場合、keystone-allコマンドを実行

$keystone-all --config-file /etc/keystone/keystone.conf --debug

  (38−2)keystoneが動いてるか確認、curlでレスポンスが帰ってくるかどうか

$curl --noproxy '*' -k http://<ip>:35375/v2.0/

  (38−3)openstack client (python-openstack-client) を使うための環境変数を設定

       →servicetoken(設定ファイルで設定している)を用いて認証する。

$export OS_TOKEN=<keystone設定ファイルに記入した、service_token>
$export OS_URL=http://<ip>:5000/v2.0

  (38−4)openstack client を使い下記のような、テナント(プロジェクト)、ユーザ、ロールを作成

# Tenant               User       Roles
# ------------------------------------------------------------------
# --                       --             servic
# --                       --             ResellerAdmin
# --                       --             Member
# admin                admin      admin
# demo                 admin      admin
# demo                 demo       Member, anotherrole
# invisible_to_admin   demo       Member
# service               --             --

    (38−4−1) adminテナントの作成

$openstack project create  admin

    (38−4−2) adminテナントを主要テナントとするadminユーザを作成する

$openstack user create admin --project  <project-id(admin)> --email admin@example.com --password admin-password 

    (38−4−3) adminロールを作成

$openstack role create admin

    (38−4−4) adminユーザにadminテナントのadmin権限を与える

$openstack role add <role-id(admin)>  --project  <project-id(admin)> --user <user-id(admin)>

    (38−4−5) serviceテナントの作成、serviceロールを作成

        →各コンポーネントは、このserviceテナントのユーザ(role:admin)にならないといけない

$openstack project create service
$openstack role create service

    (38−4−6) ResellerAdminロールを作成

        → swiftの中のadminロールは、自分のテナントの管理しかできないが

        → ResellerAdminロールは、すべてのテナントの管理ができるため、Nova , Ceilometer等はこちらを使う

        → ResellerAdminロールの名前は、swiftswift-proxy.confで設定できる

$openstack role create ResellerAdmin

    (38−4−7)Memberロールを作成

        → SwiftとHorizonで使われるロール

$openstack role create Member

    (38−4−8)anotherroleロールを作成

        → 一般的な権限として使われるロールを作成

$openstack role create antherrole

    (38−4−9)invisible_to_adminテナントの作成

        → adminユーザが見ることのできないテナント

$openstack project create invisible_to_admin

    (38−4−10)demoテナントとdemoユーザを作成

$openstack project create demo
$openstack user create demo --project <project-id(demo)> --email demo@example.com --password <demo-pass>

    (38−4−11)demoユーザとadminユーザの権限の設定

$openstack role add --project <project-id(demo)> --user <user-id(demo)> <role-id(member)>
$openstack role add --project <project-id(demo)> --user <user-id(admin)> <role-id(admin)>
$openstack role add --project <project-id(demo)> --user <user-id(demo)> <role-id(another role)>
$openstack role add --project <project-id(invisible_to_admin)> --user <user-id(demo)> <role-id(Member)>

  (38−5)Keystoneコンポーネントのサービスカタログの登録、エンドポイントの登録 (38−5−1)サービスの登録

$openstack service create  keystone --type identity ---description "Keystone Identity Service"

    (38−5−2)エンドポイントの登録

$openstack endpoint create <service-id(keystone)> --region RegionOne 
    --publicurl http://<ip>:5000/v2.0
    --adminurl http://<ip>:35375/v2.0
    --internalurl http://<ip>:5000/v2.0

   →public_url:インターネット経由のアクセス(エンドユーザを想定)

   →admin_url:管理操作用のアクセス

   →internal_url:他のOpenStackコンポーネント用のLAN経由のアクセス

  (38−6)Novaコンポーネントのユーザ作成、サービスカタログの登録、エンドポイントの登録

    (38−6−1)novaユーザの作成、serviceテナントのadmin権限の付与

$openstack user create nova --password <password> --project <project-id(service)> --email nova@example.com 
$openstack add role <role-id(admin)> --project <project-id(service)> --user <user-id(nova)>

    (38−6−2)novaのサービスカタログの登録

$openstack service create nova --type=compute --description="Nova Compute Service"

    (38−6−3)novaのエンドポイントの登録

$openstack endpoint create <service-id(nova)> --region RegionOne 
   --publicurl  "http://<ip>:8774/v2/$(tenant_id)s"
   --adminurl  "http://<ip>:8774/v2/$(tenant_id)s"
   --internalurl  "http://<ip>:8774/v2/$(tenant_id)s"    

    (38−6−4)nova v3 API用のサービスの登録

$openstack service create novav3 --type=computev3 --description="Nova Compute Service V3"

    (38−6−5)nova v3 API用のエンドポイントの登録

$openstack endpoint create $NOVA_V3_SERVICE --region RegionOne 
   --publicurl "http://<ip>:8774/v3"
   --adminurl "http://<ip>:8774/v3"
   --internalurl  "http://<ip>:8774/v3"

    (38−6−6)EC2互換API用のサービスの登録

$openstack service create  ec2 --type ec2  --description "EC2 Compatibility Layer"

    (38−6−7)EC2互換API用のエンドポイントの登録

$openstack endpoint create ec2 --region RegionOne
   --publicurl  "http://<ip>:8773/services/Cloud"
   --adminurl  "http://<ip>:8773/services/Admin"
   --internalurl  "http://<ip>:8773/services/Cloud"

    (38−6−8)novaがswift経由でイメージをダウンロードする可能性がある場合(swiftが有効になっている場合)ResellerAdmin ロールを付与する必要がある

$openstack  add role <role-id(ResellerAdmin)>  --project <project-id(service)> --user <user-id(nova)>

  (38−7)Glanceコンポーネントのユーザ作成、サービスカタログの登録、エンドポイントの登録

    (38−7−1)glanceユーザの作成、serviceテナントのadmin権限の付与

$openstack user create glance --password <password>  --project <project-id(service) --email glance@example.com
$openstack  add role <role-id(admin)> --project <project-id(service)>  --user <user-id(glance) >

    (38−7−2)glanceのサービスカタログの登録

$openstack service create  --type image --description "Glance Image Service"  glance

    (38−7−3)glanceのエンドポイントの登録

$openstack endpoint create  glance --region RegionOne
   --publicurl  "http://<ip>:9292"
   --adminurl  "http://<ip>:9292"
   --internalurl  "http://<ip>:9292"

  (38−8)Cinderコンポーネントのユーザ作成、サービスカタログの登録、エンドポイントの登録

     (38−8−1)Cinderユーザの作成、serviceテナントのadmin権限の付与

$openstack user create cinder  --password <password> --project <project-id(service)> --email cinder@example.com
$openstack role add <role-id(admin)>  --project <project-id(service)>  --user <user-id(cinder)>

    (38−8−2)Cinder v1API用のサービスカタログを登録する

$openstack service create cinder --type  volume  --description="Cinder Volume Service" 

    (38−8−3)Cinder v1API用のエンドポイントを登録する

$openstack endpoint create <service-id(cinder)>  --region RegionOne
   --publicurl  http://<ip>:8776/v1/$(tenant_id)s
   --adminurl  http://<ip>:8776/v1/$(tenant_id)s
   --internalurl http://<ip>:8776/v1/$(tenant_id)s

    (38−8−4)Cinder v2API用のサービスカタログを登録する

$openstack  service create cinderv2  --type=volumev2 --description="Cinder Volume Serbvice V2"

    (38−8−5)Cinder v2API用のエンドポイントを登録する

$openstack endpoint create cinderv2 --region RegionOne
   --publicurl  http://<ip>:8776/v2/$(tenant_id)s
   --adminurl  http://<ip>:8776/v2/$(tenant_id)s
   --internalurl http://<ip>:8776/v2/$(tenant_id)s

  (38−9)Neutronコンポーネントのユーザ作成、サービスカタログの登録、エンドポイントの登録

    (38−9−1)Neutronユーザの作成、serviceテナントのadmin権限の付与

$openstack user create neutron --password <pass> --project <project-id(service)> --email neutron@example.com
$openstack role  add  <role-id(admin)> --project <project-id(service)> --user <user-id(neutron)>

    (38−9−2)Neutron API用のサービスカタログを登録

$openstack service create neutron --type=network  --description="Network Service"

    (38−9−3)Neutron API用のエンドポイントを登録する

$openstack endpoint  create  <service-id(neutron)>  --region RegionOne
   --publicurl  "http://<ip>:9696/"
   --adminurl  "http://<ip>:9696/"
   --internalurl "http://<ip>:9696/"

(39)Token-flow authの終了

  →各々のコンポーネントのユーザを作成したので、token認証をやめる。

$unset OS_TOKEN
$unset OS_URL

(40)password認証のための環境変数を設定

$export OS_AUTH_URL=http://<ip>:5000/v2.0
$export OS_TENANT_NAME=admin
$export OS_USERNAME=admin
$export OS_PASSWORD=<pass>
Horizon

(41)Horizonの初期設定

  (41−1)/opt/stack/horizon/openstack_dashboard/local/localsettings.py.exampleをlocalsettings.pyにリネーム

    →horizon GUIで有効にするタブ、設定などを定義する(ex, ロードバランサー、ファイヤーウォール)

  (41−2)localsettings.pyを自分の環境に合わせて、変更   
  (41−3)apacheがドキュメントルートとして使うディレクトリを作成する

$sudo mkdir -p /opt/stack/horizon/.blackhole

  (41−4) 000-defaultのサイトを無効にする

$sudo a2dissite 000-default

  (41−5)/etc/apache2/sites-available配下に、horizon.confを下記のように作成する

horizon.conf

<VirtualHost *:80>
    WSGIScriptAlias / /opt/stack/horizon/openstack_dashboard/wsgi/django.wsgi
    WSGIDaemonProcess horizon user=<実行ユーザ> group=<実行ユーザ> processes=3 threads=10 home=/opt/stack/horizon
    WSGIApplicationGroup %{GLOBAL}

    SetEnv APACHE_RUN_USER <実行ユーザ>
    SetEnv APACHE_RUN_GROUP <実行ユーザ>
    WSGIProcessGroup horizon

    DocumentRoot /opt/stack/horizon/.blackhole/
    Alias /media /opt/stack/horizon/openstack_dashboard/static

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Directory /opt/stack/horizon/>
        Options Indexes FollowSymLinks MultiViews
        Require all granted
        AllowOverride None
        Order allow,deny
        allow from all
    </Directory>

    ErrorLog /var/log/apache2/horizon_error.log
    LogLevel warn
    CustomLog /var/log/apache2/horizon_access.log combined
</VirtualHost>

WSGISocketPrefix /var/run/apache2

(42)apacheを再起動して、horizonを有効にする

$sudo service apache start
Glance

(43)Glanceの初期設定

  (43−1)Glance イメージを格納するディレクトリを作成

$mkdir -p /opt/stack/data/glance/images

     (43−2)Glance イメージのローカルキャッシュディレクトリを作成

$mkdir -p /opt/stack/data/glance/cache

  (43−3)Glance用のDBを作成

$mysql
>DROP DATABASE IF EXISTS glance 
>CREATE DATABASE glance CHARACTER SET utf8

  (43−4)DBのマイグレーション

$glance-manage db_sync

  (43−5)cache用のディレクトリの作成

$sudo mkdir -p /var/cache/glance/api
$sudo chown <実行ユーザ> /var/cache/glance/api
$sudo mkdir -p /var/cache/glance/registry
$sudo chown <実行ユーザ> /var/cache/glance/registry
Neutron

(44)Neutronの初期設定

  (44−1)設定ファイル格納ディレクトリの作成、ownerの変更

$sudo mkdir /etc/neutron
$sudo chown <実行ユーザ> /etc/neutron

  (44−2)設定ファイルのひな形のコピー

$cp /opt/stack/neutron/etc/neutron.conf /etc/neutron

  (44−3)設定ファイルを下記のように編集

neutron.conf

[DEFAULT]
verbose = True
debug = True
policy_file = /etc/neutron/policy.json
allow_overlapping_ips = True
auth_strategy = keystone
notify_nova_on_port_status_change = True
norify_nova_on_port_data_change = True
nova_url = http://<nova-api>:8774/v2
nova_admin_username = nova
nova_admin_password = <nova-password>
nova_admin_tenant_id = <nova-admin-tenant-id>
nova_admin_auth_url = http://<nova-amin-api>:35357/v2.0
state_path = /opt/stack/data/neutron
rpc_backend = neutron.openstack.common.rpc.impl_kombu
rabbit_hosts = <rabbit-ip>
rabbit_password = <rabbit-password>
lock_path = $state_path/lock
core_plugin = ml2
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin
[matchmaker_redis]
[matchmaker_ring]
[quotas]
[agent]
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
[keystone_authtoken]
auth_host = <keystone-ip>
auth_port = 35357
auth_protocol = http
admin_tenant_name = service
admin_user = neutron
admin_password = <neutron-pass>
signing_dir = /var/cache/neutron
[database]
[service_providers]
service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default

  (44−4)ml2プラグイン用の設定ファイルのひな形をコピー

$mkdir -p /etc/neutron/plugins/
$cp  /opt/stack/neutron/etc/neutron/plugins/ml2/ml2_conf.ini  /etc/neutron/plugins/

  (44−5)ml2_conf.iniを下記のように編集

ml2_conf.ini

[ml2]
mechanism_drivers=openvswitch,linuxbridge
type_drivers=local,flat,vlan,gre,vxlan
[ovs]
local_ip = <ip>
[database]
connection=mysql://<user>:<pass>@<ip>/neutron_ml2?charset=utf8
[ml2_type_flat]
[ml2_type_vlan]
[ml2_type_gre]
[ml2_type_vxlan]
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
[agent]
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf

  (44−6)rootwrap設定

    (44−6−1)mkdir -p -m 755 /etc/neutron/rootwrap.d

$mkdir -p -m 755 /etc/neutron/rootwrap.d

    (44−6−2)cp -pr /opt/stack/neutron/etc/neutron/rootwrap.d/* /etc/neutron/rootwrap.d/

$cp -pr /opt/stack/neutron/etc/neutron/rootwrap.d/* /etc/neutron/rootwrap.d/

    (44−6−3)sudo chown -R root:root /etc/neutron/rootwrap.d

$sudo chown -R root:root /etc/neutron/rootwrap.d

    (44−6−4)sudo chmod 644 /etc/neutron/rootwrap.d/*

$sudo chmod 644 /etc/neutron/rootwrp.d/*

    (44−6−5)rootwrap.confのコピー

$cp -p /opt/stack/neutron/etc/neutron/rootwrap.conf /etc/neutron

    (44−6−6)rootwrap.confを下記のように追記

rootwrap.conf

filters_path = /etc/cinder/rootwrap.conf

    (44−6−7)sudo chown root:root /etc/neutron/rootwrap.conf

$sudo chown root:root /etc/neutron/rootwrap.conf

      (44−6−8)sudo chmod 0644 /etc/neutron/rootwrap.conf

$sudo chmod 0644 /etc/neutron/rootwrap.conf

    (44−6−9)/etc/sudoers.d/neutron-rootwrapを下記内容で作成

neutron-rootwrap

<実行ユーザ> ALL=(root) NOPASSWD: /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf *

  (44−7)neutron-l2agentとneutron-serverの共通初期化処理

    (44−7−1)api-paste.ini , policy.jsonをコピー

$cp /opt/stack/neutron/etc/api-paste.ini /etc/neutron/api-paste.ini
$cp /opt/stack/neutron/etc/policy.json /etc/neutron/policy.json

  (44−8)neutron-l2agentの初期化処理

    (44−8−1)neutron-ovs-cleanupを実行

$neutron-ovs-cleanup

    (44−8−2)br-intブリッジの作成

$sudo ovs-vsctl --no-wait -- --may-exist add-br br-int
    #→--no-wait:vswitchd からの応答を待たない(switchedが起動していないときに使わないとエラーで落ちる)
    #→ --may-exist :同じ名前のbridgeがいても、新しく作る(初期化される)
$sudo ovs-vsctl --no-wait br-set-external-id br-int bridge-id br-int

  (44−9)neutron-dhcpagentの初期化処理

    (44−9−1)設定ファイルのコピー

$cp  /opt/stack/neutron/etc/dhcp_agent.ini  /etc/neutron/dhcp_agent.ini

    (44−9−2)dhcp_agent.iniを下記のように編集

[DEFAULT]
verbose = True
debug = True
use_namespaces = True
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
ovs_use_veth = False
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
dhcp_agent_manager = neutron.agent.dhcp_agent.DhcpAgentWithStateReport

  (44−10)neutronl3-agentの初期化処理

    (44−10−1)設定ファイルのコピー

$cp  /opt/stack/neutron/etc/l3_agent.ini  /etc/l3_agent.ini

    (44−10−2)l3_agent.iniを下記のように編集

[DEFAULT]
verbose = True
debug = True
use_namespaces = True
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
ovs_use_veth = False
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
external_network_bridge = br-ex
l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport

    (44−10−3)$neutron-ovs-cleanupを実行

    (44−10−4)br-exブリッジを作成

$sudo ovs-vsctl --no-wait --may-exist add-br br-ex
$sudo ovs-vsctl br-set-external-id br-ex bridge-id br-ex

       (44−10−5)br-exに割り当てられたIPを削除

$sudo ip addr flush dev br-ex

  (44−11)neutron-metaagentの初期化処理

    (44−11−1)設定ファイルコピー

$cp  /opt/stack/neutron/etc/metadata_agent.ini /etc/neutron/metadata_agent.ini

    (44−11−2)metadata_agent.iniの設定を下記のように変更する

[DEFAULT]
verbose = True
debug = True
nova_metadata_ip = <nova-ip>
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
auth_host = <keystone-ip>
auth_port = 35375
auth_protocol = http
admin_tenant_name = service
admin_user =  neutron
admin_password = <password>

    (44−11−3)cache用のディレクトリの作成

$sudo mkdir -p /var/cache/neutron

  (44−12)neutron-debug-command用の初期化処理

    (44−12−1)設定ファイルをコピー

$cp /opt/stack/neutron/etc/l3_agent.ini  /etc/neutron/debug.ini

    (44−12−2) 下記のように、設定ファイルを変更

debug.ini

[DEFAULT]
verbose = False
debug = False
use_namespaces = True
ovs_use_veth = False
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
external_network_bridge = br-ex
[agent]
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf

  (44−13)neutron用のDBの作成

$mysql
>DROP DATABASE IF EXISTS neutron
>CREATE DATABASE neutron CHARACTER SET utf8

  (44−14)DBのマイグレーション

$neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2_plugin.ini upgrade head

(45)neutron-dhcpagent用の初期化

  (45−1)NetworkManagerから実行されたdnsmasq以外のdnsmasqプロセスをkill

pidof NetworkManagerの出力がなにもなければ、「$sudo killall dnsmasq」

  (45−2)iptablesのエントリを削除(clean_iptables in lib/nova)

# Delete rules
$sudo iptables -S -v | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" | grep "\-A" |  sed "s/-A/-D/g" | awk '{print "sudo iptables",$0}' | bash

# Delete nat rules
$sudo iptables -S -v -t nat | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" |  grep "\-A" | sed "s/-A/-D/g" | awk '{print "sudo iptables -t nat",$0}' | bash

# Delete chains
$sudo iptables -S -v | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" | grep "\-N" |  sed "s/-N/-X/g" | awk '{print "sudo iptables",$0}' | bash

# Delete nat chains
$sudo iptables -S -v -t nat | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" |  grep "\-N" | sed "s/-N/-X/g" | awk '{print "sudo iptables -t nat",$0}' | bash

  (45−3)ホストOSのIPフォワーディングを有効にする

$sudo sysctl -w net.ipv4.ip_forward=1
Volume Service

(46)Cinderの初期設定

  (46−1)Cinder用のDBの作成

$mysql
>DROP DATABASE IF EXISTS cinder
>CREATE DATABASE cinder CHARACTER SET utf8

  (46−2)DBのマイグレーション

$cinder-manage db_sync

  (46−3)Cinder用ボリュームグループの作成

     (46−3−1)ボリュームグループのフィジカルボリュームにするための、イメージを作成

$truncate -s 20000 /opt/stack/data/cinder/stack-image-backing-file

     (46−3−2)ループバックでバイスとimageファイルの結びつけ

$sudo losetup -f  --show  /opt/stack/data/cinder/stack-image-backing-file

     (46−3−3)ボリュームグループの作成

$sudo vgcreate  stack-volume <ループバックデバイス(例:/dev/loop0)>

     (46−3−4)tgtで後で使用するディレクトリの作成

$sudo mkdir -p /opt/stack/data/cinder/volumes

  (46−4)iscsiターゲットを削除

$sudo tgtadm --op show --mode target #→iscsiターゲットの確認
$sudo tgt-admin --delete <tgt-id>   #→iscsiターゲットを削除

  (46−5)もし、論理ボリュームが残っていたら削除

  (46−6)キャッシュ用ディレクトリを作成

$sudo mkdir  /var/cache/cinder/
$sudo chown <実行ユーザ> /var/cache/cinder
Nova

(47)Novaの初期設定

  (47−1)Nova用のDBの作成

$mysql
>DROP DATABASE  IF EXISTS nova
>CREATE DATABASE CHARACTER SET latin1  #=>なぜlatin1?

  (47−2)DBのマイグレーション

$nova-manage db_sync

  (47−3)キャッシュ用のディレクトリの作成

$sudo mkdir -p  /var/cache/nova
$sudo chown <実行ユーザ>  /var/cache/nova

  (47−4)キーペアを保存するディレクトリの作成

$sudo mkdir -p /opt/stack/data/nova/keys
$sudo chown -R <実行ユーザ>  /opt/stack/data/nova

  ※Devstackだとこのあたりで、neutronを使うためにnovaの設定ファイルを編集する(novaのセキュリティグループの無効化とか)

Openstakコンポーネントの起動〜起動〜

Glance

(48)glance-registryの起動

$glance-registry  --config-file /etc/glance/glance-registry.conf

(49)glance-apiの起動

$glance-api  --config-file /etc/glance/glance-api.conf

(50)glanceにイメージの登録(ここは、なんでもいいのでイメージを登録)

  (50−1) tokenの取得

$keystone token-get

  (50−2)イメージの登録(イメージは適当にさがしてください)

$glance --os-auth-token <token> --os-image-url http://<ip>:9292 image-create --name "test" --is-public True --disk-format=qcow2  --copy-from "<imageのurl>"
Nova

(51)nova-apiの起動

$nova-api
Neuron

(52)neutron-serverの起動

$neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2_plugin.ini

(53)neutron-l2-agentの起動(neutron-openvswitch-agent)

$neutron-openvswitch-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2_plugin.ini

(54)neutron-dhcp-agentの起動

$neutron-dhcp-agent --config-file /etc/neutron/neutron.conf  --config-file /etc/neutron/dhcp_agent.ini

(55)neutron-l3-agentの起動

$neutron-l3-agent --config-file /etc/neutron/neutron.conf  --config-file /etc/neutron/l3_plugin.ini

(56)neutron-metadata-agentの起動

$neutron-metadata-agent  --config-file /etc/neutron/neutron.conf  --config-file /etc/neutron/metadata_agent.ini

(57)初期ネットワークの作成(demoテナントのネットワークとか)

  (57−1)デモテナントのプライベートネットワーク作成

$openstack project list #→demoテナントのidをメモ
$neutron net-create --tenant-id <tenant-id(demo)> "private"

  (57−2)デモテナントのプライベートサブネットの作成

$neutron subnet-create --tenant-id <tenant-id(demo)>  --ip_version 4 --gateway 192.168.0.1 --name "private-subnet" <net-id(57-1で作ったやつ)> "192.168.0.0/24"

  (57−3)デモテナントのルータの作成

$neutron router-create --tenant-id <tenant-id(demo)>

  (57−4)デモテナントのルータを"private-subnet"サブネットに接続

$neutron router-interface-add <router-id(57-3で作ったやつ)> <subnet-id(57-2で作ったやつ)>

  (57−5)外部ネットワークの作成

$neutron net-create "public"  --router:external=True

  (57−6)外部ネットワークのサブネットの作成

$neutron subnet-create --ip_version 4 --gateway 172.16.0.1 --name "public-subnet" <net-id(57-5で作ったやつ)> "172.16.0.0/24"  --enable_dhcp=False

  (57−7)デモテナントのルータを外部ネットワークにつなぐ

 $neutron router-gateway-set  <router-id(57-3で作ったやつ)> <net-id(57-7で作ったやつ)>

  (57−8)ホストのbr-exインターフェースに57-6のgatewayに指定したipアドレスを設定

 $sudo ip addr add  172.16.0.1/24 dev br-ex

  (57−9)br-exインターフェースをアップ

 $sudo ip link set br-ex up

  (57−10)デモテナントのprivateネットワークへのrouteをホストに追加

 $sudo route add -net 192.168.0.0/24 gw 172.16.0.1
Nova

(58)nova-computeの起動

$sg libvirtd nova-compute --config-file /etc/nova/nova.conf

  (59)nova-conductorの起動

$nova-conductor --config-file /etc/nova/nova.conf

(60)nova-schedulerの起動

$nova-scheduler --config-file /etc/nova/nova.conf

(61)nova-novncproxyの起動

$nova-novncproxy --config-file /etc/nova/nova.conf --web /opt/stack/noVNC

(62)nova-xvpvncproxyの起動

$nova-xvpvncproxy --config-file /etc/nova/nova.conf

(63)nova-consoleauthの起動

$nova-consoleauth  --config-file /etc/nova/nova.conf
Cinder

(64)/opt/stack/data/cinder/volumesのシンボリックリンクを/etc/tgt/stack.dに置く

$sudo ln -sf  /opt/stack/data/cinder/volumes  /etc/tgt/stack.d

(65)tgt用の設定ファイルを作成

$echo "include /etc/tgt/stack.d/*" | sudo tee -a /etc/tgt/targets.conf

(66)tgtサービスの再起動

$sudo service tgt restart

(67)tgtの設定

$sudo tgtadm --mode system --op update --name debug --value on

(68)cinder-apiの起動

$cinder-api --config-file /etc/cinder/cinder.conf

(69)cinder-schedulerの起動

$cinder-scheduler --config-file /etc/cinder/cinder.conf

(70)cinder-backupの起動

$cinder-backup --config-file /etc/cinder/cinder.conf

(71)cinder-volumeの起動

$cinder-volume --config-file  /etc/cinder/cinder.conf

おめでとうございます。ここまで無事たどりついたらOpenstackが動いているはずです。

Devstackはどんなことをしているのか

はじめに

OpenStack (2枚目) Advent Calendar 2014/12/15です。

あまり書慣れていないのですが、がんばります。

この前、DevStackのソースを読んで、Devstackがやっていることを手作業で再現してみるということをやってみたので、Devstackが大体どんなことをやっているのか?を5つのポイントにしてまとめてみました

また、付録としてdevstackに沿って手作業でインストールしたときの手順書を掲載します。興味ある方はご覧ください

Devstackのソースを読むことのすすめ

devstackを普段使っている方、使いたいと思ってる方はざっとでいいので、一度devstackのスクリプトを読むことをオススメします(特に初級〜中級技術者の人)理由としては、下記の点があげられます。

  1. openstackがどういう過程を踏んで、構築されるかが分かる
  2. 手作業でOpenstackをインストールできるようになる
  3. ./stack.shで失敗したときに、その原因の推測が容易にできるようになる
  4. シェルスクリプトに大分なれることができる

本題、Devstackが大体どんなことをしているのか

1. Openstackに必要なパッケージのインストール

 devstack/files/apts 配下に、各コンポーネントの名前(一部プロセス名)のファイルがあり、その中に、必要なパッケージファイルが羅列されています。  Devstackは、ENABLED_SERVICES で指定されているコンポーネントに必要なパッケージファイルを devstack/files/apts 配下のファイルより読み取り、apt-get等でインストールします

2. pipのインストールと、特定のライブラリをあらかじめインストール

 pipは、pythonのパッケージ関連システムです。Openstackはソースコードを取得して、pipでローカルインストールします。

pipのインストール

$curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
$sudo -E python get-pip.py

prettytableとhttplib2というライブラリは、バージョンの指定があるようなので、先にインストール

$sudo pip install "prettytable=0.7.2"
$sudo pip install "httplib2=0.8"

3. ここからが、肝心のOpenstackコンポーネントのインストール

keystoneとかをインストールする前に共通コンポーネントをインストールする必要がある。

その中でも、「requirements」「pbr」2つの共通コンポーネントは一番最初にインストールする。

3-1. openstack/requirementsコンポーネントのインストール

requirementsコンポーネントは、

各コンポーネントのrequirements.txtをチェックしrequirementsコンポーネントglobal-requirements.txtに定義されていないライブラリはないか?

各コンポーネントのrequirements.txtで定義されているライブラリのバージョンはglobal-requirements.txtより古くないか?

をチェックしてくれるもの。All in One構成を想定して各コンポーネントのライブラリ同士が悪さをしないようにするものらしい。(バージョンの違いとか)

特にインストールとかはせず、checkoutするだけ

$ git clone git://git.openstack.org/openstack/requirements.git stable/juno
3-2. openstack-dev/pbrコンポーネントのインストール

pbrコンポーネントは、

インストールオプションをsetup.cfgに書いて、setuptoolsでインストールするときにsetupメソッドをフックしてその、オプションを適用してくれるらしい。

インストールは下記の手順

$git clone git://git.openstack.org/openstack-dev/pbr.git

$cd /opt/stack/requirements

$./update.py /opt/stack/pbr  #=>requirements.txtのチェックをしてくれる

$sudo pip install /opt/stack/pbr
3-3. その他のコンポーネントのインストール

 その他の共通コンポーネント(openstack/oslo.config , openstack/oslo.messaging など)やkeystone,novaなどのコンポーネントのインストール

どのコンポーネントも手順は、3-2と同じ

  1. gitでcheckout

  2. update.py で requirements.txtをチェック(openstack/requirements)

  3. pip install

4. 設定ファイルの編集、起動

 最後に、各コンポーネントに関する設定ファイルの編集。

多分devstackのスクリプトを読むのが一番めんどくさいのがここ。というのも、devstackでは結構いろんな設定をすることができてそれを柔軟に対応するために、

~~~~が設定されてたら、AとBとCという設定ファイルに*******を追加して、Dという設定ファイルを追加で作成する

みたいなことがたくさん書かれているためである

5. 各クライアントツールを使って初期データの投入

5-1. keystone
  1. 各テナントの作成「admin,demo,service,invisible_to_admin」
  2. 各ユーザの作成「admin,demo」「nova,glance,neutron,cinder」
  3. 各ロールの作成「admin,Member,anotherrole,ResellerAdmin,service」
  4. 各ユーザとテナントに対してロールを設定する(下記に表を示す)
  5. サービスカタログとエンドポイントの登録

ユーザとロールの対応表(参考)

ユーザ テナント ロール
admin admin admin
admin demo admin
demo demo Member,anotherrole
demo invisible_to_admin Member
nova service admin
glance service service
neutron service admin
cinder service admin

→各コンポーネントのユーザは、serviceテナントに所属させる必要がある

5-2. glance
  1. cirrosイメージの登録
5-3. neutron
  1. デモテナント用のプライベートネットワーク、サブネットの作成(dhcp有効)
  2. 外部ネットワーク、サブネットの作成(dhcp無効)
  3. デモテナント用のルータの作成
  4. デモテナント用のルータのインターフェスの作成(プライベートネットワーク)
  5. デモテナント用のルータにgatewayの設定(外部ネットワーク)

→外部ネットワークでは、dhcpが無効になっていることに注意。つまりadminテナントでインスタンスを作って外部ネットワークに直接接続しても、ipが降ってこないのでssh等でアクセスすることができない。

→あと、devstackではデモテナントのプライベートネットワークにホスト(OpenstackをインストールしたPC)上からアクセスできるように、 下記の二つを実施している

  1. br-exインターフェースにIPアドレスを振って(ip addr add dev br-ex)
  2. routeを追加してる(ip route add -net gw <デモテナントのgw側のIFのアドレス>)

6.インストールは終了、あとは遊ぶだけ!

まとめ

今回、devstackがどんなことをしているのか5つのポイントにしてまとめてみましたが、ここでは、設定ファイルの編集については具体的には触れていません。

というのもopenstackの使う機能によって、作る設定ファイル、内容がまったく違うからです。devstackでは、それらに対応するためコードが複雑化しているように見えます。私はこれらの背景より、devstackでどのように設定ファイルを編集しているかを知ることはあまり意味がないと考えています。なのでここでは4ステップ目に「設定ファイルの編集、起動」とだけ記しています。

この後に、Devstackが行っていることを手作業で再現したときの手順メモを付録(別日記)として載せますので、もう少しdevstackがどんなことをしているかを知りたい方、手作業でインストールしてみたい方は参考にしてみてください。