PVE-Zabbix/PVEApi.py

182 lines
6.5 KiB
Python
Executable File

import urllib
import urllib2
import ssl
import json
from VM import VM
from Node import Node
from Storage import Storage
import time
CACHEFILE='/tmp/zabbix_ticket.json'
def get_auth(host, username, password):
"""
Handles ticket and csrf token collection for PVEApi class
:param host: ip of pve host with port
:param username: zabbix user
:param password: zabbix password
:return: list with csrf token and auth ticket
"""
postdata = urllib.urlencode({'username': username, 'password': password})
url = "https://" + host + "/api2/json/access/ticket"
req = urllib2.Request(url, postdata)
response = urllib2.urlopen(req, context=ssl._create_unverified_context())
response = json.load(response)
return response['data']['CSRFPreventionToken'], response['data']['ticket']
class PVEApi(object):
"""Handle API Connection and authorization"""
def __init__(self, host, username, password):
"""
Creates connection object
:param self:
:param host: ip of pve host with port
:param username: zabbix user
:param password: zabbix password
:return:
"""
self.host = host
self.url = "https://" + self.host + "/api2/json"
if self.check_cacheexpire():
self.csrftoken = get_auth(self.host, username, password)[0]
self.ticket = get_auth(self.host, username, password)[1]
self.write_ticketcache()
else:
self.csrftoken = self.read_ticketcache()['csrf']
self.ticket = self.read_ticketcache()['ticket']
def check_cacheexpire(self):
"""
Checks if API ticket is expired.
Proxmox says ticket is valid for 2 hours. For safety we use 1 hour
:return: Boolean value of True if ticket is considered expired. False if opposite.
"""
with open(CACHEFILE, 'r') as f:
data = json.load(f)
timestamp = data['timestamp']
return True if time.time() - timestamp > 3600 else False
def write_ticketcache(self):
"""
Function writes API login ticket cache to tmp
"""
data = {}
data['csrf'] = self.csrftoken
data['ticket'] = self.ticket
data['timestamp'] = time.time()
with open(CACHEFILE, 'w') as f:
json.dump(data, f)
def read_ticketcache(self):
"""
Reads API login ticket cache file
:return: returns json parsed dict
"""
with open(CACHEFILE, 'r') as f:
data = json.load(f)
return data
def get_request(self, url):
"""
Handles adding auth ticket to API request
:param url: url to create request to
:return: request to handle with urlopen
"""
req = urllib2.Request(url)
req.add_header('Cookie', 'PVEAuthCookie=' + self.ticket)
return req
def get_node_list(self):
"""
Gets Node names from cluster data
:return: List of node names
"""
url = self.url + '/nodes'
response = json.load(urllib2.urlopen(self.get_request(url), context=ssl._create_unverified_context()))
resources = response['data']
nodes = list()
for node in resources:
if type(node) is dict:
nodeobj = Node(node[u'node'].encode("ascii"))
nodes.append(nodeobj)
return nodes
def get_cluster_vmlist(self, nodelist, detailed=False):
"""
Creates Virtual Machine List
:return: list of VM class objects
"""
vmlist = list()
for node in nodelist:
url = self.url + '/nodes/' + node.name + '/qemu'
response = json.load(urllib2.urlopen(self.get_request(url), context=ssl._create_unverified_context()))
resources = response['data']
for machine in resources:
name = machine[u'name']
status = machine[u'status']
uptime = machine[u'uptime']
diskread = machine[u'diskread']
diskwrite = machine[u'diskwrite']
memusage = machine[u'mem']
pid = machine[u'pid']
vmid = machine[u'vmid']
netin = machine[u'netin']
netout = machine[u'netout']
cpus = machine[u'cpus']
template = machine[u'template']
disk = machine[u'disk']
cpuusage = machine[u'cpu']
maxdisk = machine[u'maxdisk']
maxmem = machine[u'maxmem']
vm = VM(node, name, status, uptime, diskread, diskwrite, memusage, pid, vmid, netin, netout, cpus,
template, disk, cpuusage, maxdisk, maxmem, url)
if detailed is True:
vm_dattr = self.get_details(url, vmid)
for k, v in vm_dattr.items():
vm.__setattr__('det_' + k, v)
vmlist.append(vm)
return vmlist
def get_details(self, url, vmid):
"""
Gets vm detailed data from PVE API (its slower than just basic data)
:param url: url used in vm data get
:param vmid: vmid to create new url for detailed data
:return: dict of detailed data params
"""
url = url + '/' + vmid + '/status/current'
response = json.load(urllib2.urlopen(self.get_request(url), context=ssl._create_unverified_context()))
resources = response['data']
attributedict = dict()
for param, paramvalue in resources.items():
attributedict.update({param: paramvalue})
return attributedict
def get_cluster_storagelist(self, nodelist):
"""
Creates Virtual Machine List
:return: list of VM class objects
"""
storagelist = list()
for node in nodelist:
url = self.url + '/nodes/' + node.name + '/storage'
response = json.load(urllib2.urlopen(self.get_request(url), context=ssl._create_unverified_context()))
resources = response['data']
for storage in resources:
name = storage[u'storage']
total = storage[u'total']
used = storage[u'used']
active = storage[u'active']
enabled = storage[u'enabled']
avail = storage[u'avail']
used_fraction = storage[u'used_fraction']
stor = Storage(node, name, total, used, active, enabled, avail, used_fraction)
storagelist.append(stor)
return storagelist