如果亲手配置过openstack,不论是standalone的还是分布式的,肯定对类似这样一句有深刻的印象:
connection=mysql://xxx/glance
xxx是user:passwd@url的形式,当然了大部分情况下使用的都是mysql,也有postgresql,sqlite的,但是我知道最多的还是mysql
sqlalchemy是什么?简单的说用来做ORM,或者说做数据的持久化,为什么需要sqlalchemy?两个主要原因:
第一:封装,并不是所有人都擅长写sql语句,也不是所有人都关心具体的实现,怎么select,怎么insert,update,使用sqlalchemy封装了这一层,使得开发人员可以更加
关注上层的逻辑;
第二:还是封装,使用sqlalchemy可以配不同的backend,就像上面说的有sqlite,mysql,postgresql等,不用在刻意关注不同backend的差异,同样的将注意力放在逻辑上。
sqlalchemy在哪里:
>>> print sqlalchemy.__path__
['/usr/lib64/python2.7/site-packages/sqlalchemy'],注意这里是lib64,libvirt的库也在这个目录下
同时,我们能在source code中发现”两个“sqlalchemy,一个是上面说到的,另一个在oslo.db中(针对openstack使用做了一些小的封装)
ok,在配置openstack的时候,都有创建数据库的印象,类似于:
# mysql -u root -p
mysql> CREATE DATABASE nova;
mysql> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \
IDENTIFIED BY 'openstack';
mysql> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \
IDENTIFIED BY 'openstack';
这一步创建了数据库,有数据库才有数据表,那么创建数据表是在哪一步呢?
nova-manage db_sync
btw: 其他的模块,比如keystone,neutron,都是类似的情况,关键在于
xx-manage db_sync发生了什么:
在CentOS下查看脚本/usr/bin/nova-manage
from nova.cmd.manage import main
if __name__ == "__main__":
sys.exit(main())
执行DbCommands:
@args('--version', metavar='<version>', help='Database version')
def sync(self, version=None):
"""Sync the database up to the most recent version."""
return migration.db_sync(version) #即nova/db/sqlalchemy/migrations.py中的db_sync方法
trace一下这个函数,一般的version为None
current_version = db_version()
执行_find_migrate_repo,对应的path为nova/db/sqlalchemy/migrate_repo目录,返回repo为:_REPOSITORY = Repository(path)
记住此处的Repository类,
current_version = versioning_api.db_version(get_engine(), repository) #为migrate/vesioning/api.py中的db_version方法
其中get_engine()将通过oslo/db/sqlalchemy/中:
EngineFacade.from_config(CONF).get_engine执行:
engine = sqlalchemy.create_engine(url, **engine_args) 得到engine
repository就是刚才得到的Repository
version从哪里来的呢,trace代码,version从version_table而来,而在nova/db/sqlalchemy/migrate_repo/migrate.cfg中配置:
repository_id=nova
version_table=migrate_version
于是进入nova数据库中:
MariaDB [nova]> select * from migrate_version;
+---------------+------------------------------------------------------------------+---------+
| repository_id | repository_path | version |
+---------------+------------------------------------------------------------------+---------+
| nova | /usr/lib/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo | 254 |
+---------------+------------------------------------------------------------------+---------+
得出version为254
repository = _find_migrate_repo()
if version is None or version > current_version:
return versioning_api.upgrade(get_engine(), repository, version) #可以trace一下,从当前version到新versin的升级过程
else:
return versioning_api.downgrade(get_engine(), repository,
version)
问题是这样看起来像是从某一个版本向上upgrade,但是一开始的时候migrate_repo中的version是怎么写到数据库的呢?
migrate/versioning/api.py中的version_control方法的doc中有一段:
By default, the database begins at version 0 and is assumed to be
empty. If the database is not empty, you may specify a version at
which to begin instead. No attempt is made to verify this
version's correctness - the database schema is expected to be
identical to what it would be if the database were created from
scratch.
初始化,第一次执行db sync时,select * from migrate_version;得到的version是0,会执行migrate_repo中的.py文件的upgrade来创建表,
自己添加之后运行db_sync则会将新添加或修改的表同步到数据库中。
openstack的数据库部分有很多需要改进的地方,数据库是openstack极其重要的一部分,由于sqlalchemy的出现,一般地你感觉不到数据库的存在,
然而这让数据库更加重要,数据的同步,更新,持久化必然是cloud中的重要核心。