OpenvSwitchとnamespaceで仮想ネットワークにVLANを構築する

■概要

今回はOpen vSwitchとnetwork namespaceの機能を使って一台のマシンの中に仮想的なVLANネットワークを構築します。
今回作る構成は下の図のような感じです。
OS : Ubuntu16.04

f:id:k-midorikawa:20161105140446j:plain


■参考

http://app.f.m-cocolog.jp/t/typecast/1766421/1776113/88010845


■Open vSwitchのインストール

Open vSwitchをインストールし、サービスを起動します。

$ sudo -i
# apt install openvswitch-switch
# systemctl start openvswitch-switch

■仮想VLANの構築

この章では、namespaceとOVSブリッジを用いて仮想的なVLANを構築し、同一VLANタグを持つインターフェース同士が通信できることを確認します。

OVSブリッジの作成

VLANインターフェースを持つovs1とovs2を作成します。

# ovs-vsctl add-br ovs1
# ovs-vsctl add-br ovs2

namespaceの作成

OVSブリッジに接続するnamespaceを作成します。

# ip netns add ns1
# ip netns add ns2
# ip netns add ns3
# ip netns add ns4

vethの作成

OVSブリッジとnamespaceを接続するveth(仮想的なLANケーブル)を作成します。
※指定されている2つの名前(ns1ovs1, ovs1ns1など)はLANケーブルの両端を表します。
※今回の命名規則は「接続元」+「接続先」となっています。

# ip link add name ns1ovs1 type veth peer name ovs1ns1
# ip link add name ns2ovs1 type veth peer name ovs1ns2
# ip link add name ns3ovs2 type veth peer name ovs2ns3
# ip link add name ns4ovs2 type veth peer name ovs2ns4

OVSブリッジ同士を接続するvethを作成します。

# ip link add name ovs1ovs2 type veth peer name ovs2ovs1

vethの接続

namespaceとOVSブリッジをvethで接続します。

namespaceにvethを接続

# ip link set ns1ovs1 netns ns1
# ip link set ns2ovs1 netns ns2
# ip link set ns3ovs2 netns ns3
# ip link set ns4ovs2 netns ns4

OVSブリッジにvethを接続
ns1,ns3を接続するポートにはVLANタグ10を、ns2,ns4を接続するポートにはVLANタグ20を割り当てます。

# ovs-vsctl add-port ovs1 ovs1ns1 tag=10
# ovs-vsctl add-port ovs1 ovs1ns2 tag=20
# ovs-vsctl add-port ovs2 ovs2ns3 tag=10
# ovs-vsctl add-port ovs2 ovs2ns4 tag=20

OVSブリッジ同士を接続

# ovs-vsctl add-port ovs1 ovs1ovs2
# ovs-vsctl add-port ovs2 ovs2ovs1

バイスをUP

OVSブリッジをUPします。

# ip link set ovs1 up
# ip link set ovs2 up

OVSブリッジ同士を接続しているvethをUPします。

# ip link set ovs1ovs2 up
# ip link set ovs2ovs1 up

OVSに接続したvethをUPします。

# ip link set ovs1ns1 up
# ip link set ovs1ns2 up
# ip link set ovs2ns3 up
# ip link set ovs2ns4 up

namespaceに接続したvethをUPします。

# ip netns exec ns1 ip link set ns1ovs1 up
# ip netns exec ns2 ip link set ns2ovs1 up
# ip netns exec ns3 ip link set ns3ovs2 up
# ip netns exec ns4 ip link set ns4ovs2 up

namespace内のループバックアドレスをUPします。

# ip netns exec ns1 ip link set lo up
# ip netns exec ns2 ip link set lo up 
# ip netns exec ns3 ip link set lo up
# ip netns exec ns4 ip link set lo up

IPアドレスの割当

namespaceに接続したvethにIPアドレスを割り当てます。

# ip netns exec ns1 ip addr add 192.168.122.10/24 dev ns1ovs1
# ip netns exec ns2 ip addr add 192.168.122.20/24 dev ns2ovs1
# ip netns exec ns3 ip addr add 192.168.122.30/24 dev ns3ovs2
# ip netns exec ns4 ip addr add 192.168.122.40/24 dev ns4ovs2

動作確認

同じVLANタグを持つインターフェース同士が通信できることを確認します。

tag=10を持つns1とns3の通信

# ip netns exec ns1 ping 192.168.122.30
# ip netns exec ns3 ping 192.168.122.10

tag=20を持つns2とns4の通信

# ip netns exec ns2 ping 192.168.122.40
# ip netns exec ns4 ping 192.168.122.20

異なるVLANタグを持つインターフェース同士が通信できないことを確認します。

ns1(tag=10)からns2,ns4(tag=20)への通信

# ip netns exec ns1 ping 192.168.122.20
# ip netns exec ns1 ping 192.168.122.40

ns2(tag=20)からns1,ns3(tag=10)への通信

# ip netns exec ns2 ping 192.168.122.10
# ip netns exec ns2 ping 192.168.122.30

■インターネットに接続

この章では、先ほど作ったnamespaceからインターネットにアクセスできるようにする設定を行います。

外部ネットワーク接続用ブリッジの作成

ホストのnic(ens3)に接続するためのブリッジを作成します。

# ip link add br-ex type bridge

ホストのnic(ens3)にbr-exを接続します。

# ip link set ens3 master br-ex

ホストのnic(ens3)に割り当てられているIPアドレスを削除します。

# ip addr del 192.168.122.6/24 dev ens3

OVSブリッジとbr-exの接続

OVSブリッジとbr-exを接続するためのvethを作成します。

# ip link add name tag10brex type veth peer name brextag10
# ip link add name tag20brex type veth peer name brextag20

OVSブリッジとbr-exを接続します。

# ip link set brextag10 master br-ex
# ip link set brextag20 master br-ex
# ovs-vsctl add-port ovs1 tag10brex tag=10
# ovs-vsctl add-port ovs1 tag20brex tag=20

バイスをUP

br-exをUPします。

# ip link set br-ex up

OVSブリッジに接続したvethをUPします。

# ip link set tag10brex up
# ip link set tag20brex up

br-exに接続したvethをUPします。

# ip link set brextag10 up
# ip link set brextag20 up

ルーティングの設定

namespace内にデフォルトゲートウェイ(192.168.122.1)を設定します。

# ip netns exec ns1 ip route add default via 192.168.122.1
# ip netns exec ns2 ip route add default via 192.168.122.1
# ip netns exec ns3 ip route add default via 192.168.122.1
# ip netns exec ns4 ip route add default via 192.168.122.1

インターネットに接続できるか確認

それぞれのnamespaceからインターネットに接続できるか確認してみます。

# ip netns exec ns1 curl -kIL www.google.com
# ip netns exec ns2 curl -kIL www.google.com
# ip netns exec ns3 curl -kIL www.google.com
# ip netns exec ns4 curl -kIL www.google.com

■後片付け

OVSブリッジを削除します。

# ovs-vsctl del-br ovs1
# ovs-vsctl del-br ovs2

ipコマンドで作った資材はリブートすると揮発します。

# reboot

Ubunu16.04でOpenVPNサーバーを作る

■概要

今回は図のような構成でVPNサーバーを立て、外のネットワークから、自宅のネットワークに安全に接続できるようにします。 サーバーOS : Ubuntu16.04 クライアントOS : Ubuntu16.04

f:id:k-midorikawa:20161103211545j:plain


■参考資料


ルーターの設定

外部ネットワークから、自宅のネットワークへの接続を許可するためにグローバルIPの1194番ポート宛の通信をVPNサーバーの1194番ポート(192.168.10.11:1194)にフォワーディングする必要があります。
※設定の仕方はルーターによって異なりますが、私が使っているルーターだと下のような感じになりました。

f:id:k-midorikawa:20161103212119p:plain


VPNサーバーの設定

OpenVPNのインストール

openvpnとeasy-rsaをインストールします。

$ sudo -i
# apt update
# apt install -y openvpn easy-rsa

設定ファイルを準備します。

# mkdir /etc/openvpn/easy-rsa/
# cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
# cd /etc/openvpn/easy-rsa

認証局の準備

今回は自己認証局を利用するので、VPNサーバー内で認証局証明書と認証局秘密鍵を作成します。

はじめに、認証局の所在地や組織名を決めます。(任意の値で良いです)

# vim vars

以下の内容を設定します。

export KEY_COUNTRY="JP"
export KEY_PROVINCE="Saitama"
export KEY_CITY="Niiza"
export KEY_ORG="Example Company"
export KEY_EMAIL="hoge@example.com"
export KEY_OU="MyVPN"
export KEY_NAME="MyVPN"
export KEY_CN="MyVPN"
export KEY_ALTNAMES="MyVPN"

環境変数を読み込み、認証局証明書(ca.crt)、認証局秘密鍵(ca.key)作成します。
(/etc/openvpn/easy-rsa/keysにca.crtとca.keyが生成されます。)

# source vars
# ./clean-all
# ./build-ca

./build-caを実行するといくつか質問されますが、すべてEnterを押してください。

Generating a 2048 bit RSA private key
(中略)
Country Name (2 letter code) [JP]: ★Enter
State or Province Name (full name) [Saitama]: ★Enter
Locality Name (eg, city) [Niiza]: ★Enter
Organization Name (eg, company) [Example Company]: ★Enter
Organizational Unit Name (eg, section) [MyVPN]: ★Enter
Common Name (eg, your name or your server's hostname) [MyVPN]: ★Enter
Name [MyVPN]: ★Enter
Email Address [hoge@example.com]: ★Enter

サーバーで必要な鍵の作成

サーバー秘密鍵(server.key)、サーバー証明書(server.crt)を作成します。
(/etc/openvpn/easy-rsa/keysにserver.crtとserver.keyが生成されます。)

# ./build-key-server server

実行するといろいろ聞かれますが、すべてEnterを押してください。[y/n]の質問にはyと答えてください。

Generating a 2048 bit RSA private key
(中略)
Country Name (2 letter code) [JP]: ★Enter
State or Province Name (full name) [Saitama]: ★Enter
Locality Name (eg, city) [Niiza]: ★Enter
Organization Name (eg, company) [Example Company]: ★Enter
Organizational Unit Name (eg, section) [MyVPN]: ★Enter
Common Name (eg, your name or your server's hostname) [server]: ★Enter
Name [MyVPN]: ★Enter
Email Address [hoge@example.com]: ★Enter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: ★Enter
An optional company name []: ★Enter
(中略)
Sign the certificate? [y/n]: ★y


1 out of 1 certificate requests certified, commit? [y/n] ★y
Write out database with 1 new entries
Data Base Updated

DH鍵を作成します。※時間がかかります
(/etc/openvpn/easy-rsa/keysにdh2048.pemが生成されます。)

# ./build-dh

tls-auth鍵を作成します。
(/etc/openvpn/easy-rsa/keysにta.keyが生成されます。)

# cd keys
# openvpn --genkey --secret ta.key

サーバー証明書、サーバー秘密鍵認証局証明書、DH鍵、tls-auth鍵を/etc/openvpnにコピーします。

# cp server.crt server.key ca.crt dh2048.pem ta.key /etc/openvpn

クライアントで必要な鍵の作成

クライアント秘密鍵(client.key)、クライアント証明書(client.crt)を作成します。
(/etc/openvpn/easy-rsa/keysにclient1.crtとclient1.keyが生成されます。)

# cd /etc/openvpn/easy-rsa
# source vars
# ./build-key client1

実行するといろいろ聞かれますが、すべてEnterを押してください。[y/n]の質問にはyと答えてください。

Generating a 2048 bit RSA private key
(中略)
Country Name (2 letter code) [JP]: ★Enter
State or Province Name (full name) [Saitama]: ★Enter
Locality Name (eg, city) [Niiza]: ★Enter
Organization Name (eg, company) [Example Company]: ★Enter
Organizational Unit Name (eg, section) [MyVPN]: ★Enter
Common Name (eg, your name or your server's hostname) [server]: ★Enter
Name [MyVPN]: ★Enter
Email Address [hoge@example.com]: ★Enter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: ★Enter
An optional company name []: ★Enter
(中略)
Sign the certificate? [y/n]: ★y


1 out of 1 certificate requests certified, commit? [y/n] ★y
Write out database with 1 new entries
Data Base Updated

ここまで完了したら、/etc/openvpn/easy-rsa/keys配下のca.crt, ta.key, client1.key, client1.crtを安全な方法でクライアントとなる端末に転送してください。

コンフィグファイルの編集

# cd /etc/openvpn/
# vim /etc/openvpn/server.conf

下記を設定

port 1194
proto tcp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
mode server
tls-server
tls-auth ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3

その他設定

ipv4のフォワーディングを有効にします。

# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# sysctl -p

ログの初期設定を行います。

# journalctl --identifier ovpn-server

OpenVPNサーバー起動

openvpnサービスを起動します。

# systemctl start openvpn
# systemctl start openvpn@server

サービスが正常に起動しているか確認します。

# systemctl status openvpn
# systemctl status openvpn@server

トンネルデバイスが生成されているか確認します。

# ifconfig tun0

VPNクライアントの設定

OpenVPNのインストール

openvpnとeasy-rsaをインストールします。

$ sudo -i
# apt update
# apt install -y openvpn

先ほどサーバーから転送したca.crt, ta.key, client1.crt, client1.keyを/etc/openvpn配下に配置します。
※下記パーミッションとなっていることを確認してください。

-rw-r--r--   1 root root  1704 11月  3 19:19 ca.crt
-rw-r--r--   1 root root  5437 11月  3 22:09 client1.crt
-rw-------   1 root root  1704 11月  3 22:09 client1.key
-rw-------   1 root root   636 11月  3 21:42 ta.key

コンフィグファイルの編集

# cd /etc/openvpn/
# vim /etc/openvpn/client.conf

下記を設定

client
dev tun
proto tcp
remote xx.xx.xx.xx 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
ca ca.crt
cert client1.crt
key client1.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-128-CBC
comp-lzo
verb 3

※xx.xx.xx.xxにはVPNサーバーがあるネットワークのグローバルIPを設定してください。
グローバルIPを調べるにはVPNサーバーで下記コマンドを実行してください。

$ curl inet-ip.info

OpenVPNの起動

VPNサーバーとは異なるネットワークで起動してください。 openvpnを起動します。

# systemctl start openvpn
# systemctl start openvpn@client

サービスが正常に起動しているか確認します。

# systemctl status openvpn
# systemctl status openvpn@client

トンネルデバイスが生成されているか確認します。

$ ifconfig tun0

VPNサーバーにpingが通るか確認します。

pign 10.8.0.1

■おまけ

上記の設定だと、VPNサーバー以外のノードにアクセスするには、一旦VPNサーバーにログインしたあとにアクセスしなければいけません。 以下の設定に変更すると、クライアントから、VPNサーバー以外のノードに直接アクセスできるようになります。

f:id:k-midorikawa:20161103235854j:plain

サーバー側の設定

サーバー側の設定ファイルを下記のように変更します。

# vim /etc/openvpn/server.conf
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.10.0 255.255.255.0"
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 192.168.10.1"
keepalive 10 120
mode server
tls-server
tls-auth ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
fragment 1280
mssfix 1280
link-mtu 1400

IPマスカレードの設定を行います。※この設定は再起動すると揮発します。

下記はソースアドレスが10.8.0.0/24で、eth0(vpnで直接繋ぎたいセグメント)を通過するパケットのソースアドレスをeth0に設定されているアドレスに書き換える設定です。 これによって、vpnクライアントから内部ネットワークへのパケットはvpnサーバーを経由してクライアント返ってくるようになります。

# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

openvpnサービスを起動します。

# systemctl start openvpn
# systemctl start openvpn@server

サービスが正常に起動しているか確認します。

# systemctl status openvpn
# systemctl status openvpn@server

トンネルデバイスが生成されているか確認します。

# ifconfig tun0

クライアント側の設定

サーバー側の設定ファイルを下記のように変更します。
※xx.xx.xx.xxにはVPNサーバーがあるネットワークのグローバルIPを設定してください。

# vim /etc/openvpn/client.conf
client
proto udp
dev tun
remote xx.xx.xx.xx 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
ca ca.crt
cert client1.crt
key client1.key
ns-cert-type server
remote-cert-tls server
tls-auth ta.key 1
cipher AES-128-CBC
comp-lzo
verb 3
fragment 1280
mssfix 1280
link-mtu 1400

※下記はVPNサーバーとは異なるネットワークで行ってください。

openvpnを起動します。

# systemctl start openvpn
# systemctl start openvpn@client

サービスが正常に起動しているか確認します。

# systemctl status openvpn
# systemctl status openvpn@client

トンネルデバイスが生成されているか確認します。

$ ifconfig tun0

VPNサーバーにpingが通るか確認します。

pign 192.168.10.11

VPNサーバー以外のノードにpingが通るか確認します。

pign 192.168.10.12

仮想ディスクでLVMの操作をしてみる

今回は、ファイルを仮想ディスク(ブロックデバイス)化し、LVMの作成、拡張、削除などを行う。 OS : Ubuntu16.04

■準備

$ sudo -i
# mkdir /tmp/lvm_test
# cd /tmp/lvm_test

■仮想ディスクの作成

ブロックデバイスにするファイルを作成する。

# dd if=/dev/zero of=disk.img bs=1M count=1200

作成したdisk.imgを空いているループバックデバイスに割り当てる

# losetup -f disk.img

確認

★disk.imgにループバックデバイスが割り当てられているか確認
# losetup -l
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         0  0 /tmp/lvm_test/disk.img

ディスクラベルを作成

# parted -s -a optimal /dev/loop0 mklabel gpt

パーティションを作成。
今回は基本パーティションを3つ作成する。

# parted -s -a optimal /dev/loop0 mkpart primary 0% 30%
# parted -s -a optimal /dev/loop0 mkpart primary 30% 60%
# parted -s -a optimal /dev/loop0 mkpart primary 60% 100%

パーティションのディスクフォーマットをlinux lvmに設定する。

# parted -s -a optimal /dev/loop0 set 1 lvm on
# parted -s -a optimal /dev/loop0 set 2 lvm on
# parted -s -a optimal /dev/loop0 set 3 lvm on

確認

★フラグlvmの基本パーティションが3つ作成されている。
# parted /dev/loop0 p
モデル: Loopback デバイス (loopback)
ディスク /dev/loop0: 1258MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始    終了    サイズ  ファイルシステム  名前     フラグ
 1    1049kB  377MB   376MB                     primary  lvm
 2    377MB   755MB   377MB                     primary  lvm
 3    755MB   1257MB  502MB                     primary  lvm

★作成されたパーティションと同数の仮想デバイスファイルが生成されている。
# lsblk
NAME                  MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                     8:0    0 119.2G  0 disk 
├─sda1                  8:1    0   487M  0 part /boot
├─sda2                  8:2    0     1K  0 part 
└─sda5                  8:5    0 118.8G  0 part 
  ├─ubuntu--vg-root   252:0    0 114.9G  0 lvm  /
  └─ubuntu--vg-swap_1 252:1    0   3.9G  0 lvm  [SWAP]
loop0                   7:0    0   1.2G  0 loop 
├─loop0p1             259:0    0   359M  0 loop 
├─loop0p2             259:1    0   360M  0 loop 
└─loop0p3             259:2    0   479M  0 loop 

■LVMの作成

LVMの作成は下の様な手順で行う [PVの作成]->[PVをVGに登録]->[VGからLVを作成]->[LVをマウント]

PV(フィジカルボリューム)の作成

/dev/loop0p1と/dev/loop0p2をPVとして登録する

# pvcreate /dev/loop0p1 /dev/loop0p2

確認

★/dev/loop0p1と/dev/loop0p2がPVに登録されている。
# pvdisplay
  "/dev/loop0p1" is a new physical volume of "359.00 MiB"
  --- NEW Physical volume ---
  PV Name               /dev/loop0p1
  VG Name               
  PV Size               359.00 MiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               xihABl-WX3v-1JYW-lV4v-EL4A-P8VK-fqkrts
   
  "/dev/loop0p2" is a new physical volume of "360.00 MiB"
  --- NEW Physical volume ---
  PV Name               /dev/loop0p2
  VG Name               
  PV Size               360.00 MiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               74Pt3v-oXmk-RGyx-ynEk-VyAY-5aRZ-L31j0M

VG(ボリュームグループ)の作成

先ほど作成したPVをtest_vgという名前のVGに登録する。

# vgcreate test_vg /dev/loop0p1 /dev/loop0p2

確認

★test_vgという新しいVGが作成されている。
vgdisplay
  --- Volume group ---
  VG Name               test_vg
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               712.00 MiB
  PE Size               4.00 MiB
  Total PE              178
  Alloc PE / Size       0 / 0   
  Free  PE / Size       178 / 712.00 MiB
  VG UUID               Qapao3-sI8J-1TFN-5lFW-HFlN-P3fJ-A9QU7k

★PVを確認してもtest_vgに登録されたことがわかる。
# pvdisplay
  --- Physical volume ---
  PV Name               /dev/loop0p1
  VG Name               test_vg
  PV Size               359.00 MiB / not usable 3.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              89
  Free PE               89
  Allocated PE          0
  PV UUID               xihABl-WX3v-1JYW-lV4v-EL4A-P8VK-fqkrts
   
  --- Physical volume ---
  PV Name               /dev/loop0p2
  VG Name               test_vg
  PV Size               360.00 MiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              89
  Free PE               89
  Allocated PE          0
  PV UUID               74Pt3v-oXmk-RGyx-ynEk-VyAY-5aRZ-L31j0M

LV(ロジカルボリューム)を作成する

先ほど作成したtest_vgからtest_lvというロジカルボリュームを切り出す。

# lvcreate -L 600M -n test_lv test_vg

確認

★ロジカルボリュームを作成すると、/dev/<VG名>/<LV名>というデバイスマッパー生成される。
# lvdisplay
  --- Logical volume ---
  LV Path                /dev/test_vg/test_lv
  LV Name                test_lv
  VG Name                test_vg
  LV UUID                LFYF2y-S49k-jrdn-pwaY-jLAs-qlqE-mtnJwk
  LV Write Access        read/write
  LV Creation host, time dynabook, 2016-10-12 08:29:34 +0900
  LV Status              available
  # open                 0
  LV Size                600.00 MiB
  Current LE             150
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:2

マウント

先ほど作成したLVのファイルシステムext4にフォーマットする。

# mkfs.ext4 /dev/test_vg/test_lv

マウント

# mount -t ext4 /dev/test_vg/test_lv /mnt/work-mido/lvm/

確認

★/mnt/work-mido/lvmに/dev/test_vg/test_lvがマウントされている
# df -Th
Filesystem                  Type      Size  Used Avail Use% Mounted on
udev                        devtmpfs  1.9G     0  1.9G   0% /dev
tmpfs                       tmpfs     385M  6.2M  379M   2% /run
/dev/mapper/ubuntu--vg-root ext4      113G   55G   53G  51% /
tmpfs                       tmpfs     1.9G  316K  1.9G   1% /dev/shm
tmpfs                       tmpfs     5.0M  4.0K  5.0M   1% /run/lock
tmpfs                       tmpfs     1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sda1                   ext2      472M  155M  293M  35% /boot
cgmfs                       tmpfs     100K     0  100K   0% /run/cgmanager/fs
tmpfs                       tmpfs     385M   60K  385M   1% /run/user/1000
/dev/mapper/test_vg-test_lv ext4      575M  468K  533M   1% /mnt/work-mido/lvm

アンマウント

# umount /mnt/work-mido/lvm

■VGとLVの拡張

/dev/loop0p3を新たにtest_vgに登録し、test_lvを900MBに拡張する。
/dev/loop0p3をPVに登録する

# pvcreate /dev/loop0p3

test_vgに/dev/loop0p3を追加する

# vgextend test_vg /dev/loop0p3

test_lvを拡張する

# lvextend -L 900M /dev/test_vg/test_lv

■LVの縮小

test_lvを300MBに縮小する。
ファイルシステムのチェックを行う。

# e2fsck -f /dev/test_vg/test_lv 

ファイルシステムを300MBに縮小する

# resize2fs /dev/test_vg/test_lv 300M

test_lvを縮小する。

# lvreduce -L 300M /dev/test_vg/test_lv 

■VGの縮小

test_vgから/dev/loop0p3を削除する。

# vgreduce test_vg /dev/loop0p3

■PVの削除

/dev/loop0p3のPVとしての登録を解除する。

# pvremove /dev/loop0p3

■LVの削除

test_lvを削除する。

# lvremove /dev/test_vg/test_lv

■VGの削除

test_vgを削除する。

# vgremove test_vg 

■後片付け

# pvremove /dev/loop0p1 /dev/loop0p2
# losetup -d /dev/loop0
# rm disk.img

仮想ディスクでパーティションの作成とマウント

今回は、ファイルを仮想ディスク(ブロックデバイス)化し、パーティションファイルシステムを作成する。(おまけでマウントまで行う)
OSはUbuntu16.04

準備

$ sudo -i
# mkdir /tmp/sample
# cd /tmp/sample



仮想ディスクを作成する

仮想ディスクとなるファイルdisk.imgを作成し、ddコマンドで1000MBまでファイルをゼロ埋め。

# touch disk.img
# dd if=/dev/zero of=disk.img bs=1M count=1000


先ほど作成したdisk.imgをループバックデバイスとして登録する。

# losetup /dev/loop0 disk.img


ループバックデバイスがブロックデバイスとして認識されているか確認。

# lsblk
NAME                  MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                     8:0    0 119.2G  0 disk 
├─sda1                  8:1    0   487M  0 part /boot
├─sda2                  8:2    0     1K  0 part 
└─sda5                  8:5    0 118.8G  0 part 
  ├─ubuntu--vg-root   252:0    0 114.9G  0 lvm  /
  └─ubuntu--vg-swap_1 252:1    0   3.9G  0 lvm  [SWAP]
loop0                   7:0    0  1000M  0 loop   ★認識されている



パーティションを作成する

先ほど作成したループバックデバイス(/dev/loop0)にディスクラベルを作成する。(今回はmsdos)
ディスクサイズが2TBを超える場合は、ディスクラベルにgptを設定する。

# parted -s -a optimal /dev/loop0 mklabel msdos


続いてパーティションを作成する。今回は基本パーティションを3つ作成。

# parted -s -a optimal /dev/loop0 mkpart primary 0% 30%
# parted -s -a optimal /dev/loop0 mkpart primary 30 60%
# parted -s -a optimal /dev/loop0 mkpart primary 60% 100%


パーティションが作成されているか確認する。

# parted /dev/loop0 p
モデル: Loopback デバイス (loopback)
ディスク /dev/loop0: 1049MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos  ★ディスクラベルはmsdos
ディスクフラグ: 

番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    1049kB  315MB   314MB   primary   ★0%-30%までの基本パーティション
 2    315MB   629MB   315MB   primary   ★30%-60%までの基本パーティション
 3    629MB   1049MB  419MB   primary   ★60%-100%までの基本パーティション


パーティションを作成すると、ループバックデバイスにもパーティションに対応するデバイスが自動的に生成される。

# ls -alF /dev/loop0p*
brw-rw---- 1 root disk 259,   0 10月  5 22:18 /dev/loop0p1
brw-rw---- 1 root disk 259,   1 10月  5 22:18 /dev/loop0p2
brw-rw---- 1 root disk 259,   2 10月  5 22:18 /dev/loop0p3



ファイルシステムを作成する。

ubuntu16.04のデフォルトのファイルシステムであるext4で各パーティションをフォーマットする。

# mkfs -t ext4 /dev/loop0p1
# mkfs -t ext4 /dev/loop0p2
# mkfs -t ext4 /dev/loop0p3


ファイルシステムができているか確認する。

# parted /dev/loop0 p
モデル: Loopback デバイス (loopback)
ディスク /dev/loop0: 1049MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ: 

番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    1049kB  315MB   314MB   primary  ext4  ★ext4で作成されている
 2    315MB   629MB   315MB   primary  ext4
 3    629MB   1049MB  419MB   primary  ext4



パーティションをマウント

マウント用のディレクトリを作成する。

# mkdir part{1,2,3}


パーティションを先ほど作成したディレクトリにマウントする。

# mount -t ext4 /dev/loop0p1 /tmp/sample/part1
# mount -t ext4 /dev/loop0p2 /tmp/sample/part2
# mount -t ext4 /dev/loop0p3 /tmp/sample/part3


マウントされているか確認する。

# df -Th
Filesystem                  Type      Size  Used Avail Use% Mounted on
udev                        devtmpfs  1.9G     0  1.9G   0% /dev
tmpfs                       tmpfs     385M  6.2M  379M   2% /run
/dev/mapper/ubuntu--vg-root ext4      113G   54G   54G  50% /
tmpfs                       tmpfs     1.9G  4.8M  1.9G   1% /dev/shm
tmpfs                       tmpfs     5.0M  4.0K  5.0M   1% /run/lock
tmpfs                       tmpfs     1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sda1                   ext2      472M  200M  249M  45% /boot
cgmfs                       tmpfs     100K     0  100K   0% /run/cgmanager/fs
tmpfs                       tmpfs     385M   76K  385M   1% /run/user/1000
/dev/loop0p1                ext4      282M  2.1M  261M   1% /tmp/sample/part1   ★マウントされている
/dev/loop0p2                ext4      283M  2.1M  262M   1% /tmp/sample/part2
/dev/loop0p3                ext4      380M  2.3M  354M   1% /tmp/sample/part3


ということで、今回はこんなところで一通り終了。


後片付け

パーティションをアンマウントする。

# umount /tmp/sample/part1
# umount /tmp/sample/part2
# umount /tmp/sample/part3


ループバックデバイスを解除する。

# losetup -d /dev/loop0

確認

# losetup -l
★何も表示されなければうまく解除出来ている

virtualenvでPython3.5の隔離環境を作成する

今回はubuntu16.04にvirtualenvをインストールしてPython3.5の隔離環境を作成する。
よくやり方を忘れるので、、、

python3.5にpipをインストール


ルートユーザーになる

sudo -i

リポジトリを更新してpipをインストール

apt update
apt install python3-pip

virtualenvをインストール


pipをアップデートしてvirtualenvをインストール

pip3 install --upgrade pip
pip3 install virtualenv

virtualenvを使って隔離環境を作成する


~/myenvに隔離環境を作成

virtualenv -p /usr/bin/python3 ~/myenv

隔離環境をアクティベート

source ~/myenv/bin/activate



以後、Pythonインタープリタの起動や、Pythonスクリプトを実行、pipによるパッケージのインストールは、全て隔離環境のPythonで行われる。
確かめたい人は以下のコマンドでPythonのパスがどこにあるか見てみると良い。

which python

隔離環境の使用を終了するときは

deactivate

隔離環境を削除するときは

rm -r ~/myenv

Ubuntu15.04でpipでMatplotlibがインストールできない件

matplotlibのドキュメント(Installing — Matplotlib 1.4.3 documentation)にはこんな感じで書いてありました。

 

Linux : using your package manager

If you are on Linux, you might prefer to use your package manager. matplotlib is packaged for almost every major Linux distribution.

 

Ubuntuでインストールするときはapt-get使おうねってことなんですが、ここで問題が、、、

この方法だと、どうやってもvirtualenv環境にはインストールできないですね。

 

pipでのインストール方法を探すと、ありました。さすがスタックオーバーフロー。

python - Pip install Matplotlib error with virtualenv - Stack Overflow

 

どうやら先に、libpng-devとlibjpeg8-devとlibfreetype6-devをapt-getでインストールしておくと、うまくいくみたいです。

:~$ sudo apt-get install libpng-dev libjpeg8-dev libfreetype6-dev
:~$ workon hoge
(hoge):~$pip3 install matplotlib

うまくインストール出来ました。

 

 

CodeKata第二問 : 素数判定 @Python3.4

今日は素数判定ということで、与えられた数字が素数かどうかを判定するプログラムを作って行きたいと思います。

例によって、いい書き方があれば教えてください。m(_ _)m

 

問題

与えられた数が素数であるかどうかを調べなさい。

また、与えられた数までの素数を列挙しなさい。

 

 

考え方

まず素数の定義は「1と対象となる数以外には約数がない正の整数」です。

ちなみに「1」は素数ではありません。

この時点で、「負の整数」、「0」、「1」、「2以外の偶数」は素数となりえません。

よって、上記の数が入力された場合は「素数ではない」と判断します。

上記以外の整数nに関しては、nを2~(n-1)までの数で順に割っていって、あまりが0になるパターンがあれば「素数ではない」、なければ「素数」というように判断していきます。

 

 

コード


def prime_num(n):
    #n=2であったら「素数」
    if n == 2:
        return True
        
    #nが2より小さい or 偶数であれば「素数ではない」
    if (n < 2) or (n % 2 == 0):
        return False
        
    #nを2~(n-1)までの数で割り、あまりが0となるパターンがあれば「素数ではない」
    for i in range(2,n):
        if n % i == 0:
            return False
    #「if n % i == 0:」に引っかからずfor文が終われば「素数」
    return True

if __name__ == "__main__":
    for n in range(101):            #1〜100までの数を素数判定する
        print("{} {}".format(n,prime_num(n)))

 

解説

引数に取った数が素数であればTrue、素数でなければFalseを返す関数を作成しました。

1〜100までの数を素数判定し、順に出力していくコードはmainに記述しました。

今回は、考え方で書いた内容をそのままコードに起こした、という感じです。

ただ、偶数を判定するときに2を除外しておかないと、2をFalse と判定してしまうため、2のみ一番初めにif文で判定するようにしています。

あとは特筆すべきところは特にない気がします。

 

今回使用した要素


>>>"hello {}".format("world")   #文字列の中の{}に引数に取った値を代入する
'hello world'

>>>for i in range(5):
...    "{}".format(i)
...
'0'
'1'
'2'
'3'
'4'