2016-09-23 68 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完成相同类型的请求,但比使用请求库更繁琐。 –