OpenStack API

soruce /etc/keystone/admin-openrc.sh

openstack user show admin

openstack project show admin	=`openstack project list

openstack endpoint list

OpenStack 中调用任何API,在执行请求前都 要经过Keystone 认证,需要使用用户的证书来获取Authentication Token,证书包含了用户名、 密码和项目。在 openrc.sh 文件中可以找到它们。Token 允许用户不需要再次认证就能和其他 的serviceendpoints 交互。

image-20220303141431521

image-20220303141600931

image-20220303142158221

HTTP Header X-Auth-Token:$token

x-subject-token

image-20220303160832426

image-20220303161237231

JSON 语法规则

  • 数据为 键/值 对
  • 数据由逗号分隔
  • 大括号保存对象
  • 方括号保存数组

有一个web api接口, 要求:调用时,需要将身份认证令牌“token”加到HTTP 头的“X-Token”字段中,以便验证调用者身份。 接口调用成功 以后,将返回Pos数据是否添加成功。 在实际调用时,应该怎样做此类请求呢?

openstack所有组件的相关认证都由Keystone组件来进行管理。在对openstackAPI进行测试时需要在请求头部分指定参数:X-Auth-TokenContent-Type。第一个参数的值为token,第二个参数的值为响应类型。

Token认证中,X-Subject-Token和X-Auth-Token的区别? 调用token接口,响应成功后在响应消息头中包含的“X-Subject-Token”的值即为Token值; 调用业务接口,在请求消息头中增加“X-Auth-Token”,“X-Auth-Token”的取值为前面从“X-Subject-Token”获取的Token。

Openstack X-auth-token 和 token

​ 我使用这个外壳:(1)

curl -X POST http://192.168.100.10:5000/v2.0/tokens -d '{"auth":{"passwordCredentials":{"username": "admin", "password":"000000"}}}' -H "Content-type: application/json"

在 http.log 我找到一个实例:(2)

curl -i -X GET http://10.0.3.139:35357/v3/projects -H "User-Agent: python-keystoneclient" -H "Forwarded: for=10.0.3.139;by=python-keystoneclient" -H "X-Auth-Token: 04ef789a010c6f252a9f572347cac345

问:在(1)中,我可以得到一个长的 json 字符串。它包括 token.id 。但我不知道 (2) 中的 X-auth-token 和 token.id 有什么区别。

由于第一个查询是针对端口 5000 的端点,因此它正在返回一个用户令牌。
第二个查询针对端口 35357 的端点,通常设置为 Keystone 的管理端点。因此,该令牌将有所不同,而且该调用针对的是 /projects 而不是 /tokens。
您可以将 X-auth-token 作为后续 http 请求的标头传递,但要意识到管理员令牌和用户令牌提供对资源的不同访问权限。
Keystone 服务由 2 个端点提供,一个具有端口 5000,另一个是 35357。35357 端口提供与管理相关的操作,而端口 5000 提供通用 API 功能。	

`令牌可以是有范围的(针对特定项目/域)或无范围的(仅使用用户名/密码生成)。当您使用 v2 api 请求令牌时,您会在响应中收到 tokenId,而在 v3 api 中,tokenId 在 key 的响应标头中:X-Subject-Token。`

您需要在每个 API 请求中提供 X-Auth-Token 。您还可以在 X-Auth-Token 标头中使用超级用户。keystone.conf 中存在超级用户令牌(admin_token 键)

Scope

A scope can be a Project/Tenant, or a Domain. Identity operations work on a Domain scope to create an authentication token, and then can operate on a Project scope. All other services operate in a Project scope.

范围
范围可以是项目/租户或域。身份操作在域范围内工作以创建身份验证令牌,然后可以在项目范围内进行操作。所有其他服务都在项目范围内运行 

scope token

在keystone中scope token主要有以下几种类型:

  • project-scoped token:该类型token表示用户对具体项目的访问权限,token信息主要包括用户可访问的服务目录、拥有的权限、以及项目信息。
  • domain-scoped token:该类型token表示用户在域范围具有的权限,例如如果用户对域内具有管理员权限,则该用户就能管理域内的所有项目以及用户。跟project-scoped token不同的是project-scoped token包含了可访问项目信息,而domain-scoped token则包含了具有操作权限的域信息。
  • trust-scoped token:当truster授予trustee一定的权限后,trustee可以使用该类型token来操作truster资源,该类型token信息包括truster的项目/域信息以及一系列权限,服务目录。

tokentoken即令牌,身份的凭证。在整个openstack项目中服务与服务之间的通信都需要token来进行身份认证,我们来举个例子:

wKioL1jp7GnwkcNWAAK982FGrh0835.png如上图所示,一个用户需要创建一台虚拟机,用户首先要登入之后先拿到一个project_scope token 这个token包含了用户具有的角色以及服务列表,用户拿着这个令牌去请求nova服务,nova首先会去keystone认证该token是否有效,之后会向glance发送获取镜像的请求,glance接收请求后也会向之前的步骤一样去keystone认证token有效性,最终返回镜像给nova,nova再用镜像去给用户创建虚拟机。 另外需要说明的是token中包含用户所拥有的角色,nova和其他服务还会根据token中的role来判断用户是否有操作权限。

获取token的方式

1.通过openstack命令获取

加载环境变量。 [root@controller ~]# source admin-openrc 获取token [root@controller ~]# openstack token issue

2.通过curl获取

完整的curl命令如下,在该命令中,指定了用户名为admin,密码为ADMIN_PASS,domain的名字为default,project名字为admin。认证地址为IP_ADDRES。在使用的时候,这些参数都需要做对应的更改。

  curl -i -X POST -H "Content-type: application/json" -d '{
      "auth":{
          "identity":{
              "methods":["password"],
              "password":{
                  "user":{
                      "id":"d99f1a888f2d4b7fa42a191fe408d954",
                      "password":"000000"
                  }
              }
          },"scope":{
              "project":{
                  "id":"70c50f20ad754291805e5c7620b336bf"
              }
          }
      }
  }
  ' http://192.168.100.10:5000/v3/auth/tokens
\[ curl -i -X POST -H "Content-type: application/json" -d '{ "auth": { "identity": { "methods": [ "password" ], "password": { "user": { "domain": { "name": "default" }, "name": "admin", "password": "000000" } } }, "scope": { "project": { "domain": { "name": "default" }, "name": "admin" } } } } ' http://192.168.100.10:5000/v3/auth/tokens \]

curl 参数说明: -i :显示头信息 -X:指定请求方式为POST -H:指定请求头参数 -d:指定请求体参数 -s: 不显示错误输出

openstack 接入 用户名、密码验证,这有几点说明: 1.如果接入用户没有项目内(即没有租户,没有project),那么无法获得其他信息。 2.如果接入用户在项目内的角色不是管理员,同样没有权利获取其他信息 3.如果接入用户同时在多个项目内(在多个租户下),是否遍历所有信息;

curl -si -d @token-request.json -H "Content-type:application/json" http://controller:35357/v3/auth/tokens 其中: http://controller:35357/v3就是Keystone服务对外的AP1接口。 http://controller1:35357/v3/auth/tokens就是Keystone服务对外的获取令牌的API接口

openstack任何命令加上参数”--debug“即可看到当前命令使用的api端点。

例如:

[root@controller ~]# openstack user list --debug

//验证接入是否成功 curl -s -X POST http://192.168.122.106:5000/v2.0/tokens -H "Content-Type: application/json" -d '{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin", "password": "000000"}}}' | python -m json.tool

//flavor $token->tokenid 项目id->项目id curl -s -H "X-Auth-Token: $token" http://controller:8774/v2/项目id/flavors | python -m json.tool //images curl -s -H "X-Auth-Token: $token" http://controller:8774/v2/项目id/images | python -m json.tool //servers instances curl -s -H "X-Auth-Token: $token" http://controller:8774/v2/项目id/servers | python -m json.tool

curl获取user

curl -s -H "X-Auth-Token:$token"   http://controller:5000/v3/users   | python -m json.tool

//project

curl -s -H "X-Auth-Token:$token"   http://controller:5000/v3/projects   | python -m json.tool

//network curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/networks | python -m json.tool

//extensions curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/extensions | python -m json.tool

//ports curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/ports | python -m json.tool //floatingips curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/floatingips | python -m json.tool //routers curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/routers | python -m json.tool //subnetpools curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/subnetpools | python -m json.tool //subnets curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/subnets | python -m json.tool //Security group rules curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/security-group-rules | python -m json.tool //Security groups curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/security-groups | python -m json.tool //quotas curl -s -H "X-Auth-Token: $token" http://controller:9696/v2.0/quotas | python -m json.tool //search nova-compute curl -s -H "X-Auth-Token: $token" http://controller:8774/v2/项目id/os-services?binary=nova-compute | python -m json.tool

\[ 5.通过一条组合命令获取镜像列表信息,该组合命令包含: (1)使用 curl 命令获取镜像列表信息; (2)使用 openstack 相关命令获取的 token 值; (3)仅使用 awk 命令且用“|”作为分隔符获取 token 具体参数值。curl -i -H "X-Auth-Token:$(openstack token issue | awk -F "|" '/\sid\s/{print $3}')" http://controller:9292/v2/images \]

3.通过Postman获取

  1. 指定请求方法POST

  2. 指定访问地址

  3. Body->raw 处添加请求信息

    img

响应结果的Header中出现的参数X-Subject-Token即为token值 在这里插入图片描述

云主机

1、正常安装python3.6 2、pip3 install certifi-2019.11.28-py2.py3-none-any.whl 3、pip3 install urllib3-1.25.11-py3-none-any.whl 4、pip3 install idna-2.8-py2.py3-none-any.whl 5、pip3 install chardet-3.0.4-py2.py3-none-any.whl 6、pip3 install requests-2.24.0-py2.py3-none-any.whl tar -zxvf Python-api.tar.gz cd Python-api tar -zxvf python-3.6.8.tar.gz yum -y install python-3.6.8/packages/* pip3 install *.whl

\[ 通过OpenStack API 启动服务器云主机 通过OpenStack API 创建和管理云主机资 源 yum install -y python-openstackclient pip install openstacksdk pip show openstacksdk \]

基本使用方法

下面以OpenStack的创建连接为例,进行说明。为了使用OpenStack云,首 先需要使用凭证(credentials) 创建一 个到它的连接。连接的创建有3种方式: 使用OpenStack的类、 配置文集和环境变量。建议使用配置文件,因为相同的配 置可以跨工具和语言使用,兼容性较好。使用OpenStack Python SDK中的 connect()工厂函数创建连接:

def create_connection(auth_url, region, project_name, username, password):
		return openstack.connect(                 
		auth_url=auth_url,                  //auth_url               	   	
		project_name=project_name,          //项目名称 
    username=username,                  //用户名     
    password=password,                  //密码
    region_name=region,   
    app_name='examples',                 
    app_version='1.0', 
    )  

完整案例代码如下所示:

import argparse   
import os    
import openstack  
from openstack.config import loader   
import sys    
openstack.enable_logging(True, stream=sys.stdout)   
#:  在配置文件中定义OpenStack 配置云密钥 
#:  配置文件通常在$HOME/.config/openstack/clouds.yaml.    
#:  配置信息将决定运行实例的位置,以及将使用说明样的资源默认值,来运行实例  
TEST_CLOUD = os.getenv('OS_TEST_CLOUD', 'devstack-admin')
config = loader.OpenStackConfig()  
cloud = openstack.connect(cloud=TEST_CLOUD)    
class Opts(object):   
def __init__(self, cloud_name='devstack-admin', debug=False): 
self.cloud = cloud_name  
self.debug = debug   
# Use identity v3 API for examples.   
self.identity_api_version = '3'    
#:  获取资源值,resource_key:资源秘钥 
def _get_resource_value(resource_key, default):   
return config.get_extra_config('example').get(resource_key, default) 
TEST_CLOUD = os.getenv('OS_TEST_CLOUD', 'devstack-admin')  
config = loader.OpenStackConfig()  
cloud = openstack.connect(cloud=TEST_CLOUD)    
class Opts(object): 
def __init__(self, cloud_name='devstack-admin', debug=False):   
self.cloud = cloud_name   
self.debug = debug   
# Use identity v3 API for examples.   
self.identity_api_version = '3'   
def_get_resource_value(resource_key, default):     
			return config.get_extra_config('example').get(resource_key, default)  
 SERVER_NAME = 'openstacksdk-example'   
 IMAGE_NAME = _get_resource_value('image_name', 'cirros-0.4.0-x86_64-disk')   
 FLAVOR_NAME = _get_resource_value('flavor_name', 'm1.small') 
 NETWORK_NAME = _get_resource_value('network_name', 'private') 
 KEYPAIR_NAME = _get_resource_value('keypair_name',      'openstacksdk-example')  
 SSH_DIR = _get_resource_value(       
 'ssh_dir', '{home}/.ssh'.format(home=os.path.expanduser("~")))   
 PRIVATE_KEYPAIR_FILE = _get_resource_value(     
 'private_keypair_file', '{ssh_dir}/id_rsa.{key}'.format(                     ssh_dir=SSH_DIR, key=KEYPAIR_NAME))
 EXAMPLE_IMAGE_NAME = 'openstacksdk-example-public-image'
 def create_connection_from_config():  
 return openstack.connect(cloud=TEST_CLOUD) 
 def create_connection_from_args():      
 parser = argparse.ArgumentParser()  
 return openstack.connect(options=parser) 
 def create_connection(auth_url, region, project_name, username, password):    
 return openstack.connect(       
 auth_url=auth_url,   
 project_name=project_name,  
 username=username,          
 password=password,     
 region_name=region,  
 app_name='examples',  
 app_version='1.0',   ) 

使用Python调用OpenStack API

了解OpenStack API 了解Python语法 使用Python编写代码, 调用OpenStack API 查询用户列表信息

image-20220302095803277

运行CMD程序,进入restAPl.py文件所在的目录下,如图所示。

执行python restAPI.py命令,运行程序,python restAPI.py 成功获取到OpenStack平台的用户列表。

程序解读(restAPI.py文件)

image-20220302100243276
import requests
import json  
#  定义全局路径 
os_auth_url = "http://xiandian" 
#  定义请求体 
body = {
    "auth":{
        "identity":{
            "methods":["password"],
            "password":{
                "user":{
                    "id":"ef2b3098367943bfa85d0487bb3df24f",
                    "password":"000000"
                }
            }
        },"scope":{
            "project":{
                "id":"e10e1ab80d654e5bbd3b4846f2609e4b"
            }
        }
    }
}
#  设置请求头
headers = {}
headers["Content-Type"] = "application/json" 
headers["Accept"] = "*/*"   
#  获取token 值 
def get_token():    
#  获取tokens 的url    
os_auth_url_token = os_auth_url + ":35357/v3/auth/tokens"  
#  使用requests 模拟请求,返回json,获取token 
result = requests.post(os_auth_url_token, headers=headers, data=json.dumps(body)).headers["X-Subject-Token"]     
return result  
 def user_list():   
 #  获取users 的url     
 os_auth_url_users = os_auth_url + ':35357/v3/users' 
 #  调用get_token()方法,获取token 值,放进headers 中   
 headers["X-Auth-Token"] = get_token() 
 #  使用requests 模拟请求  返回users json    
 result = requests.get(os_auth_url_users, headers=headers).json()         	
 print(result)  
 return result
 #  调用user_list()方法 
 user_list()  

Python调用OpenStack api

编写python代码创建flavor

编写python代码对接OpenStack API,完成flavor的创建。在all-in-one节点的/root目录下创建create_flavor.py文件,在该文件中编写python代码对接openstack api,要求在openstack私有云平台上创建一个云主机类型,名字为test、vcpu为1个、内存为1024m、硬盘为20G、ID为199999。执行完代码要求输出“云主机类型创建成功”。create_flavor.py的文件内容如下:

import requests,json,time

# *******************全局变量IP*****************************
#执行代码前,请修改controller_ip的IP地址,与指定router,IP可以input,也可以写成静态
controller_ip = input("请输入访问openstack平台控制节点IP地址:(xx.xx.xx.xx)\n")

try:
    url  = f"http://{controller_ip}:5000/v3/auth/tokens"
    body =body={
        "auth": {
            "identity": {
                "methods": ["password"],
                "password": {
                    "user": {
                        "id": "d99f1a888f2d4b7fa42a191fe408d954",
                        "password": "000000"
                    }
                }
            },
            "scope": {
                "project": {
                    "id": "70c50f20ad754291805e5c7620b336bf"
                }
            }
        }
    }
    headers = {
                    "Content-Type": "application/json",
                }
    Token = requests.post(url, data=json.dumps(body),headers=headers).headers['X-Subject-Token']
    headers = {
                    "X-Auth-Token": Token
                }
except Exception as e:
    print(f"获取Token值失败,请检查访问云主机控制节点IP是否正确?输出错误信息如下:{str(e)}")
    exit(0)  
class flavor_api:
    def __init__(self,handers:dict,resUrl:str):
        self.headers=handers
        self.resUrl=resUrl

    #创建flavor类型
    def create_flavor(self,flavor_name:str,ram,vcpus,disk,id):
        self.headers['Content-Type']="application/json"
        body={
            "flavor":{
                "name":flavor_name,
                "ram":ram,
                 "vcpus":vcpus,
                "disk":disk,
                "id":id,
            }
        }
        status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers).text
    #获取flavor_id
    def get_flavor_id(self,flavor_name:str):
        result = json.loads(requests.get(self.resUrl,headers=self.headers).text)
        for item in result['flavors']:
            if(item['name']==flavor_name):
                return item['id']
flavor_api=flavor_api(headers,f"http://{controller_ip}:8774/v2.1/flavors")

flavor_api.create_flavor(flavor_name="test",ram=1024,vcpus=1,disk=20,id=199999)
flavor_id = flavor_api.get_flavor_id(flavor_name="test")
print("云主机类型创建成功,flavor_id为:",flavor_id)

'''
#注意调用方法应该放在最前面!!!
'''
编写完python代码后,使用如下命令执行:
[root@openstack ~]# python3 create_flavor.py 
请输入访问openstack平台控制节点IP地址:(xx.xx.xx.xx)
172.30.18.29
云主机类型创建成功,flavor_id为: 199999
正确执行,返回flavor的id为199999,使用命令查看flavor是否被成功创建,命令如下:
[root@openstack ~]# source /etc/keystone/admin-openrc.sh 
[root@openstack ~]# openstack flavor list
+--------+------+------+------+-----------+-------+-----------+
| ID     | Name |  RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------+------+------+------+-----------+-------+-----------+
| 199999 | test | 1024 |   20 |         0 |     1 | True      |
+--------+------+------+------+-----------+-------+-----------+
确认创建flavor成功。

编写python代码创建镜像

编写python代码对接OpenStack API,完成镜像的上传。在all-in-one节点的/root目录下创建create_image.py文件,在该文件中编写python代码对接openstack api,要求在openstack私有云平台中上传镜像cirros-0.3.4-x86_64-disk.img,名字为cirros001,disk_format

为qcow2,container_format为bare。执行完代码要求输出“镜像创建成功,id为:xxxxxx”。create_image.py的文件内容如下:

import requests,json,time

# *******************全局变量IP*****************************
#执行代码前,请修改controller_ip的IP地址,与指定router,IP可以input,也可以写成静态
controller_ip = input("请输入访问openstack平台控制节点IP地址:(xx.xx.xx.xx)\n")

try:
    url  = f"http://{controller_ip}:5000/v3/auth/tokens"
    body = {"auth": {"identity": {"methods": ["password"], "password": {
                "user": {"domain": {"name": "demo"}, "name": "admin", "password": "000000"}}},
                   "scope": {"project": {"domain": {"name": "demo"}, "name": "admin"}}}}
    headers = {
                    "Content-Type": "application/json",
                }
    Token = requests.post(url, data=json.dumps(body), headers=headers).headers['X-Subject-Token']
    headers = {
                    "X-Auth-Token": Token
                }
except Exception as e:
    print(f"获取Token值失败,请检查访问云主机控制节点IP是否正确?输出错误信息如下:{str(e)}")
    exit(0)

class glance_api:
    def __init__(self, headers: dict, resUrl: str):
        self.headers = headers
        self.resUrl = resUrl
    #创建glance镜像
    def create_glance(self, image_name: str, container_format="bare", disk_format="qcow2"):
        body = {
            "container_format": container_format,
            "disk_format": disk_format,
            "name": image_name,
        }
        status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers).status_code
    #获取glance镜像id
    def get_glance_id(self,image_name:str):
        result = json.loads(requests.get(self.resUrl,headers=self.headers).text)
        for item in result['images']:
            if(item['name']==image_name):
                return item['id']
    #上传glance镜像
    def update_glance(self,image_name:str,file_path=""):
        self.resUrl=self.resUrl+"/"+self.get_glance_id(image_name)+"/file"
        self.headers['Content-Type'] = "application/octet-stream"
        seatus_code = requests.put(self.resUrl,data=open(file_path,'rb').read(),headers=self.headers).status_code
glance_api = glance_api(headers,f"http://{controller_ip}:9292/v2/images")
glance_api.create_glance(image_name="cirros001")  #调用glance-api中创建镜像方法
print("镜像创建成功,id为: ",glance_api.get_glance_id(image_name="cirros001"))
glance_api.update_glance(image_name="cirros001",file_path="./cirros-0.3.4-x86_64-disk.img")
执行代码,命令如下:
# python3 create_image.py 
请输入访问openstack平台控制节点IP地址:(xx.xx.xx.xx)
172.30.18.29
镜像创建成功,id为:  714882f6-b6d4-4eb3-b655-8b63207755f0
可以看见执行代码成功,使用命令查看镜像是否上传成功,命令如下:
[root@allinone ~]# openstack image list
+--------------------------------------+-----------+--------+
| ID                                   | Name      | Status |
+--------------------------------------+-----------+--------+
| 714882f6-b6d4-4eb3-b655-8b63207755f0 | cirros001 | active |
+--------------------------------------+-----------+--------+
镜像是active状态,代码执行成功。

编写python代码创建用户

编写python代码对接OpenStack API,完成用户的上传。在all-in-one节点的/root目录下创建create_user.py文件,在该文件中编写python代码对接openstack api,要求在openstack私有云平台中创建用户chinaskill。具体代码如下:

import requests,json,time,os
#encoding=UTF-8

controller_ip = '172.30.18.29'
url = f"http://{controller_ip}:5000/v3/auth/tokens"
body={
        "auth": {
            "identity":{
                "methods": ["password"]
                ,"password": {
                    "user": {
                        "domain": {
                            "name": "demo"
                        },
                        "name": "admin",
                        "password": "000000"
                        }
                    }
            },
            "scope": {
                "project": {
                    "domain": {
                        "name": "demo"
                    },
                    "name": "admin"
                }
            }
        }
    }    
headers = {
        "Content-Type": "application/json",
    }
Token = requests.post(url, data=json.dumps(body), headers=headers).headers['X-Subject-Token']
headers = {
        "X-Auth-Token": Token
    } 
class openstack_role_api:
    def __init__(self, handers: dict, resUrl: str):
        self.headers = handers
        self.resUrl = resUrl

    def create_roles(self, role_name):
        body = {
            "role": {
                "description": "My new role",
                "name": role_name
            }
        }
        status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers)
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        role_name = role_name
        for i in result['roles']:
            if i['name'] == role_name:
                return f"角色 {role_name} 创建成功,ID为{i['id']}"

    def get_role_id(self, role_name):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        role_name = role_name
        for i in result['roles']:
            if i['name'] == role_name:
                return (f"角色 {role_name} 的ID为{i['id']}")

    def delete_role(self, role_name):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        for i in result['roles']:
            if i['name'] == role_name:
                i = i['id']
                status_code = requests.delete(f'http://{controller_ip}:5000/v3/roles/{i}', headers=self.headers)
                return f"角色 {role_name} 已删除!"

    def list_roles(self):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        roles = []
        for i in result['roles']:
            if i['name'] not in roles:
                roles.append(i['name'])
        return "该平台的角色为:\n"+'\n'.join(roles)




class openstack_user_api:
    def __init__(self, handers: dict, resUrl: str):
        self.headers = handers
        self.resUrl = resUrl
    def create_users(self, user_name):
        body = {
            "user": {
                "description": "API create user!",
                "domain_id": "fa8baeb025724e1183b0416056378cc3",
                "name": user_name
            }
        }
        status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers).text
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        user_name = user_name
        for i in result['users']:
            if i['name'] == user_name:
                return f"用户 {user_name} 创建成功,ID为{i['id']}"
    def list_users(self):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        roles = []
        for i in result['users']:
            if i['name'] not in roles:
                roles.append(i['name'])
        return "该平台的用户为:\n"+'\n'.join(roles)

    def get_user_id(self, user_name):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        user_name = user_name
        for i in result['users']:
            if i['name'] == user_name:
                return (f"用户 {user_name} 的ID为{i['id']}")

    def delete_user(self, user_name):
        result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
        for i in result['users']:
            if i['name'] == user_name:
                i = i['id']
                status_code = requests.delete(f'http://{controller_ip}:5000/v3/users/{i}', headers=self.headers)
                return f"用户 {user_name} 已删除!"



openstack_role_api = openstack_role_api(headers, f"http://{controller_ip}:5000/v3/roles")
openstack_user_api = openstack_user_api(headers, f"http://{controller_ip}:5000/v3/users")


# print(openstack_role_api.create_roles("xxx"))
# print(openstack_role_api.list_roles())
# print(openstack_user_api.create_users("xxx"))
# print(openstack_user_api.list_users())
# print(openstack_user_api.delete_user("xxx"))
上面的详细代码定义了两个类,一个user类,一个role类,每个类下面有查询,创建,列出,删除四个函数,实例化一个类然后调用函数,例如创建用户chinaskill,就在代码的最下方调用create函数,具体如下:
print(openstack_user_api.create_users("chinaskill"))
执行代码,效果如下:
[root@allinone ~]# python3 create_user.py 
用户 chinaskill 创建成功,ID为76372e3b4ef749b88871a65aa19824fc
使用命令查看用户列表,确定是否创建成功,命令如下:
[root@allinone ~]# openstack user list
+----------------------------------+-------------------+
| ID                               | Name              |
+----------------------------------+-------------------+
| 0f8782af6a654d77b587e25a32f91f28 | cinder            |
| 1ab30f77400448eba6b2d47e55084540 | demo              |
| 2550fa93b1fe4cb582f1f46353b836d8 | ceilometer        |
| 2d2a345336184b1ebbdf022f710084e8 | neutron           |
| 48b816f9db9541b4bd9ca49ad453574c | glance            |
| 76372e3b4ef749b88871a65aa19824fc | chinaskill        |
| 765a16c99d7d42a4b69ff941f7791b54 | aodh              |
| 788efa329f324b91a431ad56cd7b9a14 | nova              |
| 7ecae98d16d54483b964c9c2548fd7bc | swift             |
| 962612a3e7784df38d0c98fea1f30320 | heat              |
| 9ee4731c00c24f659b8790be6b77bc8a | admin             |
| d6fdd1e5e1a348e0b6c5b8c7f33ba5fa | placement         |
| d957a578fed2452ab91bc651f2f1fb97 | heat_domain_admin |
| e91070fa751e49689963b566db999bee | gnocchi           |
+----------------------------------+-------------------+
可以查看到chinaskill用户,python脚本执行成功。如果要调用其他功能,可按照上面的方法自行实验。
注:代码中的"domain_id": "fa8baeb025724e1183b0416056378cc3",需要改成实际执行环境中的domain_id。

非查询请求体

body={
        "auth": {
            "identity":{
                "methods": ["password"]
                ,"password": {
                    "user": {
#                       "domain": {
#                           "name": "demo"
#                       },
#                       "name": "admin",
#                       "password": "000000"
                        }
                    }
            },
            "scope": {
                "project": {
#                   "domain": {
#                       "name": "demo"
#                   },
#                   "name": "admin"
                }
            }
        }
    }

需查询请求体

body={
        "auth": {
            "identity": {
                "methods": ["password"],
                "password": {
                    "user": {
#                       "id": "d99f1a888f2d4b7fa42a191fe408d954",
#                       "password": "000000"
                    }
                }
            },
            "scope": {
                "project": {
#                  "id": "70c50f20ad754291805e5c7620b336bf"
                }
            }
        }
    }