chefとcapistrano(Webistrano)っぽいのをPythonで(構築のみ)

Fabric+Webistranoっぽいのの構築したメモです。
rubyに入門しませんでしたm(_ _)m!!使用は、Pythonでいきたいなぁーっと。
pythonとshellの方が自分に実績があって、手に馴染むだけです。chefとcapistranoの方が、
現状では情報が多いので、誰得?になってしまうんだろうけど、自分用の記録。長編。。。

前は、phpでmakuoさん使ったデプロイツール作って使ってましたが(遠い目)今回は自前は辞め、
pythonで、chefっぽいものと、capistranoっぽいものを構築することが目的です。(capistranoはWebistranoを目標)

構築した環境は、Scientific Linux 6.4 x86_64です。
(インストール時のオプションは、Basic Serverで、カスタマイズで開発ツールを追加しています。)

■Fabricのインストール
Fabricはすでに有名ですね。FabricとCuisineの組み合わせが有名でchefの変わりとします。次の資料がまとまっています。


Facebookでは、chefがデプロイのようですが、instagramでは、デプロイはFabricみたいなので、
いいじゃん!!って言うようにしましょうw まぁ標準でPythonは入っていますので、導入は楽ですね。
rubyが好きな人や、そちらが手に馴染む人はそっちを選んだ方が賢いかもしれません。
というか、何度やっても同じ結果を求めるなら、chefのようなものを求めるべきな気もします。

今後、運用やら、Fabric周りの内容も記載していきたいと思います。

それでは、導入手順。SL6.4では、上記インストールオプションだと、最初から、
python-setuptools(easy_install)は導入されていました。virtualenvとかは今回切らずに、
system pythonを使うことにします。とりあえず、devel系の必要なパッケージを導入と、
なにはともあれまず、pipをインストールします。

yum install python-devel
yum install openssl-devel
easy_install pip

で、このあと、さぁ pip でFabricをインストールだぁー!!っと意気込むのですが、いきなりハマりまして。。
そのまま、pipでインストールしてFabric起動すると、こんなエラーがでちゃいます。

pip install Fabric
Downloading/unpacking Fabric
  Running setup.py egg_info for package Fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
Requirement already satisfied (use --upgrade to upgrade): paramiko>=1.10.0 in /usr/lib/python2.6/site-packages (from Fabric)
Requirement already satisfied (use --upgrade to upgrade): pycrypto>=2.1,!=2.4 in /usr/lib64/python2.6/site-packages (from paramiko>=1.10.0->Fabric)
Installing collected packages: Fabric
  Running setup.py install for Fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
    Installing fab script to /usr/bin
Successfully installed Fabric
Cleaning up...

でfabコマンド叩くと、エラーがつらずら〜ってでます。ドキュメント読むと、
Fabric1.6の導入では、PyCryptoが2.1以上を求められます。

pipで抜いてインストールし直してもなおらなくて、なんでかなぁーとかなやんでたら、
パッケージで、python-cryptoパッケージが実は入っていました。依存解消してくれないんですよね。。。

yum info python-crypto

Available Packages
Name        : python-crypto
Arch        : x86_64
Version     : 2.0.1
Release     : 22.el6
Size        : 157 k
Repo        : sl
Summary     : Cryptography library for Python
URL         : http://www.amk.ca/python/code/crypto.html
License     : Public Domain
Description : Python-crypto is a collection of both secure hash functions (such as MD5 and
            : SHA), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.).

あぁー。。。気づくまでに時間かかりました。。。
なので、先にremoveしましょう。そして、依存解決してくれるだろうけど、PyCryptoをpipで先に導入しておきます。
(関連っぽい、paramikoもuninstallして入れなおしました)

yum remove python-crypto
pip uninstall paramiko
pip install pycrypto
pip install Fabric

これで、導入されました。

fab --version
Fabric 1.6.0
Paramiko 1.10.0

さて、これでchefっぽいことはできるので、次のwebistranoを構築に移ります。
いろいろ探したところ、これが唯一動いてしかも、良さげでした。

使用ソフトはauroraです。

Aurora is a web interface for deploy tool fabric created for remote deploying and "console scared" boys. Inspired by Webistrano.

とかΣd(゚∀゚d)イカス! ってなことで、Djangoで作られてますね。導入は簡単でした。
基本はREADME通りです。(vitualenvはしてないから無視)

git clone https://github.com/ak3n/aurora.git
cd aurora

して、README記載どおり、fab local_setupをします。途中、初回ログインようのアカウントを聞いてくるので、登録します。

fab local_setup
[localhost] local: pip install -r requirements.txt
Downloading/unpacking Django==1.4.1 (from -r requirements.txt (line 1))
  Downloading Django-1.4.1.tar.gz (7.7MB): 7.7MB downloaded
  Running setup.py egg_info for package Django
Downloading/unpacking Fabric==1.5.3 (from -r requirements.txt (line 2))
  Running setup.py egg_info for package Fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
  Requested Fabric==1.5.3 (from -r requirements.txt (line 2)), but installing version 1.6.0
Downloading/unpacking South==0.7.6 (from -r requirements.txt (line 3))
  Downloading South-0.7.6.tar.gz (91kB): 91kB downloaded
  Running setup.py egg_info for package South
Downloading/unpacking argparse==1.2.1 (from -r requirements.txt (line 4))
  Downloading argparse-1.2.1.tar.gz (69kB): 69kB downloaded
  Running setup.py egg_info for package argparse
    warning: no previously-included files matching '*.pyc' found anywhere in distribution
    warning: no previously-included files matching '*.pyo' found anywhere in distribution
    warning: no previously-included files matching '*.orig' found anywhere in distribution
    warning: no previously-included files matching '*.rej' found anywhere in distribution
    no previously-included directories found matching 'doc/_build'
    no previously-included directories found matching 'env24'
    no previously-included directories found matching 'env25'
    no previously-included directories found matching 'env26'
    no previously-included directories found matching 'env27'
Downloading/unpacking django-annoying==0.7.6 (from -r requirements.txt (line 5))
  Downloading django-annoying-0.7.6.tar.gz
  Running setup.py egg_info for package django-annoying
Downloading/unpacking django-debug-toolbar==0.9.4 (from -r requirements.txt (line 6))
  Downloading django-debug-toolbar-0.9.4.tar.gz (150kB): 150kB downloaded
  Running setup.py egg_info for package django-debug-toolbar
    no previously-included directories found matching 'example'
Downloading/unpacking wsgiref==0.1.2 (from -r requirements.txt (line 7))
  Downloading wsgiref-0.1.2.zip
  Running setup.py egg_info for package wsgiref
Downloading/unpacking pexpect==2.4 (from -r requirements.txt (line 8))
  Downloading pexpect-2.4.tar.gz (113kB): 113kB downloaded
  Running setup.py egg_info for package pexpect
Downloading/unpacking gunicorn==0.17.2 (from -r requirements.txt (line 9))
  Downloading gunicorn-0.17.2.tar.gz (360kB): 360kB downloaded
  Running setup.py egg_info for package gunicorn
Requirement already satisfied (use --upgrade to upgrade): paramiko>=1.10.0 in /usr/lib/python2.6/site-packages (from Fabric==1.5.3->-r requirements.txt (line 2))
Requirement already satisfied (use --upgrade to upgrade): pycrypto>=2.1,!=2.4 in /usr/lib64/python2.6/site-packages (from paramiko>=1.10.0->Fabric==1.5.3->-r requirements.txt (line 2))
Installing collected packages: Django, Fabric, South, argparse, django-annoying, django-debug-toolbar, wsgiref, pexpect, gunicorn
  Running setup.py install for Django
    changing mode of build/scripts-2.6/django-admin.py from 644 to 755
    changing mode of /usr/bin/django-admin.py to 755
  Found existing installation: Fabric 1.6.0
    Uninstalling Fabric:
      Successfully uninstalled Fabric
  Running setup.py install for Fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
    Installing fab script to /usr/bin
  Running setup.py install for South
  Running setup.py install for argparse
    warning: no previously-included files matching '*.pyc' found anywhere in distribution
    warning: no previously-included files matching '*.pyo' found anywhere in distribution
    warning: no previously-included files matching '*.orig' found anywhere in distribution
    warning: no previously-included files matching '*.rej' found anywhere in distribution
    no previously-included directories found matching 'doc/_build'
    no previously-included directories found matching 'env24'
    no previously-included directories found matching 'env25'
    no previously-included directories found matching 'env26'
    no previously-included directories found matching 'env27'
  Running setup.py install for django-annoying
  Running setup.py install for django-debug-toolbar
    no previously-included directories found matching 'example'
  Running setup.py install for wsgiref
  Running setup.py install for pexpect
  Running setup.py install for gunicorn
    Installing gunicorn_paster script to /usr/bin
    Installing gunicorn script to /usr/bin
    Installing gunicorn_django script to /usr/bin
Successfully installed Django Fabric South argparse django-annoying django-debug-toolbar wsgiref pexpect gunicorn
Cleaning up...
[localhost] local: python manage.py syncdb
Syncing...
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
Creating table south_migrationhistory

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'root'): admin # 環境に合わせて設定ください。
E-mail address: admin@localhost # 環境に合わせて設定ください。
Password: 
Password (again): 
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

Synced:
 > django.contrib.auth
 > django.contrib.contenttypes
 > django.contrib.sessions
 > django.contrib.sites
 > django.contrib.messages
 > django.contrib.staticfiles
 > django.contrib.admin
 > south

Not synced (use migrations):
 - aurora.cruiser
(use ./manage.py migrate to migrate these)
[localhost] local: python manage.py migrate
Running migrations for cruiser:
 - Migrating forwards to 0005_auto__del_field_stage_host__add_field_stage_hosts.
 > cruiser:0001_initial
 > cruiser:0002_auto__add_field_deploy_branch
 > cruiser:0003_auto__chg_field_deploy_status__chg_field_deploy_finished_at__chg_field
 > cruiser:0004_auto__add_field_deploy_comment
 > cruiser:0005_auto__del_field_stage_host__add_field_stage_hosts
 - Loading initial data for cruiser.
Installed 0 object(s) from 0 fixture(s)
[localhost] local: touch aurora/local_settings.py
[localhost] local: echo "DEBUG = True" > aurora/local_settings.py

Done.

これで、

python manage.py run_gunicorn

ってやると起動しますが、ローカルでしか動かない(0.0.0.0とかどうやって設定したらいいかわからなかったので)
とりあえず、Apacheのproxyで受けて後ろに流すだけという形で今回対応。

yum install httpd

んで、confの設定。includeしてvituralconfで対応します。セキュリティ設定とかその他、各自で。。。
(とりあえず、動かすこと目標。iptablesselinuxも止めちゃった。(*ノω・*)テヘ)

vim /etc/httpd/conf/httpd.conf

# 一番最後の行に追加
include /etc/httpd/conf/virtualhost_aurora.conf
vim /etc/httpd/conf/virtualhost_aurora.conf

<VirtualHost *:80>
        ServerName example.com
        ServerAlias example.com

        <Proxy *>
          Order allow,deny
          Allow from all
        </Proxy>

        #Directive to properly generate url (clone url) for pylons
        ProxyPreserveHost On

        ProxyPass / http://127.0.0.1:8000/
        ProxyPassReverse / http://127.0.0.1:8000/

        #to enable https use line below
        #SetEnvIf X-Url-Scheme https HTTPS=1

</VirtualHost>

これで、httpd起動して、python manage.py run_gunicorn とかするとWEBサイトは表示されますが、
デーモン化したいよねってことで、init scriptを作ります。
これ参考にちょっと変えただけ。
なんで2ポート立てないといけないかとわかんなかったんで、Pythonな方教えてください。m(_ _)m

PROJECTLOC等、各環境PATHはご自身の環境に合わせてください。

vim /etc/rc.d/init.d/gunicorn

#!/bin/sh
#
# gunicorn        Startup script for the gunicorn Server
#
# chkconfig: - 85 15
# description: The python Django gunicorn Server is an efficient and extensible  \
#              server implementing.

# processname: python
# config: /
# config: /
# pidfile: /$PROJECTLOC/$SERVER_PORT.pid
 
# http://nathanvangheem.com/news/gunicorn-startup-script-for-django
# Place the script in the file - /etc/init.d/gunicorn or whatever you'd like to call it
# make it executable - chmod +x /etc/init.d/gunicorn
# And finally, wire it up - update-rc.d gunicorn defaults
 
ADDRESS='127.0.0.1'
PYTHON="/usr/bin/python"
GUNICORN="/usr/bin/gunicorn_django"
PROJECTLOC="/home/aurora"
MANAGELOC="$PROJECTLOC/manage.py"
DEFAULT_ARGS="--workers=3 --daemon --bind=$ADDRESS:"
BASE_CMD="$GUNICORN $DEFAULT_ARGS"
 
SERVER1_PORT='8200'
SERVER1_PID="$PROJECTLOC/$SERVER1_PORT.pid"
SERVER2_PORT='8000'
SERVER2_PID="$PROJECTLOC/$SERVER2_PORT.pid"
 
start_server () {
  if [ -f $1 ]; then
    #pid exists, check if running
    if [ "$(ps -p `cat $1` | wc -l)" -gt 1 ]; then
       echo "Server already running on ${ADDRESS}:${2}"
       return
    fi
  fi
  cd $PROJECTLOC
  echo "starting ${ADDRESS}:${2}"
  $BASE_CMD$2 --pid=$1
}
 
stop_server (){
  if [ -f $1 ] && [ "$(ps -p `cat $1` | wc -l)" -gt 1 ]; then
    echo "stopping server ${ADDRESS}:${2}"
    kill -9 `cat $1`
    rm $1
  else 
    if [ -f $1 ]; then
      echo "server ${ADDRESS}:${2} not running"
    else
      echo "No pid file found for server ${ADDRESS}:${2}"
    fi
  fi
}
 
case "$1" in
'start')
  start_server $SERVER1_PID $SERVER1_PORT 
  start_server $SERVER2_PID $SERVER2_PORT
  ;;
'stop')
  stop_server $SERVER1_PID $SERVER1_PORT
  stop_server $SERVER2_PID $SERVER2_PORT
  ;;
'restart')
  stop_server $SERVER1_PID $SERVER1_PORT
  sleep 2
  start_server $SERVER1_PID $SERVER1_PORT
  sleep 2
  stop_server $SERVER2_PID $SERVER2_PORT
  sleep 2
  start_server $SERVER2_PID $SERVER2_PORT
  ;;
*)
  echo "Usage: $0 { start | stop | restart }"
  ;;
esac
 
exit 0

あとは、chkconfig追加したら、OKっと。。。

chmod 755 /etc/init.d/gunicorn
chkconfig gunicorn on
chkconfig httpd on

/etc/init.d/gunicorn restart
/etc/init.d/httpd restart

とかで、起動、再起動とかできるようになりました。ちなみに、auroraの画面はこんな感じです。
auroraが動くのは簡単に確認してますが、Fabric連携とかまだです。。。
ホントに導入しただけの状態ですんであしからず。。。m(_ _)m

■ログイン画面

■ログイン後

■プロジェクト追加

■ステージ追加

■タスク追加

■管理画面