« 2020年9月 | トップページ | 2020年11月 »

2020年10月

2020年10月24日 (土)

Kill Python

request.postをhttpsで実行したらどうなるんだろう(サーバーはhttps未対応)とおもって試したらPython Shellがハングった、というかCtl+CつまりKeyboardInterruptを受け付けなくなった。で、強制終了となった。

以下、実行したこと。

pi@raspberrypi:~ $ ps aux | grep python
root 467 0.0 0.3 55084 13500 ? Ssl 21:23 0:00 /usr/bin/python3 -m webiopi -l /var/log/webiopi -c /etc/webiopi/config
pi 1033 0.7 0.9 110308 36004 ? Sl 21:24 0:05 /usr/bin/python3.7 /usr/bin/idle-python3.7
pi 1211 0.3 0.6 52492 25704 ? Sl 21:24 0:02 /usr/bin/python3.7 -c __import__('idlelib.run').run.main(True) 48843
pi 1328 0.0 0.0 3916 572 pts/2 S+ 21:36 0:00 grep --color=auto python
pi@raspberrypi:~ $ kill -KILL 1211

Killコマンドを実行したら、プログラムが走ったままだけど本当にKillしてもいいのか?って優しく忠告してくれるダイアログがShellターミナル上に表示された。OKをクリックしたらShellウインドウが閉じた。
この後Python Shellを再度立ち上げてプログラムを実行したらちゃんと動いたので、とりあえずキレイにKillできたみたい。

しかし、KeyboardInterrputが効かなくなるのは困る。。。

2020年10月12日 (月)

VNCサーバーとの付き合い方

VNCサーバーと付き合う事になった。

まず相手を迎えいれる。

# yum install tigervnc-server

次に相手を知る。

[root@localhost ~]# vncserver help

usage: vncserver [:<number>] [-name <desktop-name>] [-depth <depth>]
[-geometry <width>x<height>]
[-pixelformat rgbNNN|bgrNNN]
[-fp <font-path>]
[-cc <visual>]
[-fg]
[-autokill]
[-noxstartup]
[-xstartup <file>]
<Xvnc-options>...

vncserver -kill <X-display>

vncserver -list

で、実際に語り掛けてみる。
ここでnumberはポート590xのxになる。以下では7を指定しているのでポート5907でアクセスすることになる。カラーデプスは16bitに、画角は1280x800とした。パスワードを設定する。Read-Only Passwordはここでは設定しない。なお、このサーバーのIPアドレスは192.168.1.60となっている。

[root@localhost ~]# vncserver :7 -name PATHPILOT -depth 16 -geometry 1280x800

You will require a password to access your desktops.

Password:
Verify:
Would you like to enter a view-only password (y/n)? n
A view-only password is not used

New 'PATHPILOT' desktop is localhost.localdomain:7

Creating default startup script /root/.vnc/xstartup
Creating default config /root/.vnc/config
Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/localhost.localdomain:7.log

[root@localhost ~]#

VNC Viewerでアクセスしてみる。起動時に設定した名前はタイトルバーに現れた。

215536

見てもわかるように、クライアント(この場合はMac)でスクリーンショットを撮っている。Defaultではこれができない。スクリーンショットキーがVNC Server側に送られてしまうからのようだ。で、以下のようにSendSpecialKeysをFalseにすると、Macでスクリーンショットが撮れるようになる(で実際に撮ったわけ)。

215605

なお、この交際には邪魔者がいて、Firewallが立ちはだかる。なのでFirewallに止まってもらうか、ポートレンジとして例えば5901-5910を開けるなどする必要がある。

まずは交際初日の記録でした。

2020年10月11日 (日)

RestletにBasic認証を構成してみた

やっぱりRestletサーバーは守りたいので認証を実装するのは常道。そこでBasic認証を実験してみた。

まずRestletサーバー側の実装。認証保護の入れ物を作って、そこに保護するアプリケーションを投げ込む感じのようだ。

   String userid1="user1";
   String passwd1="pass";
// Basic認証で保護する入れ物をつくる。名前はPATHPilot-realm。
   ChallengeAuthenticator guard1 = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "PATHPilot-realm");
// IDとシークレットのVerifierをつくる。
   MapVerifier mapVerifier1 = new MapVerifier();
// useridとpasswordペアを登録する。
   mapVerifier1.getLocalSecrets().put(userid1, passwd1.toCharArray());
   guard1.setVerifier(mapVerifier1);
   Restlet restout1 = new DataOutput1().dataout;
// 入れ物にrestout1をいれる。入れられるものはRestletクラスのもの。
   guard1.setNext( restout1 );

   Component component = new Component();
   component.getServers().add(Protocol.HTTP, 8010);
// URIが/nextの場合にguard1に飛ぶ
   component.getDefaultHost().attach("/next",guard1);


認証保護の入れ物に投げ込んだアプリケーションは以下のとおり。

public class DataOutput1 extends Application {

   Restlet dataout = new Restlet(){
      @Override
      public void handle ( Request requet, Response response){

         response.setEntity(new StringRepresentation("hello, my friend from Next", MediaType.TEXT_PLAIN));

      }
   };
}

WEBブラウザー(Firefox)からアクセスしてみる。

http://192.168.1.62:8010/next

すると以下のポップアップが現れた。認証保護入れ物の名前のPATHPilot-realmも表示されている。

Auth

当然のことながら、user1/passと入力すると認証がパスして以下が表示される。違う組み合わせだと認証エラー。予定通りだ。

Auth2

次にRaspberry PiのPythonのコード実装に移る。

こちらは至って簡単で以下のコードを書くだけ。

import reqeusts
from requests.auth import HTTPBasicAuth

      response=requests.post("http://192.168.1.62:8010/next", auth=HTTPBasicAuth("user1","pass"))

reponseとして以下が返ってくる。
hello, my friend from Next

これで私のRaspberry PiとしかRestletサーバーは会話しないように出来る。めでたし、めでたし。

RestletでのAnnotationの続き

日曜日にやっと時間がとれたのでRestletのAnnotationの続きを試してみた。

RestletのAnnotationはパラメータを指定できる。で、それってどのように動作するのか試してみた。

以下のコードを用意

public class DataInput extends ServerResource {

   @Post ("txt")
   public String represent(Representation entity) {

      String str = getReference().getPath();
      System.out.println( str );
      return "Post:txt "+str;
   }


   @Post ("json")
   public String representjson(Representation entity) {

      String str = getReference().getPath();
      System.out.println( str );
      return "Post:json "+str;
   }

}

Restクライアントでは、まずは以下のPythonコードを実行した。

   response=request.post('http://192.168.1.62:8010/command/datain/temp", headers={'Content-Type':'text/plain'})

responseは Post:txt /command/datain/temp

次に以下を実行した。

   response=request.post('http://192.168.1.62:8010/command/datain/temp",headers={'Content-Type':'application/json'})

responseは Post:json /command/datain/temp

つまり、同じPOSTでもContent-Typeで実行するコードを使い分けることができるわけだ。

これは便利な気がする。

2020年10月10日 (土)

Bondで1日縛られた土曜日

とある事からBondを試すことになった。なんだかんだで結構時間がかかってしまって、朝から初めてもう外は薄暗くなってきてしまった。
で、いつものように備忘録。

環境はVMWare Player上の仮想サーバーのCentOS7.8。ネットワークアダプターは3つ用意して接続状態に設定。そのうち一つだけにIPアドレスを手動で設定しておくけれども、残り2つは何も事前設定しないでおく。

CentOSが立ち上がった直後のインターフェース状態は以下の通り。ens33だけにIPアドレスをセットしてある。

[root@localhost ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.60 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::20c:29ff:fe89:51ca prefixlen 64 scopeid 0x20<link>
inet6 240b:11:4541:9100:20c:29ff:fe89:51ca prefixlen 64 scopeid 0x0<global>
ether 00:0c:29:89:51:ca txqueuelen 1000 (Ethernet)
RX packets 74 bytes 6888 (6.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 82 bytes 9410 (9.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 00:0c:29:89:51:d4 txqueuelen 1000 (Ethernet)
RX packets 27 bytes 2082 (2.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 00:0c:29:89:51:de txqueuelen 1000 (Ethernet)
RX packets 27 bytes 2082 (2.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 68 bytes 5908 (5.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 68 bytes 5908 (5.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:b1:f3:35 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens33にはインターフェース情報が設定されていて、のこりの2つのネットワークデバイスのens37とens38はいずれもstateはUPになっているけれどもインターフェース情報は未設定。

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:89:51:ca brd ff:ff:ff:ff:ff:ff
inet 192.168.1.60/24 brd 192.168.1.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 240b:11:4541:9100:20c:29ff:fe89:51ca/64 scope global mngtmpaddr dynamic
valid_lft 2591893sec preferred_lft 604693sec
inet6 fe80::20c:29ff:fe89:51ca/64 scope link
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:89:51:d4 brd ff:ff:ff:ff:ff:ff
4: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:89:51:de brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:b1:f3:35 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:b1:f3:35 brd ff:ff:ff:ff:ff:ff

で、これらをまとめると現在はこんな状態。インターフェース名ens33に対してのみネットワークデバイスens33が紐づけられている。

[root@localhost ~]# nmcli c
NAME UUID TYPE DEVICE
ens33 5fe6b09c-d12c-456e-9b1f-1d018a789fd2 ethernet ens33
virbr0 3de4169c-88a9-424f-b931-52ae87288f01 bridge virbr0
ens37 23a1e399-5010-4b12-842e-f43fcb6fb36c ethernet --
ens38 204e9f07-1a89-4c28-9ef1-1e0f775f9352 ethernet --

BondingのMasterを作成する。接続名とインターフェース名の両方とも名前はbond0と命名。モードはactive-backup。

[root@localhost ~]# nmcli connection add type bond autoconnect no con-name bond0 ifname bond0 mode active-backup
接続 'bond0' (329498e1-1f6b-4ed5-9885-c1a401cc63dc) が正常に追加されました。

確認。bond0が作られている。

[root@localhost ~]# nmcli c
NAME UUID TYPE DEVICE
ens33 5fe6b09c-d12c-456e-9b1f-1d018a789fd2 ethernet ens33
virbr0 3de4169c-88a9-424f-b931-52ae87288f01 bridge virbr0
bond0 329498e1-1f6b-4ed5-9885-c1a401cc63dc bond --
ens37 23a1e399-5010-4b12-842e-f43fcb6fb36c ethernet --
ens38 204e9f07-1a89-4c28-9ef1-1e0f775f9352 ethernet --

ens37とens38をSlaveとしてMaster bond0に登録する。

[root@localhost ~]# nmcli connection add type bond-slave autoconnect no ifname ens37 master bond0
接続 'bond-slave-ens37' (a2516f43-5725-425f-80c0-f6226d125f84) が正常に追加されました。
[root@localhost ~]# nmcli connection add type bond-slave autoconnect no ifname ens38 master bond0
接続 'bond-slave-ens38' (5c1e4b8b-dc77-414b-8a91-3ab3cc809056) が正常に追加されました。

状況の確認。いずれもbond-slaveとして接続名が登録されている。

[root@localhost ~]# nmcli c
NAME UUID TYPE DEVICE
ens33 5fe6b09c-d12c-456e-9b1f-1d018a789fd2 ethernet ens33
virbr0 3de4169c-88a9-424f-b931-52ae87288f01 bridge virbr0
bond-slave-ens37 a2516f43-5725-425f-80c0-f6226d125f84 ethernet --
bond-slave-ens38 5c1e4b8b-dc77-414b-8a91-3ab3cc809056 ethernet --
bond0 329498e1-1f6b-4ed5-9885-c1a401cc63dc bond --
ens37 23a1e399-5010-4b12-842e-f43fcb6fb36c ethernet --
ens38 204e9f07-1a89-4c28-9ef1-1e0f775f9352 ethernet --

Masterであるbond0にIPアドレス等を設定する。

[root@localhost ~]# nmcli c mod bond0 ipv4.method manual ipv4.address "192.168.1.61/24" ipv4.gateway "192.168.1.1" ipv4.dns "192.168.1.1" ipv6.method ignore

以降のシステム再起動でens37とens38が自動で接続状態にならないように、かつbond-slave-ens37とbond-slave-ens38とbond0が自動で接続状態になるように設定する。つまり、ens37とens38は単独ではイネーブルにならないであくまでbond-slaveとしてイネーブルされることを明示的に設定するわけだ。

[root@localhost ~]# nmcli c m ens37 connection.autoconnect no
[root@localhost ~]# nmcli c m ens38 connection.autoconnect no
[root@localhost ~]# nmcli c m bond-slave-ens37 connection.autoconnect yes
[root@localhost ~]# nmcli c m bond-slave-ens38 connection.autoconnect yes
[root@localhost ~]# nmcli c m bond0 connection.autoconnect yes

設定状態を確認する。

[root@localhost ~]# nmcli -f connection c s bond-slave-ens37
connection.id: bond-slave-ens37
connection.uuid: a2516f43-5725-425f-80c0-f6226d125f84
connection.stable-id: --
connection.type: 802-3-ethernet
connection.interface-name: ens37
connection.autoconnect: はい
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 1602314980
connection.read-only: いいえ
connection.permissions: --
connection.zone: --
connection.master: bond0
connection.slave-type: bond
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: 不明
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)


[root@localhost ~]# nmcli -f connection c s bond-slave-ens38
connection.id: bond-slave-ens38
connection.uuid: 5c1e4b8b-dc77-414b-8a91-3ab3cc809056
connection.stable-id: --
connection.type: 802-3-ethernet
connection.interface-name: ens38
connection.autoconnect: はい
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 1602314980
connection.read-only: いいえ
connection.permissions: --
connection.zone: --
connection.master: bond0
connection.slave-type: bond
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: 不明
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)


[root@localhost ~]# nmcli -f connection c s bond0
connection.id: bond0
connection.uuid: 329498e1-1f6b-4ed5-9885-c1a401cc63dc
connection.stable-id: --
connection.type: bond
connection.interface-name: bond0
connection.autoconnect: はい
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 1602314980
connection.read-only: いいえ
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: 不明
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)

一連の変更を反映させるためにネットワークサービスの再起動を行う。

[root@localhost ~]# systemctl restart NetworkManager
[root@localhost ~]# systemctl restart network.service

出来上がった結果は以下のとおり。

[root@localhost ~]# nmcli c
NAME UUID TYPE DEVICE
ens33 5fe6b09c-d12c-456e-9b1f-1d018a789fd2 ethernet ens33
bond0 329498e1-1f6b-4ed5-9885-c1a401cc63dc bond bond0
virbr0 b8211a91-b2aa-4c8d-af4d-7207588fadff bridge virbr0
bond-slave-ens37 a2516f43-5725-425f-80c0-f6226d125f84 ethernet ens37
bond-slave-ens38 5c1e4b8b-dc77-414b-8a91-3ab3cc809056 ethernet ens38
ens37 23a1e399-5010-4b12-842e-f43fcb6fb36c ethernet --
ens38 204e9f07-1a89-4c28-9ef1-1e0f775f9352 ethernet --

 

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:89:51:ca brd ff:ff:ff:ff:ff:ff
inet 192.168.1.60/24 brd 192.168.1.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 240b:11:4541:9100:20c:29ff:fe89:51ca/64 scope global mngtmpaddr dynamic
valid_lft 2591984sec preferred_lft 604784sec
inet6 fe80::20c:29ff:fe89:51ca/64 scope link
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP group default qlen 1000
link/ether 00:0c:29:89:51:d4 brd ff:ff:ff:ff:ff:ff
4: ens38: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP group default qlen 1000
link/ether 00:0c:29:89:51:d4 brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:b1:f3:35 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:b1:f3:35 brd ff:ff:ff:ff:ff:ff
8: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:89:51:d4 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.61/24 brd 192.168.1.255 scope global noprefixroute bond0
valid_lft forever preferred_lft forever
inet6 240b:11:4541:9100:20c:29ff:fe89:51d4/64 scope global mngtmpaddr dynamic
valid_lft 2591984sec preferred_lft 604784sec
inet6 fe80::20c:29ff:fe89:51d4/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]#

そとから192.168.1.61でpingして疎通確認を行ってオッケー。

この作業を行って分かったことは、Bonding設定が終わるとSlaveに設定したens37とens38のMACアドレスが同じになる(末尾d4)ことと、Masterのbond0のMACアドレスも同じになること。試しにってことでもう一つSlaveを追加しても同じMACアドレスになった。ということはMasterのIPアドレスをこのMACアドレスに設定して、Slaveに設定したどのポートも外からは金太郎飴に見えるようにするってことなんだろうなぁ、、、とぼや~と理解した感じ(少なくともactive-standbyでは)。

まぁ、時間は費やしたけれど、新しい理解(ぼや~だけど)を得られたみたいだから良しとするか。

追記:
モニターの前から離れる前に、この理解は本当に正しいのかなぁって思ってちょっと調べてみたんだけれども、どうやら正しい感じだ。で、更に現在のBonding状態がActiveなSlaveの切り替え方法が見つかったので実際にやってみた。

[root@localhost ~]# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: None
Currently Active Slave: ens37
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: ens37
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:89:51:d4
Slave queue ID: 0

Slave Interface: ens38
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:89:51:de
Slave queue ID: 0

ActiveなSlaveを切り替えてみる。現在ens37がActive。
[root@localhost ~]# cat /proc/net/bonding/bond0 | grep Currently
Currently Active Slave: ens37

切り替え実行。

[root@localhost ~]# ifenslave -c bond0 ens38

切り替え確認。

[root@localhost ~]# cat /proc/net/bonding/bond0 | grep Currently
Currently Active Slave: ens38
[root@localhost ~]#

ちゃんと動いているようだ。めでたし、めでたし。

追記2:

Masterのbond0のIPアドレスは/etc/sysconfig/network-scripts/ifcfg-bond0にかかれているIPADDRを変更すれば良いが、変更後NetworkManagerやnetwork.serviceをrestartしただけではIPアドレスが更新されなかった。で、実際には以下を実行することで変更を反映させた。

# nmcli c down bond0
# nmcli c up bond0

これは知ってないとハマるところだろうなぁ。まぁ、たまたまnmcli c up コマンドを実行した直後にこの課題にぶつかったので、試しにこのコマンド投げてみたら、、、ってことに過ぎなかったから。

追記3:

いろいろと先人の知恵を学んでいるとどうやら正解は以下のようだ。

# nmcli c reload <接続名>   ここではbond0
# nmcli c down <接続名>
# nmcli c up <接続名>

2020年10月 9日 (金)

RestletでのAnnotationとは

RestletでのAnnotationって実はよく分かってなかった。そこで、実際はどういうものなのか簡単なコードを書いて確認してみた(今更感がありますが、、、)。

以下コードを書いてみた。このクラスはRouterから呼ばれている。URIが/command/で以下にDispatchしてくる。
重要なのは以下のDataInputがServerResourceのExtendsであること。
このClassはMethodとしてpost()、get()を備えている。

public class DataInput extends ServerResource {

    @Post
    public String represent(Representation entity) {

        String str = getReference().getPath();
        System.out.println( str );

        return "Post: "+str;
    }

    @Get
    public String getrep(Representation entity) {

        String str1 = getReference().getPath();
        System.out.println( str1 );

        return "get: " +str1;

    }

}

最初から結論を言うと、@Postはその直下のfunctionでpost() methodを置き換える。同様に@Getはその直下のfunctionでget()を置き換える。@Overrideはその直下のfunctionでそのクラスの同名methodを置き換えるのだけれども、@Postや@Getは置き換えるfunction名はなんもよいのだね。

では、このコードをクライアント上のPythonから呼んでみる。

まずはpostで呼んでみる。
response=requests.post("http://192.168.1.62:8010/command/datain/temp")

responseとして以下が返ってくる。
Post: /command/datain/temp

次にgetで呼んでみる。
response=requests.get("http://192.168.1.62:8010/command/datain/temp")

responseとして以下が返ってくる。
get: /command/datain/temp

URIは同じなので両方ともDataInput()が呼ばれる訳だけれども、その中でpost時に呼ばれるmethodとget時に呼ばれるmethodをそれぞれカスタマイズしたfunctionに置き換えるわけだ。

なるほど、なるほど。

2020年10月 4日 (日)

JSON形式のリクエストボディからkeyとvalueを抜き出す

Raspberry Piからの話しをRestletサーバーがちゃんと聞き分けられるように作業している。

RestletのパッケージからgetEntityAsFormが削除さている。これが使えると、指定したkeyのvalueが容易に取得できるんだけれども、それが使えない。

しょうがないのでリクエストボディをgetEntityAsTextで文字列として取得してから、keyを探し出して、その直後にあるダブルクォーテーションで囲まれた文字列を抜き出すコードを書いてみた。なんだか年寄りの書いた古臭いコードだけれども備忘録として書いておく。

ちなみにkeyは"temp"、そのvalueは文字列としての温度数値。

public String represent(Representation entity) {

   String str = getReference().getPath();
   System.out.println( str );
   int index = str.indexOf("/datain/");
   index += "/datain/".length();
   String indata = str.substring(index);
   System.out.println("keyword:" + indata );

   String key = "temp";

   String pline = getRequest().getEntityAsText();
   System.out.println("request body:"+pline); /* {"temp": "27.123"} */

   index = pline.indexOf(key+"\":");
   index += key.length() + 1;
   String temp = pline.substring(index, pline.length()); /* コロンの後の文字列 */
   System.out.println( temp );

   index = temp.indexOf("\"");
   temp = temp.substring(index+1,temp.length()); /* 最初のダブルクォーテーション以後の文字列 */
   System.out.println( temp );

   int last_index = temp.indexOf("\"");
   temp = temp.substring(0,last_index); /* 最初のダブルクォーテーションまでの文字列 */
   System.out.println("temp="+temp);   /* コロン直後のダブルクォーテーションに挟まれた文字列 */


return pline;

以上

Raspberry Piからの語りかけ、リクエストボディの違い

Raspberry PiからRestletサーバーに話かけるんだけれど、どうもcurlとは違う会話をするようで、調べてみた。

会話の違いを調べるため、Restletサーバー上で以下のコードを書いてみた。

@Post
public String represent(Representation entity) {

  String str = getReference().getPath();
  System.out.println( str );
  String pline = getRequest().getEntityAsText();
  System.out.println("request body:"+pline);

このRestサーバーにcurlとpythonからリクエスト投げてみた

curl

>curl -X POST http://192.168.1.62:8010/command/datain/temp -d {"temp":123, "humi":345}

Restサーバーのアウトプット

/command/datain/temp
request body:'{temp:123,humi:354}'
2020-10-04 12:04:03 192.168.1.12 - - 8010 POST /command/datain/temp - 200 18 21 1 http://192.168.1.62:8010 curl/7.65.2 -

Python

s = str(inputValue)  #温度センサーから読み取った値
response = requests.post('http://192.168.1.62:8010/command/datain/temp', {'temp':s})

Restサーバーのアウトプット

/command/datain/temp
request body:temp=28.0625
2020-10-04 12:04:38 192.168.1.17 - - 8010 POST /command/datain/temp - 200 18 12 1 http://192.168.1.62:8010 python-requests/2.21.0 -

なんとリクエストボディの中身が違う。
curlはjson形式で送るのに対して、Pythonはデータとして送っているのか?
調べてみるとcurlの-dオプションはjson形式でリクエストボディを送るようだ。
では、Pythonでjson形式でリクエストボディを送ることが出来ればよいことになる(同じデータを送るという意味で)。
で、調べてみるとデータ形式をjsonに変換して送る方法がある。早速試してみる。

payload = {'temp': s }
response=requests.post("http://192.168.1.62:8010/command/datain/temp", json.dumps(payload), headers={'Content-Type':'application/json'})

実行してみた結果は期待通り。

/command/datain/temp
keyword:temp
request body:{"temp": "28.1875"}
2020-10-04 12:47:14 192.168.1.17 - - 8010 POST /command/datain/temp - 200 19 19 3 http://192.168.1.62:8010 python-requests/2.21.0 -

明示的にjson.dumpsを使ってJSON化しないとdataとして送られてしまうようだ。
めでたし、めでたし。と思ったけれど、どうもおかしい。

Pythonと同じデータをcurlで渡すと以下になる。

curl -X POST http://192.168.1.62:8010/command/datain/temp -d {"temp":"34.567"}

/command/datain/temp
keyword:temp
request body:{temp:34.567}
temp=567}
2020-10-04 15:31:18 192.168.1.12 - - 8010 POST /command/datain/temp - 200 13 13 0 http://192.168.1.62:8010 curl/7.65.2 -

ダブルクォーテーションが付かないのだ。つまりKeyもValueも文字列扱いがされていない。

これはどうしたら良いのだろう???

いろいろ調べてみると、-dオプションでRESTリクエストでjson形式データを送る場合は、以下のように設定しないと”が文字化けするとある。

-d {\"temp\":\"34.567\"}

つまり、\(逆スラッシュ)を付けてエスケープ(文字列化)してやる必要があるそうな。

この方法でcurlを投げたら以下となった。

request body: {"temp":"34.567"}

とりあえずcurlで-dオプション付き(JSON形式リクエストボディ)でRESTリクエストが送れるようになった。つまりPythonと同じリクエストボディを送ることができるようになったわけだ。

« 2020年9月 | トップページ | 2020年11月 »