数据库自动化运维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程序会部署到各个数据库服务器上)
整体流程图:
- 用户提供用户信息(用户名以及用户密码)。
- 服务器端读取redis readonly replica的信息。
- 验证。
- 成功则返回包含用户角色信息的token。
- 用户调用API并且提供上一步得到的token。
- 服务器端decode token得到role list,并且和API endpoint比较是否包含。
- 验证成功则调用相应的API并且将结果以及http code返回给用户。
- 失败则返回失败信息以及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的主要内容,如果未能解决你的问题,请参考以下文章
数据库自动化运维2-Restful API JWT and Redis authorization