はじめに
以前投稿した「IPアドレスの管理方法を考える①」では、IPアドレスを管理する専用のファンクションを作成して、実験的なIPアドレス管理方法を提案してみた。
今回はより実践的なIPアドレス情報の管理方法を考えてみよう。
ネットワークとサーバ(ノード)の関係
コンピュータ・ネットワークは2つ以上のコンピュータ(サーバ)を結び相互に通信することを可能にするので、1つのネットワークには複数のサーバ(ノード)が存在する。
一方、1台のサーバはクライアントにサービスを提供するためのサービス・セグメントだけでなく、運用や監視のために運用管理セグメントに接続されていることが一般的だ。つまり1台のサーバにも複数のネットワークが存在している。(複数のネットワークに「足を出す」)
すなわち、ネットワークとサーバには多対多の関係が成り立つのでリレーショナル・データベースではこれらをそのまま管理することはできない。
このため、ネットワークとサーバの間に別のエンティティを持ってきて、2つの一対多関係を組み合わせるモデルとする必要がある。
この中間エンティティは文字通りの「ネットワーク・インターフェース」となる。具体的にはサーバに挿さった複数のNIC(ネットワーク・インターフェース・カード)上のポートとなる。
そしてこれらのポートを識別するのがIPアドレスとなる。
1枚のNICに仮想IP(VIP)として複数のIPアドレスを割り当てることもできるが、このようなモデルを導入すれば仮想IPも管理することができる。
IPアドレス、ネットワークアドレス、サブネットマスクの関係(おさらい)
TCP/IPは1つのIPアドレスでネットワークとノードをまとめて表すことができるのが特徴である。
IPv4 32bitアドレスは、ネットワークを識別する上位のネットワーク部とノードを識別する下位のホスト部に分けられる。
ホスト部のビットが全て0となっているIPアドレスは、ネットワークを識別するアドレスとして特に「ネットワークアドレス」と呼ばれる。
ネットワーク部とホスト部を示すための情報がサブネットマスクで、IPアドレスの32bit値とBIT AND演算(論理積)を施したものがネットワークアドレスとなる。
つまり、IPアドレスが論理的にあるネットワークに属していることを表すことに必要な情報がサブネットマスクであるとも言える。
例:
IPアドレス :192.168. 1.1(11000000 10101000 00000001 00000001)
+
サブネットマスク :255.255.255.0(11111111 11111111 11111111 00000000)
------------------------------------------------------------------
ネットワークアドレス :192.168. 1.0(11000000 10101000 00000001 00000000)
データベースでIPをアドレスを管理するためには、制約等でこれらの関係を考慮する仕組みを考える必要がある。
テーブル等作成(DDL)
上のER図を基に、テーブル等を作成するDDLを紹介する。
DDL
DROP TABLE NETWORK_INTERFACE PURGE; DROP TABLE NETWORKS PURGE; DROP TABLE SERVER PURGE; -- ネットワーク CREATE TABLE NETWORKS ( NETWORK_ADDRESS NUMBER(12,0) NOT NULL, SUBNET_MASK NUMBER(12,0) NOT NULL, DEFAULT_GATEWAY NUMBER(12,0) NOT NULL, BROADCAST_ADDRESS NUMBER(12,0) NOT NULL, NETWORK_NAME VARCHAR2(30) NOT NULL, REMARKS VARCHAR2(2000) ); ALTER TABLE NETWORKS ADD(CONSTRAINT PK_NETWORK PRIMARY KEY (NETWORK_ADDRESS, SUBNET_MASK) USING INDEX) ; -- ネットワークインターフェース CREATE TABLE NETWORK_INTERFACE ( IP_ADDRESS NUMBER(12,0) NOT NULL, NETWORK_ADDRESS NUMBER(12,0) NOT NULL, SUBNET_MASK NUMBER(12,0) NOT NULL, INTERFACE_NAME VARCHAR2(30) NOT NULL, HOST_NAME VARCHAR2(30), SERVER_ID NUMBER(5,0), REMARKS VARCHAR2(2000) ); ALTER TABLE NETWORK_INTERFACE ADD(CONSTRAINT PK_NETWORK_INTERFACE PRIMARY KEY (IP_ADDRESS) USING INDEX) ; ALTER TABLE NETWORK_INTERFACE ADD(CONSTRAINT CHK_NETWORK CHECK (BITAND(IP_ADDRESS,SUBNET_MASK)=NETWORK_ADDRESS)) ; -- サーバ CREATE TABLE SERVER ( SERVER_ID NUMBER(5,0) NOT NULL, NODE_NAME VARCHAR2(30) NOT NULL, SERVER_GROUP_ID NUMBER(5,0) NOT NULL, OS_RELEASE_ID NUMBER(5,0) NOT NULL, REMARKS VARCHAR2(2000) ); ALTER TABLE SERVER ADD(CONSTRAINT PK_SERVER PRIMARY KEY (SERVER_ID) USING INDEX) ; -- 参照整合性制約 ALTER TABLE NETWORK_INTERFACE ADD(CONSTRAINT FK_NETWORK_INTERFACE FOREIGN KEY(NETWORK_ADDRESS, SUBNET_MASK) REFERENCES NETWORKS (NETWORK_ADDRESS, SUBNET_MASK)) ; ALTER TABLE NETWORK_INTERFACE ADD(CONSTRAINT FK_SERVER_NETWORK_INTERFACE FOREIGN KEY(SERVER_ID) REFERENCES SERVER (SERVER_ID)) ;
解説
ネットワーク(4行目〜)
原則的にIPアドレス関連は32bit値を10進数表現した形で格納する。「IPアドレスの管理方法を考える①」で紹介したinet_aton関数およびinet_ntoa関数を挿入あるいは参照時に利用する。
ネットワーク・インターフェース(19行目〜)
ネットワーク表の子表であるがIPアドレスでユニークに識別できるのでIPアドレスのみを主キーにしている。(サブネットマスクとネットワークアドレスは外部キー)
(多対多リレーションを解決する関連エンティティは主キーを複合主キーとする(この場合はサーバIDとネットワークアドレス+サブネットマスク)場合が多いが、サーバ情報はネットワーク情報がある状態で登録する(つまり後で更新する)イメージなので、あえて非依存関係のモデルとしている。)
チェック制約(CHK_NETWORK)で、挿入されるIPアドレスの論理的妥当性(ネットワークアドレスとの整合性)確認を行っている。
サーバ(39行目〜)
サーバのデータ作成に関しては次回とするので今回は割愛。
参照整合性制約(52行目〜)
参照整合性制約(外部キー制約)を作成する際のTipsとしては一番最後に実行するのがよい。
データ作成と確認
環境が整ったところで、実際にデータを作成してみよう。
サンプルとして
「Oracle VM VirtualBox を用いた Oracle Real Application Clusters (RAC) 12c Release 1 環境の構築」
の「2.4 ネットワーク p.9〜」にあるネットワーク情報のデータを作成してみる。
NETWORKS表
DML
INSERT INTO NETWORKS VALUES ( INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,INET_ATON('192.168.56.1') ,INET_ATON('192.168.56.255') ,'PUBLIC NETWORK' ,'パブリック・ネットワーク' ); INSERT INTO NETWORKS VALUES ( INET_ATON('192.168.100.0') ,INET_ATON('255.255.255.0') ,INET_ATON('192.168.100.1') ,INET_ATON('192.168.100.255') ,'PRIVATE NETWORK1' ,'プライベート・ネットワーク1' ); INSERT INTO NETWORKS VALUES ( INET_ATON('192.168.200.0') ,INET_ATON('255.255.255.0') ,INET_ATON('192.168.200.1') ,INET_ATON('192.168.200.255') ,'PRIVATE NETWORK2' ,'プライベート・ネットワーク2' ); COMMIT;
確認
SQL> col DEFAULT_GATEWAY for a16 SQL> col NETWORK_NAME for a17 SQL> SELECT 2 INET_NTOA(NETWORK_ADDRESS) NETWORK_ADDRESS 3 ,INET_NTOA(SUBNET_MASK) SUBNET_MASK 4 ,INET_NTOA(DEFAULT_GATEWAY) DEFAULT_GATEWAY 5 ,NETWORK_NAME 6 FROM 7 NETWORKS; NETWORK_ADDRESS SUBNET_MASK DEFAULT_GATEWAY NETWORK_NAME ---------------- ---------------- ---------------- ----------------- 192.168.56.0 255.255.255.0 192.168.56.1 PUBLIC NETWORK 192.168.100.0 255.255.255.0 192.168.100.1 PRIVATE NETWORK1 192.168.200.0 255.255.255.0 192.168.200.1 PRIVATE NETWORK2
NETWORK_INTERFACE表
DML
INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.101') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.102') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.201') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0:1'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.202') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0:2'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.203') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0:3'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.56.254') ,INET_ATON('192.168.56.0') ,INET_ATON('255.255.255.0') ,'eth0'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.100.101') ,INET_ATON('192.168.100.0') ,INET_ATON('255.255.255.0') ,'eth1'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.100.102') ,INET_ATON('192.168.100.0') ,INET_ATON('255.255.255.0') ,'eth1'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.200.101') ,INET_ATON('192.168.200.0') ,INET_ATON('255.255.255.0') ,'eth2'); INSERT INTO NETWORK_INTERFACE ( IP_ADDRESS ,NETWORK_ADDRESS ,SUBNET_MASK ,INTERFACE_NAME) VALUES ( INET_ATON('192.168.200.102') ,INET_ATON('192.168.200.0') ,INET_ATON('255.255.255.0') ,'eth2'); COMMIT;
確認
SQL> col IP_ADDRESS for a16 SQL> col NETWORK_ADDRESS for a16 SQL> col SUBNET_MASK for a16 SQL> col INTERFACE_NAME for a16 SQL> SELECT 2 INET_NTOA(IP_ADDRESS) IP_ADDRESS 3 ,INET_NTOA(SUBNET_MASK) SUBNET_MASK 4 ,INTERFACE_NAME 5 FROM 6 NETWORK_INTERFACE; IP_ADDRESS SUBNET_MASK INTERFACE_NAME ---------------- ---------------- ---------------- 192.168.56.101 255.255.255.0 eth0 192.168.56.102 255.255.255.0 eth0 192.168.56.201 255.255.255.0 eth0:1 192.168.56.202 255.255.255.0 eth0:2 192.168.56.203 255.255.255.0 eth0:3 192.168.56.254 255.255.255.0 eth0 192.168.100.101 255.255.255.0 eth1 192.168.100.102 255.255.255.0 eth1 192.168.200.101 255.255.255.0 eth2 192.168.200.102 255.255.255.0 eth2 10行が選択されました。
チェック制約の確認
間違ったIPアドレスをエラーとするチェック制約の動作を確認する。
SQL> INSERT INTO NETWORK_INTERFACE ( 2 IP_ADDRESS 3 ,NETWORK_ADDRESS 4 ,SUBNET_MASK 5 ,INTERFACE_NAME) 6 VALUES ( 7 INET_ATON('192.168.57.101') <== 第2オクテットをわざと間違えてInsert 8 ,INET_ATON('192.168.56.0') 9 ,INET_ATON('255.255.255.0') 10 ,'eth0'); INSERT INTO NETWORK_INTERFACE ( * 行1でエラーが発生しました。: ORA-02290: チェック制約(CM.CHK_NETWORK)に違反しました
今回はここまで