2016-09-23 62 views
0

我正在使用以下腳本從服務器收集清單信息並將其發送到名爲Device42的產品。該腳本目前正常工作,但我嘗試添加的API之一使用PUT而不是POST。我不是程序員,只是開始在這個腳本中使用python。這個腳本使用鐵蟒。該腳本中可以使用PUT方法嗎?需要幫助將API PUT方法添加到Python腳本

""" 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
""" 
################################################## 
# a sample script to show how to use 
# /api/ip/add-or-update 
# /api/device/add-or-update 
# 
# requires ironPython (http://ironpython.codeplex.com/) and 
# powershell (http://support.microsoft.com/kb/968929) 
################################################## 

import clr 

clr.AddReference('System.Management.Automation') 

from System.Management.Automation import (
PSMethod, RunspaceInvoke 
) 
RUNSPACE = RunspaceInvoke() 

import urllib 
import urllib2 
import traceback 
import base64 
import math 
import ssl 
import functools 
BASE_URL='https://device42_URL' 

API_DEVICE_URL=BASE_URL+'/api/1.0/devices/' 
API_IP_URL =BASE_URL+'/api/1.0/ips/' 
API_PART_URL=BASE_URL+'/api/1.0/parts/' 
API_MOUNTPOINT_URL=BASE_URL+'/api/1.0/device/mountpoints/' 
API_CUSTOMFIELD_URL=BASE_URL+'/api/1.0/device/custom_field/' 

USER  ='usernme' 
PASSWORD ='password' 

old_init = ssl.SSLSocket.__init__ 
@functools.wraps(old_init) 
def init_with_tls1(self, *args, **kwargs): 
kwargs['ssl_version'] = ssl.PROTOCOL_TLSv1 
old_init(self, *args, **kwargs) 
ssl.SSLSocket.__init__ = init_with_tls1 

def post(url, params): 
""" 
http post with basic-auth 
params is dict like object 
""" 
try: 
    data= urllib.urlencode(params) # convert to ascii chars 
    headers = { 
     'Authorization' : 'Basic '+ base64.b64encode(USER + ':' + PASSWORD), 
     'Content-Type' : 'application/x-www-form-urlencoded' 
    } 

    req = urllib2.Request(url, data, headers) 

    print '---REQUEST---',req.get_full_url() 
    print req.headers 
    print req.data 

    reponse = urllib2.urlopen(req) 

    print '---RESPONSE---' 
    print reponse.getcode() 
    print reponse.info() 
    print reponse.read() 
except urllib2.HTTPError as err: 
    print '---RESPONSE---' 
    print err.getcode() 
    print err.info() 
    print err.read() 
except urllib2.URLError as err: 
    print '---RESPONSE---' 
    print err 

def to_ascii(s): 
    # ignore non-ascii chars 
    return s.encode('ascii','ignore') 

def wmi(query): 
    return [dict([(prop.Name, prop.Value) for prop in psobj.Properties]) for psobj in RUNSPACE.Invoke(query)] 
def closest_memory_assumption(v): 
    return int(256 * math.ceil(v/256.0)) 

def add_or_update_device(): 
    computer_system = wmi('Get-WmiObject Win32_ComputerSystem -Namespace "root\CIMV2"')[0] # take first 
    bios    = wmi('Get-WmiObject Win32_BIOS -Namespace "root\CIMV2"')[0] 
    operating_system = wmi('Get-WmiObject Win32_OperatingSystem -Namespace "root\CIMV2"')[0] 
    environment  = wmi('Get-WmiObject Win32Reg_ESFFarmNode -Namespace "root\CIMV2"')[0] 
    mem    = closest_memory_assumption(int(computer_system.get('TotalPhysicalMemory'))/1047552) 
    dev_name   = to_ascii(computer_system.get('Name')).upper() 
    fqdn_name  = to_ascii(computer_system.get('Name')).upper() + '.' + to_ascii(computer_system.get('Domain')).lower() 
device = { 
    'memory'  : mem, 
    'os'   : to_ascii(operating_system.get('Caption')), 
    'osver'   : operating_system.get('OSArchitecture'), 
    'osmanufacturer': to_ascii(operating_system.get('Manufacturer')), 
    'osserial'  : operating_system.get('SerialNumber'), 
    'osverno'  : operating_system.get('Version'), 
    'service_level' : environment.get('Environment'), 
    'notes'   : 'Test w/ Change to Device name collection' 
} 
devicedmn = '' 
for dmn in ['Domain1', 'Domain2', 'Domain3', 'Domain4', 'Domain5']: 
    if dmn == to_ascii(computer_system.get('Domain')).strip(): 
     devicedmn = 'Domain' 
     device.update({ 'name' : fqdn_name, }) 
     break  
if devicedmn != 'Domain': 
    device.update({ 
     'name': dev_name, 
     }) 
manufacturer = '' 
for mftr in ['VMware, Inc.', 'Bochs', 'KVM', 'QEMU', 'Microsoft Corporation', 'Xen']: 
    if mftr == to_ascii(computer_system.get('Manufacturer')).strip(): 
     manufacturer = 'virtual' 
     device.update({ 'manufacturer' : 'vmware', }) 
     break  
if manufacturer != 'virtual': 
    device.update({ 
     'manufacturer': to_ascii(computer_system.get('Manufacturer')).strip(), 
     'hardware': to_ascii(computer_system.get('Model')).strip(), 
     'serial_no': to_ascii(bios.get('SerialNumber')).strip(), 
     'type': 'Physical', 
     })  
cpucount = 0 
for cpu in wmi('Get-WmiObject Win32_Processor -Namespace "root\CIMV2"'): 
    cpucount += 1 
    cpuspeed = cpu.get('MaxClockSpeed') 
    cpucores = cpu.get('NumberOfCores') 
if cpucount > 0: 

    device.update({ 
     'cpucount': cpucount, 
     'cpupower': cpuspeed, 
     'cpucore': cpucores, 
     }) 
hddcount = 0 
hddsize = 0 
for hdd in wmi('Get-WmiObject Win32_LogicalDisk -Namespace "root\CIMV2" | where{$_.Size -gt 1}'): 
    hddcount += 1 
    hddsize += hdd.get('Size')/1073741742 
if hddcount > 0: 

    device.update({ 
     'hddcount': hddcount, 
     'hddsize': hddsize, 
     }) 
post(API_DEVICE_URL, device) 

for hdd in wmi('Get-WmiObject Win32_LogicalDisk -Namespace "root\CIMV2" | where{$_.Size -gt 1}'): 
    mountpoint = { 
      'mountpoint' : hdd.get('Name'), 
      'label' : hdd.get('Caption'), 
      'fstype' : hdd.get('FileSystem'), 
      'capacity' : hdd.get('Size')/1024/1024, 
      'free_capacity' : hdd.get('FreeSpace')/1024/1024, 
      'device' : dev_name, 
      'assignment' : 'Device', 
    } 
    post(API_MOUNTPOINT_URL, mountpoint) 

network_adapter_configuration = wmi('Get-WmiObject Win32_NetworkAdapterConfiguration -Namespace "root\CIMV2" | where{$_.IPEnabled -eq "True"}') 

for ntwk in network_adapter_configuration: 
    for ipaddr in ntwk.get('IPAddress'): 
     ip = { 
      'ipaddress' : ipaddr, 
      'macaddress' : ntwk.get('MACAddress'), 
      'label'  : ntwk.get('Description'), 
      'device'  : dev_name, 
     } 
     post(API_IP_URL, ip) 

def main(): 
    try: 
     add_or_update_device() 
    except: 
     traceback.print_exc() 

if __name__ == "__main__": 
    main() 
+0

是的,可以使用'PUT'方法,但是你需要先寫它。 –

+0

我試圖通過基本上覆制「def post」部分並修改它來使用put來添加PUT。然後,我添加了一段與我想要「放入」API的數據,但我不斷收到API只允許PUT的消息,這意味着該腳本仍在嘗試執行POST。 – user3783772

回答

0

我的標準答案是用Requests包替換urllib2。它使得HTTP的工作更容易。

但看看this SO answer爲'黑客'得到PUT工作。

1

確定第一件事首先你需要了解PUT和POST之間的區別。我會寫出來,但社區的另一位成員對這兩個here進行了很好的描述。

現在,您可以使用該腳本的請求。下面是使用python的請求庫,以便安裝的要求,如果你有點子安裝安裝像這樣的例子:

pip install requests 

現在恐怕要經過使用請求庫,文檔可以的一些例子被發現here

HTTP Get Request。因此,對於此示例,您可以從請求庫中調用get函數,將url作爲參數,然後可以從返回的touple中打印出文本。由於GET會返回一些東西,它通常會在文本部分的touple中讓你打印它。

r = requests.get('http://urlhere.com/apistuffhere') 
print(r.text) 

HTTP POST:張貼到一個URL,根據API是如何設置將返回的東西,它一般不用於錯誤處理,但你也必須在參數傳遞。以下是向新用戶條目發送POST請求的示例。再次,你可以打印從touple文本檢查從API

payload = {'username': 'myloginname', 'password': 'passwordhere'} 
r = requests.post('https://testlogin.com/newuserEntry', params=payload) 
print(r.text) 

響應另外,您可以只打印r和它應該返回你的迴應200應該是成功的。

對於PUT:您必須牢記放置響應無法緩存,因此您可以將數據發佈到PUT url,但是您不會知道是否有錯誤,但使用與POST相同的語法。我沒有嘗試在使用請求庫的PUT請求中打印出文本響應,因爲我沒有在我編寫的任何API中使用PUT。

requests.put('http://urlhere.com/putextension') 

現在實施到你的代碼這一點,你已經有了網址的基礎上,在您的文章的登錄只是做:

payload = {'username': USERNAME, 'passwd':PASSWORD} 
r = requests.post('https://loginurlhere.com/', params=payload) 
#check response by printing text 
print (r.text) 

至於把數據傳輸到API的擴展,讓我們假設你已經有一個有效載荷變量願與您需要的信息,例如API設備擴展:

requests.put(API_DEVICE, params=payload) 

,並應付諸網址。如果您在下面有任何問題評論,如果您願意,我可以回答他們。

+0

我發現這些信息,但是進一步的研究使得它看起來好像請求模塊不適用於鐵蟒,或者至少這對工作很有挑戰性。 – user3783772

+0

您可以使用urllib2完成相同類型的請求,但比使用請求庫更繁瑣。 –