読者です 読者をやめる 読者になる 読者になる

プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

オフラインでの地図表示と経路検索 (OpenStreetMap と Graphhopper)

ある android アプリを作ろうと思い立ったのですが、そのためには、オフラインでの地図表示と経路検索を行う必要が出てきました。 当初は、Google Map での実現を考えたのですが、オフライン地図に対応していない地域もあるため、あきらめました。

で、次にあがった候補が、 OpenStreetMap です。OSM の Wiki を調べてみるとオフライン動作についての情報がまとまったページがありました。

ここを見ると、経路検索をオフラインで行えるものとして、 Graphhopper というライブラリが使えそうです。 日本語の情報もあまりないようなので、Graphhopper のデモapkを動かすところまで試したことをまとめておきます。

作業環境は以下の通りです。

  • Windows 10 Pro, 1607, 64bit なお、Bash on Ubuntu on Windows (以下 BoW) も併用してます
  • Android Studio
  • Nexus 5 (6.0.1)

Graphhopperの準備

Graphhopper を見ると商用サービスのように思えますが、オープンソース版があります。 このページのリンクをたどると、Github のプロジェクトページにたどり着きます。

github.com

ここの『For Mobile Apps』から、androidでのデモの説明ページに行きます。

graphhopper/index.md at master · graphhopper/graphhopper · GitHub

android版のデモapkはgraphhopperのリポジトリに含まれているようです。 さて、デモを動かすには、デモ版のソースコードと各種データが必要になりますが、この説明ページの内容が少しわかりにくいので、自分の行った手順とまとめておきます。

まずは、Maps のセクションを参考に、デモapkに必要なデータを準備します。

  1. OpenStreetMap の raw データをダウンロードします。今回は、三重県を含むデータで試したので、kinki のデータを落としました。 なお、いろいろと書いてありますがよくわからない面もあったので、標準的と思われる、 kansai-latest.osm.pbf というファイルをダウンロードしました。
  2. map データを落とします。ダウンロードサイトから japan.map をダウンロードしました。なお、mapデータとはあとでも出てくる mapsforge という地図表示ライブラリで使うデータになります。

以下の作業は、Graphhopperのリポジトリをcloneしてから行います。なお、この部分は BoW 上で作業しています。また、シェルスクリプトを動作させるために、java と zip/unzip を BoW 上でインストールしています。

  1. $ git clone git://github.com/graphhopper/graphhopper.git graphhopper
    
    なお、 git clone を実行したディレクトリに kansai-latest.osm.pbf および japan.map ファイルがあるものとします

  2. $ cd graphhopper
    $ ./graphhopper.sh import ../kansai-latest.osm.pbf
    
    kansai-latest.osm-gh というディレクトリが作成されて、中に必要なデータが作成されます

  3. C:\Users\mor> adb push kansai-latest.osm-gh/edges /sdcard/Download/graphhopper/maps/kansai-gh/
    
    kansai-latest.osm-gh ディレクトリ内のすべてのファイル(edges, geometry など)を、androidの外部ストレージ領域にコピーします。 この際、コピー先に kansai-gh (地域名-gh)のフォルダを用意しておきます。

  4. C:\Users\mor> adb push japan.map /sdcard/Download/graphhopper/maps/kansai-gh/
    
    japan.map もandroidの外部ストレージにコピーします

  5. C:\Users\mor> adb shell
    $ cd /sdcard/Download/graphhopper/maps/kansai-gh/
    $ mv japan.map kansai.map
    
    japan map を kansai.map にリネームします

ここまでできれば、データの準備は完了です。

なお、説明ページではzip圧縮したファイルを使うこともできるとあったので、androidへのコピー処理が簡単にできるかと思い、試したのですが、最終的なデモ動作がうまくいきませんでした。

デモapkプロジェクトの読み込み

以下のページに Android Studio でのデモapkを動作させる手順があります。

graphhopper/android-studio-setup.md at master · graphhopper/graphhopper · GitHub

ただ、自分の環境だと、Android Studio が Windows 上にあるので、 BoW 上の先ほどcloneしたリポジトリとは別に、graphhopperのリポジトリをcloneしておきます。 また、リポジトリのブランチをmasterではなく、 0.8.2 のタグに切り替えておきます。

あとは、説明ページと同様に、 graphhopper/android をオープンするプロジェクトとして指定すれば完了です。

サンプルapkの動作

オープンしたプロジェクトを実行します。正常に実行できると下記の様な画面が表示されると思います。

f:id:junichim:20170515005829p:plain:w300

Local のラベルの隣のスピナーで、オフラインデータとして設定した地域名(今回の場合は kansai)を選択して、OKボタンを押すと地図が表示されます (ただ、最初に表示される場所は、海の中のため、適当にズームアウトしないと陸地が表示されません)。なお、地図で日本を表示しようとした場合、後述の対策が必要です。

地図が表示されれば、ロングタップで経路を求める始点を指定します。

f:id:junichim:20170515005844p:plain:w300

赤線で囲んだ緑の旗(伊勢神宮の外宮前あたりを指しています)が始点を表しています。なお、この際、親切にメッセージを表示したり、音やバイブレーションで設定完了を教えてくれないので注意深く画面を見てください。始点が表示されていれば、設定できた、という感じです。

経路を求める終点は同じく、ロングタップで設定します。 終点を設定すると自動的に経路を求めて表示します。下記画面内の赤線で囲った赤の旗が終点、ちょっと見にくいですが37という数字が振られた道路を経由している緑の点線が経路です。

f:id:junichim:20170515005857p:plain:w300

トーストでも情報を出してくれますが、消えるのが早すぎて何を出しているのか正直分かりません(距離ぐらいはあったかな?)。

次の経路を求めたければ、地図上のどこかの地点をロングタップして、再度始点・終点を指定することになります。 一応、これで、オフラインの動作ができているということになりそうです。

なお、このデモapkの他の動作は次のようになっているようです。 Remoteスピナーから、地域名を選択して『downloding』ボタンを押すと、該当地域の地図データおよび経路データをダウンロードしてくれます。 で、ダウンロード後のデータは、ローカルに保存され、次回起動からはローカルデータとしてアクセスできます。 (デモだけなら、データの準備いらないんじゃ・・・)

注意

実は、デモapkそのままでは、日本のデータ(japan.map)が対象の場合、正しく日本の地図が表示されません。

f:id:junichim:20170515005909p:plain:w300

Android Studio につないで実行してみると、どうも地図データのブロックサイズが制限オーバーの様です。

f:id:junichim:20170515003734p:plain

調べてみると、このGraphhopperのデモアプリでは、地図の表示に mapsforge というライブラリを利用しているようなのですが、そのライブラリ側のデータ読み込み時の制限に引っかかっているようです。 ネットにも類似の議論がありました。

github.com

上記の記事からもわかるように、動的に読み込みバッファサイズを変更できるようなので、その部分だけ手直ししてみます。 具体的には、デモapkの MainActivity.java の 346行目付近に MapFile を生成する処理があったので、その直前にバッファサイズを変更するメソッドを追加してみました。

    void loadMap(File areaFolder) {
        logUser("loading map");
        ReadBuffer.setMaximumBufferSize(7000000); // for test
        MapDataStore mapDataStore = new MapFile(new File(areaFolder, currentArea + ".map"));

なお、指定のバッファサイズは、上記ログ画面で出力されているサイズをカバーするように適当に設定しています。

この状態で試すと問題なく表示できました。 ただし、レンダリングに結構時間がかかっているので、テスト時にはご注意ください。

まとめ

今回試してみた印象としては、

  • オフラインでの地図表示、経路検索はできそう
  • 経路検索の条件指定などは詳しく調べる必要がある
  • 地図のレンダリングは思っていたより遅い(端末のせいか?)
  • 地図データのセットアップ方法を考える必要がありそう

という感じでした。必要に応じて詳しく調べていきたいと思います。

第16回伊勢IT交流会を開催しました

2017年4月15日(土)に第16回伊勢IT交流会を開催しました。

伊勢IT交流会とは、伊勢志摩地域のIT系のエンジニアを始め、多くの方々がお互いに知り合って、雑談などをできる場が欲しいと思い、スタートしたものです。 概要をまとめたものを slideshare にあげてありますので、そちらもご参照ください。

www.slideshare.net

当日用の様子は参加者の方がまとめてくれたブログやfacebookページ等に記事があるので、そちらを見てもらうとして、ここでは主催者としての感想などを書いておきます。

開催しての感想

当初、1月に伊勢IT交流会を開催する予定でしたが、主催者の私がまさかのインフルエンザにかかったため、開催直前に中止となっていました。 今回はその仕切り直しという形でした。 とはいえ、日付が変わると、参加予定だった方が都合あわずに来れなくなったりして、申し訳なかったです。

最近は、参加者が10名前後で推移しており、一時期のようにやめたくなるほど誰も来ないというのはなくなりました(参加者の皆さま、ありがとうございます)。 今回も予定していた定員いっぱいになり、うれしい限りです。

参加者は伊勢近郊の方が多いのは当然として、最近、松阪付近からこられる方が増えてきました。 参加者の方とお話ししているときにも話題になっていたのですが、松阪でこういう会はないのか?という話も出ていました。 新しい勉強会なり交流会なりを立ち上げてみるのも面白いかもしれませんね > 松阪近郊の皆様

さて、LTの詳しい内容は、前述のブログ等をご覧いただくとして、最近のLTの傾向としては、なんとなくIoT絡みのものが増えてきているような印象があります。 たまたまなのかもしれませんが、やはり時流というのはあるんでしょうね。あと、この近辺って意外と電子機器系の会社とかがあるので、その影響もあるかもしれません(根拠なしの憶測ですが)。

まだ、当面はやっていこうと思っていますので、今後ともご参加のほどよろしくお願いします。

なお、次回は 2017年8月~10月 ぐらいのどこかでできればと思っていますので、告知を見かけて、都合が合えばお気軽にご参加ください。

EC2 t1.micro -> t2.nano への移行( Redmine 2.4.1 -> 3.3.2 へ移行) その1

開発時のサーバーとして今までは、 EC2 を使って、Subversion+Redmineを立ち上げていました。構築時の記事はこちらをご覧ください。

でも、最近はソースコード管理は Git (Bitbucket) ばかりだし、運用していた EC2 は t1.micro で、そろそろいろいろ新しくしたいなと思っておりました。 このサーバーは t1.micro のリザーブドインスタンスで運用していたのですが、昨年、無事にリザーブドインスタンスの期間が満了したので、新しいサーバーへ移行することにしました。

目をつけていたのは、運用費用を抑えられそうな t2.nano のインスタンス。自分の開発用のredmine動かすぐらいなら、これで十分じゃないかな?という目論見です。

ということで、 t1.micro 上の Redmine 2.4.1 を t2.nano 上の Redmine 3.3.2 へ移行したので、その際の作業を自分用のメモとしてまとめておきます。

一応、移行前後の情報をまとめておきます。

移行前 移行後
EC2インスタンス t1.micro t2.nano
仮想化種類 PV HVM
OS, Ubuntu 64bit 12.04 14.04
Redmine 2.4.1 3.3.2

※ 両方とも、Bitnamiのスタックを利用して立ち上げ

なお、移行前は Subversion のリポジトリも運用していましたが、最近は使ってないので、新サーバーでは Subversion は使わないことにします。

EC2 インスタンスの立ち上げ

というわけで、まずは t2.nano のインスタンスを立ち上げます。といっても、目的は Redmine を動かすことなので、前と同じく、 Bitnami を利用したいと思います。 リンク先ページで東京リージョンを選択して、amiのリンクをクリックするか、AWS のコンソールにログインして、インスタンスの立ち上げを選択して、コミュニティAMIで検索すれば、立ち上げたいAMIを見つけることができます。インスタンスは、財布にやさしい t2.nano を選択しておきます。

あとは、デフォルト設定で起動すれば、新しい環境が出来上がりです。 さて、ここからが、面倒そうなデータのマイグレーションになります。

Redmine 3.3.2 へマイグレーション

さて、新しいサーバー(とRedmine)が立ち上がったので、古いサーバー上の Redmine のデータを移行したいと思います。 幸い、Redmineのプラグインとかは一切入れていなかったので、比較的簡単に移行できると思います。

移行データの取得

古いサーバーにログインして、移行に必要なデータを取得しておきます。下記などに、データのバックアップ方法が載っているので、その通りにします。

データのバックアップ方法 — Redmine.JP

Bitnami のRedmineスタックの場合、 /opt/bitnami/apps/redmine/htdocs/ にファイルなどがあります。

bitnami@ip-10-134-200-227:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@ip-10-134-200-227:/opt/bitnami/apps/redmine/htdocs$ tar zcvf ~/files.tgz files/
bitnami@ip-10-134-200-227:/opt/bitnami/apps/redmine/htdocs$ cd
bitnami@ip-10-134-200-227:~$ 
bitnami@ip-10-134-200-227:~$ mysqldump -u bitnami -pxxxxxx bitnami_redmine > redmine.dump

こんな感じですね。mysqlへの接続時のユーザー名・パスワード・データベース名などは、

bitnami@ip-10-134-200-227:~$ cat /opt/bitnami/apps/htdocs/config/database.yml

で確認できます。

データのリストア

ネットを調べると、いろいろと移行手順が見つかりますが、最終的に、下記のドキュメントを参考に作業を行いました。

Bitnami Redmine for AWS Cloud

準備として、先ほど取得したredmineのデータを新しいサーバーにアップロードしておきます。 次に、mysqlにログインします。

bitnami@ip-172-30-0-93:~$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
(略)

mysql> 

このときのパスワードが何かがちょっとわからなかったのですが、下記ページのデフォルトのアプリケーションパスワードと同じでした。

Redmine Cloud Hosting on Amazon EC2

既存のredmineのデータベースを削除して、もう一度作り直します。

mysql> drop database bitnami_redmine;
Query OK, 55 rows affected (2.01 sec)

mysql> create database bitnami_redmine;
Query OK, 1 row affected (0.00 sec)

mysql> grant all privileges on bitnami_redmine.* to 'bitnami'@'localhost' identified by 'データベースのパスワードを指定';
Query OK, 0 rows affected (0.00 sec)

mysql> 

ここで、パスワードは、 /opt/bitnami/apps/redmine/htdocs/config/database.yml 記載のものと一致させています。 自分で、パスワードを設定した場合は、 database.yml 側のパスワードを変更することになると思います(未確認)。

次に、データのインポートを行います。

bitnami@ip-172-30-0-93:~$ mysql -u root -p bitnami_redmine < redmine.dump 
Enter password: 
bitnami@ip-172-30-0-93:~$ 

上記のredmine.dumpが既存サーバーから落としたデータです。

bitnami@ip-172-30-0-93:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ 
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ mv files/ files.org                                                                                          
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ sudo tar zxvf ~/files.tgz                                                                                    
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ 

次にマイグレーションを行うのですが、その前に、ログファイルの所有者を変更しておきます。というのも、デフォルトのままマイグレーションを行ったら、ログファイルへの書き込み権限がないというエラーで、マイグレーションが失敗したためです。

bitnami@ip-172-30-0-93:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ cd log
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs/log$ ls -l
total 4
-rw-r--r-- 1 daemon daemon 2253 Apr  3 15:23 production.log
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs/log$ cp -p production.log production.log.org                                                                  
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs/log$ sudo chown bitnami production.log                                                                        
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs/log$ ls -l
total 8
-rw-r--r-- 1 bitnami daemon  2253 Apr  3 15:23 production.log
-rw-r--r-- 1 bitnami bitnami 2253 Apr  3 15:23 production.log.org
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs/log$ 

ここまで来たら、マイグレーションを行います。

bitnami@ip-172-30-0-93:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake db:migrate RAILS_ENV=production

エラーが表示されなければOKだと思います。

あとは、キャッシュのクリアをして、

bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:cache:clear
bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:sessions:clear

Redmineをリスタートさせます。

bitnami@ip-172-30-0-93:/opt/bitnami/apps/redmine/htdocs$ cd ../../..
bitnami@ip-172-30-0-93:/opt/bitnami$ sudo ./ctlscript.sh restart

新サーバーへアクセスすると、既存のRedmineのユーザーでログインしたり、プロジェクトやチケットが見れればOKだと思います。

あとは、サーバーとしていろいろ設定を行いたいと思います。

EC2 t1.micro -> t2.nano への移行( Redmine 2.4.1 -> 3.3.2 へ移行) その2

前の記事で書いたように Redmine の移行ができたので、あとはサーバーとしてあれこれ設定しておきます。 主に、過去に行った作業の繰り返しですが、メモなので大目に見てください。

雑多な設定

  • SSH ポートの変更
  • システムアップデート
  • ロケール変更
  • タイムゾーン変更
  • 日本語環境の設定
  • NTPサーバー変更

を行っています。過去の

blog.mori-soft.com

を参考にして設定しました。

ただ、NTPについては、この設定だけでは再起動時に再設定するのみだったと気づいたので、cronで定期的に更新するようにしました。

/etc/cron.d/ntpdate を下記のように作成しました。

# m h dom mon dow user  command
5 */4   * * *   root    /usr/sbin/ntpdate-debian -s 2> /dev/null                                                                                                      

(参考) Ubuntuサーバの管理 | Think IT(シンクイット) ntpdateで時刻を自動的に合わせる - 試験運用中なLinux備忘録

SSL 自己証明証明書のインストール

過去に作った証明書を割り当てておきます(独自ドメインのサブドメインでアクセスするため)。作ったときの記事はこちらになります。 以前作ったオレオレ証明書をそのまま流用するなら、適切な場所にコピーすればいいだけです。場所の情報などは下記を参照してください。

Bitnami Redmine for AWS Cloud

/opt/bitnami/apache2/conf ディレクトリにコピーします。

コピーするファイルは2つ。

/opt/bitnami/apache2/conf/server.crt
/opt/bitnami/apache2/conf/server.key

というふうにファイルをコピーして、所有者とパーミッションを修正しておきます。

bitnami@ip-172-30-0-93:/opt/bitnami/apache2/conf$ sudo chown root:root server.crt
bitnami@ip-172-30-0-93:/opt/bitnami/apache2/conf$ sudo chown root:root server.key
bitnami@ip-172-30-0-93:/opt/bitnami/apache2/conf$ sudo chmod 600 server.crt
bitnami@ip-172-30-0-93:/opt/bitnami/apache2/conf$ sudo chmod 600 server.key

とすれば終わりです。 なお、ファイル名が異なる場合は、 /opt/bitnami/apache2/conf/bitnami/bitnami.conf 中のファイル名を変更する必要があります。

Elastic IP の割り当て

既存のサーバーに割り当てているElastic IP を新サーバーに割り当てます。 既存サーバーは、結構昔(2012年ごろ)に立ち上げたため、EC2 Classic のインスタンスでした。このため、新サーバーへ割り当てなおすにあたり、Elastic IP を VPC に移行するという操作が必要になりました。

docs.aws.amazon.com

移行後は、このElastic IP を新サーバーへ割り当てれば終わりです。

なお、VPCの場合は、インスタンスを停止してもElastic IP の関連付けが解除されることはないので、過去にやったように、起動時にElastic IP を自動で割り当てるなどの処理は不要になりました。 一応、一度インスタンスを停止して、再開後、独自ドメイン名でアクセスできることを確認しておきます。

Security Group の自動変更

以前、Security Group の自動更新を設定した際は、EC2 CLI ツールをインストールしていました。 でも、最近は、AWS CLI ツールを使うのがおすすめの様です。

docs.aws.amazon.com

せっかくなので、ここでは、AWS CLI ツールをインストールして、これを使って操作します。ちなみに、 AWS CLI ツールはpython製のようです(EC2 CLI ツールはJava製)。

インストール手順はamazonのドキュメントにも載っていますが、これだと、作業ユーザーのホームディレクトリ以下にインストールされるので別の方法をとります。

ネットを調べてみると、CentOSでAWS CLI をインストールする方法がありました。

CentOSにAWS CLIをインストールする – kumonchu.com

標準のパッケージマネージャを使って、pipをインストールして、それから、awscliをインストールしています。Ubuntuでも同様にできると思います。

探してみます。

bitnami@ip-172-30-0-73:~$ apt-cache search python-pip                                                                                                                 
python-pip - alternative Python package installer
python-pipeline - iterator pipelines for Python
python-pip-whl - alternative Python package installer
bitnami@ip-172-30-0-73:~$ 

ありますね。インストールします。

bitnami@ip-172-30-0-73:~$ sudo apt-get update
bitnami@ip-172-30-0-73:~$ 
bitnami@ip-172-30-0-73:~$ sudo apt-get install python-pip

AWS CLI も探します

bitnami@ip-172-30-0-73:~$ pip search awscli
awscli-plugin-endpoint    - Endpoint plugin for AWS CLI
aws-s3-url2uri            - Make awscli s3 commands work with URL
awscli-cwlogs             - AWSCLI CloudWatch Logs plugin
awsclpy                   - Chain AWSCLI commands in Python.
awscli-keyring            - AWS command line credentials from OS X Keychain and other keyrings.
awscli                    - Universal Command Line Environment for AWS.
bitnami@ip-172-30-0-73:~$ 

見つかりました。インストールします。

bitnami@ip-172-30-0-73:~$ sudo pip install awscli

確認します。

bitnami@ip-172-30-0-73:~$ which aws
/usr/local/bin/aws
bitnami@ip-172-30-0-73:~$ 
bitnami@ip-172-30-0-73:~$ aws --version
aws-cli/1.11.71 Python/2.7.6 Linux/3.13.0-115-generic botocore/1.5.34
bitnami@ip-172-30-0-73:~$ 

問題なさそうですね。とりあえず簡易設定を行います。

bitnami@ip-172-30-0-73:~$ aws configure
AWS Access Key ID [None]: AWS IAM のアクセスキー
AWS Secret Access Key [None]: AWS IAM のシークレットキー
Default region name [None]: ap-northeast-1
Default output format [None]: 
bitnami@ip-172-30-0-73:~$ 

IAM はEC2操作用に作成したユーザーを使っています。

一応、内容を確認しておきます。

bitnami@ip-172-30-0-73:~/.aws$ cat config 
[default]
region = ap-northeast-1
bitnami@ip-172-30-0-73:~/.aws$ cat credentials                                                                                                                        
[default]
aws_access_key_id = AWS IAM のアクセスキー
aws_secret_access_key = AWS IAM のシークレットキー
bitnami@ip-172-30-0-73:~/.aws$ 

適当なコマンドを実行してみて問題なく動作することも確認できました。 肝心な、Security Group の自動変更のやり方ですが、基本的には以前と同じです。ただ、スクリプトで使うAPIをAWS CLI 用に修正しました。

サーバー間のバックアップ

さくらインターネットで公開しているHPのデータを、Redmineのサーバーへバックアップしていました。 なので、新サーバーにも同様にバックアップを行います。

といっても、新しくやったことはなくて、こちらの記事の設定を確認して、バックアップが動作することをチェックしただけです。

S3へのバックアップ

また、定期的に HP の内容をS3へもバックアップしています。 いままでは、こちらの記事と同様に、s3cmd を使っていたのですが、この機にawscliを使う形に変更しました。

処理する内容は基本的に同じで、サーバー間のバックアップで取ったファイルをtarでまとめたものを、月に一度S3に保存するというものです。 なお、IAMユーザーは、EC2用とS3用で分けています。

自動スナップショットとローテーション

自動スナップショットとローテーションも過去記事を参考に再設定します。 やってることは同じですが、 AWS CLI を使うように変更します。

なお、実行スクリプトでは、 API の結果を処理して、既存のスナップショットの数やIDを調べているのですが、 AWS CLI の場合は、JMESPATH というのを使って処理ができるそうです。

aws — AWS CLI 1.11.76 Command Reference

使い方は下記などを参照してください。

http://dev.classmethod.jp/cloud/aws/aws-cli-filter-and-query-howto/

AWS CLI の query による絞り込み - Qiita

JMESPathでソートや部分一致も | AWS情報ブログ

セキュリティアップデートの自動実行

過去記事と同様に、Ubuntu 14.04 でもセキュリティアップデートの自動実行を行います。 既に、 unattended-upgrades パッケージがインストール済みだったので、自動実行の設定だけ行います。

sudo dpkg-reconfigure -plow unattended-upgrades

なお、セキュリティアップデートの設定を下記のように行いました。

/etc/apt/apt.conf.d/50unattended-upgrads ファイルへ下記を追記

Unattended-Upgrade::Mail "xxxxx@mori-soft.com";         # メール通知
Unattended-Upgrade::Remove-Unused-Dependencies "true";  # 不要パッケージの削除(autoremove)

/etc/apt/apt.conf.d/20auto-upgrades ファイルへ下記を追記

APT::Periodic::AutocleanInterval "6";                   # 不要アーカイブファイルの削除(autoclean)

また、サーバーにメール送信環境がなかったため、メール送信設定を s3fsが予期せずアンマウントされた場合への対策 - プログラマーのメモ書き に参考を行いました(sSMTP と mailutils を使った送信)。

(参考) qiita.com

Cloud watch

以前、ディスクの空き容量が不足してひどい目にあったので、CloudWatch を設定して監視します。やり方は過去記事と同じです。

Amazon CloudWatch Monitoring Scripts for Linux の説明ページが切れていたので、下記に再掲しておきます。

docs.aws.amazon.com

スクリプトのダウンロード元

Amazon CloudWatch Monitoring Scripts for Linux : Sample Code & Libraries : Amazon Web Services

redmine のバックアップ

せっかく新しいサーバーに移行したので、redmine の添付ファイルとdbの内容をバックアップするようにします。 やり方は、redmine のデータのバックアップを cron で毎日定期的に行うようにするだけです。また、それを月に一度、S3に保管します。

既存サーバーの停止

ここまで行えば、あとは既存サーバーを停止するだけです。当面は、既存サーバーを停止したままインスタンスは残しておき、何かあれば、再度起動できるようにします。 ただ、新サーバーにて運用を開始しているので、既存サーバーの Elastic IP の自動割り当てだけ解除しておきます。

終わりに

いろいろと設定していたら、予想以上に時間がかかってしまいましたが、一応これで新サーバーにて運用できそうです。 にしても、 t2.nano は思ったより快適ですね。今回の目的であれば、十分使えそうです。

更新履歴

2017/4/14 セキュリティアップデートの自動実行の記述で、autoremove/autoclean/メール送信環境の設定 を追記しました

QNAP TS-251+ の設定(UPSおよび他NASとの連携)

昨年10月頃に購入した、 QNAP TS-251+ にやっとUPSをつないだので、その経緯をまとめてみました。

QNAP の NAS は USBでUPSを接続して、簡単に停電時の電源断などの設定ができます。このとき、自分をマスターにして、ネットワーク経由で他のNASをUPSと連動させることもできます。1台のUPSに複数の機器を接続しているときに有効ですね。ちなみに、他社製のNASでも類似の機能はよくあります。

なので、TS-251+ にUPSを繋げて、既存のNETGEARのReadyNASと連動させればいいんじゃないの?と簡単に考えて、設定したのですがこれがどうもうまくいきません。 久しぶりにドはまりしました。何とかして連携させるようにしたので、その顛末をまとめておきます。

の前に、やりたいことをまとめるとこうなります

同じUPSについないでいる2台のNASを連動させたい

  • UPS : APC ES 550G
  • QNAP TS-251+
  • NETGEAR ReadyNAS Ultra2

ところで、NAS の UPS 機能、自社シリーズしか対応していないというのが多いような印象ですが、これなんとかならないですかね? > 各メーカーさん

NUTについて

ReadyNAS (Ultra2) は古い機種なので、同じようなことで悩んでいる先人がきっといるはず、ということで、ググってみると、一応それなりに情報が出てきました。 基本的には、QNAP も ReadyNAS も NUT (Network UPS Tools) というのを元に、これらの機能を実現しているようです。NUT自体はオープンソースのようです(ライセンスGPL2、こちらで言及)。

なので、NUTの設定さえなんとかなれば、なんとかなるんじゃないかという甘い期待を持ちつつ、いろいろと調べていきました。

実現方法

どちらのNASも一方をマスターにして、その他のNASをスレーブ(ネットワーク経由でUPSを監視)として動作させることができます。 結論からすると、今回の場合、最終的に実現したのは、

  • QNAP : master
  • ReadyNas : slave

として動作させることでした。

基本的な設定方法としては、

http://www.ryanbibbey.com/2014/10/26/setup-nas-remote-ups-monitoring/

https://community.netgear.com/t5/New-to-ReadyNAS/Duo-V2-Remote-UPS-monitoring-sorted-v-5-3-7/td-p/862527

に従っています。

QNAP 側の設定

まず、UPSを TS-251+ に接続します。 この状態で、NASにログインすると、外部機器が接続されました』というダイアログが表示されます。

f:id:junichim:20170224112426p:plain

『外部デバイス設定を表示する』を選択するとUPSの設定画面が表示されます。 正しく接続できていれば、画面下部に、UPSのバッテリー残量などの情報が表示されます。

f:id:junichim:20170224102228p:plain

表示されていない場合は、接続に問題ないか、TS-251+ で使えるUPSかどうか、などを調べてみてください。

まずは、TS-251+ 側でUPSを設定します。

f:id:junichim:20170224102900p:plain

このとき、必ず『ネットワークUPSサポートを有効にする』にチェックを入れて、通知先になるNAS(スレーブとして動作するReadyNAS)のIPアドレスを入力しておきます(ちょっと面倒ですが、GUIからは、個別のIPアドレスでの入力になります)。

次に、SSH経由でログインします。NUT関係の設定は、 /etc/config/ups にあります。 upsd.users ファイルを開き、masterに接続する際のユーザー情報を修正します。

[admin]
                password = 123456
                allowfrom = localhost
                actions = SET
                instcmds = ALL
                upsmon master           # or upsmon slave

とある、allowfromを

                allowfrom = ALL

のように、ローカルホスト外からでも接続できるように変更しておきます。

設定を変更したら、

upsd -c reload

として、変更後の設定を読み込ませておきます。

ReadyNAS (Ultra2) 側の設定

まず、SSHでログインします。

ReadyNAS のNUT関係の設定は、 /etc/nut にあります。 upsmon.conf ファイルを開き

MONITOR UPS@localhost 1 monuser pass master

の行を

MONITOR qnapups@ts-251+のIPアドレス 1 admin 123456 slave

と変更します。

『qnapups』がUPS名で、QNAPの /etc/config/ups/ups.conf で定義されている名前になります。 『admin 123456』がネットワーク経由で接続する際のユーザー名とパスワードで、QNAP の /etc/config/ups/upsd.users で定義されています。

QNAP側のUPSの機能として、これらの名前を変更することができないようです。なお、ReadyNAS側は、UPS名が UPS で固定です。これが、メーカー間の連動ができない一因ですかね。

次に、 /etc/init.d/readynas_startup を開いて

if [ "$ENABLE_REMOTE_UPS" = "1" ]; then
  if [ -s /etc/frontview/ups.conf ]; then              
    . /etc/frontview/ups.conf                          
    UPSID="`upsc UPS@$UPS_SERVER 2>$DBG|awk -F': ' '/ups.mfr:|ups.model:/ { if($1==\"ups.mfr\") printf $2 \" \"; else print $2; }'`"
    if /sbin/upsmon -p &>$DBG; then                                                                                      
      echo "${UPSID}!!OK" >/var/log/frontview/ups.log
    else                                             
      echo "${UPSID}!!FAIL" >/var/log/frontview/ups.log
    fi                                                 
  else                              
    echo "Unknown UPS!!FAIL" >/var/log/frontview/ups.log
  fi                                                    
fi                    

の部分を

if [ "$ENABLE_REMOTE_UPS" = "1" ]; then
  if [ -s /etc/frontview/ups.conf ]; then              
    . /etc/frontview/ups.conf                          
    # change for qnap nas    
    #UPSID="`upsc UPS@$UPS_SERVER 2>$DBG|awk -F': ' '/ups.mfr:|ups.model:/ { if($1==\"ups.mfr\") printf $2 \" \"; else print $2; }'`"
    UPS=`awk '/^MONITOR/ { print $2 }' /etc/nut/upsmon.conf`                                                                         
    UPSID="`upsc $UPS 2>$DBG|awk -F': ' '/ups.mfr:|ups.model:/ { if($1==\"ups.mfr\") printf $2 \" \"; else print $2; }'`"
    if /sbin/upsmon -p &>$DBG; then                                                                                      
      echo "${UPSID}!!OK" >/var/log/frontview/ups.log
    else                                             
      echo "${UPSID}!!FAIL" >/var/log/frontview/ups.log
    fi                                                 
  else                              
    echo "Unknown UPS!!FAIL" >/var/log/frontview/ups.log
  fi                                                    
fi                    

と変更します。

(たぶん)ReadyNAS起動時に、 upsc を使って、接続先となるUPSの情報を取得して、/var/log/frontview/ups.log に書き込んでいる処理になります。 この際に、UPS名が固定だったのを、設定ファイルの内容を反映するようにしました。

このままでは、リモートUPSの設定が有効ではないので、 /etc/default/services を開いて

ENABLE_REMOTE_UPS=0

ENABLE_REMOTE_UPS=1

と変更します。 また、 /etc/frontview/ups.conf を開いて

UPS_SERVER= ts-251+のIPアドレス

と、リモートUPSサーバーのIPアドレスを指定しておきます(upsmon.conf のIPアドレスと同じです)。 なお、下記設定ファイル

  • /etc/nut/upsmon.conf
  • /etc/default/services
  • /etc/frontview/ups.conf

は管理画面から設定を行うと書き換えられるので、その点には注意してください。

ここまで、設定したらいったん再起動します。 設定に問題がなければ、ReadyNAS の管理画面にログインすると UPS のアイコンがグリーンに点灯していると思います(マウスを重ねるとバッテリー残量などの情報も見れます)。

ここまでくれば、最後は動作テストです。 UPSの電源ケーブルを抜いて、しばらく待つと、TS-251+, ReadyNAS Ultra ともにシャットダウンしました。問題ないようですね。

実は、現在手元にあるNASだと、最初に示したリンク先の設定方法(/etc/init.d/ups-monitor を使う方法)では、GUIのアイコンにUPSの情報が反映されませんでした。 一連の動作を見ていたら、/var/log/frontview/ups.log が正しく作られないようです。 詳細なところは不明だったのですが、上記の readynas_startup スクリプト中に ups.log を作成するところがあったので、ここを修正したら、動くようになったという次第です。

(参考)うまくいかなかった方法など

上記とは逆に、

  • QNAP : slave
  • ReadyNAS : master

で構成することも考えられます。ネット上にもいくつか参考となる情報があり、

https://forum.qnap.com/viewtopic.php?t=81908 https://forum.qnap.com/viewtopic.php?f=182&t=60166

上記の方法でやろうとしたのですが、今のReadyNAS には、dummy-ups ドライバが入っていなくて断念しました。

nasxxx:/etc/nut# ls /lib/nut/
hidups  newhidups  snmp-ups  usbhid-ups
nasxxx:/etc/nut# 

なお、dummy-ups ドライバーを使う場合は、下記の様に起動に失敗するときがあるそうです。

http://serverfault.com/questions/655797/nut-ups-dummy-driver-in-repeater-mode-for-synology-nas

次善の方法として、upsutilを切って、upsmonで起動する というのも試しました。 upsmonを起動できるとあるので、upsutil をkill後起動してみたが、 いつの間にやら、upsutilのプロセスが立ち上がってました。

https://xn3.wiki/qnap/qnap-upsmon http://www.mtom.cz/url/Linux/QNAP+a+NUT

あと、upsmonについては起動できているようで、マスター側(ReadyNAS側)のログに接続成功が出ていたのですが、QNAP側のGUIにはUPSのステータスなどが表示されませんでした。 ということで、この方法は断念しました。

なお、参考までに、upsutilをapcupsdに入れ替える記事というのがあったので、

http://itarou.blogspot.jp/2010/05/ts-419papcupsd.html

これを参考にして、 upsutil を upsmon に入れ替えれば実現できるかもしれません(やってないのでわかりませんが)。

その他にも、TS-251+ では docker/vm が動かせるので、 USB パススルーを使って仮想マシン側にUPSを管理さえればいいんじゃないか、とも思ったのですが、どうもうまくUSB(UPS)のパススルーが設定できなかったので実現できませんでした。

(参考)バージョンなど

QNAP TS-251+ NUT 2.6.5 Readynas Ultra2 NUT 2.0.5

ReadyNas 側の設定内容

  • 設定ファイルの場所:/etc/nut
  • UPS名 (ups.confのセクション名): UPS
  • ユーザー定義 (upsd.users) : monuser, pass

QNAP側の設定内容

  • 設定ファイルの場所:/etc/config/ups
  • UPS名 (ups.confのセクション名): qnapups
  • ユーザー定義 (upsd.users) : admin, 123456