将POST网址中的JSON数组(带有会话)请求发送到python脚本中的vcenter

时间:2019-09-30 17:27:11

标签: python json api url vcenter

尝试在POST URL API中发送基本的json数组以使用vmware vcenter。

我是用Python编写的,这是我的新手。

在发布此示例之前,先看了一些示例,但它们似乎不适合此应用程序。

我一直在搜索类似的示例并尝试使用它们,但没有一个起作用。

我有一个很大的JSON数组要发布在此URL中。这样做还需要身份验证,因此在执行第二个API之前首先请求cookie会话。

此API用于从库中的模板克隆VM。

只是想知道是否有人可以帮助我。不需要了解vcenter,只需在会话认证后需要有关基本URL POST的帮助即可 并能够在帖子中正确发送JSON数组。

JSON数组是使用邮递员开发的,邮递员似乎添加了许多斜杠,但无论有没有斜杠都没有运气。

可能只是我看不到的简单错字...

谢谢,堆

我尝试在代码的这一行中更改结尾标头选项,其中“ data = json”。还尝试使用参数,数据和JSON。

item_detail_json_array=s.post('https://'+vcip+'/rest/vcenter/vm-template/library-items/37a0484b-bd8c-486f-b110-36c79c2295f7?action=deploy', data=json)

还尝试使用“和”重新排列带有或不带有缩进和换行符的JSON数组。

import requests
import json
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

s=requests.Session()
s.verify=False

import json
vcip="xxx.xxx.xxx.xxx"





json = "{\r\n    \"spec\": {\r\n        \"description\": \"\",\r\n        \"disk_storage\": {\r\n            \"datastore\": \"datastore-25\",\r\n            \"storage_policy\": {\r\n                \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\r\n                \"type\": \"USE_SPECIFIED_POLICY\"\r\n            }\r\n        },\r\n        \"disk_storage_overrides\": [\r\n            {\r\n                \"key\": \"2000\",\r\n                \"value\": {\r\n                    \"datastore\": \"datastore-25\",\r\n                    \"storage_policy\": {\r\n                        \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\r\n                        \"type\": \"USE_SPECIFIED_POLICY\"\r\n                    }\r\n                }\r\n            }\r\n        ],\r\n        \"guest_customization\": {\r\n            \"name\": null\r\n        },\r\n        \"hardware_customization\": {\r\n            \"cpu_update\": {\r\n                \"num_cores_per_socket\": null,\r\n                \"num_cpus\": null\r\n            },\r\n            \"disks_to_update\": [\r\n                {\r\n                    \"key\": \"2000\",\r\n                    \"value\": {\r\n                        \"capacity\": 32212254721\r\n                    }\r\n                }\r\n            ],\r\n            \"memory_update\": {\r\n                \"memory\": null\r\n            },\r\n            \"nics\": [\r\n                {\r\n                    \"key\": \"4000\",\r\n                    \"value\": {\r\n                        \"network\": \"network-26\"\r\n                    }\r\n                }\r\n            ]\r\n        },\r\n        \"name\": \"cloned via api6\",\r\n        \"placement\": {\r\n            \"folder\": \"group-v18\",\r\n            \"resource_pool\": \"resgroup-23\"\r\n        },\r\n        \"powered_on\": true,\r\n        \"vm_home_storage\": {\r\n            \"datastore\": \"datastore-25\",\r\n            \"storage_policy\": {\r\n                \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\r\n                \"type\": \"USE_SPECIFIED_POLICY\"\r\n            }\r\n        }\r\n    }\r\n}"

def get_vc_session(vcip,username,password):
         s.post('https://'+vcip+'/rest/com/vmware/cis/session', auth=(username,password))
         return s


def get_vms(vcip):
        item_detail_json_array=s.post('https://'+vcip+'/rest/vcenter/vm-template/library-items/37a0484b-bd8c-486f-b110-36c79c2295f7?action=deploy', data=json)
        return item_detail_json_array


vcsession = get_vc_session(vcip,"administrator@vcenterserver","password1234")

itemid_json_array = get_vms(vcip)   #executes the api enquiry stores as array


for x in itemid_json_array:

    print(x) # just to get the response working for now

UPDATE --------------------------------

该代码正在起作用,似乎vcenter只希望此方法中的会话ID发布在标头中。丑陋而且不是很简单,但是至少可以说是有效的。我尝试仅执行一个URL请求,在其中拥有所有参数并使用AUTH参数,但是vcenter一直随口吐痰。因此,我相信我已将其范围缩小到了身份验证错误。似乎可以与我的原始解决方案一起使用,但是在这种情况下,我们将发布一个大型json数组。在这种情况下,在尝试执行会话请求之后,Vcenter似乎不喜欢以前的解决方案所吐露的内容,并且在请求第二个API在vcenter中克隆VM时,似乎更喜欢标头中显示的会话ID。这个想法大部分来自POSTMAN使用vcenter的SDK库吐出的示例。

import requests
import json


s=requests.Session()
s.verify=False


vcip = "xxx.xxx.xxx.xxx"
vmname = "testclonepython2"
username = 'administrator@vcenterdomain'
password = 'vcenterpass'

def get_vc_session(username,password):
         s.post('https://'+vcip+'/rest/com/vmware/cis/session', auth=(username,password))
         return s


get_vc_session(username,password)


cookie = s.cookies['vmware-api-session-id']


url = "https://"+vcip+"/rest/vcenter/vm-template/library-items/37a0484b-bd8c-486f-b110-36c79c2295f7"

querystring = {"action":"deploy"}

payload = "{\n    \"spec\": {\n        \"description\": \"\",\n        \"disk_storage\": {\n            \"datastore\": \"datastore-25\",\n            \"storage_policy\": {\n                \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\n                \"type\": \"USE_SPECIFIED_POLICY\"\n            }\n        },\n        \"disk_storage_overrides\": [\n            {\n                \"key\": \"2000\",\n                \"value\": {\n                    \"datastore\": \"datastore-25\",\n                    \"storage_policy\": {\n                        \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\n                        \"type\": \"USE_SPECIFIED_POLICY\"\n                    }\n                }\n            }\n        ],\n        \"guest_customization\": {\n            \"name\": null\n        },\n        \"hardware_customization\": {\n            \"cpu_update\": {\n                \"num_cores_per_socket\": null,\n                \"num_cpus\": null\n            },\n            \"disks_to_update\": [\n                {\n                    \"key\": \"2000\",\n                    \"value\": {\n                        \"capacity\": 32212254721\n                    }\n                }\n            ],\n            \"memory_update\": {\n                \"memory\": null\n            },\n            \"nics\": [\n                {\n                    \"key\": \"4000\",\n                    \"value\": {\n                        \"network\": \"network-26\"\n                    }\n                }\n            ]\n        },\n        \"name\": \""+vmname+"\",\n        \"placement\": {\n            \"folder\": \"group-v18\",\n            \"resource_pool\": \"resgroup-23\"\n        },\n        \"powered_on\": true,\n        \"vm_home_storage\": {\n            \"datastore\": \"datastore-25\",\n            \"storage_policy\": {\n                \"policy\": \"aa6d5a82-1c88-45da-85d3-3d74b91a5bad\",\n                \"type\": \"USE_SPECIFIED_POLICY\"\n            }\n        }\n    }\n}"
headers = {
    'Content-Type': "application/json",
    'Accept': "*/*",
    'Cache-Control': "no-cache",
    'Host': vcip,
    'vmware-api-session-id': cookie,
    'Accept-Encoding': "gzip, deflate",
    'Connection': "keep-alive",
    'cache-control': "no-cache"
    }


response = requests.request("POST", url, data=payload, headers=headers, params=querystring, verify=False)

print(response.text)

1 个答案:

答案 0 :(得分:0)

在反斜杠引号等期间,请勿尝试手动构建JSON字符串。

使用该功能传递内置于requests中的python字典。这些参数是:

params :用于URL参数

data :用于POST有效负载数据

还要查看API的实际文档,以查看您的请求应该是什么样的:https://vmware.github.io/vsphere-automation-sdk-rest/6.7.1/index.html

因此template library deploy function希望发出POST请求,例如:

  

POST https://{server}/rest/vcenter/vm-template/library-items/{template_library_item}?action=deploy

他们给出了一个示例请求主体有效负载,除了结尾附近,几乎都是有效的python数据结构:

"powered_on": true,

应更改为:

"powered_on": True,

您确实应该根据要使这些变量成为什么来动态地构建它,但让我们继续使用示例,将其作为有效的python数据结构:

req_body = {'spec': {'description': 'string', 'disk_storage': {'datastore': 'obj-103', 'storage_policy': {'policy': 'obj-103', 'type': 'USE_SPECIFIED_POLICY'}}, 'disk_storage_overrides': [{'key': 'obj-103', 'value': {'datastore': 'obj-103', 'storage_policy': {'policy': 'obj-103', 'type': 'USE_SPECIFIED_POLICY'}}}], 'guest_customization': {'name': 'string'}, 'hardware_customization': {'cpu_update': {'num_cores_per_socket': 1, 'num_cpus': 1}, 'disks_to_remove': ['obj-103', 'obj-103'], 'disks_to_update': [{'key': 'obj-103', 'value': {'capacity': 1}}], 'memory_update': {'memory': 1}, 'nics': [{'key': 'obj-103', 'value': {'network': 'obj-103'}}]}, 'name': 'string', 'placement': {'cluster': 'obj-103', 'folder': 'obj-103', 'host': 'obj-103', 'resource_pool': 'obj-103'}, 'powered_on': True, 'vm_home_storage': {'datastore': 'obj-103', 'storage_policy': {'policy': 'obj-103', 'type': 'USE_SPECIFIED_POLICY'}}}}

请注意,URL上也有?action=deploy,所以我们可以做类似的事情:

req_params = {'action':'deploy'}

现在构建请求,例如:

server = 'localhost' # My example
item = '37a0484b-bd8c-486f-b110-36c79c2295f7'
url = 'https://%s/rest/vcenter/vm-template/library-items/%s' % (server,item)

resp = r.post(url, params = req_params, data = req_body)

如果此时您在控制台中,则可以看到完整的URL:

>>> resp.url
'https://localhost/rest/vcenter/vm-template
/library-items/37a0484b-bd8c-486f-b110-36c79c2295f7?action=deploy'

和JSON响应:

>>> resp.json()

应显示以下内容:

{
    "value": "obj-103"
}

根据API文档,value是“已部署虚拟机的标识符”。


编辑有关身份验证

我没有要测试的软件,只有没有REST API的ESXi。我认为您需要从this section

  
      
  • 连接到查找服务
  •   
  • 发现安全令牌服务(STS)端点URL
  •   
  • 连接到安全令牌服务以获得SAML令牌。
  •   

但是create部分仅提到了响应,它是一个秘密字符串(大概是您然后将其提供给其他REST端点),但没有提到如何首先提供SAML令牌,除非我缺少一些东西。

可能会看到以下答案:https://stackoverflow.com/a/56185704/2052575