LDAP Server 前端Openldap + 后端Mysql Cluster
- 摘要:此处假定你已经熟悉LDAP协议,Openldap和Mysql Cluster的基本概念。我们可以用Openldap+Mysql Cluster来构建企业级或者电信级统一的用户数据管理,以下是理想的逻辑模型:Load Balancer可以采用F5或者LVS等,Openldap本身不直接提供对NDB访问的Distribution Access Layer机制。
- 为简化起见,本次实验只会用到下面的实验模型:一台32位Linux虚拟机, 由于Mysql Cluster是内存数据库,带有4G内存的Laptop中只能启动2个Data Node,而且所有的实验节点都在同一台VM
- 安装Mysql Cluster
- Extract mysql-cluster-gpl-7.2.12-linux2.6-i686.tar.gz to “/usr/local/mysql-cluster-gpl-7.2.12-linux2.6-i686”
-
ln -s /usr/local/mysql-cluster-gpl-7.2.12-linux2.6-i686 /usr/local/mysqlc # 将/usr/local/mysqlc/bin/:/usr/local/mysqlc/scripts/添加到PATH echo "/usr/local/mysqlc/lib" >> /etc/ld.so.conf ldconfig -v
- 安装Openldap
- 安装openssl-1.0.1e
cd ./openssl-1.0.1e ./Configure --prefix=/usr/local/ssl make make install
- 安装BerkeleyDB db-5.3.21.gz
cd ./db-5.3.21 cd build_unix ../dist/configure --prefix=/usr/local/BerkeleyDB make make install
echo "/usr/local/BerkeleyDB/lib" >> /etc/ld.so.conf
ldconfig -v - 安装Openldap mysql-cluster-gpl-7.2.12-linux2.6-i686.tar.gz
cd ./openldap-2.4.26 export CPPFLAGS="-I/usr/local/BerkeleyDB/include -I/usr/local/ssl/include -I/usr/local/ssl/include/openssl" LDFLAGS="-L/usr/local/BerkeleyDB/lib -L/usr/local/ssl/lib" ./configure --with-tls=openssl --enable-ndb --enable-meta --enable-ldap --enable-dynamic --prefix=/usr/local/openldap make depend make make install
# 将 /usr/local/openldap/bin/:/usr/local/openldap/sbin/:/usr/local/openldap/libexec/ 添加到PATH
- 安装openssl-1.0.1e
- 配置Mysql Cluster
- 本实验在同一台机器VM上配置2套Mysql Cluster, 鉴于内存有限,每一套Mysql Cluster配置1一个Data Node,3个API Node(2个也可以),一个MGM Node. 以root用户启动Openldap和Mysql Cluster
- 配置第一套Mysql Cluster作为Master
# Config master cluster mkdir -p /root/ws/mysql_cluster/test3/sql1/conf mkdir -p /root/ws/mysql_cluster/test3/sql1/log mkdir -p /root/ws/mysql_cluster/test3/sql1/mgmt_data mkdir -p /root/ws/mysql_cluster/test3/sql1/mysqld_data mkdir -p /root/ws/mysql_cluster/test3/sql1/ndb_data
# cat /root/ws/mysql_cluster/test3/sql1/conf/config.ini [ndb_mgmd default] datadir=/root/ws/mysql_cluster/test3/sql1/mgmt_data [ndb_mgmd] hostname=localhost logdestination=FILE:filename=/root/ws/mysql_cluster/test3/sql1/log/megm.log NodeId=1 portnumber=1186 [ndbd default] noofreplicas=1 datadir=/root/ws/mysql_cluster/test3/sql1/ndb_data LockPagesInMainMemory=1 DataMemory=16M IndexMemory=15M FragmentLogFileSize=8M NoOfFragmentLogFiles=8 [ndbd] hostname=localhost NodeId=3 [mysqld] hostname=localhost NodeId=50 [mysqld] hostname=localhost NodeId=51 [mysqld] hostname=localhost NodeId=52
# cat /root/ws/mysql_cluster/test3/sql1/conf/my.cnf [mysqld] ndbcluster datadir=/root/ws/mysql_cluster/test3/sql1/mysqld_data basedir=/usr/local/mysqlc port=3306 socket=/root/ws/mysql_cluster/test3/sql1/mysqld_data/mysql.socket general_log=1 general_log_file=/root/ws/mysql_cluster/test3/sql1/log/query.log log_error=/root/ws/mysql_cluster/test3/sql1/log/error.log log-bin=/root/ws/mysql_cluster/test3/sql1/mysqld_data/binlogs #Database name which can be replicated. Please keep it as the same in Openldap config file mentioned later. binlog-do-db=openldap
- 配置第二套Mysql Cluster作为Slave
# Config master cluster mkdir -p /root/ws/mysql_cluster/test3/sql2/conf mkdir -p /root/ws/mysql_cluster/test3/sql2/log mkdir -p /root/ws/mysql_cluster/test3/sql2/mgmt_data mkdir -p /root/ws/mysql_cluster/test3/sql2/mysqld_data mkdir -p /root/ws/mysql_cluster/test3/sql2/ndb_data
# cat /root/ws/mysql_cluster/test3/sql2/conf/config.ini [ndb_mgmd default] datadir=/root/ws/mysql_cluster/test3/sql2/mgmt_data [ndb_mgmd] hostname=localhost logdestination=FILE:filename=/root/ws/mysql_cluster/test3/sql2/log/megm.log NodeId=1
#Here we installed 2 clusters on the same VM, so it's mandatory to change the second cluster mgm port from default 1186 to other port like 1286 portnumber=1286 [ndbd default] noofreplicas=1 datadir=/root/ws/mysql_cluster/test3/sql2/ndb_data LockPagesInMainMemory=1 DataMemory=16MM IndexMemory=15M FragmentLogFileSize=8M NoOfFragmentLogFiles=8 [ndbd] hostname=localhost NodeId=3 [mysqld] hostname=localhost NodeId=50 [mysqld] hostname=localhost NodeId=51 [mysqld] hostname=localhost NodeId=52# cat /root/ws/mysql_cluster/test3/sql2/conf/my.cnf [mysqld] ndbcluster datadir=/root/ws/mysql_cluster/test3/sql2/mysqld_data basedir=/usr/local/mysqlc
# Here we installed 2 clusters on the same VM, so it's mandatory to change mysqld listening port from default 3306 to other ports like 3406 port=3406 socket=/root/ws/mysql_cluster/test3/sql2/mysqld_data/mysql.socket general_log=1 general_log_file=/root/ws/mysql_cluster/test3/sql2/log/query.log log_error=/root/ws/mysql_cluster/test3/sql2/log/error.log # Replicate database "openldap" from master to slave replicate-do-db=openldap skip-slave-start slave_allow_batching=1 relay-log-purge=1 slave-net-timeout=10
- 启动Master Cluster
- Start the Management Node and Data Node
-
#cd /usr/local/mysqlc
#./scripts/mysql_install_db --no-defaults --datadir=/root/ws/mysql_cluster/test3/sql1/mysqld_data
# Start Management node
#ndb_mgmd --skip-config-cache --ndb-nodeid=1 --initial -f /root/ws/mysql_cluster/test3/sql1/conf/config.ini# Start ndb node
#ndbmtd --ndb-nodeid=3 --ndb-connectstring=localhost:1186 --initial-start# Please wait node node to be from "starting" state to "started" as below:
# ndb_mgm -e show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 1 node(s)
id=3 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12, Nodegroup: 0, Master)
[ndb_mgmd(MGM)] 1 node(s)
id=1 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12)
[mysqld(API)] 3 node(s)
id=50 (not connected, accepting connect from localhost)
id=51 (not connected, accepting connect from localhost)
id=52 (not connected, accepting connect from localhost) - After Ndb started, please Start one API node(Actually Openldap tool will use it for provision data and as master to handle replication)
# mysqld --defaults-file=/root/ws/mysql_cluster/test3/sql1/conf/my.cnf --port=3306 --skip-name-resolve --ndb-nodeid=50 --ndb-connectstring=localhost:1186 --user=root --datadir=/root/ws/mysql_cluster/test3/sql1/mysqld_data --server-id=20001 & # ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 1 node(s) id=3 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12, Nodegroup: 0, Master) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12) [mysqld(API)] 3 node(s) id=50 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12) id=51 (not connected, accepting connect from localhost) id=52 (not connected, accepting connect from localhost)
-
# you can use below commands to log in to the cluster to check status and grant privilege to slave mysql -uroot --socket /root/ws/mysql_cluster/test3/sql1/mysqld_data/mysql.socket mysql -uroot -h 127.0.0.1 -P 3306 mysql> grant all privileges on *.* to 'root'@'<your VM IP>' identified by ''; mysql> grant all privileges on *.* to 'root'@'127.0.0.1' identified by ''; mysql> grant all privileges on *.* to 'root'@'localhost' identified by '';
- Check Master status
# mysql -uroot -h 127.0.0.1 -P 3306 mysql> show master status; +----------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +----------------+----------+--------------+------------------+ | binlogs.000001 | 112 | openldap | | +----------------+----------+--------------+------------------+ 1 row in set (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ndbinfo | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
- 启动Slave Cluster
- Start the Management Node and Data Node
#cd /usr/local/mysqlc #./scripts/mysql_install_db --no-defaults --datadir=/root/ws/mysql_cluster/test3/sql2/mysqld_data # Start slave mgm node #ndb_mgmd --skip-config-cache --ndb-nodeid=1 --initial -f /root/ws/mysql_cluster/test3/sql2/conf/config.ini #Start slave ndb node ndbmtd --ndb-nodeid=3 --ndb-connectstring=localhost:1286 --initial-start
# Please wait node node to be from "starting" state to "started" as below: # ndb_mgm -c localhost:1286 -e show Connected to Management Server at: localhost:1286 Cluster Configuration --------------------- [ndbd(NDB)] 1 node(s) id=3 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12, Nodegroup: 0, Master) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12) [mysqld(API)] 3 node(s) id=50 (not connected, accepting connect from localhost) id=51 (not connected, accepting connect from localhost) id=52 (not connected, accepting connect from localhost) - After Ndb started, please Start one API node(as slave to do replication)
# mysqld --defaults-file=/root/ws/mysql_cluster/test3/sql2/conf/my.cnf --port=3316 --skip-name-resolve --ndb-nodeid=50 --ndb-connectstring=localhost:1286 --user=root --datadir=/root/ws/mysql_cluster/test3/sql2/mysqld_data --server-id=20011 & # ndb_mgm -c localhost:1286 -e show Connected to Management Server at: localhost:1286 Cluster Configuration --------------------- [ndbd(NDB)] 1 node(s) id=3 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12, Nodegroup: 0, Master) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12) [mysqld(API)] 3 node(s) id=50 @127.0.0.1 (mysql-5.5.30 ndb-7.2.12) id=51 (not connected, accepting connect from localhost) id=52 (not connected, accepting connect from localhost)
# you can use below commands to log in to the cluster to check status and grant privilege to slave mysql -uroot --socket /root/ws/mysql_cluster/test3/sql2/mysqld_data/mysql.socket mysql -uroot -h 127.0.0.1 -P 3316 mysql> grant all privileges on *.* to 'root'@'<your VM IP>' identified by ''; mysql> grant all privileges on *.* to 'root'@'127.0.0.1' identified by ''; mysql> grant all privileges on *.* to 'root'@'localhost' identified by '';
- Change master configuration on Slave cluster as
# mysql -uroot -h 127.0.0.1 -P 3316 mysql> change master to master_host='localhost', master_port=3306, master_user='root'; mysql> start slave; mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: localhost Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: binlogs.000001 Read_Master_Log_Pos: 112 Relay_Log_File: Ubuntu-VM1-relay-bin.000002 Relay_Log_Pos: 261 Relay_Master_Log_File: binlogs.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: openldap Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 112 Relay_Log_Space: 427 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 20001 Master_Bind: 1 row in set (0.00 sec)
- Start the Management Node and Data Node
- 启动Openldap Server
- Schema 准备,这里不创建新的Schema文件,使用Openldap自带的Schema
- 配置slapd.conf(Openldap Server 配置文件):
1 root@Ubuntu-VM1:~/ws/ldap/test4# cat slapd.conf 2 # slapd.conf - Configuration file for LDAP SLAPD 3 ########## 4 # Basics # 5 ########## 6 include /usr/local/openldap/etc/openldap/schema/core.schema 7 include /usr/local/openldap/etc/openldap/schema/cosine.schema 8 include /usr/local/openldap/etc/openldap/schema/inetorgperson.schema 9 include /usr/local/openldap/etc/openldap/schema/nis.schema 10 pidfile /usr/local/openldap/var/run/slapd.pid 11 argsfile /usr/local/openldap/var/run/slapd.args 12 loglevel 255 13 #modulepath /usr/local/openldap/lib 14 # modulepath /usr/local/libexec/openldap 15 #moduleload back_hdb 16 ########################## 17 # Database Configuration # 18 ########################## 19 database ndb 20 suffix "dc=example,dc=com" 21 rootdn "cn=Manager,dc=example,dc=com" 22 rootpw secret 23 dbconnect localhost 24 dbhost 127.0.0.1 25 dbname openldap 26 #dbsocket /tmp/mysql.sock 27 dbport 3306 28 dbuser root 29 dbpass "" 30 #dbflag 0 31 dbconnections 1 32 directory /usr/local/openldap/var/openldap-data
- 初始数据规划
##共5条DN记录
Initial Data
- 数据文件 test.ldif
##共5条DN记录
root@Ubuntu-VM1:~/ws/ldap/test4# cat test.ldif dn: dc=example,dc=com objectClass: dcObject objectClass: organizationalUnit dc: example ou: Example Dot Com dn: ou=people,dc=example,dc=com objectClass: organizationalUnit ou: people dn: ou=groups,dc=example,dc=com objectClass: organizationalUnit ou: groups dn: cn=example,ou=groups,dc=example,dc=com objectClass: posixGroup cn: example gidNumber: 10000 dn: uid=lionel,ou=people,dc=example,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: lionel sn: Porcheron givenName: Lionel cn: Lionel Porcheron displayName: Lionel Porcheron uidNumber: 1000 gidNumber: 10000 gecos: Lionel Porcheron loginShell: /bin/bash homeDirectory: /home/lionel shadowExpire: -1 shadowFlag: 0 shadowWarning: 7 shadowMin: 8 shadowMax: 999999 shadowLastChange: 10877 mail: lionel.porcheron@example.com postalCode: 31000 l: Toulouse o: Example mobile: +33 (0)6 xx xx xx xx homePhone: +33 (0)5 xx xx xx xx title: System Administrator postalAddress: initials: LP - 用Debug模式启动Openldap server(这里建议开始时启动Debug模式,配置一切OK以后再重新启动Daemon进程)
# slapd -d 255 -f slapd.conf #以下为控制台输出,表示成功连接Master NDB 518c9177 slapd startup: initiated. 518c9177 backend_startup_one: starting "cn=config" 518c9177 config_back_db_open Backend ACL: access to * by * none 518c9177 config_back_db_open: line 0: warning: cannot assess the validity of the ACL scope within backend naming context 518c9177 config_back_db_open: No explicit ACL for back-config configured. Using hardcoded default 518c9177 config_build_entry: "cn=config" 518c9177 config_build_entry: "cn=schema" 518c9177 >>> dnNormalize: <cn={0}core> 518c9177 <<< dnNormalize: <cn={0}core> 518c9177 config_build_entry: "cn={0}core" 518c9177 >>> dnNormalize: <cn={1}cosine> 518c9177 <<< dnNormalize: <cn={1}cosine> 518c9177 config_build_entry: "cn={1}cosine" 518c9177 >>> dnNormalize: <cn={2}inetorgperson> 518c9177 <<< dnNormalize: <cn={2}inetorgperson> 518c9177 config_build_entry: "cn={2}inetorgperson" 518c9177 >>> dnNormalize: <cn={3}nis> 518c9177 <<< dnNormalize: <cn={3}nis> 518c9177 config_build_entry: "cn={3}nis" 518c9177 config_build_entry: "olcDatabase={-1}frontend" 518c9177 config_build_entry: "olcDatabase={0}config" 518c9177 config_build_entry: "olcDatabase={1}ndb" 518c9177 backend_startup_one: starting "dc=example,dc=com" 518c9177 ndb_db_open: "dc=example,dc=com" 518c9178 slapd starting 518c9178 daemon: added 4r listener=(nil) 518c9178 daemon: added 7r listener=0x8396740 518c9178 daemon: added 8r listener=0x83a0638 518c9178 daemon: epoll: listen=7 active_threads=0 tvp=NULL 518c9178 daemon: epoll: listen=8 active_threads=0 tvp=NULL 518c9178 daemon: activity on 1 descriptor 518c9178 daemon: activity on:518c9178 518c9178 daemon: epoll: listen=7 active_threads=0 tvp=NULL 518c9178 daemon: epoll: listen=8 active_threads=0 tvp=NULL
##检查Master的状态 #mysql -uroot -h 127.0.0.1 -P 3306 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ndbinfo | | openldap | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec) mysql> show master status; +----------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +----------------+----------+--------------+------------------+ | binlogs.000001 | 1708 | openldap | | +----------------+----------+--------------+------------------+ 1 row in set (0.00 sec) mysql> use openldap; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +--------------------+ | Tables_in_openldap | +--------------------+ | OL_dn2id | | OL_nextid | | OL_opattrs | +--------------------+ 3 rows in set (0.00 sec) mysql> use openldap mysql> select count(*) from OL_dn2id, OL_nextid, OL_opattrs; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)
##检查Slave Cluster的状态
#mysql -uroot -h 127.0.0.1 -P 3316 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ndbinfo | | openldap | | performance_schema | | test | +--------------------+ 6 rows in set (0.03 sec) mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: localhost Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: binlogs.000001 Read_Master_Log_Pos: 1708 Relay_Log_File: Ubuntu-VM1-relay-bin.000002 Relay_Log_Pos: 1857 Relay_Master_Log_File: binlogs.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: openldap Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1708 Relay_Log_Space: 2023 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 20001 Master_Bind: 1 row in set (0.00 sec) mysql> use openldap mysql> show tables; +--------------------+ | Tables_in_openldap | +--------------------+ | OL_dn2id | | OL_nextid | | OL_opattrs | +--------------------+ 3 rows in set (0.00 sec) mysql> select count(*) from OL_dn2id, OL_nextid, OL_opattrs; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.01 sec) mysql> desc OL_dn2id; +----------------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------------+------+-----+---------+-------+ | eid | bigint(20) unsigned | NO | UNI | NULL | | | object_classes | varchar(1024) | NO | | NULL | | | a0 | varchar(128) | NO | PRI | | | | a1 | varchar(128) | NO | PRI | | | | a2 | varchar(128) | NO | PRI | | | | a3 | varchar(128) | NO | PRI | | | | a4 | varchar(128) | NO | PRI | | | | a5 | varchar(128) | NO | PRI | | | | a6 | varchar(128) | NO | PRI | | | | a7 | varchar(128) | NO | PRI | | | | a8 | varchar(128) | NO | PRI | | | | a9 | varchar(128) | NO | PRI | | | | a10 | varchar(128) | NO | PRI | | | | a11 | varchar(128) | NO | PRI | | | | a12 | varchar(128) | NO | PRI | | | | a13 | varchar(128) | NO | PRI | | | | a14 | varchar(128) | NO | PRI | | | | a15 | varchar(128) | NO | PRI | | | +----------------+---------------------+------+-----+---------+-------+ 18 rows in set (0.00 sec)
- Provision Data via LDAP client
- Openldap提供了一些Tool来Provison 数据,例如ldapadd(运行它之前必须先启动Openldap Server的进程“slapd”), slapadd(不需要启动slapd, 该工具将直接将数据导入NDB, 命令形式如slapadd -d 255 -f slapd.conf -l test.ldif), 这里我们用ldapadd, 所以我们在前一步已经启动了slapd进程
root@Ubuntu-VM1:~/ws/ldap/test4# ldapadd -x -D "cn=Manager,dc=example,dc=com" -w secret -d 256 -f test.ldif
adding new entry "dc=example,dc=com"adding new entry "ou=people,dc=example,dc=com"
adding new entry "ou=groups,dc=example,dc=com"
adding new entry "cn=example,ou=groups,dc=example,dc=com"
adding new entry "uid=lionel,ou=people,dc=example,dc=com"
- 用ldapsearch查询我们插入的数据test.ldif是否成功
root@Ubuntu-VM1:~/ws/ldap/test4# ldapsearch -xLLL -b "dc=example,dc=com" dn: dc=example,dc=com objectClass: dcObject objectClass: organizationalUnit dc: example ou: Example Dot Com dn: ou=groups,dc=example,dc=com objectClass: organizationalUnit ou: groups dn: cn=example,ou=groups,dc=example,dc=com objectClass: posixGroup cn: example gidNumber: 10000 dn: ou=people,dc=example,dc=com objectClass: organizationalUnit ou: people dn: uid=lionel,ou=people,dc=example,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount postalCode: 31000 l: Toulouse cn: Lionel Porcheron gidNumber: 10000 sn: Porcheron title: System Administrator displayName: Lionel Porcheron givenName: Lionel homePhone: +33 (0)5 xx xx xx xx initials: LP mail: lionel.porcheron@example.com mobile: +33 (0)6 xx xx xx xx o: Example uid: lionel uidNumber: 1000 homeDirectory: /home/lionel loginShell: /bin/bash gecos: Lionel Porcheron shadowLastChange: 10877 shadowMin: 8 shadowMax: 999999 shadowWarning: 7 shadowExpire: -1 shadowFlag: 0
- 查看后台Mysql Cluster变化:
#检查Master的状态 #mysql -uroot -h 127.0.0.1 -P 3306 mysql> show master status; +----------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +----------------+----------+--------------+------------------+ | binlogs.000001 | 9987 | openldap | | +----------------+----------+--------------+------------------+ 1 row in set (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ndbinfo | | openldap | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec) mysql> use openldap; Database changed mysql> show tables; +----------------------+ | Tables_in_openldap | +----------------------+ | OL_dn2id | | OL_nextid | | OL_opattrs | | dcObject | | inetOrgPerson | | organizationalPerson | | organizationalUnit | | person | | posixAccount | | posixGroup | | shadowAccount | +----------------------+ 11 rows in set (0.02 sec)
mysql> select count(*) from OL_dn2id; ##此处说明我们插入了5条数据,想想前面的初始数据规划,我们有5条DN记录
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.03 sec)#检查Slave的状态 #mysql -uroot -h 127.0.0.1 -P 3316 mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: localhost Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: binlogs.000001 Read_Master_Log_Pos: 9987 Relay_Log_File: Ubuntu-VM1-relay-bin.000002 Relay_Log_Pos: 10136 Relay_Master_Log_File: binlogs.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: openldap Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 9987 Relay_Log_Space: 10302 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 20001 Master_Bind: 1 row in set (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | ndbinfo | | openldap | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec) mysql> use openldap; mysql> show tables; +----------------------+ | Tables_in_openldap | +----------------------+ | OL_dn2id | | OL_nextid | | OL_opattrs | | dcObject | | inetOrgPerson | | organizationalPerson | | organizationalUnit | | person | | posixAccount | | posixGroup | | shadowAccount | +----------------------+ 11 rows in set (0.03 sec)
- Openldap提供了一些Tool来Provison 数据,例如ldapadd(运行它之前必须先启动Openldap Server的进程“slapd”), slapadd(不需要启动slapd, 该工具将直接将数据导入NDB, 命令形式如slapadd -d 255 -f slapd.conf -l test.ldif), 这里我们用ldapadd, 所以我们在前一步已经启动了slapd进程
- 数据转换分析,对照NDB表和Provisioned test.ldif
- DN 记录到DB表OL_dn2id的转换:
-
#mysql -uroot -h 127.0.0.1 -P 3306 mysql>use openldap; mysql> select * from OL_dn2id; +------+------------------------------------------------------------------------------+--------+------------+-----------+------------+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+ | eid | object_classes | a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | a10 | a11 | a12 | a13 | a14 | a15 | +------+------------------------------------------------------------------------------+--------+------------+-----------+------------+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+ | 1 | dcObject organizationalUnit @ top | dc=com | dc=example | | | | | | | | | | | | | | | | 4 | inetOrgPerson posixAccount shadowAccount @ top person organizationalPerson | dc=com | dc=example | ou=people | uid=lionel | | | | | | | | | | | | | | 3 | organizationalUnit @ top | dc=com | dc=example | ou=groups | | | | | | | | | | | | | | | 2 | organizationalUnit @ top | dc=com | dc=example | ou=people | | | | | | | | | | | | | | | 1001 | posixGroup @ top | dc=com | dc=example | ou=groups | cn=example | | | | | | | | | | | | | +------+------------------------------------------------------------------------------+--------+------------+-----------+------------+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+ 5 rows in set (0.07 sec)
mysql> desc OL_dn2id; +----------------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------------+------+-----+---------+-------+ | eid | bigint(20) unsigned | NO | UNI | NULL | | | object_classes | varchar(1024) | NO | | NULL | | | a0 | varchar(128) | NO | PRI | | | | a1 | varchar(128) | NO | PRI | | | | a2 | varchar(128) | NO | PRI | | | | a3 | varchar(128) | NO | PRI | | | | a4 | varchar(128) | NO | PRI | | | | a5 | varchar(128) | NO | PRI | | | | a6 | varchar(128) | NO | PRI | | | | a7 | varchar(128) | NO | PRI | | | | a8 | varchar(128) | NO | PRI | | | | a9 | varchar(128) | NO | PRI | | | | a10 | varchar(128) | NO | PRI | | | | a11 | varchar(128) | NO | PRI | | | | a12 | varchar(128) | NO | PRI | | | | a13 | varchar(128) | NO | PRI | | | | a14 | varchar(128) | NO | PRI | | | | a15 | varchar(128) | NO | PRI | | | +----------------+---------------------+------+-----+---------+-------+ 18 rows in set (0.00 sec)
Openldap 将一条DN的信息例如dn: cn=example,ou=groups,dc=example,dc=com 作为一条记录插入DB 表OL_dn2id中
#从客户端Provision时test.ldif 的部分数据 dn: cn=example,ou=groups,dc=example,dc=com objectClass: posixGroup cn: example gidNumber: 10000
#DN记录转换规则
将DN的每个RDN从Root到Leaf转成OL_dn2id表中16个字段(a0,a1,a2,a3,....,a15),也就是说如果配置NDB作为LDAP的Backend,DIT(Data information Tree)的最大深度是16.
#DN记录的ObjectClass及属性转换
将DN关联的Objceclass作为字符串记录到OL_dn2id表中字段object_classes,此处DB表中存储的是"posixGroup @ top"(@表示ObjectClass的继承关系)
进一步查看DB表posixGroup的数据:mysql> select * from posixGroup;
+------+-----+------------------+-----------+-----------+
| eid | vid | cn | gidNumber | memberUid |
+------+-----+------------------+-----------+-----------+
| 4 | 0 | Lionel Porcheron | 10000 | NULL |
| 1001 | 0 | example | 10000 | NULL |
+------+-----+------------------+-----------+-----------+
2 rows in set (0.02 sec)此处vid在的作用是防止LDAP中一个属性对应多个Value(例如cn的值可以有多个)
mysql> desc posixGroup;
+-----------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+-------+
| eid | bigint(20) unsigned | NO | PRI | NULL | |
| vid | int(10) unsigned | NO | PRI | NULL | |
| cn | varchar(128) | YES | | NULL | |
| gidNumber | varchar(128) | YES | | NULL | |
| memberUid | varchar(128) | YES | | NULL | |
+-----------+---------------------+------+-----+---------+-------+
5 rows in set (0.04 sec) -
相关源码:在openldap-2.4.35/servers/slapd/back-ndb中有相关的转换代码
-rw-rw-r-- 1 2000 2000 12189 Mar 28 23:41 tools.cpp -rw-rw-r-- 1 2000 2000 100 Mar 28 23:41 TODO -rw-rw-r-- 1 2000 2000 21638 Mar 28 23:41 search.cpp -rw-rw-r-- 1 2000 2000 3481 Mar 28 23:41 proto-ndb.h -rw-rw-r-- 1 2000 2000 41251 Mar 28 23:41 ndbio.cpp -rw-rw-r-- 1 2000 2000 14667 Mar 28 23:41 modrdn.cpp -rw-rw-r-- 1 2000 2000 17815 Mar 28 23:41 modify.cpp -rw-rw-r-- 1 2000 2000 1643 Mar 28 23:41 Makefile.in -rw-rw-r-- 1 2000 2000 11441 Mar 28 23:41 init.cpp -rw-rw-r-- 1 2000 2000 8370 Mar 28 23:41 delete.cpp -rw-rw-r-- 1 2000 2000 9865 Mar 28 23:41 config.cpp -rw-rw-r-- 1 2000 2000 4212 Mar 28 23:41 compare.cpp -rw-rw-r-- 1 2000 2000 3884 Mar 28 23:41 bind.cpp -rw-rw-r-- 1 2000 2000 4186 Mar 28 23:41 back-ndb.h -rw-rw-r-- 1 2000 2000 772 Mar 28 23:41 attrsets.conf -rw-rw-r-- 1 2000 2000 9191 Mar 28 23:41 add.cpp # cat init.cpp static int ndb_db_open( BackendDB *be, ConfigReply *cr ) { struct ndb_info *ni = (struct ndb_info *) be->be_private; char sqlbuf[BUFSIZ], *ptr; int rc, i; if ( be->be_suffix == NULL ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: need suffix" ); Debug( LDAP_DEBUG_ANY, "%s\n", cr->msg, 0, 0 ); return -1; } Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(ndb_db_open) ": \"%s\"\n", be->be_suffix[0].bv_val, 0, 0 ); if ( ni->ni_nconns < 1 ) ni->ni_nconns = 1; ni->ni_cluster = (Ndb_cluster_connection **)ch_calloc( ni->ni_nconns, sizeof( Ndb_cluster_connection *)); for ( i=0; i<ni->ni_nconns; i++ ) { ni->ni_cluster[i] = new Ndb_cluster_connection( ni->ni_connectstr ); rc = ni->ni_cluster[i]->connect( 20, 5, 1 ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: ni_cluster[%d]->connect failed (%d)", i, rc ); goto fail; } } for ( i=0; i<ni->ni_nconns; i++ ) { rc = ni->ni_cluster[i]->wait_until_ready( 30, 30 ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: ni_cluster[%d]->wait failed (%d)", i, rc ); goto fail; } } mysql_init( &ni->ni_sql ); if ( !mysql_real_connect( &ni->ni_sql, ni->ni_hostname, ni->ni_username, ni->ni_password, "", ni->ni_port, ni->ni_socket, ni->ni_clflag )) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: mysql_real_connect failed, %s (%d)", mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) ); rc = -1; goto fail; } sprintf( sqlbuf, "CREATE DATABASE IF NOT EXISTS %s", ni->ni_dbname ); rc = mysql_query( &ni->ni_sql, sqlbuf ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: CREATE DATABASE %s failed, %s (%d)", ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) ); goto fail; } sprintf( sqlbuf, "USE %s", ni->ni_dbname ); rc = mysql_query( &ni->ni_sql, sqlbuf ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: USE DATABASE %s failed, %s (%d)", ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) ); goto fail; } ptr = sqlbuf; ptr += sprintf( ptr, "CREATE TABLE IF NOT EXISTS " DN2ID_TABLE " (" "eid bigint unsigned NOT NULL, " "object_classes VARCHAR(1024) NOT NULL, " "a0 VARCHAR(128) NOT NULL DEFAULT '', " "a1 VARCHAR(128) NOT NULL DEFAULT '', " "a2 VARCHAR(128) NOT NULL DEFAULT '', " "a3 VARCHAR(128) NOT NULL DEFAULT '', " "a4 VARCHAR(128) NOT NULL DEFAULT '', " "a5 VARCHAR(128) NOT NULL DEFAULT '', " "a6 VARCHAR(128) NOT NULL DEFAULT '', " "a7 VARCHAR(128) NOT NULL DEFAULT '', " "a8 VARCHAR(128) NOT NULL DEFAULT '', " "a9 VARCHAR(128) NOT NULL DEFAULT '', " "a10 VARCHAR(128) NOT NULL DEFAULT '', " "a11 VARCHAR(128) NOT NULL DEFAULT '', " "a12 VARCHAR(128) NOT NULL DEFAULT '', " "a13 VARCHAR(128) NOT NULL DEFAULT '', " "a14 VARCHAR(128) NOT NULL DEFAULT '', " "a15 VARCHAR(128) NOT NULL DEFAULT '', " "PRIMARY KEY (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15), " "UNIQUE KEY eid (eid) USING HASH" ); /* Create index columns */ if ( ni->ni_attridxs ) { ListNode *ln; int newcol = 0; *ptr++ = ','; *ptr++ = ' '; for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) { NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data; ptr += sprintf( ptr, "`%s` VARCHAR(%d), ", ai->na_name.bv_val, ai->na_len ); } ptr = lutil_strcopy(ptr, "KEY " INDEX_NAME " (" ); for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) { NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data; if ( newcol ) *ptr++ = ','; *ptr++ = '`'; ptr = lutil_strcopy( ptr, ai->na_name.bv_val ); *ptr++ = '`'; ai->na_ixcol = newcol + 18; newcol++; } *ptr++ = ')'; } strcpy( ptr, ") ENGINE=ndb" ); rc = mysql_query( &ni->ni_sql, sqlbuf ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: CREATE TABLE " DN2ID_TABLE " failed, %s (%d)", mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) ); goto fail; } rc = mysql_query( &ni->ni_sql, "CREATE TABLE IF NOT EXISTS " NEXTID_TABLE " (" "a bigint unsigned AUTO_INCREMENT PRIMARY KEY ) ENGINE=ndb" ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: CREATE TABLE " NEXTID_TABLE " failed, %s (%d)", mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) ); goto fail; } { NdbOcInfo *oci; rc = ndb_aset_get( ni, &ndb_optable, ndb_opattrs, &oci ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: ndb_aset_get( %s ) failed (%d)", ndb_optable.bv_val, rc ); goto fail; } for ( i=0; ndb_oplens[i] >= 0; i++ ) { if ( ndb_oplens[i] ) oci->no_attrs[i]->na_len = ndb_oplens[i]; } rc = ndb_aset_create( ni, oci ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: ndb_aset_create( %s ) failed (%d)", ndb_optable.bv_val, rc ); goto fail; } ni->ni_opattrs = oci; } /* Create attribute sets */ { ListNode *ln; for ( ln = ni->ni_attrsets; ln; ln=ln->ln_next ) { NdbOcInfo *oci = (NdbOcInfo *)ln->ln_data; rc = ndb_aset_create( ni, oci ); if ( rc ) { snprintf( cr->msg, sizeof( cr->msg ), "ndb_db_open: ndb_aset_create( %s ) failed (%d)", oci->no_name.bv_val, rc ); goto fail; } } } /* Initialize any currently used objectClasses */ { Ndb *ndb; const NdbDictionary::Dictionary *myDict; ndb = new Ndb( ni->ni_cluster[0], ni->ni_dbname ); ndb->init(1024); myDict = ndb->getDictionary(); ndb_oc_read( ni, myDict ); delete ndb; } #ifdef DO_MONITORING /* monitor setup */ rc = ndb_monitor_db_open( be ); if ( rc != 0 ) { goto fail; } #endif return 0; fail: Debug( LDAP_DEBUG_ANY, "%s\n", cr->msg, 0, 0 ); ndb_db_close( be, NULL ); return rc; }
- 最后推荐一款图形化的LDAP客户端http://jxplorer.org/index.html