Alibaba Cloud DevOps Cookbook Part 1 — CLI, SDK, SSH, SFTP

Part 1. Working with the CLI

{
"LoadBalancers": {
"LoadBalancer": [
{
"VpcId": "",
"RegionIdAlias": "us-west-1",
"Address": "47.254.99.119",
"AddressType": "internet",
"LoadBalancerStatus": "active",
"LoadBalancerName": "NeoPrime-SLB",
"PayType": "PayOnDemand",
"SlaveZoneId": "us-west-1b",
"ResourceGroupId": "rg-abcdefe6zn3hvwi",
"CreateTimeStamp": 1526271303000,
"VSwitchId": "",
"LoadBalancerId": "lb-abcdef1a7bf644x6s1fzg",
"InternetChargeType": "4",
"MasterZoneId": "us-west-1a",
"NetworkType": "classic",
"CreateTime": "2018-05-14T12:15Z",
"RegionId": "us-west-1"
}
]
},
"TotalCount": 1,
"PageNumber": 1,
"RequestId": "3AB8086E-1111-2222-3333-B4BC43AB548E",
"PageSize": 1
}
{
"LoadBalancers": {
"LoadBalancer": [
{
"Count": 2,
"MasterSlaveVServerGroups": {
"MasterSlaveVServerGroup": []
},
"VServerGroups": {
"VServerGroup": []
},
"BackendServers": {
"BackendServer": [
{
"NetworkType": "vpc",
"VmName": "i-0123451kxyhfs89rykzg",
"Weight": 50
},
{
"NetworkType": "vpc",
"VmName": "i-01234538slefk99bps9h",
"Weight": 50
}
]
},
"LoadBalancerId": "lb-abcdef1a7bf644x6s1fzg"
}
]
},
"Message": "successful",
"RequestId": "D3FA6102-B103-4CC5-9482-2F688C38DC7D",
"Success": true
}
"VmName": "i-0123451kxyhfs89rykzg",            "VmName": "i-01234538slefk99bps9h",
set CMD="put -o c:/tmp/hello.txt /var/www/html/hello.txt" sftpc -keypairfile=Test-KeyPair.pem root@47.254.99.120 -cmd=%CMD% 
sftpc -keypairfile=Test-KeyPair.pem root@47.254.99.121 -cmd=%CMD%

Part 2. Automate the CLI with Python

import json
import os
import pysftp
import subprocess
import sys
import myutils
#
# This value is the full path to the CLI
#
program_cli = 'C:\\Python27\\Scripts\\aliyuncli.exe'
#
# This function will take an IP Address and upload a file using SFTP
#
# ip - this is the Public IP address
# username - This is the username to use with the Key Pair. For Ubuntu this is "root"
# keypair - This is the SSK Key Pair (PEM file) to connect to the ECS instance
# local_path - This is the path on the Windows system of the file to be uploaded
# remote_path - This is the path on the ECS instance. This needs to be a full path.
#
# WARNING: There is a security issue with this code. This function does NOT verify the
# host fingerprint.
#
def ECS_UploadFile(ip, username, keypair, local_path, remote_path):
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
try:
with pysftp.Connection(
ip,
username=username,
private_key=keypair,
cnopts=cnopts) as sftp:
myutils.printf("Uploading %s to %s:%s", local_path, ip, remote_path)
sftp.put(local_path, remote_path)
except Exception as ex:
print("Exception: ", ex)
sys.exit(-1)
#
# This function will take a VmName (from the SLB json) and return the Public IP Address
#
# vmname - This is the VmName value returned from "aliyuncli slb DescribeLoadBalancersRelatedEcs"
#
def ECS_GetPublicIp(vmname):
args = [
program_cli,
'ecs',
'DescribeInstanceAttribute',
'--InstanceId',
vmname,
'--filter',
'PublicIpAddress.IpAddress[0]'
]
process = subprocess.Popen(args, stdout=subprocess.PIPE)
(output, err) = process.communicate()
rc = process.wait()
data = json.loads(output) return data#
# This function will return a list of Server Load Balancers
#
# This CLI command will list the SLBs
# aliyuncli slb DescribeLoadBalancers
#
def SLB_GetServerLoadBalancers():
args = [
program_cli,
'slb',
'DescribeLoadBalancers',
'--filter',
'LoadBalancers.LoadBalancer[].LoadBalancerId'
]
process = subprocess.Popen(args, stdout=subprocess.PIPE)
(output, err) = process.communicate()
rc = process.wait()
if rc != 0:
return []
data = json.loads(output) return data#
# List the ECS instances running under this load balancer
# aliyuncli slb DescribeLoadBalancersRelatedEcs --LoadBalancerId lb-abcdef1a7bf644x6s1012
#
def SLB_GetBackendInstances(slb_id):
args = [
program_cli,
'slb',
'DescribeLoadBalancersRelatedEcs',
'--LoadBalancerId',
slb_id
]
try:
print("Describing Load Balancer ECS Instances")
process = subprocess.Popen(args, stdout=subprocess.PIPE)
(output, err) = process.communicate()
rc = process.wait()
if rc != 0:
return []
except Exception as ex:
print("Exception: ", ex)
return []
#print(output) data = json.loads(output) slbs = data['LoadBalancers']
slb = slbs['LoadBalancer'][0]
bes = slb['BackendServers']['BackendServer']
return bes
import json
import os
import pysftp
import subprocess
import sys
import myutils
import myslb
#
# This value is the full path to the CLI
#
program_cli = 'C:\\Python27\\Scripts\\aliyuncli.exe'
# This is the SSH login
username ="root"
# Key Pair for SSH to connect to the ECS instance
key_pair = "../Test-KeyPair.pem"
# Local file to upload to the ECS instance
# local_path = "c:/tmp/hello.txt"
# Remote file that will be uploaded to the ECS instance
# remote_path = "/var/www/html/hello.txt"
# This is the Alibaba Cloud SLB that we want to work with
slb_id = ''
# Array of Backend Servers (ECS instances attached to a server load balancer
bes = []
if len(sys.argv) < 3:
print("Error: Missing command line arguments")
print("Usage: slb_upload local_path remote_path [slb_id]")
sys.exit(-1)
local_path = sys.argv[1]
remote_path = sys.argv[2]
# Verify that the CLI exists
if os.path.exists(sys.argv[0]) == False:
print("Error: Missing aliyun CLI: ", args[0])
sys.exit(-1)
# Get the list of Server Load Balancers
slbs = myslb.SLB_GetServerLoadBalancers()
if len(slbs) == 0:
print("Error: You do not have any server load balancers")
sys.exit(1)
# if there is only one SLB, use that one
if len(slbs) == 1:
slb_id = slbs[0]
else:
# if there is more than one SLB, then use the one specified on the command line
if len(sys.argv) < 4:
# The user did not specify a Server Load Balancer
print("Error: You have more than one server load balancer")
print("Please specify the server load balancer ID on the command line")
sys.exit(1)
slb_id = sys.argv[3]# Make sure that we have an SLB ID (not empty test)
if slb_id == '':
print("Error: Missing server load balancer ID")
print("Usage: slb_upload local_path remote_path [slb_id]")
sys.exit(1)
# Get the list of ECS instances attached to this SLB
bes = myslb.SLB_GetBackendInstances(slb_id)
if len(bes) == 0:
print("Error: Your SLB does not have any ECS instances attached")
sys.exit(1)
print("Total Backend ECS Servers: ", len(bes))
#print(slb['BackendServers'])
# We have everything, upload files
print('Processing:')
print("------------------------------------------------------------")
for index, vm in enumerate(bes):
vmname = vm['VmName']
#print("VmName: ", vmname)
ip = myslb.ECS_GetPublicIp(vmname)
#print("Public IP:", ip)
myslb.ECS_UploadFile(ip, username, key_pair, local_path, remote_path)
print("------------------------------------------------------------")
sys.exit(0)

Part 3. Automating with Python and the SDKs

############################################################
# Version 1.01
# Date Created: 2018-05-15
# Last Update: 2018-05-16
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################
"""
Functions to support SLB and ECS
"""
import json
import subprocess
import sys
import myutils
import pysftp
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526 import DescribeInstanceAttributeRequest
from aliyunsdkslb.request.v20140515 import DescribeLoadBalancersRequest
from aliyunsdkslb.request.v20140515 import DescribeLoadBalancersRelatedEcsRequest
#
# This function will take an IP Address and upload a file using SFTP
#
# ip - this is the Public IP address
# username - This is the username to use with the Key Pair. For Ubuntu this is "root"
# keypair - This is the SSK Key Pair (PEM file) to connect to the ECS instance
# local_path - This is the path on the Windows system of the file to be uploaded
# remote_path - This is the path on the ECS instance. This needs to be a full path.
#
# WARNING: There is a security issue with this code. This function does NOT verify the
# host fingerprint.
#
def ECS_UploadFile(ip, username, keypair, local_path, remote_path):
""" This function will take an IP Address and upload a file using SFTP """
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
try:
with pysftp.Connection(
ip,
username=username,
private_key=keypair,
cnopts=cnopts) as sftp:
myutils.printf("Uploading %s to %s:%s", local_path, ip, remote_path)
sftp.put(local_path, remote_path)
except Exception as ex:
print("Exception: ", ex)
sys.exit(-1)
#
# This function will take a VmName (from the SLB json) and return the Public IP Address
#
# cred - This is the dictionary of credentials (AccessKey, AccessKeyScret, Region)
# vmname - This is the VmName value returned from "aliyuncli slb DescribeLoadBalancersRelatedEcs"
#
def ECS_GetPublicIp(cred, vmname, debugFlag=False):
""" This function will take a VmName (from the SLB json) and return the Public IP Address """
client = AcsClient(cred['AccessKey'], cred['AccessKeySecret'], cred['Region']) request = DescribeInstanceAttributeRequest.DescribeInstanceAttributeRequest() request.set_InstanceId(vmname) try:
response = client.do_action_with_exception(request)
data = json.loads(response)
except Exception as ex:
print("Exception: ", ex)
return False;
ip = data['PublicIpAddress']['IpAddress'] if len(ip) > 0:
return ip[0]
return False;#
# This function will return a list of Server Load Balancers
#
# This CLI command will list the SLBs
# aliyuncli slb DescribeLoadBalancers
#
def SLB_GetServerLoadBalancers(cred, debugFlag=False):
""" This function will return a list of Server Load Balancers """
client = AcsClient(cred['AccessKey'], cred['AccessKeySecret'], cred['Region']) request = DescribeLoadBalancersRequest.DescribeLoadBalancersRequest() try:
response = client.do_action_with_exception(request)
data = json.loads(response)
except Exception as ex:
print("Exception: ", ex)
return [];
slbs = data['LoadBalancers'] if len(slbs) == 0:
return []
ids = [] for slb in slbs['LoadBalancer']:
ids.append(slb['LoadBalancerId'])
return ids;#
# List the ECS instances running under this load balancer
# aliyuncli slb DescribeLoadBalancersRelatedEcs --LoadBalancerId lb-abcdef1a7bf644x6s1012
#
def SLB_GetBackendInstances(cred, slb_id, debugFlag=False):
""" List the ECS instances running under this load balancer """
client = AcsClient(cred['AccessKey'], cred['AccessKeySecret'], cred['Region']) request = DescribeLoadBalancersRelatedEcsRequest.DescribeLoadBalancersRelatedEcsRequest() request.set_LoadBalancerId(slb_id) try:
response = client.do_action_with_exception(request)
data = json.loads(response)
except Exception as ex:
print("Exception: ", ex)
return [];
slbs = data['LoadBalancers'] if len(slbs['LoadBalancer']) == 0:
return []
slb = slbs['LoadBalancer'][0]
bes = slb['BackendServers']['BackendServer']
return bes
############################################################
# Version 1.01
# Date Created: 2018-05-15
# Last Update: 2018-05-16
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################
""" Automating with Python and the Alibaba Cloud SDKs """import os
import sys
import platform
import configparser
def getHomeDir():
dir = ""
if platform.system() == "Windows":
dir = os.environ['HOMEDRIVE'] + os.environ['HOMEPATH']
pass
else:
dir = os.environ['HOME']
pass
return dirdef getCredentialsPath():
dir = getHomeDir()
dir = dir + "\\.aliyuncli/credentials" return dirdef getConfigurePath():
dir = getHomeDir()
dir = dir + "\\.aliyuncli/configure" return dirdef loadConfigureFile(path, cred, profileName='default'):
if os.path.exists(path) is False:
print("Error: Cannot load configure file from file")
print("File: ", path)
return False;
config = configparser.ConfigParser()
config.read(path)
try:
cred['Region'] = config[profileName]['region']
except Exception as ex:
print("Exception: ", ex)
print("Error: Cannot load configure profile name: ", profileName)
return False;
return cred;
def loadCredentialsFile(path, profileName='default'):
cred = {
'AccessKey': '',
'AccessKeySecret': '',
'Region': ''
}
if os.path.exists(path) is False:
print("Error: Cannot load credentials file from file")
print("File: ", path)
return False;
config = configparser.ConfigParser()
config.read(path)
try:
cred['AccessKey'] = config[profileName]['aliyun_access_key_id']
cred['AccessKeySecret'] = config[profileName]['aliyun_access_key_secret']
except Exception as ex:
print("Exception: ", ex)
print("Error: Cannot load credential profile name: ", profileName)
return False;
return cred;def LoadCredentials(profileName='default'):
cred_file = getCredentialsPath()
conf_file = getConfigurePath()
cred = loadCredentialsFile(cred_file, profileName) if cred is False:
return False;
loadConfigureFile(conf_file, cred, profileName) return cred;
############################################################
# Version 1.01
# Date Created: 2018-05-15
# Last Update: 2018-05-16
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################
""" Automating with Python and the Alibaba Cloud SDKs """import os
import sys
import platform
# Begin: Verify that we are running under Python version 3.6 or greaterif platform.sys.version_info.major < 3:
print("This software requires Python 3.6 or greater")
sys.exit(-1)
if platform.sys.version_info.major == 3 and platform.sys.version_info.minor < 6:
print("This software requires Python 3.6 or greater")
sys.exit(-1)
if sys.version_info[0] < 3:
print("This software requires Python 3.6 or greater")
sys.exit(-1)
# End: Verify that we are running under Python version 3.6 or greaterimport myslb
import optparse
from slb_cmdline import process_cmdline, usage
# My library for processing Alibaba Cloud Services (ACS) credentials
import mycred_acs
# This is the SSH login
username = "root"
# Key Pair for SSH to connect to the ECS instance
key_pair = "../Test-KeyPair.pem"
# Local file to upload to the ECS instance
# local_path = "c:/tmp/hello.txt"
# Remote file that will be uploaded to the ECS instance
# remote_path = "/var/www/html/hello.txt"
# This is the Alibaba Cloud SLB that we want to work with
slb_id = ''
# This is the Alibaba Cloud Region that we want to work with
region_id = ''
# Array of Backend Servers (ECS instances attached to a server load balancer
bes = []
# We need a minimum of 2 command line parameters (argv >= 3)
if len(sys.argv) < 3:
print("Error: Missing command line arguments")
usage();
sys.exit(-1)
# Process the command line
(options, args) = process_cmdline()
if len(args) < 2:
print("Error: Not enough command line arguments")
usage();
sys.exit(-1)
if len(args) > 2:
print("Error: Too many command line arguments")
usage();
sys.exit(-1)
local_path = args[0]
remote_path = args[1]
# Load the Alibaba Cloud Credentials (AccessKey)
cred = mycred_acs.LoadCredentials(profileName = options.profile)
if cred is False:
sys.exit(-1)
if options.debug:
print(cred)
# Verify that the CLI exists
if os.path.exists(sys.argv[0]) is False:
print("Error: Missing aliyun CLI: ", sys.argv[0])
sys.exit(-1)
if options.slb_id:
slb_id = options.slb_id
if options.slb_id is False:
# Get the list of Server Load Balancers
slbs = myslb.SLB_GetServerLoadBalancers(cred, options.debug)
if options.debug:
print("Server Load Balancers")
print(slbs)
#if len(slbs) == 0:
n = len(slbs)
if n == 0:
print("Error: You do not have any server load balancers")
sys.exit(1)
# if there is only one SLB, use that one
if len(slbs) == 1:
slb_id = slbs[0]
else:
# if there is more than one SLB, then use the one specified on the command line
# The user did not specify a Server Load Balancer
print("Error: You have more than one server load balancer")
print("Please specify the server load balancer ID on the command line")
sys.exit(1)
else:
if options.debug:
print("SLB ID: ", slb_id)
# Make sure that we have an SLB ID (not empty test)
if slb_id == '':
print("Error: Missing server load balancer ID")
usage();
sys.exit(1)
# Get the list of ECS instances attached to this SLB
bes = myslb.SLB_GetBackendInstances(cred, slb_id, options.debug)
#if len(bes) == 0:
n = len(bes)
if n == 0:
print("Error: Your SLB does not have any ECS instances attached")
sys.exit(1)
print("Total Backend ECS Servers: ", len(bes))
#print(slb['BackendServers'])
if options.debug:
print("Backend Servers")
print(bes)
# We have everything, upload files
print('Processing:')
print("------------------------------------------------------------")
for index, vm in enumerate(bes):
vmname = vm['VmName']
#print("VmName: ", vmname)
ip = myslb.ECS_GetPublicIp(cred, vmname, options.debug) if ip is False:
print("Error: Cannnot determine IP address for instance: ", vmname)
continue;
print("Public IP:", ip) myslb.ECS_UploadFile(ip, username, key_pair, local_path, remote_path)
print("------------------------------------------------------------")
sys.exit(0)

Developer Documents

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store