- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Openstack 使用migrate进行数据库升级实现方案详细介绍由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Openstack 使用migrate进行数据库升级实现方案详细介绍 。
OpenStack中随着版本的切换,新版本加入一些数据库表或者增加字段等是必然的事情,如何比较容易的进行这些数据库升级的适配和管理,这里就要用到oslo_db中的migrate了,这里以为M版本的heat为例,讲解一下migrate管理db的原理.
我们使用migrate需要用到的主要包含以下两部分:1.versions里面的为版本号+数据库适配脚本;2.migrate.cfg为migrate需要用到的配置文件,两部分的命名是固定的.
使用migrate进行数据库升级非常简单,heat这边提供了heat-manage db_sync, db_version的命令用来升级db以及查看当前db的版本号,这里以执行heat-manages db_sync,看下migrate的过程.
1
2
3
4
5
|
def db_sync(engine, version=None):
path = os.path.
join
(os.path.abspath(os.path.dirname(__file__)),
'migrate_repo'
)
return
oslo_migration.db_sync(engine, path, version,
init_version=INIT_VERSION)
|
heat代码的入口在这里,需要传入engine用来连接db,version为我们需要升级到的版本,这里没有传,可以看到heat这边是直接使用oslo_migrate的db_sync方法,我们看下三方库中的这个方法.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
def db_sync(engine, abs_path, version=None, init_version=0, sanity_check=
True
):
""
"Upgrade or downgrade a database.
Function runs the upgrade() or downgrade() functions in change scripts.
:param engine: SQLAlchemy engine instance for a given database //连接数据库
:param abs_path: Absolute path to migrate repository. //migrate仓库的绝对路径
:param version: Database will upgrade/downgrade until this version. //需要升级或者降级到的版本号,如果不传则默认升级到最新版本
If None - database will update to the latest
available version.
:param init_version: Initial database version //数据库的初始版本号,会以该初始版本为起点升级
:param sanity_check: Require schema sanity checking for all tables //合理性检查
"
""
if version
is
not
None:
try:
version =
int
(version)
except
ValueError:
raise exception.DBMigrationError(_(
"version should be an integer"
))
current_version = db_version(engine, abs_path, init_version)
repository = _find_migrate_repo(abs_path)
if sanity_check:
_db_schema_sanity_check(engine)
if version
is
None
or
version > current_version:
migration = versioning_api.upgrade(engine, repository, version)
else
:
migration = versioning_api.downgrade(engine, repository,
version)
if sanity_check:
_db_schema_sanity_check(engine)
return
migration
|
代码很清晰,简洁。可以看到,整个过程就是先查询下当前db的版本,然后声明一个migrate仓库示例,对db做合理性检查(主要是针对mysql),然后根据传入的version和当前的version决定是升级或者降低,最后再次检查,整个migrate就完成了.
首先是查询当前数据库的版本, 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
def db_version(engine, abs_path, init_version):
""
"Show the current version of the repository.
:param engine: SQLAlchemy engine instance for a given database
:param abs_path: Absolute path to migrate repository
:param init_version: Initial database version
"
""
repository = _find_migrate_repo(abs_path)
try:
return
versioning_api.db_version(engine, repository)
except
versioning_exceptions.DatabaseNotControlledError:
meta = sqlalchemy.MetaData()
meta.reflect(bind=engine)
tables = meta.tables
if len(tables) == 0
or
'alembic_version'
in
tables:
db_version_control(engine, abs_path, version=init_version)
return
versioning_api.db_version(engine, repository)
else
:
raise exception.DBMigrationError(
_(
"The database is not under version control, but has "
"tables. Please stamp the current version of the schema "
"manually."
))
|
首先是根据传入的绝对路径,构造一个仓库对象的示例,这里比较关键,初始化方法如下,可以看到我们前面提到migrate.cfg和versions就是在这里被使用的,而且名字也是固定的,必须为migrate.cfg和versions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Repository(pathed.Pathed):
""
"A project's change script repository"
""
_config = 'migrate.cfg
'
_versions = '
versions
'
def __init__(self, path):
log.debug('
Loading repository %s...
' % path)
self.verify(path)
super(Repository, self).__init__(path)
self.config = cfgparse.Config(os.path.join(self.path, self._config))
self.versions = version.Collection(os.path.join(self.path,
self._versions))
log.debug('
Repository %s loaded successfully
' % path)
log.debug('
Config: %r' % self.config.to_dict())
|
这里会验证我们传入的path下面是否存在versions和migrate.cfg,因此我们的代码目录结构也必须按照这个放。self.config主要是用来管理migrate.cfg的配置,self.versions主要用来管理如何升级,repository对象另外还包含3个比较重要的属性,latest:最新的版本(versions中版本号最大的),这里是73,version_table:用来记录和管理migrate版本号的数据库表,这里是migrate_version,id用来存放我们管理的数据库标示,这里是heat,后两项都是从数据库里面取.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@property
def latest(self):
""
"API to :attr:`migrate.versioning.version.Collection.latest`"
""
return
self.versions.latest
@property
def version_table(self):
""
"Returns version_table name specified in config"
""
return
self.config.get(
'db_settings'
,
'version_table'
)
@property
def id(self):
""
"Returns repository id specified in config"
""
return
self.config.get(
'db_settings'
,
'repository_id'
)
|
回到之前的代码 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
try:
return
versioning_api.db_version(engine, repository)
except
versioning_exceptions.DatabaseNotControlledError:
meta = sqlalchemy.MetaData()
meta.reflect(bind=engine)
tables = meta.tables
if len(tables) == 0
or
'alembic_version'
in
tables:
db_version_control(engine, abs_path, version=init_version)
return
versioning_api.db_version(engine, repository)
else
:
raise exception.DBMigrationError(
_(
"The database is not under version control, but has "
"tables. Please stamp the current version of the schema "
"manually."
))
|
这里会根据数据库引擎和刚才的repository实例对象获取当前数据库的版本号,其实就是从migrate本身所在数据表中去查找当前的版本号(version_version),假如是第一次使用migrate,由于还没有建立migrate_version表,所以引发异常。这里会去查一下当前数据库中的所有数据表,如果已有其他数据库表,则会引发DBMigrationError的异常,因为migrate必须在建立其他数据表之前先建立才能管控所有的数据表,假如我们之前没有使用migrate机制但是想在后面的db控制中使用起来,这里有2个思路:手动插入migrate_version数据表并配置合适的版本或者手动插入alebic_version.
继续往下面看,如果是第一次使用migrate, 。
1
|
db_version_control(engine, abs_path, version=init_version)
|
会建立migrate_version,并设置合适的初始值,也就是传入的init_version,后续的数据库升级等操作就可以通过migrate管控起来了。migrate_version表建立起来后,就回到了最初的流程,根据我们db_sync传入的版本号和当前的版本号,migrate会执行versions里面每个版本的upgrade()方法直至升级完成并更新migrate_version中的版本号.
使用migrate的好处在于,可以很方便的集中记录和管理每次对数据库的变动,在后续升级过程中,一键式完成对应的适配操作,非常方便,并且不会出现重复增加字段等操作,在开发过程中,我们只要知道了migrate的原理,就能很方便的使用起来了.
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持! 。
原文链接:http://blog.csdn.net/Sylvernass/article/details/53368896 。
最后此篇关于Openstack 使用migrate进行数据库升级实现方案详细介绍的文章就讲到这里了,如果你想了解更多关于Openstack 使用migrate进行数据库升级实现方案详细介绍的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个 openstack私有(private)云部署在我的组织中。我有一些 虚拟图像 比如通过openstack仪表板上传的ubuntu图像、windows图像。但我想知道图像存储位置在 open
我感兴趣如何向其他应用程序通知 openstack 中的事件。例如,我不想在我的应用程序中知道 nova 中的实例何时被挂起或恢复。是否有任何网络钩子(Hook)或类似的东西我可以在哪里获取该信息?
我在 CentOs VM 上安装了 Openstack,当我尝试查看已启动实例的列表时,出现此错误 $ openstack server list Ignoring domain related co
在我的本地机器上使用 CreateObjectFromFile 方法将文件上传到机架空间云时,虽然没问题。但是当我从客户端机器执行此操作时,我得到 net.openstack.Core.Excepti
我正在通过 this 在我的本地机器上安装 OpenStack关联。但是我无法从本地计算机中完全删除已安装的组件。我运行了以下命令:- $ sudo ./unstack.sh tgtadm: can'
当我向 OpenStack-ansible 添加新的计算节点时,一切似乎都正常,但无法在其上创建任何实例 NoValidHost: No valid host was found. There are
我需要将一些字节附加到存储在 Openstack Swift 中的现有对象,例如日志文件对象,并不断向其附加新日志。这可能吗? 此外,我可以将一些字节(指定偏移量和长度)更改(覆盖)到现有对象吗? 最
我目前正在研究 OpenStack,并想了解可用于调试在 VM 上运行时出现的不同问题的开发环境。通过开发环境,我指的是可以帮助我理解 OpenStack 的功能和调用流程的 IDE。我在我的机器上安
OpenStack“Heat”的编排引擎可以部署计算资源和配置软件,称为 HOT 模板。 github 上有很多例子: https://github.com/openstack/heat-templa
如何重新启动使用 devstack 安装的特定 openstack-service? 最佳答案 重新加入堆栈屏幕为 ./rejoin-stack.sh 并使用 ctrl+a+"移动到指定的服务页面,然
我已经使用 devstack 安装了开放堆栈。推出了 ciros 镜像。我可以从 VNC 控制台连接到该实例,但无法 ping 到该实例。 最佳答案 您应该将安全组配置为允许传入 ICMP (ping
我尝试使用 Terraform 创建 OpenStack 实例,但收到以下错误: Error applying plan: 1 error(s) occurred: * openstack_compu
有人知道获取用户租户列表的方法吗?我知道我可以获得租户的用户,我可以获得所有租户的列表,所以从技术上讲,我可以遍历所有租户并寻找特定用户,但这似乎是一种麻烦的方法。 最佳答案 不知道 keystone
我是 OpenStack 的新手,我需要更改当前设置为 80 的 dashboard(horizon) 的默认 http 端口。我已经使用 devstack 脚本安装/部署了 OpenStack。
也许我的问题没有意义,但这就是我想要做的: 我有一个运行在 CoreOS 上的裸机 Kubernetes 集群。 我正在尝试使用 Cinder 从 OpenStack 云提供商挂载块存储。 根据我的阅
我想用 microStack 设置一个多节点 OpenStack,但它总是失败。 我正在关注这个:https://ubuntu.com/openstack/install#multi-node-dep
注意:我看到这个问题和错误被发布在不同的论坛和这里,但没有一个对我有用,它们属于 openstack 的早期版本。所以,我发布了一个新问题。 我一直在根据其安装文档设置 OpenStack Train
我是 openstack heat 文件的新手。我进行了搜索,但没有找到与我的问题相关的答案。这是我的模板热 yaml 文件: heat_template_version: newton descri
按照文档的步骤 http://docs.openstack.org/developer/swift/overview_large_objects.html 我成功地放入了 3 个段文件和 1 个 li
如何配置 OpenStack SWIFT 以发送所有适当的 CORS header 以响应客户端的 OPTIONS 请求?我知道 SWIFT 管道的跨域插件,但文档只说允许如下内容: [filter:
我是一名优秀的程序员,十分优秀!