Apache ZeppelinとAngularJS(Selectタグ,tags-input)の試行錯誤

全然、理解できていないけど、たまたま動いたので試行錯誤した内容を記載。
この記事は読んでも何も解決しないし余計混乱するだけの可能性が高いので要注意。

やりたかったことは、Apache Zeppelin上で条件を変更しながらデータを参照したかった。
なので、AngularJSを使ってHTMLを生成し、検索条件を選べるようにしたかった。
理想はこんなの

参考
AngularJS で select タグを思い通りに作る
spark2.0.0 API(Dataset)
Back-end Angular API in Apache Zeppelin

前提知識
AngularJSはFramework。Client側で動くものではなくて、Server側でも動きます。

とりあえず、お試しでいろんなサイトのごちゃまぜ版

import org.apache.zeppelin.display.angular.paragraphscope._
import AngularElem._

val pj_list = Map[Int,String](
    (1, "プロジェクトA")
    ,(2, "プロジェクトB")
    ,(3, "プロジェクトC")
)

val pj_list2 = List("プロジェクトA", "プロジェクトB", "プロジェクトC")

z.angularBind("pj_list", pj_list)
z.angularBind("pj_list2", pj_list2)

println("""%angular {{pj_list}}""")
// {"key1":1,"value1":"プロジェクトA","key2":2,"value2":"プロジェクトB","key3":3,"value3":"プロジェクトC"}
// mapではない。。。オブジェクトのままで良いのに、なぜか変なListに置換される。これはバグじゃないかと思ってる。

println("""%angular 
<select ng-model="select" ng-options="data for (num, data)  in {{pj_list}}" multiple="multiple">

""")

println(“””%angular {{pj_list}}”””)の結果を見てもらえばわかるが、
key1というkeyに1、value1というkeyにプロジェクトAが割り当てられている。
なので、表示は「プロジェクトA」「プロジェクトB」「プロジェクトC」にはならず、「1」「プロジェクトA」「2」「プロジェクトB」「3」「プロジェクトC」となる。

ここまでも結構時間がかかったので、これがバグだったらちょっと殺意が湧くレベル。

でも、思ったよりもやりたいことはできそうだったので、思い切ってこの状態からBindするデータをDBから取得するように変更。
なんとなくダメだろうと思いつつ、上記のソースを書き換えてみた。

// scala
import org.apache.zeppelin.display.angular.paragraphscope._
import AngularElem._

// user Tableについては、別でDBから抽出済み。
val location = sqlContext.sql("SELECT location from user GROUP BY location")
val a = location.collectAsList()

z.angularBind("a", a)

println("""%angular 
<select ng-model="select" ng-options="b.values for b  in {{a}}" multiple="multiple">

""")

あれ?なぜかObjectでBindできてるし。。
Map[Int,String]がわるいのかと思いつつも、StringはObject型じゃないん?とか考えつつも、key,valueにこだわりは今のところ無いので深追いせずに終了。
ちなみに、aの型はjava.util.List[org.apache.spark.sql.Row]。
もしかして、Mapを直接Bindするんじゃなくて、ListのMapをBindすればよかったのか。

<select ng-model=”select” ng-options=”data for (num, data) in {{pj_list}}” multiple=”multiple”>
ここも後で見直すと分からなくなりそうなので補足。
ng-modelにある値が同じ場合、そのタグは別のタグの操作を反映して連動する。
ng-optionはSelectタグのoption。最初のdataが最終的にvalueに入る変数。(num, data)は{{pj_list}}配列の1データ。key,value形式なので(key, value)のように書いている。
どこかのサイトを見る限り、keyの値は勝手に振られるらしい。

zeppelin7.0から手順からなくなっているけど、npmインストールしたらtags-inputも使えるようになるのかな。

ZeppelinでNotebookを開くと別サイトにリダイレクトされちゃう問題

angularを使ったりなどで、Webサイトを丸ごと生成しようとするとハマってしまう。

一度生成してしまったらWeb画面から削除できなくなってしまうので、正直バグじゃないかと思うが対処法。
適当に調べてみても見つからなかった。
この時期にZepplinを使うような人はさすがに自己解決できるのかな。

cd ./zeppelin/notebook/
ll ./**/*

-rw-r--r-- 1 15437 Sep 17 19:31 ./2A94M5J1Z/note.json
-rw-r--r-- 1 39530 Sep 17 19:31 ./2BQA35CJZ/note.json
-rw-r--r-- 1 5922 Sep 17 14:07 ./2BVW41M8Q/note.json
-rw-r--r-- 1 311701 Sep 17 11:54 ./2BWVKB8MT/note.json
-rw-r--r-- 1 106937 Sep 17 19:29 ./2BWYU34J7/note.json
-rw-r--r-- 1 48399 Sep 17 12:11 ./2BX45R6Q9/note.json
-rw-r--r-- 1 43073 Sep 17 15:42 ./2BX54X9C4/note.json

grep -R "/test\"" ./*

Zeppelinの仕様として、
一度生成したものはサーバ上にデータを確保しておくことで、サーバを再起動してもコマンドをキックすることなく過去の結果が表示される。
なので、デバッグ中にリダイレクトされてしまうような結果が保持されてしまった場合にはWeb画面上からはどうにもできない。
なので、直接サーバ上に保持されているファイルを修正する。

上記の結果を見ていただければわかるが、notebook単位で分かれているものの、notebookの名前で保持されているわけではない。
今回は、/xxx/test/というnotebookを作っていたため、最後にgrepを行って対象のnotebookを特定している。

拡張子から見てわかる通り、notebookの内容は全てnote.jsonで保持されている。
結果は”msg”というkeyで保持されているので、そこの内容を削除する。

vi ./xxxxx/note.json
/msg
削除したい先頭位置からd$で末尾まで削除する。(””で囲まれているため、最後に”を追加しましょう。)

最後に、メモリ上に展開されている内容をクリアするためにzeppelinの再起動。

これで何とか復旧。。。

CentOS7.2 + Zeppelin0.7.0 + Spark2.0 + R3.3.1 + RMeCab

3度目のZeppelinインストール。なぜこんなことに。
毎回、はまるポイントが異なって色々気づけることが多いのは良いことかもしれない。

今回はZeppelin上でRのtable関数がうまく動かないので、SparkのVersionを1.6から2.0にあげる。
という名目。
Zeppelinがわかってきたので無駄なインストールたちも省いていく。
色々ごにょごにょやればtable関数もうまく動くようだけど、新しいのに乗り換えてうまくいくならそれでいいよね。
Overviewにそれっぽいことかいているし。
※この記事がUPされるころにはうまくいってるのは確認済みです。

過去記事
CentOS7.2へZeppelin0.7.0のインストール

過去記事にもあるけど、参考にした公式
Spark2.0が出たばかりの頃はなかったのに、いつの間にかSpark2.0も反映されている。

■事前準備

yum update
yum install git
yum install java-1.8.0-openjdk-devel
yum install npm
yum install fontconfig-devel

curl -O http://www.eu.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
sudo tar -zxf apache-maven-3.3.9-bin.tar.gz -C /usr/local/
sudo ln -s /usr/local/apache-maven-3.3.9/bin/mvn /usr/local/bin/mvn

mavenは8Mくらいだけど遅い。
と思ったけど、さくらのクラウドの問題だったぽい。
Cloud環境によってはイメージが異なるので、一部インストールが要らなかったりなど微妙な違いがあるのが許せない。

■Rインストール
毎回ここでハマるのと、Rをめっちゃ使うことがわかってきたので今回は解決させる。

yum --enablerepo=epel -y install R R-devel libcurl-devel openssl-devel

+ devtools with `R -e "install.packages('devtools', repos = 'http://cran.us.r-project.org')"`
+ knitr with `R -e "install.packages('knitr', repos = 'http://cran.us.r-project.org')"`
+ ggplot2 with `R -e "install.packages('ggplot2', repos = 'http://cran.us.r-project.org')"`
+ Other vizualisation librairies: `R -e "install.packages(c('devtools','mplot', 'googleVis'), repos = 'http://cran.us.r-project.org'); require(devtools); install_github('ramnathv/rCharts')"`

一時的にリポジトリを有効にしてインストールするっていうのが、イマイチわかりにくい。
名前の重複を避けるためだとか、公式にサポートしていないなど事情はあるんだろうけど、もうちょっとわかりやすくならないものか。

■Rの”evavlute”をインストール
インストールしないと、Zeppelinビルド時に後述のエラーが発生する。
せっかくなので公式サイトが推奨しているのも何も考えず突っ込む。
RMeCabは後程。

`R -e "install.packages(c('evaluate','glmnet','pROC','data.table','caret','sqldf','wordcloud'), repos = 'http://cran.us.r-project.org')"`

なんか失敗している。。。でも関係なさそうだから無視。

Making 'packages.html' ... done

The downloaded source packages are in
        ‘/tmp/RtmprxNFFF/downloaded_packages’
Updating HTML index of packages in '.Library'
Making 'packages.html' ... done
ERROR: option '-g' requires an argument

■Zeppelinインストール
Hadoopに関してはSparkだけで使ってた時からハマってまともに解消するきがないので、とりあえず簡単に動くCDH版を使う。

git clone https://github.com/apache/zeppelin.git
cd zeppelin/

mvn clean package -Pspark-2.0 -Pr -Dhadoop.version=2.6.0-cdh5.5.0 -Pyarn -Ppyspark -Psparkr -Pvendor-repo -Pmapr51 -DskipTests

“evavlute”をインストールしていないと発生するエラー

[INFO] --- exec-maven-plugin:1.2.1:exec (default) @ zeppelin-zrinterpreter_2.10 ---
+++ dirname R/install-dev.sh
++ cd R
++ pwd
+ FWDIR=/root/zeppelin/r/R
+ LIB_DIR=/root/zeppelin/r/R/../../R/lib
+ mkdir -p /root/zeppelin/r/R/../../R/lib
+ pushd /root/zeppelin/r/R
+ R CMD INSTALL --library=/root/zeppelin/r/R/../../R/lib /root/zeppelin/r/R/rzeppelin/
ERROR: dependency 'evaluate' is not available for package 'rzeppelin'
* removing '/root/zeppelin/R/lib/rzeppelin'
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Zeppelin ........................................... SUCCESS [ 13.457 s]
[INFO] Zeppelin: Interpreter .............................. SUCCESS [ 27.633 s]
[INFO] Zeppelin: Zengine .................................. SUCCESS [ 14.334 s]
[INFO] Zeppelin: Display system apis ...................... SUCCESS [ 33.765 s]
[INFO] Zeppelin: Spark dependencies ....................... SUCCESS [01:32 min]
[INFO] Zeppelin: Spark .................................... SUCCESS [01:09 min]
[INFO] Zeppelin: Markdown interpreter ..................... SUCCESS [  1.031 s]
[INFO] Zeppelin: Angular interpreter ...................... SUCCESS [  0.644 s]
[INFO] Zeppelin: Shell interpreter ........................ SUCCESS [  1.079 s]
[INFO] Zeppelin: Livy interpreter ......................... SUCCESS [  1.440 s]
[INFO] Zeppelin: HBase interpreter ........................ SUCCESS [  8.939 s]
[INFO] Zeppelin: PostgreSQL interpreter ................... SUCCESS [  1.323 s]
[INFO] Zeppelin: JDBC interpreter ......................... SUCCESS [  2.281 s]
[INFO] Zeppelin: File System Interpreters ................. SUCCESS [  3.271 s]
[INFO] Zeppelin: Flink .................................... SUCCESS [ 13.398 s]
[INFO] Zeppelin: Apache Ignite interpreter ................ SUCCESS [  1.843 s]
[INFO] Zeppelin: Kylin interpreter ........................ SUCCESS [  1.182 s]
[INFO] Zeppelin: Python interpreter ....................... SUCCESS [  1.048 s]
[INFO] Zeppelin: Lens interpreter ......................... SUCCESS [  7.611 s]
[INFO] Zeppelin: Apache Cassandra interpreter ............. SUCCESS [01:47 min]
[INFO] Zeppelin: Elasticsearch interpreter ................ SUCCESS [  7.592 s]
[INFO] Zeppelin: BigQuery interpreter ..................... SUCCESS [  1.544 s]
[INFO] Zeppelin: Alluxio interpreter ...................... SUCCESS [  4.551 s]
[INFO] Zeppelin: web Application .......................... SUCCESS [02:08 min]
[INFO] Zeppelin: Server ................................... SUCCESS [ 42.821 s]
[INFO] Zeppelin: Packaging distribution ................... SUCCESS [  5.805 s]
[INFO] Zeppelin: R Interpreter ............................ FAILURE [ 43.638 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:39 min
[INFO] Finished at: 2016-08-27T19:33:15+09:00
[INFO] Final Memory: 232M/591M
[INFO] ------------------------------------------------------------------------
[WARNING] The requested profile "Scala-2.11" could not be activated because it does not exist.
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default) on project zeppelin-zrinterpreter_2.10: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:exec (default) on project zeppelin-zrinterpreter_2.10: Command execution failed.
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: Command execution failed.
        at org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:362)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
        ... 20 more
Caused by: org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
        at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:377)
        at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:160)
        at org.codehaus.mojo.exec.ExecMojo.executeCommandLine(ExecMojo.java:610)
        at org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:352)
        ... 22 more
[ERROR]
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn  -rf :zeppelin-zrinterpreter_2.10

■簡単に動作確認

./bin/zeppelin-daemon.sh start
systemctl status firewalld
firewall-cmd --list-all
firewall-cmd --add-port=8080/tcp --zone=public --permanent
firewall-cmd --reload

■設定変更するファイルのバックアップなど

cp -p ./conf/zeppelin-site.xml.template ./conf/zeppelin-site.xml
cp -p ./conf/zeppelin-env.sh.template ./conf/zeppelin-env.sh
cp -p ./conf/shiro.ini ./conf/shiro.ini.org

Login機能の有効化

shiro.ini

[users]
#admin = password1, admin
#user1 = password2, role1, role2
#user2 = password3, role3
#user3 = password4, role2

[urls]
/api/version = authc
/api/interpreter/** = authc, roles[admin]
/api/configurations/** = authc, roles[admin]
/api/credential/** = authc, roles[admin]
/** = authc

[users]領域
デフォルトのユーザをコメントアウト。
その後独自のユーザパスワード、Roleを設定。

[urls]領域
全部承認が必要なように修正。
interpreter,configureations,credentialなどいじられると困るのでadmin権限がないとダメなように設定。
※この設定だと外部へのLink Paragraphができないのでもったいない。

zeppelin-site.xml

<property>
  <name>zeppelin.anonymous.allowed</name>
  <value>false</value>
  <description>Anonymous user allowed by default</description>
</property>

anonymousの許可を無効化(valueをtrue→false)

RMeCabのインストール(日本語形態素解析)

公式情報

以下、mecab-0.996.tar.gz,mecab-ipadic-2.7.0-20070801.tar.gzダウンロードした前提で手順を記載

tar zxfv mecab-0.996.tar.gz
cd mecab-0.996
./configure --with-charset=utf8
make
make install
cd ..
tar zxfv mecab-ipadic-2.7.0-20070801.tar.gz
cd mecab-ipadic-2.7.0-XXXX
./configure --with-charset=utf8
make
/usr/local/libexec/mecab/mecab-dict-index -f euc-jp -t utf-8
make install
cd ..

上記手順でMeCabをサーバにインストールする。

RとMeCabを連携させる

echo "/usr/local/lib"  >> /etc/ld.so.conf.d/R-x86_64.conf
ldconfig
R
Sys.getlocale()
Sys.setlocale("LC_ALL", 'en_US.UTF-8')
install.packages("RMeCab", repos = "http://rmecab.jp/R")
RMeCabC("すもももももももものうち")
q()

R言語おまけ

R言語の設定

listenファイルのメッセージ列から情報を取得し、名詞だけを取り出す。


listen <- read.table("listen.sql", header=T, sep=";")
listen["message"]

library(RMeCab)

b <- RMeCabDF(listen, "message", 1)
b2 = unlist(b)
b2[names(b2) == "名詞"]

これで、下記の問題は解消。
http://stackoverflow.com/questions/33311240/using-sparkr-jvm-to-call-methods-from-a-scala-jar-file