Add config file support

This commit is contained in:
Joshua Boniface 2018-06-08 12:19:48 -04:00
parent 33e0100687
commit 6cd84f725a
4 changed files with 53 additions and 17 deletions

View File

@ -24,9 +24,10 @@ import os, sys, socket, time, libvirt, kazoo.client, threading, fencenode, ansii
class NodeInstance(): class NodeInstance():
# Initialization function # Initialization function
def __init__(self, name, t_node, s_domain, zk): def __init__(self, name, t_node, s_domain, zk, config):
# Passed-in variables on creation # Passed-in variables on creation
self.zk = zk self.zk = zk
self.config = config
self.name = name self.name = name
self.state = 'stop' self.state = 'stop'
self.t_node = t_node self.t_node = t_node
@ -35,6 +36,7 @@ class NodeInstance():
self.inactive_node_list = [] self.inactive_node_list = []
self.s_domain = s_domain self.s_domain = s_domain
self.domain_list = [] self.domain_list = []
self.ipmiaddress = ''
# Zookeeper handlers for changed states # Zookeeper handlers for changed states
@zk.DataWatch('/nodes/{}/state'.format(self.name)) @zk.DataWatch('/nodes/{}/state'.format(self.name))
@ -193,9 +195,12 @@ class NodeInstance():
# Close the Libvirt connection # Close the Libvirt connection
conn.close() conn.close()
# Get IPMI address
self.ipmiaddress = fencenode.getIPMIAddress()
# Display node information to the terminal # Display node information to the terminal
ansiiprint.echo('{}{} keepalive{}'.format(ansiiprint.purple(), self.name, ansiiprint.end()), '', 't') ansiiprint.echo('{}{} keepalive{}'.format(ansiiprint.purple(), self.name, ansiiprint.end()), '', 't')
ansiiprint.echo('{0}CPUs:{1} {2} {0}Free memory:{1} {3} {0}Load:{1} {4}'.format(ansiiprint.bold(), ansiiprint.end(), self.cpucount, self.memfree, self.cpuload), '', 'c') ansiiprint.echo('{0}CPUs:{1} {2} {0}Free memory:{1} {3} {0}Load:{1} {4} {0}IPMI Address:{1} {5}'.format(ansiiprint.bold(), ansiiprint.end(), self.cpucount, self.memfree, self.cpuload, self.ipmiaddress), '', 'c')
ansiiprint.echo('{}Active domains:{} {}'.format(ansiiprint.bold(), ansiiprint.end(), ' '.join(self.domain_list)), '', 'c') ansiiprint.echo('{}Active domains:{} {}'.format(ansiiprint.bold(), ansiiprint.end(), ' '.join(self.domain_list)), '', 'c')
# Update our local node lists # Update our local node lists

View File

@ -24,10 +24,11 @@ import os, sys, uuid, socket, time, threading, libvirt, kazoo.client, ansiiprint
class VMInstance: class VMInstance:
# Initialization function # Initialization function
def __init__(self, domuuid, zk, thishypervisor): def __init__(self, domuuid, zk, config, thishypervisor):
# Passed-in variables on creation # Passed-in variables on creation
self.domuuid = domuuid self.domuuid = domuuid
self.zk = zk self.zk = zk
self.config = config
self.thishypervisor = thishypervisor self.thishypervisor = thishypervisor
# These will all be set later # These will all be set later

7
pvcd.conf Normal file
View File

@ -0,0 +1,7 @@
# pvcd configuration file
[test1.i.bonilan.net]
zookeeper = localhost:2181
keepalive_interval = 5
ipmi_hostname = test1-lom.i.bonilan.net
ipmi_username = admin
ipmi_password = admin

51
pvcd.py
View File

@ -23,44 +23,62 @@
import kazoo.client import kazoo.client
import libvirt import libvirt
import sys import sys
import os
import socket import socket
import uuid import uuid
import VMInstance import VMInstance
import NodeInstance import NodeInstance
import time import time
import atexit import atexit
import configparser
import apscheduler.schedulers.background import apscheduler.schedulers.background
import fencenode
import ansiiprint import ansiiprint
def help(): print(ansiiprint.bold() + "pvcd - Parallel Virtual Cluster management daemon" + ansiiprint.end())
print(ansiiprint.bold() + "pvcd - Parallel Virtual Cluster management daemon" + ansiiprint.end())
# exit(0)
help() # Get the config file variable from the environment
try:
pvcd_config_file = os.environ['PVC_CONFIG_FILE']
except:
print('ERROR: The "PVC_CONFIG_FILE" environment variable must be set before starting pvcd.')
exit(1)
print('Loading configuration from file {}'.format(pvcd_config_file))
def readConfig(pvcd_config_file, myhostname):
o_config = configparser.ConfigParser()
o_config.read(pvcd_config_file)
entries = o_config[myhostname]
config = {}
for entry in entries:
config[entry] = entries[entry]
return config
myhostname = socket.gethostname()
config = readConfig(pvcd_config_file, myhostname)
# Connect to local zookeeper # Connect to local zookeeper
zk = kazoo.client.KazooClient(hosts='127.0.0.1:2181') zk = kazoo.client.KazooClient(hosts=config['zookeeper'])
try: try:
print('Connecting to Zookeeper instance at {}'.format(config['zookeeper']))
zk.start() zk.start()
except: except:
print(ansiiprint.red() + "Failed to connect to local Zookeeper instance" + ansiiprint.end()) print('ERROR: Failed to connect to Zookeeper')
exit(1) exit(1)
def zk_listener(state): def zk_listener(state):
if state == kazoo.client.KazooState.LOST: if state == kazoo.client.KazooState.LOST:
cleanup() cleanup()
exit(2) exit(1)
elif state == kazoo.client.KazooState.SUSPENDED: elif state == kazoo.client.KazooState.SUSPENDED:
cleanup() cleanup()
exit(2) exit(1)
else: else:
pass pass
zk.add_listener(zk_listener) zk.add_listener(zk_listener)
myhostname = socket.gethostname()
mynodestring = '/nodes/%s' % myhostname
def cleanup(): def cleanup():
try: try:
update_timer.shutdown() update_timer.shutdown()
@ -80,12 +98,17 @@ else:
print("Node is " + ansiiprint.red() + "absent" + ansiiprint.end() + " in Zookeeper; adding new node") print("Node is " + ansiiprint.red() + "absent" + ansiiprint.end() + " in Zookeeper; adding new node")
keepalive_time = int(time.time()) keepalive_time = int(time.time())
zk.create('/domains/{}'.format(myhostname), 'hypervisor'.encode('ascii')) zk.create('/domains/{}'.format(myhostname), 'hypervisor'.encode('ascii'))
# Basic state information
zk.create('/domains/{}/state'.format(myhostname), 'stop'.encode('ascii')) zk.create('/domains/{}/state'.format(myhostname), 'stop'.encode('ascii'))
zk.create('/domains/{}/cpucount'.format(myhostname), '0'.encode('ascii')) zk.create('/domains/{}/cpucount'.format(myhostname), '0'.encode('ascii'))
zk.create('/domains/{}/memfree'.format(myhostname), '0'.encode('ascii')) zk.create('/domains/{}/memfree'.format(myhostname), '0'.encode('ascii'))
zk.create('/domains/{}/cpuload'.format(myhostname), '0.0'.encode('ascii')) zk.create('/domains/{}/cpuload'.format(myhostname), '0.0'.encode('ascii'))
zk.create('/domains/{}/runningdomains'.format(myhostname), ''.encode('ascii')) zk.create('/domains/{}/runningdomains'.format(myhostname), ''.encode('ascii'))
# Keepalives and fencing information
zk.create('/domains/{}/keepalive'.format(myhostname), str(keepalive_time).encode('ascii')) zk.create('/domains/{}/keepalive'.format(myhostname), str(keepalive_time).encode('ascii'))
zk.create('/domains/{}/ipmiaddress'.format(myhostname), ''.encode('ascii'))
zk.create('/domains/{}/ipmiusername'.format(myhostname), ''.encode('ascii'))
zk.create('/domains/{}/ipmipassword'.format(myhostname), ''.encode('ascii'))
t_node = dict() t_node = dict()
s_domain = dict() s_domain = dict()
@ -101,7 +124,7 @@ def updatenodes(new_node_list):
if node in t_node: if node in t_node:
t_node[node].updatenodelist(t_node) t_node[node].updatenodelist(t_node)
else: else:
t_node[node] = NodeInstance.NodeInstance(node, t_node, s_domain, zk) t_node[node] = NodeInstance.NodeInstance(node, t_node, s_domain, zk, config)
@zk.ChildrenWatch('/domains') @zk.ChildrenWatch('/domains')
def updatedomains(new_domain_list): def updatedomains(new_domain_list):
@ -110,7 +133,7 @@ def updatedomains(new_domain_list):
print(ansiiprint.blue() + 'Domain list: ' + ansiiprint.end() + '{}'.format(' '.join(domain_list))) print(ansiiprint.blue() + 'Domain list: ' + ansiiprint.end() + '{}'.format(' '.join(domain_list)))
for domain in domain_list: for domain in domain_list:
if not domain in s_domain: if not domain in s_domain:
s_domain[domain] = VMInstance.VMInstance(domain, zk, t_node[myhostname]); s_domain[domain] = VMInstance.VMInstance(domain, zk, config, t_node[myhostname]);
for node in node_list: for node in node_list:
if node in t_node: if node in t_node:
t_node[node].updatedomainlist(s_domain) t_node[node].updatedomainlist(s_domain)
@ -121,7 +144,7 @@ update_zookeeper = this_node.update_zookeeper
# Create timer to update this node in Zookeeper # Create timer to update this node in Zookeeper
update_timer = apscheduler.schedulers.background.BackgroundScheduler() update_timer = apscheduler.schedulers.background.BackgroundScheduler()
update_timer.add_job(update_zookeeper, 'interval', seconds=5) update_timer.add_job(update_zookeeper, 'interval', seconds=config['keepalive_interval'])
update_timer.start() update_timer.start()
# Tick loop # Tick loop