2015年7月27日月曜日

Djangoでajaxを利用する方法

目的:Djangoでajaxを利用したい時にすぐ参照できるように、必要な情報をコンパクトにまとめておく。
対象読者:Djangoユーザー
概要:DjangoにはCSRF対策が入っている関係上、ajaxを利用するためには以下のような作業が必要です。

動作サンプル:https://whiteblack-cat.info/ja-jp/ajax_sample/
ソースコード:https://github.com/ccat/django_ajax_sample



1. 背景(またはどうしてajaxを利用したいのにできないのか)

Djangoには入力フォームの生成と入力データの取得を補助する強力な仕組みが存在するため、 ちょっとしたアプリを作成する分には何の苦労もなくPOSTでデータを送信することができます。 しかし、JavascriptでPOST送信を行おうとすると、途端に403 Forbiddenで悩まされることになります。

これは、DjangoがCSRF対策が デフォルトで有効になっているためです。 CSRF対策をOFFにすることも可能ですが、セキュリティ上の脆弱性が出来てしまうため、リスクを十分に把握した上でなければお勧めできません。 そこで、CSRF対策をONにしたままajaxを利用する方法を記載します。
なお、本内容はhttps://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax の内容を、より具体的に整理したものです。
Django Webアプリケーション一式のサンプルコードは以下からダウンロードできます。
https://github.com/ccat/django_ajax_sample
テンプレートとurl、viewがセットになっており、そのままDjangoプロジェクトに組み込めば動作をテストできます。
また、本サンプルコードは下記で動作しています。
https://whiteblack-cat.info/ja-jp/ajax_sample/

2. 事前作業(ajaxを利用するために1度行えばよい作業)

まず、以下のコードをstaticかどこかに保存してください。
こちらからダウンロードするのが簡単です。

//Cite : https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
            // Send the token to same-origin, relative URLs only.
            // Send the token only if the method warrants CSRF protection
            // Using the CSRFToken value acquired earlier
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

次に、ajaxを利用するページのテンプレートに、下記コードを埋め込んでください。 なお、1行目で分かる通り、本内容はjqueryを利用することを前提としています。 また、2行目は上記のスクリプトを/static/js/配下のdjangoajax.jsと言う名称で保存したと仮定しています。別の場所、名称で保存した場合は変更してください。

<script type="text/javascript" charset="UTF-8" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript" charset="UTF-8" src="/static/js/djangoajax.js"></script>

この2つを行えば事前作業は終了です。

3. ajaxの使い方(ajaxを利用するために毎回必要な作業)

以下のサンプルコードのように、jqueryのpostとコールバックを利用して、普段通りajaxのコードを作成してください。

<script type="text/javascript">
function callback(data, status) {
  $("#echoResult").text("status:"+status+" data:"+data);
}

function sends() {
  $.post('/ajax_sample/input/',{"echo": $("#echo").val()},callback,"html");
}
</script>

<form action="#" method="post">
  {% csrf_token %}
  <input type="text" name="echo" id="echo" />
  <input type="button" value="submit" onclick="sends()" />
</form>

4. 仕組み(または如何にしてajaxを利用できるようにしているのか)

CSRF対策では、ページが表示されるたびにランダムな文字列(CSRF Token)を生成し、それをPOSTに含めることで 「ページを表示した人」と「POSTを送信してきた人」を識別しています。 jqueryデフォルトのpost関数ではCSRF Tokenを送信しないため、そこでDjangoがエラーを出力します。

そこで、djanoajax.jsではCSRF TokenをCookieから読み込み、jqueryのpost関数が呼び出された時に、 CSRF TokenをPOSTのデータに含めるように変更を行っています。

2015年5月6日水曜日

Negoni, gin gojiの簡易比較

Webフレームワークを作ってみたいと思いつつ、しっかり作る時間もないので、既存の物をまとめてセットにしたテンプレート的なものをまず作成し、必要に応じてミドルウェアの自作や置き換えを考えることにしました。

まず、URLのディスパッチや実際のWebページを表示する機能を提供するフレームワークについて調べました。
大物としてはrevel等が存在するのですが、今後入れ替え等を行う可能性を考えると、小機能なものを利用した方が良いと考え、候補から外すことにしました。

その結果、Negroni、Gin、Gojiの3つが有望そうだと感じたのですが、今一良い比較が無かったので、簡単な比較を行いました。なお、2015/05/06時点の情報です。

基礎情報

名称 Negroni Goji Gin
ライセンス MIT MIT MIT
コントリビューター 23人 14人 55人
Watch 141人 115人 175人
Star 2441人 2306人 2769人
タイプ Web Library Web Framework Web Framework
簡易説明 net/httpのHandlerの前後にミドルウェアを実行する機能を追加することで、機能拡張を行うためのライブラリ。 基本的にそれ以外の機能はほとんど存在せず、必要なミドルウェアを別途探してきてnegroniと共に導入することになる。 構造が簡単なので、net/httpに対応しているミドルウェアなら簡単に併用できる点が強み。 net/http準拠のWebフレームワークで、URLディスパッチャー、ミドルウェア、Context機能等の基本的な機能を持っている。高速なことが売り。 net/httpとは異なるWebフレームワークで、URLディスパッチャー、ミドルウェア等の基本機能以外にも機能を持っている。高速なことと、企業が利用していることが売り。

と言うことで、色々なミドルウェアを組み合わせる、接着剤のような機能を求めるならNegroni、そうでなければGojiかGinのどちらかでしょうか。
Gojiの場合、net/http準拠な分、他のミドルウェアとも相性が良さそうです。 Ginの場合、開発体制がGojiに比べると潤沢なので、Gin自身で一つのエコシステムを作れるかもしれません。Watch数やStar数を見ても、Gojiより人気なようです。

2015年4月26日日曜日

Titanium Studioでのグローバル関数/変数と画面サイズに応じたTSSファイルの調整

Titanium Studioでalloyを利用する場合、app/alloy.jsにグローバル関数/変数を設定することができます。

//app/alloy.js

//Global Functions
Alloy.Globals.closeWindow = function(windowName) {
    if(windowName in windowList){
        windowList[windowName].close();
        windowList[windowName] = null;
        delete windowList[windowName];
    }
};


//Gloval Variables
Alloy.CFG.messageFontSize = 20;
Alloy.CFG.buttonFontSize = 25;

上記のように設定し、他のファイルで普通にAlloy.Globals.closeWindow(win)等のように呼び出せば利用できます。
また、tssファイル内で計算は行えませんが、alloy.jsファイル内で設定した値は利用することができます。
そのため、下記のように画面サイズに応じて設定する値を変更すれば、1つのtssファイルで複数の画像サイズに対応できます。

//app/alloy.js

//Gloval Variables

Alloy.CFG.messageFontSize = 20;
Alloy.CFG.buttonFontSize = 25;

if(Ti.Android) {
    Ti.API.info(Ti.Platform.displayCaps.dpi);
    switch(Ti.Platform.displayCaps.dpi) {
        case 120:
            Alloy.CFG.messageFontSize = 18;
            Alloy.CFG.buttonFontSize = 20;
            break;
        case 160:
            Alloy.CFG.messageFontSize = 18;
            Alloy.CFG.buttonFontSize = 20;
            break;
        case 240:
            Alloy.CFG.messageFontSize = 18;
            Alloy.CFG.buttonFontSize = 20;
            break;
        case 320:
            //Default
            break;
     case 480:
            break;
    }
}

2015年4月12日日曜日

Titanium StudioでHTTPClientを利用

Titanium StudioでHTTPClientを作成する方法に関するメモです。
生成時にまとめて引数を指定する方法もありますが、私はだいたい生成した後に設定を入れています。

var client = Titanium.Network.createHTTPClient();
client.open('POST',"http://example.com/"); //POST or GET
client.onload = function(){
    json = JSON.parse(this.responseText);
    Ti.API.info(this.responseText);
    client.onload=null;
    client.onerror=null;
    client=null;
};
client.onerror = function(error){
    Ti.API.info(error.status);
    client.onload=null;
    client.onerror=null;
    client=null;
};
var params = {data : "test data"}; 
client.send(params);

まず「Titanium.Network.createHTTPClient」でHTTPClientを生成した後、「open」でアクセスするURLとメソッド(普通はGETかPOST)を指定します。
「onload」と「onerror」はアクセス成功時と失敗時に実行する関数を指定しています。 「onload」では「this.responseText」でアクセスしたURLの中身にアクセスできます。
また、どちらも最後にclient.onload、client.onerror、clientにnullを代入しています。これは、こうしないとメモリが解放されず、メモリリークを起こすと言う話を聞いたので、お呪いとして入れてあります。正確な検証は行っていません。
最後に、POSTの場合はPOSTで送信するデータを生成して、「send」で送信しています。

2015年4月10日金曜日

Titanium StudioのAction Bar

http://qiita.com/s4shiki/items/a1006fdd38fba29cd8d3でAction Barの消し方について2種類記載されている。

1つは「win.activity.actionBar.hide();」を利用する方法で、もう1つはカスタムテーマを利用する方法なのだが、「win.activity.actionBar.hide();」を利用する方法では画面を開いた瞬間はAction Barが表示されてしまうので、カスタムテーマを利用した方が良いようだ。

2015年3月16日月曜日

2015年3月10日火曜日

django-mptt (0.6.x) README.rst

Djangoでツリー構造を作る時に便利なdjango-mpttのreadme.rstの和訳です。 django-mpttは便利なのですが、日本語の資料が少なそうなので和訳しました。 なお、日本語として読みやすくするために、言い回しや文のつなぎの変更や省略を行っています。気になる方は原文を確認してください。
原文はこちら
他のドキュメントもそのうち和訳するかもしれません。

django-mptt

djangoモデルに修正された先行順走査(MPTT)を実装し、モデルインスタンスのツリーとして動作するユーティリティです。

プロジェクトホーム: http://github.com/django-mptt/django-mptt/
ドキュメント: http://django-mptt.github.io/django-mptt/
ディスカッショングループ: http://groups.google.com/group/django-mptt-dev

修正された先行順走査(MPTT)とは何か?

MPTTとは、階層的なデータをデータベースに保存する手法です。 検索処理を効率化することを目的としています。

効率化のトレードオフとして、要素の追加や移動がより複雑になっており、ツリー構造を保つには追加の作業が必要です。

MPTTについて、どう動作するか詳細を理解できるいくつかの記事を示しておきます。

SQLの中のツリー (Trees in SQL)

データベースに階層構造のデータを保存する (Storing Hierarchical Data in a Database)

MySQLの中の階層的なデータを管理する(Managing Hierarchical Data in MySQL)

django-mpttとは何か?

django-mpttは、簡単にMPTTをあなたのdjangoモデルで使えるようにする、再利用可能なdjangoアプリケーションです。 データベースのテーブルをツリー構造として管理し、モデルインスタンスのツリーを操作するツールを提供します。

必要要件

Python 2.6以上 (実験的なサポート:python 3.2以上)
Django 1.4.2以上

特徴

  • モデルの簡単な登録 - ツリー構造に必要なフィールドを自動的に追加します。
  • モデルインスタンスを作成・削除したり、親を変更したりすると、自動的にツリー構造を更新します。
  • あなたが選択した単一(もしくは複数)のフィールドで、ツリーの各レベルを自動的に整列させます
  • 登録されたモデルに対して、次のような新しいモデルメソッドを追加します。
    • 木の中の位置を変更
    • 祖先、兄弟、子の検索
    • 子孫の数を数える
    • その他の木に関する操作
  • 登録されたモデルに対して TreeManagerが追加され、以下のメソッドを提供します。
    • 木周辺、もしくは別の木へのノードの移動
    • 木のどこかへノードを挿入
    • 木のMPTTフィールドの再生成(djangoの外側でアップデートを行った際に利用)
  • ツリーモデル用のFormフィールド
  • ツリーモデル用のユーティリティ機能
  • ツリーを描画するためのテンプレートタグとフィルター

2015年3月8日日曜日

Pi Digit Generation Protocolの実装

go言語について、どんな感じかちょっと知りたかったこともあり、RFCの3091で定義されている、パイ(円周率)の値を延々と流し続けるサービス(Pi Digit Generation Protocol)を実装してみました。

プログラム:pidigitgen

なお、円周率の値はhttp://pi2.cc.u-tokyo.ac.jp/index.htmlからいただきました。

TCPで、www.whiteblack-cat.infoの31415ポートにアクセスすると、円周率の小数点以下の数字が延々と流れてきます。

UDPで、www.whiteblack-cat.infoの31415ポートに整数を投げると、リクエストされた桁数と小数点以下でその桁の数字を返してきます。例えば、"2"とリクエストを送ると、"2:4"(3.1415の4)が返ってきます。

2015年3月2日月曜日

Django-MPTT(0.6.x) のインストール

こちら(http://django-mptt.github.io/django-mptt/install.html)の和訳です。

Official releases

Official releaseはPyPIで利用可能です。

.zipの配布ファイルをダウンロードし、解凍してください。その中にsetup.pyと言うスクリプトが存在します。次のコマンドを入力してください。

python setup.py install
パッケージが自動的にインストールされます。

開発バージョン

別の方法として、gitから最新のソースコードを取得することもできます。

git clone git://github.com/django-mptt/django-mptt.git django-mptt

結果のフォルダをPYTHONPATHに追加するか、PYTHONPATHが通っているディレクトリ(例:Pythonのsite-packagesディレクトリ)にmpttディレクトリへのリンクを作成します。

PYTHONPATでアプリケーションが利用可能になっているか、Pythonインタプリターを起動して下記のコマンドを実行することで確認できます。

>>> import mptt
>>> mptt.VERSION
(0, 5, '+dev')
コピーしたソースコードをアップデートしたい場合、git pullコマンドをdjango-mpttディレクトリ内で実行してください。

注意:開発バージョンにはリリースバージョンには含まれていないようなバグや後方互換性の無い変更が含まれていることがあります。もしmasterブランチを利用している場合、ソースコードのアップデートを行う前に、コミット履歴をよく確認してください。

2015年3月1日日曜日

Titanium Studioでandroidのmenuを動的に変更する

Titanium Studioでアプリケーションを作成していると、ログイン/ログアウトボタンのように、動的にメニューを変更したくなる時があります。 そこで、android用のmenuを動的に変更する方法について、メモを作成しました。 なお、サンプルプロジェクトを以下に保存してあります。必要な方はご利用ください。
https://github.com/ccat/dynamic_menu

まず、メニューは動的に生成することもできますが、今回は始めにAlloyで生成した後、表示・非表示を切り替えることで動的に見た目を変更することにしました。viewのソースコードは下記の通りです。

<Alloy>
  <Window id="index" class="container">
    <Menu platform="android">
      <MenuItem id="menu1" itemId="1" title="Menu1" onClick="menu1func"  />
      <MenuItem id="menu2" itemId="2" title="Menu2" onClick="menu2func" />
    </Menu>
    <Label id="label" >Hello, World</Label>
  </Window>
</Alloy>

真ん中に存在する2つのMenuItemが、今回動的に見た目を切り替えるメニューです。Menu1を選択するとMenu1が非表示になってMenu2が表示され、Menu2を選択するとMenu2が非表示になってMenu1が表示されるようにします。
controllerからはitemIdで操作するため、忘れずにitemIdを設定するようにしてください。また、この時itemIdには整数を指定するようにしてください。整数を指定しない場合、以下のようなエラーが発生します。

[ERROR] :  TiApplication: (main) [27564,27843] Sending event: exception on thread: main msg:java.lang.NumberFormatException: Invalid int: "a1"; Titanium 3.5.0,2015/01/12 15:33,0014f83 
[ERROR] :  TiApplication: java.lang.NumberFormatException: Invalid int: "a1"

次に、controllerは下記のように記載します。


var menu1 = null;
var menu2 = null;
var menu1show=true;

function menu1func(e){
  menu1show=false;
  menuChange();
}

function menu2func(e){
  menu1show=true;
  menuChange();
}

function menuChange(){
  if(menu1!=null){
    menu1.setVisible(menu1show);
  }
  if(menu2!=null){
    menu2.setVisible(!menu1show);
  }
}

var activity=$.index.activity;
activity.onPrepareOptionsMenu = function(e) {
  var menu = e.menu;
  menu1 = menu.findItem("1");
  menu2 = menu.findItem("2");
  menuChange();
};


$.index.open();

まず「activity.onPrepareOptionsMenu」でメニューの各アイテムを取得し、各メニューが選択されるたびに表示を切り替えるようにしています。

「onPrepareOptionsMenu」は、メニューを表示する前に複数回呼び出されるため、メニューの作成をここで行う場合、同じメニューを何回も作成してしまわないように注意してください。
「onCreateOptionsMenu」の場合、1回だけ呼び出される関数なようなのですが、私の環境では1回も呼び出されなかったため、「onPrepareOptionsMenu」を利用しています。

LXCで利用するIPアドレス帯域を変更する

Ubuntuではlxcをaptでインストールすると、自動でNAT設定とDHCPの設定が行われます。そのままでも基本的に問題ありませんが、たまに設定を変更したくなる時があります。

Ubuntu 14.04では、DHCPで利用するネットワーク設定が、起動/終了スクリプトである「/etc/default/lxc-net」に下記のようにハードコーディングされています。

#/etc/default/lxc-net

LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.1.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.1.0/24"
LXC_DHCP_RANGE="10.0.1.2,10.0.1.254"
LXC_DHCP_MAX="253"

そのため、IPアドレス帯域を"10.0.10.0"に変更したい場合、下記のように変更します。

#/etc/default/lxc-net

LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.10.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.10.0/24"
LXC_DHCP_RANGE="10.0.10.2,10.0.10.254"
LXC_DHCP_MAX="253"

2015年2月22日日曜日

LXCとSoftEtherを利用してサーバー上にセキュアな作業システムを作る その2

今回はSoftEther用のLXCコンテナの作成方法についてメモします。

コンテナの作成とSoftEtherのインストール

まずコンテナを作成し、起動します。

sudo lxc-create -n コンテナ名 -t ubuntu
sudo lxc-start -n コンテナ名

その後、以下のコマンドをコンテナ内で実行することでSoftEtherがインストールされます。

sudo apt-add-repository ppa:dajhorn/softether -y
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install softether -y

なお、本コマンドでインストールされるSoftEtherは本家が配布しているdebパッケージではありません。本家からインストールする場合、makeから必要になります。 ※本debパッケージの配布元:https://launchpad.net/~paskal-07/+archive/ubuntu/softethervpn

また、lxc-wrapperをインストールしている場合は以下のコマンドでインストールできます。

sudo lxc-wrapper -c -n コンテナ名 -t softether-ubuntu

初期設定

作成したコンテナ上で下記を実行します。

sudo vpncmd /server localhost /CMD HubCreate lxcvpn /password:
sudo vpncmd /server localhost /CMD BridgeCreate lxcvpn /DEVICE:eth0
sudo vpncmd /server localhost /CMD HubDelete DEFAULT
sudo vpncmd /server localhost /CMD VpnAzureSetEnable yes
sudo vpncmd /server localhost /CMD Flush
sudo vpncmd /server localhost /CMD VpnAzureGetStatus

一番最後のコマンドでazureのサブドメインが表示されるので、SoftEther管理マネージャーからアクセスしてください。 なお、この状態ではパスワード等が設定されていないため、早めに設定変更してください。

設定のバックアップとリストア

設定のバックアップはSoftEtherの管理マネージャーから行えるので、そちらから行う方が楽でしょう。
リストアを行う場合、設定ファイルを上書きし、SoftEtherサービスを再起動してください。

sudo cp vpn_server.config /var/lib/softether/vpn_server.config
sudo service softether restart

LXCとSoftEtherを利用してサーバー上にセキュアな作業システムを作る その1

プログラム作成やシステム構築を行っていると、jenkinsなんかのツールが欲しくなってきますが、家のマシンで動かすと電源を落とせなくなりますし、クラウド上のサーバーで動かしてそのままインターネットでアクセスできる状態にするのもセキュリティ上、好ましくありません。

そこで、クラウド(今回は「さくらのVPS」を利用)上のサーバーにLXCをインストールした上で仮想マシン(正確にはコンテナ)にSoftEtherをインストールし、VPN接続することで比較的セキュアな環境を用意することにしました。

構成概要

まず、一番土台となっているlxc serverについては「さくらのVPS」の2コア・HDD100GBを利用しています。ここは、lxcが入っているだけで他は何も入っていません。
次に、lxc上で動いている「SoftEther」ですが、こちらはlxc上で動いているubuntuイメージのコンテナに、SoftEtherをインストールしたものです。
PCをVPNで接続すると、lxcのネットワークに接続され、DHCPでIPが割り振られます。また、lxc serverに直接VPN接続を行い、SoftEtherまでリダイレクトするとIPアドレス変更時等に設定変更が必要となるため、SoftEther側で用意されているAzureを経由する方式にしています。
なお、SoftEtherをホストに直接インストールする場合、lxc用に自動生成されるnicとは別にSoftEther用の仮想nicを用意しないとDHCPが正常に動作しません。
最後に自動化ツールのベースとして、jenkinsを用意し、バックアップを行わせています。

2015年2月7日土曜日

lxc-wrapper

最近、dockerの説明で「コンテナ型」とか「差分ディスク」と言うところにフォーカスされていることが多いんですが、それ自身はdockerのベースとなっているlxcでもできることで、dockerのコアではない、と個人的に思っています。ただ、lxcで差分ディスクを利用するのも結構面倒なので、ちょっとしたwrapperを作成しました。なお、ubuntu用なのでubuntu以外では動作しません。

概要説明

lxcでコンテナを作成すると、デフォルトでは「/var/lib/lxc/コンテナ名/rootfs」にシステム一式を保存します。
lxc-wrapperを利用すると、「/var/lib/lxc/images/イメージ名/rootfs」にシステム一式を保存し、「/var/lib/lxc/コンテナ名/diff」に差分を保存するコンテナを作成できます。
1つのイメージから複数コンテナ作成すれば、dockerの時と同様に、差分のみでコンテナを作成できるわけです。

なお、コンテナからイメージも作成することができますが、dockerとは異なり、差分の差分の差分の・・・と言うような構造は取らず、イメージにする時に全部コピーします。

インストール

以下の方法でインストールします。

git clone https://github.com/ccat/lxc-wrapper.git
cd lxc-wrapper
sudo sh ./install.sh

使い方

  • lxcテンプレートからイメージ作成
    sudo lxc-wrapper -m -t テンプレート名 -i イメージ名
    例:sudo lxc-wrapper -m -t ubuntu -i ubuntu_0001
  • コンテナからイメージ作成
    sudo lxc-wrapper -m -n コンテナ名 -i イメージ名
    例:sudo lxc-wrapper -m -n server1 -i server_0001
  • イメージからコンテナ作成
    sudo lxc-wrapper -c -n コンテナ名 -i イメージ名
    例:sudo lxc-wrapper -c -n server2 -i server_0001
  • なお、作成したコンテナは普通にlxcとして動作するため、lxc-start等で起動できます。

    2015年2月1日日曜日

    「売れる確信を持ってから作る」と言うこと 【Lean Startupの注意点】

    • 対象読者:Lean Startupについて調べている人
    • 概要:Lean Startupについて気づいた注意点を列挙しました

    本記事ではLean Startupの注意点をつらつらと記載しました。私自身が勉強中なので、増えたり減ったり修正したりしていくと思います。
    TOC

    Lean Startupの目標は「手元資金が尽きる前に新しい商売を立ち上げる」こと

    Lean Startupの目標は「手元資金が尽きる前に新しい商売を立ち上げる」こと。この前提がずれている場面ではあまり役に立たない。

    顧客が「お金を払ってでも入手したい」と思っていることを可能な限り確認してから生産を開始すること

    顧客が「お金を払ってでも入手したい」と思っていることを可能な限り確認してから生産を開始すること。Kickstarter等のクラウドファウンディングはその確認に最適。もし、クラウドファウンディングに出してもムダだと思えるなら、アイデアに問題があるのかもしれない。

    「誰に(Customer)」、「どんな価値を提供し(Value Proposition)」、「どう利益を得るか(Revenue)」の3点を重視すること

    ビジネスモデルキャンバスは考えの整理には良いが、全部を埋めることばかりに注力してもしょうがない。最低限、「誰に(Customer)」、「どんな価値を提供し(Value Proposition)」、「どう利益を得るか(Revenue)」の3点が考えられていれば良い。

    競合優位性が提供価値であると言うこと

    ビジネスモデルキャンバスには「競合」と言う概念は出てこないが、実際には「提供価値(Value Proposition)」は「競合」に大きく左右される。競合を知っている顧客に取って、「提供価値」は競合との差別化ポイントだけだからだ。そこに十分な魅力が無ければ競合からは移ってこない。

    競合優位性は模倣しにくい方が望ましいが、絶対条件ではないと言うこと

    競合との差別化ポイントが簡単に模倣できると、その差別化に価値があると判明した瞬間に模倣されてしまう。そのため、模倣しにく方が望ましいが、模倣を極端に恐れるのも馬鹿げている。 模倣を恐れるよりも、まずはニーズとのかい離を恐れるべきだ。

    顧客の話はよく見極めること

    顧客に話を聞くと、「こんな機能があったら欲しい」と言う意見が頻繁に出てくるが、その機能を実装するかはよく検討するべきだ。十中八九はそのような機能を実装しても結局買ってくれない。と、同時に十中一二は機能を追加すれば買ってくれる。

    Lean Startupが常に最善と言うわけではないと言うこと

    Lean Startupは設計や製造に時間がかかることを前提としている。設計や製造に時間がかかるから、先にニーズをとことん検証しよう、と言うわけだ。そのため、もし設計や製造が極端に短い時間で終わる(例えば1日とか)なら、考えるより先に作ってしまうと言う方式も成立する。

    利用する人とお金を払う人が同一とは限らないと言うこと

    実際に利用する人とお金を払う人が同一とは限らない。企業向けのシステムや子供向けのおもちゃ等はその最たる例だ。両方のニーズを満たして初めて製品が売れる。

    2015年1月31日土曜日

    Titanium StudioとGenymotionを使おうとしてハマったメモ 【Genymotion側でDeviceを起動してからDebugしましょう】

    • 対象読者:Titanium Studioの初心者
    • 概要:GenymotionでDebugする時はGenymotion側でDebugに利用するDeviceを起動してからDebugすること
    • ソフトウェアバージョン:
      • Titanium Studio : 3.4.1.201410281727
      • Genymotion : 2.3.1

    Titanium Studio

    AndroidとiPhone向けのアプリを同時に開発する、クロスプラットフォーム環境としてTitanium Studioがあります。Javascriptで作成したプログラムをAndroidでもiPhoneでもどちらでも動くようにしてくれるラッパーみたいな感じでなかなか悪くないんですけど、いかんせんDebugに利用する仮想端末が遅い。正確に言うとAndroid SDKについている仮想端末が遅いみたいなんですが、とにかくこれがいただけない。

    Genymotion

    この遅い仮想端末の代替としてGenymotionと言うものがあります。これはVirtualboxをPCにインストールして、仮想端末を本当に仮想マシンとして動作させよう、と言うもの。最近のPCだとだいたいどれもCPUが仮想化に対応しているので合理的と言えば合理的ですよね。

    Titanium StudioからGenymotionを使えない・・・

    Titanium StudioもGenymotionも、使用するためにはユーザー登録が必要だったりダウンロードのリンクが見つけにくかったりと一癖ありますが、基本的にはダウンロードしてインストールすればそのまま使えます。

    ・・・使えるはずなのですが、Genymotionで作成したDeviceがTitanium Studioで認識されず、始めは苦労しました。Titanium Studioでは左上にDebug対象のDeviceを選択する欄があるのですが、どの設定をいじってもGenymotionで作成したDeviceが表示されません。

    GenymotionでDeviceを起動すれば認識される

    始めは「なんでやねん!」となったのですが、種を明かせば簡単で、Genymotion側でDeviceを起動すると選択肢に出てきました。 Defaultの設定等、紹介されているページがありましたが、現バージョンでは設定変更は何もしなくても動くようです。