数据库自动化运维1-Restful API一个小DEMO

Posted renfengjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库自动化运维1-Restful API一个小DEMO相关的知识,希望对你有一定的参考价值。

背景

现在无论开发还是运维都开始日趋向自动化发展。
像现在正在火热的容器技术(Docker&K8S)使用volume技术,也逐步解决了数据持久化的问题,使得一些开源数据库容器化成为可能,使得数据库的部署以及配置更加灵活,并且能够很方便的绑定到持续集成的任务当中。
而像传统大型数据库Oracle Database,也推出了自己的类似容器技术(12C以后),现在只需要让Database 提供开放的Restful API即可方便的将数据库集成到持续化集成工具中(例如Jenkins、Bamboo)。

小Demo

功能很简单,核心就是提供操作数据库的Restful API。(所有restful api程序会部署到各个数据库服务器上)
整体流程图:

  1. 用户提供用户信息(用户名以及用户密码)。
  2. 服务器端读取redis readonly replica的信息。
  3. 验证。
  4. 成功则返回包含用户角色信息的token。
  5. 用户调用API并且提供上一步得到的token。
  6. 服务器端decode token得到role list,并且和API endpoint比较是否包含。
  7. 验证成功则调用相应的API并且将结果以及http code返回给用户。
  8. 失败则返回失败信息以及http code。
    Redis 工作图:

    这里数据库的app server会在未来存放所有数据库的自动上传的报警信息以及状态信息。并且充当redis master的角色,这里将统一的从AD server或者其他途径同步用户信息(包含用户名,password,roles)。

以下只是一个小demo。
简单的token
固定用户名密码验证(未来会读取redis来完成这一步)
Demo:

python2.7+flask+12C。

from flask import Flask,request, jsonify, json
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import cx_Oracle
from orcltest import util
from orcltest import myora
app = Flask(__name__)
#These things should be setup on os envirement variables before flask run
app.config['SECRET_KEY'] = 'RFJBUILDTHISHEISCOOL'
app.config['ORAPWD'] = 'oracle123'
app.config['ORAUSR'] = 'c##dex'
app.config['db'] = '123456'


@app.route('/')
def index():
    return '<h1> Hello world </h1>'
@app.route('/auth', methods=['POST'])
def auth():
    data = request.get_json()
    a = data['userId']
    b = data['passwd']
    if a != 'rfj' or b != 'abc123' :
        return quick(503,'Auth failed ');
    s = Serializer(app.config['SECRET_KEY'], expires_in = 180)
    sf = s.dumps('id': a).decode('utf-8')
    return jsonify( 'token': sf )
@app.route('/pdb/<string:pdbname>')
def pdbstatus(pdbname):
    usr=app.config['ORAUSR']
    passwd=app.config['ORAPWD']
    try:
        new_ora = myora.myOra(usr=usr, passwd=passwd, db=pdbname, isdba=True)
    except Exception as e :
        print str(e).strip()
        return quick(404,pdbname+' does not exists')
    rows = util.pdb_status(pdbname, new_ora)[0][0]
    return quick(200,'Status:'+rows)
"""
Hello Flask world
"""

def quick(http_code , message):
    response = jsonify('message': message)
    response.status_code =http_code
    return response
@app.before_request
def before_request():
    #print '***************'+str(request.endpoint)
    #print '***************'+(str(request.endpoint)=='auth')
    try:
        if request.endpoint != 'auth' and not verify_auth_token(request.headers.get('Authentication').decode('utf-8')):
            return quick(503,'Token has been expired.')
    except Exception as e :
        return quick(503,'Auth failed ')

使用效果:

[root@adirfj flaskspace]# export APICREDS='"userId": "rfj", "passwd": "abc123"'
[root@adirfj flaskspace]# token=$(curl -s -X POST -H "Content-Type: application/json" http://127.0.0.1:5000/auth -d "$APICREDS" |jq -r '.token')
[root@adirfj flaskspace]# echo $token
eyJhbGciOiJIUzUxMiIsImV4cCI6MTU2MDk0ODg1NywiaWF0IjoxNTYwOTQ4Njc3fQ.eyJpZCI6ImdiLWFkaS1hcGkifQ.7Ke1ZYhHMtH4hOdH0T7FWCXRkIMEW64AXVifolyrmNjh2ZASl3SLFeSKafmQQox_eilklwdb8bpyeefNKtXF9Q
[root@adirfj flaskspace]# curl -s -X GET -H "Content-Type: application/json" -H "Authentication: $token" http://127.0.0.1:5000/pdb/DB000111

  "message": "Status:READ WRITE"

其他文件:

util.py
#!/usr/bin/python
import cx_Oracle
from myora import *


def get_connection():
    return 1
#0 = not exists
#1 = exists
def pdb_exists(pdb_name, myora):
    sql = "SELECT count(*) from v$pdbs where name='%s' "
    params = []
    params.append(pdb_name)
    rows = myora.execute(sql,params)
    return rows
#mount or
def pdb_status(pdb_name, myora):
    sql = "SELECT open_mode from v$pdbs where name='%s' "
    params = []
    params.append(pdb_name)
    rows = myora.execute(sql,params)
    return rows
def open_pdb(pdb_name, myora):
    sql = "alter pluggable database %s open "
    params = []
    params.append(pdb_name)
    myora.execute(sql,params)
def close_pdb(pdb_name, myora):
    sql = "alter pluggable database %s close immediate "
    params = []
    params.append(pdb_name)
    myora.execute(sql,params)

myora.py
#!/usr/bin/python
import cx_Oracle
import sys

class myOra():

    def __init__(self, usr, passwd, db='adidb', isdba=False):
        dsnn = getDsn(psid=db)
        if isdba :
            #You should grant sysdba to c##user before you execute this command .
            self.conn = cx_Oracle.connect(user=usr, password=passwd, dsn=dsnn, mode=cx_Oracle.SYSDBA)
        else :
            self.conn = cx_Oracle.connect(user=usr, password=passwd, dsn=dsnn)
        print "complete"

    def getConn(self):
        return self.conn

    def execute(self, sql, binds=[], updateble= False):
        cur = self.conn.cursor()

        if len(binds) > 0 :
            for param in binds:
                sql = sql.replace('%s', param, 1)

        cur.execute(sql)

        if sql[0:6] == 'SELECT' :
            result = cur.fetchall()
        else :
        else :
            result = True

        if updateble :
            self.conn.commit()
        cur.close()
        return result

    def __del__(self):
        try:
            if self.conn:
                #print 'connection destory'
                self.conn.close
        except Exception as e :
            print 'Connection Failed'
            pass
#should have a DB server list
def getDsn(phost='127.0.0.1', pport=1521, psid='adidb'):
    dsnn =cx_Oracle.makedsn(host=phost, port=pport, service_name=psid)
    return dsnn

后面的文章里会继续完善demo,加入JWT,redis,role验证,swagger,支持postgresql等其他数据库的功能。

以上是关于数据库自动化运维1-Restful API一个小DEMO的主要内容,如果未能解决你的问题,请参考以下文章

CMDB项目管理

数据库自动化运维2-Restful API JWT and Redis authorization

数据库自动化运维2-Restful API JWT and Redis authorization

Linux运维学习之cobbler自动安装系统

Linux运维学习之cobbler自动安装系统

数据库自动化运维3-Restful API Postgres DB helpper