Доступ к базе данных itop (через oql) с помощью python urllib2
Я пытаюсь получить доступ к базе данных Itop через его общий веб-интерфейс. Я получил это работает с помощью сценария оболочки:
#!/bin/bash
export http_proxy=''
SERVER=itop-test
SELECT_STATEMENT="SELECT Ticket"
wget -q -O - \
--http-user=myusername \
--http-password=$(cat /home/dummy/private/.passwd) \
"http://${SERVER}.acme.org:8000/webservices/export.php?login_mode=basic&format=csv&expression=${SELECT_STATEMENT}&fields=${FIELDS}"
Это производит вывод CSV по желанию. Теперь, так как приложение, которое я создаю, находится на python, я хотел бы сделать то же самое на python:
#!/usr/bin/python
import csv
import urllib2
import base64
select_statement = 'SELECT Ticket'
fields = ''
itop_server = 'itop-test'
username = 'myusername'
passwd_file = '/home/dummy/private/.passwd'
# extract passwd
password = open(passwd_file,'r').read().replace('\n','')
# clear http_proxy (sometimes set on ACME systems)
proxy_support = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_support)
urllib2.install_opener(opener)
# build url
url = 'http://' + itop_server + \
'.acme.org:8000/webservices/export.php?login_mode=basic&format=csv&expression='\
+ select_statement + '&fields=' + fields
request = urllib2.Request(url)
base64string = base64.standard_b64encode('%s:%s' % (username, password)).replace('\n', '')
request.add_header('Authorization', 'Basic %s' % base64string)
result = urllib2.urlopen(request).read()
print result
Тем не менее, версия Python не работает, результат содержит, среди прочего
<p>Error the query can not be executed.</p>
<p>Unexpected token End of Input, found '0' in: <b>S</b>ELECT</p>
Я проверил, что используемые URL-адреса идентичны, поэтому я предположил, что должна быть разница в заголовке http, который посылает (?).
Вот некоторые результаты tcpdump -s 1024 -l -A dst itop-test.acme.org
Первый виджет:
..........@..#..2\.P.9..t..GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT%20Ticket&fields= HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */*
Host: itop-test.acme.org:8000
Connection: Keep-Alive
..........@Q....=..P.9.....GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT%20Ticket&fields= HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */*
Host: itop-test.acme.org:8000
Connection: Keep-Alive
Authorization: Basic asdfasdfasdfasdf
Тогда питон
..........@...W.@..P.9.....GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT Ticket&fields= HTTP/1.1
Accept-Encoding: identity
Host: itop-test.acme.org:8000
Connection: close
Authorization: Basic asdfasdfasdfasdf
User-Agent: Python-urllib/2.6
Я изменил пользовательский агент для Python, но это не помогло. Я также пытался изменить Connection
, но это не сработало.
Есть идеи о том, что здесь происходит? Что я могу попробовать сделать эту работу? Может быть, некоторые даже понимают, что происходит?:)
Оказывается, что также curl
не работает:
curl --user myusername:$(cat /home/dummy/private/.passwd) \
"http://${SERVER}.acme.org:8000/webservices/export.php?login_mode=basic&format=csv &expression=${SELECT_STATEMENT}&fields=${FIELDS}"
Тот же результат, что и с python urllib2. Я также попытался Pycurl, но безуспешно (тот же результат, что и urllib2 и curl в командной строке).
2 ответа
Оказывается, только wget способен переводить пробелы в URL в %20
, Если я заменю это сам, это работает. Таким образом, я строю свой URL, как это
url = 'http://' + itop_server + \
'.acme.org:8000/webservices/export.php?login_mode=basic&format=xml&expression='\
+ select_statement.replace(' ','%20') + '&fields=' + fields
который автоматически заменяет пробел, и я все еще могу написать свои операторы выбора с пробелом.
Я создал библиотеку для python3, которая очень легко доставляет нужные вам данные. (установить через pip install itoptop
):
from itoptop import Itop
url = 'https://itop_server_name/webservices/rest.php'
ver = '1.3'
usr = 'user'
pwd = 'password'
itop = Itop(url, ver, usr, pwd)
ticket = Itop.schema('Ticket')
query_all = {}
query_from_steve = {'caller_name': 'Steve'}
all_tickets = ticket.find(query_all)
tickets_from_steve = ticket.find(query_from_steve)
Если вам нужны конкретные поля из iTop:
team_name_field = ['team_name']
team_name_from_all_tickets = ticket.find(query_all, team_name_field)
date_fields = ['start_date', 'end_date']
tickets_datefields_from_steve = ticket.find({query_from_steve, date_fields)
Чтобы сохранить это в CSV:
def to_csv(dics, filename, keys=None):
"""
Create a CSV from a dictionary list
:param dics: dictionary list
:param filename: output filename
:param keys: Optional, subset of keys. Default is all keys.
:return: None
"""
if not keys:
keys = sorted(set().union(*(d.keys() for d in dics)))
import csv
with open(filename, 'w') as output_file:
dict_writer = csv.DictWriter(output_file, keys)
dict_writer.writeheader()
dict_writer.writerows(dics)
to_csv(all_tickets, 'all_tickets.csv')
Если вам нужно импортировать CSV в iTop:
def csv(filename):
"""
Read CSV and make a dictionary list
:param filename: csv
:return: dictionary list
"""
import csv
return list(csv.DictReader(open(filename)))
all_tickets = csv('all_tickets.csv')
ticket.insert(all_tickets)
Если вам нужно обновить определенное поле:
update_org_id = {'org_id' = 1}
ticket.update(query_from_steve, update_org_id)