Openstack 通过 SQLAlchemy-ORM 访问数据库

目录

  • 目录
  • Demo
  • SQLAlchemy
  • 数据库的初始化
  • 数据库的操作实现
  • 数据库的操作请求
    • 全部查询
    • 单个查询
    • 创建
    • 更新
    • 删除

Demo

Github/JmilkFan/my-code-repertory/openstack

SQLAlchemy

SQLAlchemy 是 Python 下的一款开源软件。提供了 SQL对象关系映射(ORM/Object Relational Mappers)工具。使开发者可以像操作对象一般的操作数据库。

SQLAlchemy 1.1 Documentation
SQLAlchemy 1.0 Documentation

数据库的初始化

在部署 Openstack Services 的过程中需要为这些 Services 创建数据库 :

CREATE DATABASE glance;

这时我们其实仅仅是建立了数据库而已, 但是数据库中并没有表结构, 所以 Openstack Services 还提供了一条初始化(同步)数据库的指令 :

glance-manage db_sync

下面是 db_sync的代码实现方式:

# octopunch/octopunch/db/sqlalchemy/migrate_repo/versions/001_octopunch_init.py
def define_tables(meta):
    vcenters = Table(
        'vcenters', meta,
        Column('created_at', DateTime),
        Column('updated_at', DateTime),
        Column('deleted_at', DateTime),
        Column('uuid', String(length=45), primary_key=True),
        Column('vc_value', String(length=255)),
        Column('name', String(length=255)),
        Column('vcs_ip', String(length=255), nullable=False),
        Column('username', String(length=255), nullable=False),
        Column('password', String(length=255), nullable=False),
        mysql_engine='InnoDB'
    )

这些 Table 的定义就是我们数据库表结构的定义, 它会在我们执行数据库初始化指令的时候被用于表的创建.

数据库的操作实现

Openstack Services 对数据库的操作一般就是对数据库中的资源表的操作, 也就是对资源的操作, 所以我们先看看 Openstack 中的资源是怎么定义的.

octopunch/octopunch/api/v1/router.py
mapper.connect() 将Resource URL & Action方法 & Controller & HTTP函数 绑定到一起, 实现HTTP请求/资源/操作函数的一一对应.

from octopunch.api.v1 import vcenter

class APIRouter(octopunch.api.openstack.APIRouter):

...

    def _setup_routes(self, mapper, ext_mgr):
        self.resources['versions'] = versions.create_resource()
        mapper.connect("versions", "/",
                       controller=self.resources['versions'],
                       action='show')

        mapper.redirect("", "/")

        self.resources['vcenters'] = vcenter.create_resource(ext_mgr)
        mapper.resource('vcenter', 'vcenters',
                         controller=self.resources['vcenters'])

octopunch/octopunch/api/v1/vcenter.py
每一个 Resource 都会对应有一个 Controller 的类定义, 包含了对应的 Action 方法的实现.

class VcenterController(wsgi.Controller):
...
    def index(self, req):
        """Show all vcenter list."""
        context = req.environ['octopunch.context']
        vcenters = self.vcenter_api.vcenter_list(context)
        return {'vcenters':vcenters}
...
def create_resource(ext_mgr):
    """Vcenter resource factory method."""
    return wsgi.Resource(VcenterController(ext_mgr))

octopunch/octopunch/vsphere/vcenter/api.py
在 Resource 目录下的 api.py 文件中定义对数据库的操作接口.

from octopunch.db import base

class API(base.Base):

    def vcenter_list(self, context, filters=None):
        """Get vcenter list.

        :param context: class:`RequestContext` instance

        :param filters: select data by filter.
        :type: ``dict``

        :return: return a list of class:`VenterInfo` instance
        """
        return self.db.vcenter_get_all(context, filters)

octopunch/octopunch/db/api.py
这一层 API 接口决定使用哪种 ORM 实现和数据库类型, 而且还定义了对应 vcenter/api.py 中数据库操作接口的函数. 这样做是为了支持 Openstack 数据库的异构性. 首先需要在 octopunch/octopunch/db/base.py 中使用self.db.dispose_engine()方法让 Openstack 与数据库建立连接.

# octopunch/octopunch/db/base.py
class Base(object):
    """DB driver is injected in the init method."""

    def __init__(self, db_driver=None):
        # NOTE(mriedem): Without this call, multiple inheritance involving
        # the db Base class does not work correctly.
        super(Base, self).__init__()
        if not db_driver:
            db_driver = CONF.db_driver
        self.db = importutils.import_module(db_driver)  # pylint: disable=C0103
        self.db.dispose_engine()
# octopunch/octopunch/db/api.py
from oslo_db import concurrency as db_concurrency
...

# 指定使用 SQLALchemy, 并指定了 SQLAlchhemy 的接口路径
_BACKEND_MAPPING = {'sqlalchemy': 'octopunch.db.sqlalchemy.api'}
IMPL = db_concurrency.TpoolDbapiWrapper(CONF, _BACKEND_MAPPING)

...
def vcenter_get_all(context, filters=None):
    """Get the vcenter list.

    :param context: class:`RequestContext` instance

    :param filters: select data by filters.
    :type: ``dict``

    :return: return a list of class:`VcenterInfo` instance.
    """
    return IMPL.vcenter_get_all(context, filters=filters)

octopunch/octopunch/db/sqlalchemy/api.py
这里是 SQLAlchemy 操作数据库的具体实现, EG: 查询

@require_context
def vcenter_get_all(context, filters=None):
    session = get_session()
    with session.begin():
        vcenters_info = session.query(models.Vcenter).all()
    return vcenters_info

ORM 的数据库操作方式中, 很重要一部分就是 Table Mapping Class 的实现:

# octopunch/octopunch/db/sqlalchemy/models.py
class Vcenter(BASE, OctopunchBase):
    """Represents the vcenter list."""

    __tablename__ = 'vcenters'
    vc_value = Column(String(255))
    name = Column(String(255))
    vcs_ip = Column(String(255), nullable=False)
    username = Column(String(255), nullable=False)
    password = Column(String(255), nullable=False)

    datacenters = relationship('Datacenter', backref='vcenters',
                               foreign_keys='Datacenter.vcenter_uuid',
                               primaryjoin='Vcenter.uuid =='
                                           'Datacenter.vcenter_uuid')

将上述的 Table 定义映射为 Class之后, 我们就可以通过对 Class instance 的操作来实现对数据库 Table 的操作.

数据库的操作请求

在调试的时候我们可以在客户端通过 curl 指令来发送 HTTP 请求, 一般来说对每个 Resource 的 HTTP 请求都具有下面 5 种类型, 每一种类型都应该在 api/v1/resourceName.py 文件下(针对本文而言, 其实可以有多种实现方式)有相应的 Action 实现函数, 当然我们还可以自定义更多的实现方法.

全部查询

GET <==> show

curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>' -X GET -H "Acceptn" -H "X: admin" -H "X-Auth-Token: <token_id>"

单个查询

GET <==> index

curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>/<ResourceID>' -X GET -H "Acceptn" -H "X-Auth-Project-Id: admin" -H "X-Auth-Token: <token_id>"

创建

POST <==> create

curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>' -X POST -H "Content-Type: application/json" -H "X-Auth-Project-Id: admin" -H "X-Auth-Token: <token_id>" -d '<body_content_dict>'

更新

PUT <==> update

curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>/<ResourceID>' -X PUT -H "Content-Type: application/json" -H "X-Auth-Project-Id: admin" -H "X-Auth-Token: <token_id>" -d '<body_content_dict>'

删除

DELETE <==> delete

curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>/<ResourceID>' -X DELETE -H "Acceptn" -H "X-Auth-Project-Id: admin" -H "X-Auth-Token: <token_id>"
时间: 2024-11-08 18:27:21

Openstack 通过 SQLAlchemy-ORM 访问数据库的相关文章

Spring实战6-利用Spring和JDBC访问数据库

主要内容 定义Spring的数据访问支持 配置数据库资源 使用Spring提供的JDBC模板 写在前面:经过上一篇文章的学习,我们掌握了如何写web应用的控制器层,不过由于只定义了SpitterRepository和SpittleRepository接口,在本地启动该web服务的时候会遇到控制器无法注入对应的bean的错误,因此我决定跳过6~9章,先搞定数据库访问者一章. 在企业级应用开发中不可避免得会涉及到数据持久化层,在数据持久化层的开发过程中,可能遇到很多陷阱.你需要初始化数据库访问框架.

基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - ORM访问器

    上一篇文章AgileEAS.NET之数据关系映射ORM简单介绍了一下AgileEAS.NET平台中ORM对象的组织机构体系,但并没有对其所执行的数据存取操作介绍,在AgileEAS.NET中,我对ORM实体及其上的数据操作实现进行了分离,实体对象只呈现数据,而实体的增加.修改.更新.删除.缓存操作都通过ORM访问器实现.     在AgileEAS.NET两个访问器IOrmAccessor和ICacheAccessor访问器. IOrmAccessor完成ORM对象(实体和表)和数据库的

delphi 通过 ado 访问数据库存储过程,如果有插入动作,为什么会执行两遍?

问题描述 delphi 通过 ado 访问数据库存储过程,如果有插入动作,为什么会执行两遍? 20C 如题.这是我反复测试后得出的结论.我实在不理解为什么. 具体测试过程是这样子的:我用ado连接数据库.然后我写了一个简单的存储过程,就是往表里插入数据.然后我用ado调用这个存储过程.然后我就发现,虽然程序里我只调用了一次,但实际上表里的数据却被插入了完全一模一样的两条. 这算是bug还是怎么回事?是不是有什么我不曾注意到的细节没处理好? 存储过程代码如下: create procedure p

实现换一换功能怎么实现 要访问数据库的

问题描述 实现换一换功能怎么实现 要访问数据库的 页面中显示了9条数据,怎么点击换一换然后从后台查询,之后的内容? 解决方案 相当于翻页,原理一样的 解决方案二: SELECT * FROM ( SELECT 表名.*, ROWNUM AS CON FROM 表名 WHERE ROWNUM <= M AND 其它查询条件 ORDER BY 排序条件 ) WHERE CON >=N;查n到m条 解决方案三: 就随机从数据库按某些条件查询另外9组数据咯

Eclipse3.0配置SQLExplorer访问数据库

sql|访问|数据|数据库 英文原文地址: http://www.onjava.com/pub/a/onjava/2005/05/11/sqlexplorer.html中文地址: http://www.matrix.org.cn/resource/article/43/43630_Eclipse_SQLExplorer.html关键词: Eclipse SQLExplorer MySQL JDBC SQLExplorer是Eclipse集成开发环境的一种插件,它可以被用来从Eclipse连接到一

学习ADO和ODBC访问数据库的一些思路整理

ado|odbc|访问|数据|数据库 最近一直在学习研究用vc++访问数据库的问题,使用过ADO,也使用过ODBC.就这两种连接数据源的接口都有好几种方式,可以利用database,也可以利用dataset.利用这个word把我学习的思路整理一下. 一.使用ADO连接数据源 一般来说当建立基于对话框的应用程序时,都选择使用ADO比较方便(这纯属个人习惯问题). 1.直接在应用程序中建立与数据库的connection 2.自己写一个ADOConnection类作为应用程序操作数据库的接口,这样操作

ADO.NET访问数据库的步骤

ado|访问|数据|数据库 不论从语法来看,还是从风格和设计目标来看,ADO.NET都和ADO有显著的不同.在ASP中通过ADO访问数据库,一般要通过以下四个步骤: 1.创建一个到数据库的链路,即ADO.Connection: 2.查询一个数据集合,即执行SQL,产生一个Recordset: 3.对数据集合进行需要的操作: 4.关闭数据链路. 在ADO.NET里,这些步骤有很大的变化.ADO.NET的最重要概念之一是DataSet.DataSet是不依赖于数据库的独立数据集合.所谓独立,就是:即

VB程序如何访问数据库

 通过[Data]控件访问数据库     (1)启动VB.    (2)出现如图10.12所示的新建工程的[新建]选项卡.    (3)出现如图10.13所示的VB主界面.    (4)如图10.14所示.    (5)出现如图10.15所示的[属性窗口]界面.    ―――――――――――――――――――――――――――――――――――――    odbc;dsn=graduateDB;uid=scott;pwd=tiger;    ――――――――――――――――――――――――――――――

用连接池提高Servlet访问数据库的效率 (-)

servlet|访问|数据|数据库 Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本.Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据.本文介绍一种充分发挥该特色的实用技术,即数据库连接池. 一.实现连接池的意义 动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问.连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证.安全上下文配置这类任务,因而往往成为最为耗时的