最近在研究阿里云服务的ecs和云redis产品,通过开发文档了解到,可以通http请求调用api接口实现ecs和云redis等实例的创建、删除、启动、停止、查询、重启等,当然还有很多其它API接口,具体的根据业务需求来开发;话不多说,python具体实现如下:

ecs_client.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
调用阿里云ECS服务API,提供创建实例、删除实例、启动、停止、重启、查询信息等方法
'''
from src.common_request import get,setBaseUrlAndVersion

base_ces_url='https://ecs.aliyuncs.com/?'

def runInstances():
    pJson = {
        'Action': 'RunInstances',
        'RegionId': 'cn-shanghai',
        'ZoneId': 'cn-shanghai-c',
        'ImageId': 'ubuntu_16_04_64_20G_alibase_20191112.vhd',
        'InstanceName': 'ecs_test',
        'Description': 'ecs_test',
        'VSwitchId': 'vsw-xxxxxxxxxxxxxxxxxxx',
        'InstanceType': 'ecs.n1.tiny',
        'SystemDisk.Size': '40',
        'SystemDisk.Category': 'cloud_ssd',# 磁盘类型组
        'SecurityGroupId': 'sg-xxxxxxxxxxxxxxxxxxxx',  # 网络计费类型
        'InternetChargeType': 'PayByTraffic',# 网络计费类型
        'InstanceChargeType': 'PostPaid',# 实例的付费方式
        'Amount': '1',# 指定创建ECS实例的数量
    }
    return get(pJson)

'''
调用StopInstance停止一台运行中(Running)的ECS实例
https://help.aliyun.com/document_detail/25501.html?spm=a2c4g.11186623.6.1189.247b4d2egbw3XU
'''
def stopInstance():
    pJson = {
        'Action': 'StopInstance',
        'InstanceId': 'i-xxxxxxxxxxxxx',
        'ForceStop': 'true'
    }
    return get(pJson)

'''
调用StartInstance启动一台ECS实例,接口调用成功后实例进入启动中状态
https://help.aliyun.com/document_detail/25500.html?spm=a2c4g.11186623.6.1187.16d81594mZpYtD
'''
def startInstance():
    pJson = {
        'Action': 'StartInstance',
        'InstanceId': 'i-xxxxxxxxxxxxx'
    }
    return get(pJson)

'''
当一台ECS实例处于运行中(Running)状态时,调用RebootInstance可以重启这台实例。
https://help.aliyun.com/document_detail/25502.html?spm=a2c4g.11186623.6.1188.27a28b40nci9hZ
'''
def rebootInstance():
    pJson = {
        'Action': 'RebootInstance',
        'InstanceId': 'i-xxxxxxxxxxxxx',
        'ForceStop': 'true'
    }
    return get(pJson)


'''
调用DescribeInstances查询一台或多台ECS实例的详细信息
https://help.aliyun.com/document_detail/25506.html?spm=a2c4g.11186623.6.1186.2d0f105fydmhuz
'''
def describeInstances():
    pJson = {
        'Action': 'DescribeInstances',
        'RegionId': 'cn-shanghai',
        'InstanceIds': ['i-xxxxxxxxxxxxx']
    }
    return get(pJson)

'''
调用DeleteInstance释放一台按量付费实例或者到期的包年包月实例
https://help.aliyun.com/document_detail/25507.html?spm=a2c4g.11186623.6.1191.3b3d7c25FnL6KI
'''
def deleteInstance():
    pJson = {
        'Action': 'DeleteInstance',
        'RegionId': 'cn-shanghai',
        'InstanceId': 'i-xxxxxxxxxxxxx',
        'Force': 'true'
    }
    return get(pJson)

'''
执行入口
'''
if __name__ == '__main__':
    setBaseUrlAndVersion(base_ces_url, '2014-05-26')
    # runInstances()
    # stopInstance()
    # startInstance()
    # rebootInstance()
    # describeInstances()
    deleteInstance()

redis_client.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
调用阿里云redis服务,提供创建实例、删除实例、网络切换、重启、查询信息等方法
'''

from src.common_request import get

'''
调用CreateInstance创建一个Redis实例
https://help.aliyun.com/document_detail/60873.html?spm=a2c4g.11186623.6.795.198748f9Y55t5D
'''
def createInstance():
    pJson = {
        'Action': 'CreateInstance',
        'RegionId': 'cn-shanghai',
        'ZoneId': 'cn-shanghai-a',
        'Capacity': '1024',
        'InstanceName': 'redis_test',
        'InstanceType': 'Redis',
        'EngineVersion': '4.0',
        'AutoUseCoupon': 'true'
    }
    return get(pJson)

'''
调用DeleteInstance释放Redis实例
https://help.aliyun.com/document_detail/60898.html?spm=a2c4g.11186623.6.798.70752ca9409Jal
'''
def deleteInstance():
    pJson = {
        'Action': 'DeleteInstance',
        'InstanceId': 'r-xxxxxxxxxxxxxxxx'
    }
    return get(pJson)

'''
调用SwitchNetwork切换Redis实例的网络类型,支持从经典网络切换为VPC网络
https://help.aliyun.com/document_detail/61005.html?spm=a2c4g.11186623.2.32.44297c0cZeSWtQ
'''
def switchNetwork():
    pJson = {
        'Action': 'SwitchNetwork',
        'InstanceId': 'r-xxxxxxxxxxxxxxxx',
        'TargetNetworkType': 'VPC',
        'VpcId': 'vpc-xxxxxxxxxxxxxxxx',
        'VSwitchId': 'vsw-xxxxxxxxxxxxxxxx'
    }
    return get(pJson)

'''
调用DescribeInstances查询一个或多个Redis实例的信息
https://help.aliyun.com/document_detail/60933.html?spm=a2c4g.11186623.6.811.6ce02b35qvM5O8
'''
def describeInstances():
    pJson = {
        'Action': 'DescribeInstances',
        'InstanceId': 'r-xxxxxxxxxxxxxxxx'
    }
    return get(pJson)

'''
调用RestartInstance重启运行中的Redis实例
https://help.aliyun.com/document_detail/116215.html?spm=a2c4g.11186623.6.821.40d5425fWcIgJP
'''
def restartInstance():
    pJson = {
        'Action': 'RestartInstance',
        'InstanceId': 'r-xxxxxxxxxxxxxxxx',
        'EffectiveTime': '0'
    }
    return get(pJson)

'''
执行入口
'''
if __name__ == '__main__':
    # createInstance()
    # deleteInstance()
    # describeInstances()
    # switchNetwork()
    restartInstance()

common_request.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
对公共参数进行统一管理,公共请求参数是指每个接口都需要使用到的请求参数。
通过http向阿里云Redis服务调用实例API,
该脚本可以做为通用公共API请求方法,已实现签名机制,其它各类实例接口只需要传入API请求参数即可
注,需安装以下依赖库:
pip3 install requests

'''

from datetime import datetime, timedelta
import time
import urllib
import urllib.request
import sys
import hmac
import hashlib
import base64
import requests

# 示例:
# 有Signature参数
# http://r-kvstore.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2015-01-01&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D
base_ali_url = 'http://r-kvstore.aliyuncs.com/?'
base_ali_version='2015-01-01'
accessKeySecret='accessKeySecret'
utcTime = datetime.now() - timedelta(hours=8)  # UTC只是比北京时间提前了8个小时

commJson = {
    'Format': 'json',
    'Version': base_ali_version,
    'SignatureVersion': '1.0',
    'AccessKeyId': 'AccessKeyId',
    'SignatureMethod': 'HMAC-SHA1',
    'Timestamp': urllib.request.quote(utcTime.strftime('%Y-%m-%dT%H:%M:%SZ')),# 注意:需要对utc时间字符串进行quote编码,后续还要再次用quote对所有参数编码,因此Timestamp实际是需要两次quote编码
    'SignatureNonce': str(int(round(time.time() * 1000)))# 毫秒级时间戳
}

'''
更改base_ali_url和base_ali_version
'''
def setBaseUrlAndVersion(url, version = None):
    global base_ali_url
    global base_ali_version
    base_ali_url=url
    if version and len(version) >0:
        base_ali_version=version
        commJson['Version']=base_ali_version

'''
将请求参数和公共参数组合并
'''
def dataAndCommToJson(values):
    for k in list(values.keys()):
        commJson[k]=values.get(k)
    return commJson

'''
对请求参数进行排序,再组合成url地址参数name=1&value=2..
'''
def requestParam(values):
    values = dataAndCommToJson(values)
    _list = list(values.keys())
    _list.sort()
    query=''
    for k in _list:
        if isinstance(values.get(k),list):
            query = query + '&' + k + '=' + urllib.request.quote(str(values.get(k))) # []数组需要通过quote转换编码
        else:
            query = query + '&' + k + '=' + values.get(k)
    return query[1:len(query)]

'''
使用sha1加密算法,返回str加密后的字符串
'''
def hashStr(key, value):
    hmacNew = hmac.new(key.encode(), value.encode(), hashlib.sha1).digest()
    return base64.b64encode(hmacNew).decode()

'''
获取加密签名串
'''
def getStringToSign(query):
    query=urllib.request.quote(query)
    stringToSign= 'GET&%2F&' + query
    print('stringToSign='+stringToSign)
    hmacStr = hashStr(accessKeySecret + '&', stringToSign) # 加密得到Signature值
    hmacStr = urllib.request.quote(hmacStr)
    sign = hmacStr.replace('/', '%2F') # 对字符“/”进行编码得到的值,即%2F,并进行替换
    print('sign='+sign)
    return sign

'''
发起http get请求
'''
def get(values):
    print('request=', values)
    data = requestParam(values)
    signature = getStringToSign(data)
    url = base_ali_url + data + '&Signature=' + signature
    print('url='+url)
    response = requests.get(url)
    text = response.text
    print('response='+text)
    return text

'''
入口,测试数据
'''
if __name__ == '__main__':
    print(sys.getdefaultencoding())
    pJson = {
             'Action': 'CreateInstance',
             'RegionId': 'cn-shanghai',
             'ZoneId': 'cn-shanghai-a',
             'Capacity': '1024',
             'InstanceName': 'redis_test',
             'VpcId': 'vpc-xxxxxxxxxxxxxxxxxxxx',
             'InstanceType': 'Redis',
             'EngineVersion': '4.0',
             'AutoUseCoupon': 'true'}
    print(pJson)
    get(pJson)

不得不感慨,java的实现版本我也写了,对比 python编程语言,python的实现代码量,去掉注释,最多也就是2百行代码。而java的实现,从封装到解析,前前后后,差不多要3~5倍的代码量。python编程语言,真的是开发利器,短小精悍。