[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] conga/luci/site/luci/Extensions LuciValidation.py



CVSROOT:	/cvs/cluster
Module name:	conga
Changes by:	rmccabe sourceware org	2007-12-12 15:43:15

Added files:
	luci/site/luci/Extensions: LuciValidation.py 

Log message:
	Separate out cluster form post validation to allow async validation

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciValidation.py.diff?cvsroot=cluster&r1=NONE&r2=1.1

/cvs/cluster/conga/luci/site/luci/Extensions/LuciValidation.py,v  -->  standard output
revision 1.1
--- conga/luci/site/luci/Extensions/LuciValidation.py
+++ -	2007-12-12 15:43:15.733027000 +0000
@@ -0,0 +1,1185 @@
+# Copyright (C) 2007 Red Hat, Inc.
+#
+# This program is free software; you can redistribute
+# it and/or modify it under the terms of version 2 of the
+# GNU General Public License as published by the
+# Free Software Foundation.
+
+from ClusterModel.RefObject import RefObject
+from ClusterModel.Service import Service
+from ClusterModel.Method import Method
+from ClusterModel.Fence import Fence
+from ClusterModel.FailoverDomain import FailoverDomain
+from ClusterModel.FailoverDomainNode import FailoverDomainNode
+from ClusterModel.QuorumD import QuorumD
+from ClusterModel.Heuristic import Heuristic
+from ClusterModel.FenceXVMd import FenceXVMd
+from ClusterModel.Lockserver import Lockserver
+from ClusterModel.Vm import Vm
+
+from conga_constants import LUCI_DEBUG_MODE, FDOM, FDOM_ADD, SERVICE_CONFIG, SERVICE_ADD, VM_CONFIG, VM_ADD
+from FenceHandler import validateFenceDevice, validateNewFenceDevice, validate_fenceinstance, FD_VAL_SUCCESS 
+
+from LuciSyslog import get_logger
+from xml.dom import minidom
+from ResourceHandler import create_resource
+from LuciZope import GetReqVars
+
+luci_log = get_logger()
+
+def validate_node_fence_config(model, request):
+	errors = list()
+
+	fvar = GetReqVars(request,
+			[ 'fence_xml', 'fence_level', 'nodename', 'clustername' ])
+
+	if fvar['fence_xml'] is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC0: no fence_xml for node %s' \
+				% fvar['nodename'])
+		return (False, {'errors': ['No fence data was supplied']})
+
+	if fvar['fence_level'] is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC1: no fence level for %s' \
+				% fvar['nodename'])
+		return (False, {'errors': ['No fence level was supplied']})
+
+	try:
+		fence_level = int(fvar['fence_level'])
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC2: invalid fence level: %s: %r %s' \
+				% (fvar['fence_level'], e, str(e)))
+		return (False, {'errors': ['"%s" is an invalid fence level' % fvar['fence_level'] ]})
+
+	nodename = fvar['nodename']
+	if nodename is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC3: no nodename: %r %s' % (e, str(e)))
+		return (False, {'errors': ['No node name was given']})
+
+	clustername = fvar['clustername']
+	if clustername is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC4: no clustername: %r %s' % (e, str(e)))
+		return (False, {'errors': ['No cluster name was given']})
+
+	try:
+		doc = minidom.parseString(fvar['fence_xml'])
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC7: error: %r %s' % (e, str(e)))
+		return (False, {'errors': ['The fence data submitted is not properly formed']})
+
+	try:
+		node = model.retrieveNodeByName(nodename)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC8: unable to find node name %s in current node list: %r %s' % (nodename, e, str(e)))
+		return (False, {'errors': ['Unable to find the cluster node %s in the node list' % nodename ]})
+
+	levels = node.getFenceLevels()
+	try:
+		method_id = levels[fence_level - 1].getAttribute('name')
+		if not method_id:
+			raise Exception, 'No method ID'
+		fence_method = Method()
+		fence_method.addAttribute('name', str(method_id))
+		levels[fence_level - 1] = fence_method
+	except Exception, e:
+		method_id = fence_level
+		fence_method = Method()
+		fence_method.addAttribute('name', str(method_id))
+
+	forms = doc.getElementsByTagName('form')
+	if len(forms) < 1:
+		delete_target = None
+		for l in levels:
+			# delete the fence level
+			if l.getAttribute('name') == method_id:
+				delete_target = l
+				break
+		if delete_target is not None:
+			try:
+				node.getChildren()[0].removeChild(delete_target)
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vNFC9: %s: %r %s' \
+						% (method_id, e, str(e)))
+				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]})
+		else:
+			return (True, {'messages': ['No changes were made'] })
+
+	form_hash = {}
+	for i in forms:
+		form_id = i.getAttribute('id')
+		if not form_id:
+			continue
+		ielems = i.getElementsByTagName('input')
+		if not ielems or len(ielems) < 1:
+			continue
+
+		dummy_form = {}
+
+		for i in ielems:
+			try:
+				input_type = str(i.getAttribute('type'))
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vNFC10: input type: %r %s' \
+						% (e, str(e)))
+				continue
+
+			if not input_type or input_type == 'button':
+				continue
+
+			try:
+				dummy_form[str(i.getAttribute('name'))] = str(i.getAttribute('value'))
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vNFC11: parsing XML: %r %s' \
+						% (e, str(e)))
+
+		if len(dummy_form) < 1:
+			continue
+
+		if dummy_form.has_key('fence_instance'):
+			try:
+				parent = dummy_form['parent_fencedev']
+			except:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vNFC12: no parent for instance')
+				return (False, {'errors': [ 'Unable to determine what device the current instance uses' ]})
+
+			try:
+				form_hash[parent][1].append(dummy_form)
+				del dummy_form['fence_instance']
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vNFC13: no parent for instance')
+				return (False, {'errors': [ 'Unable to determine what device the current instance uses' ]})
+		else:
+			form_hash[form_id] = (dummy_form, list())
+
+	fh_keys = form_hash.keys()
+	fh_keys.sort()
+	for i in fh_keys:
+		fencedev_name = None
+		fencedev_unknown = False
+
+		try:
+			fence_form, instance_list = form_hash[i]
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vNFC14: %r %s' % (e, str(e)))
+			continue
+
+		try:
+			fence_type = fence_form['fence_type']
+			if not fence_type:
+				raise Exception, 'fence type is blank'
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vNFC15: %s: %r %s' % (i, e, str(e)))
+			fence_type = None
+
+		if fence_form.has_key('existing_device'):
+			try:
+				fencedev_name = fence_form['name']
+				if not fencedev_name.strip():
+					raise Exception, 'no fence name'
+			except Exception, e:
+				errors.append('You must provide a unique name for all fence devices')
+				continue
+
+			if fence_type is None:
+				# An unknown fence device agent. Pull the data out of
+				# the model and persist it and all instances.
+				# All we care about is its name.
+				fencedev_unknown = True
+			else:
+				if not fence_form.has_key('sharable'):
+					# If it's a shared fence device that already exists, the
+					# user could not have edited it (without playing dirty
+					# games), so it's safe to pull the existing entry from
+					# the model. All we need is the device name, and nothing
+					# else needs to be done here.
+					#
+					# For an existing non-shared device update the device
+					# in the model, since the user could have edited it.
+					retcode, retmsg = validateFenceDevice(fence_form, model)
+					if retcode != FD_VAL_SUCCESS:
+						errors.extend(retmsg)
+						continue
+					else:
+						fencedev_name = retmsg
+
+					# Add back the tags under the method block
+					# for the fence instance
+					if type == 'fence_manual':
+						instance_list.append({'name': fencedev_name, 'nodename': nodename })
+					else:
+						instance_list.append({'name': fencedev_name })
+		else:
+			# The user created a new fence device.
+			retcode, retmsg = validateNewFenceDevice(fence_form, model)
+			if retcode != FD_VAL_SUCCESS:
+				errors.extend(retmsg)
+				continue
+			else:
+				fencedev_name = retmsg
+
+			# If it's not shared, we need to create an instance form
+			# so the appropriate XML goes into the <method> block inside
+			# <node><fence>. All we need for that is the device name.
+			if not fence_form.has_key('sharable'):
+				if type == 'fence_manual':
+					instance_list.append({'name': fencedev_name, 'nodename': nodename })
+				else:
+					instance_list.append({'name': fencedev_name })
+
+		if fencedev_unknown is True:
+			# Save any instances for this fence device.
+			# XXX FIX ME - instances must be saved.
+			pass
+
+		for inst in instance_list:
+			retcode, retobj = validate_fenceinstance(inst, fencedev_name, fence_type)
+			if retcode != FD_VAL_SUCCESS:
+				errors.extend(retobj)
+				continue
+			fence_method.addChild(retobj)
+
+		if len(node.getChildren()) > 0:
+			# There's already a <fence> block
+			found_target = False
+			for idx in xrange(len(levels)):
+				if levels[idx].getAttribute('name') == method_id:
+					found_target = True
+					break
+
+			if found_target is False:
+				# There's a fence block, but no relevant method
+				# block
+				node.getChildren()[0].addChild(fence_method)
+		else:
+			# There is no <fence> tag under the node yet.
+			fence_node = Fence()
+			fence_node.addChild(fence_method)
+			node.addChild(fence_node)
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+	return (True, {})
+
+def validate_clusvc_add(model, request):
+	errors = list()
+	fvar = GetReqVars(request, [ 'form_xml', 'domain', 'recovery', 'svc_name', 'action' ])
+
+	form_xml = fvar['form_xml']
+	if form_xml is None:
+		form_xml = ''
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA0: no form_xml')
+
+	forms = []
+	if form_xml.strip():
+		try:
+			doc = minidom.parseString(form_xml)
+			forms = doc.getElementsByTagName('form')
+			if len(forms) < 1:
+				raise Exception, 'invalid XML'
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vSA1: error: %r %s: %r' % (e, str(e), form_xml))
+			return (False, { 'errors': [ 'The resource data submitted for this service is not properly formed' ]})
+
+	form_hash = {}
+	form_hash['toplevel'] = { 'form': None, 'kids': [] }
+	for i in forms:
+		form_id = i.getAttribute('id')
+		form_parent = i.getAttribute('parent')
+		if not form_id or not form_parent:
+			continue
+		ielems = i.getElementsByTagName('input')
+		if not ielems or len(ielems) < 1:
+			continue
+		if not form_id in form_hash:
+			form_hash[form_id] = {'form': i, 'kids': []}
+		elif not form_hash[form_id]['form']:
+			form_hash[form_id]['form'] = i
+		if not form_parent in form_hash:
+			form_hash[form_parent] = {'form': None, 'kids': []}
+		form_hash[form_parent]['kids'].append(form_id)
+		dummy_form = {}
+
+		for i in ielems:
+			try:
+				input_type = str(i.getAttribute('type'))
+			except:
+				continue
+			if not input_type or input_type == 'button':
+				continue
+			try:
+				dummy_form[str(i.getAttribute('name'))] = str(i.getAttribute('value'))
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('vSA2: parsing XML: %r %s' \
+						% (e, str(e)))
+
+		try:
+			res_type = dummy_form['type'].strip()
+			if not res_type:
+				raise Exception, 'no resource type'
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vSA3: %r %s' % (e, str(e)))
+			return (False, { 'errors': [ 'No resource type was specified' ]})
+
+		try:
+			if res_type == 'ip':
+				dummy_form['resourceName'] = dummy_form['ip_address']
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vSA3a: type is ip but no addr: %r %s' \
+					% (e, str(e)))
+			return (False, { 'errors': [ 'No IP address was given' ]})
+
+		try:
+			if dummy_form.has_key('immutable'):
+				newRes = model.getResourceByName(dummy_form['resourceName'])
+				resObj = RefObject(newRes)
+				resObj.setRef(newRes.getName())
+			else:
+				resObj = create_resource(res_type, dummy_form, model)
+		except Exception, e:
+			resObj = None
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('vSA4: type %s: %r %s' \
+					% (res_type, e, str(e)))
+
+		if resObj is None:
+			return (False, { 'errors': [ 'An error occurred while adding %s' % res_type ]})
+
+		if dummy_form.has_key('__independent_subtree'):
+			resObj.addAttribute('__independent_subtree', '1')
+		else:
+			resObj.removeAttribute('__independent_subtree')
+		form_hash[form_id]['obj'] = resObj
+
+	if len(errors) > 0:
+		return (False, {'errors': errors})
+
+	fdom = fvar['domain']
+
+	recovery = fvar['recovery']
+	if recovery is not None and recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+		errors.append('You entered an invalid recovery option: "%s" Valid options are "restart" "relocate" and "disable."')
+
+	service_name = fvar['svc_name']
+	if service_name is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA5: no service name')
+		errors.append('No service name was given')
+
+	autostart = '1'
+	try:
+		if not request.form.has_key('autostart') or request.form['autostart'] == '0':
+			autostart = '0'
+	except Exception, e:
+		autostart = None
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA5a: error getting autostart: %r %s' \
+				% (e, str(e)))
+
+	exclusive = '0'
+	try:
+		if not request.form.has_key('exclusive') or request.form['exclusive'] != '1':
+			exclusive = '0'
+		else:
+			exclusive = '1'
+	except Exception, e:
+		exclusive = '0'
+
+	try:
+		cur_service = model.retrieveServiceByName(service_name)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA5c: no service named %s found: %r %s' \
+				% (service_name, e, str(e)))
+		cur_service = None
+
+	action = fvar['action']
+	if action is None:
+		return (False, {'errors': [ 'No action was given for service %s' % service_name ] })
+
+	if action == 'edit':
+		if cur_service is None:
+			return (False, {'errors': [ 'The service %s could not be found for editing' % service_name ]})
+		model.deleteService(service_name)
+	elif action == 'add':
+		if cur_service is not None:
+			return (False, {'errors': [ 'A service with the name %s already exists' % service_name ]})
+	else:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA4a: unknown action %s' \
+				% request.form['action'])
+		return (False, {'errors': [ 'An unknown action was specified' ]})
+
+	def buildSvcTree(parent, child_id_list):
+		for i in child_id_list:
+			try:
+				child = form_hash[i]['obj']
+				if not child:
+					raise Exception, 'No object for %s' % i
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('bST0: %r %s' % (e, str(e)))
+				continue
+			parent.addChild(child)
+			if 'kids' in form_hash[i]:
+				buildSvcTree(child, form_hash[i]['kids'])
+
+	new_service = Service()
+	new_service.addAttribute('name', service_name)
+	if fdom:
+		new_service.addAttribute('domain', fdom)
+	if recovery:
+		new_service.addAttribute('recovery', recovery)
+	new_service.addAttribute('exclusive', str(exclusive))
+	if autostart is not None:
+		new_service.attr_hash['autostart'] = autostart
+
+	buildSvcTree(new_service, form_hash['toplevel']['kids'])
+	model.resourcemanager_ptr.addChild(new_service)
+	model.setModified(True)
+
+	if action == 'edit':
+		action_type = SERVICE_CONFIG
+		action_msg = 'Configuring service "%s"' % service_name
+	else:
+		action_type = SERVICE_ADD
+		action_msg = 'Creating service "%s"' % service_name
+
+	return (True, { 'action_type': action_type, 'action_msg': action_msg })
+
+def validate_clures_add(model, request):
+	fvar = GetReqVars(request, [ 'type' ])
+
+	res_type = fvar['type']
+	if res_type is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('VRA0: type is blank')
+		return (False, { 'errors': [ 'No resource type was given']})
+
+	try:
+		res = create_resource(res_type, request.form, model)
+	except Exception, e:
+		return (False, { 'errors': e } )
+
+	resname = ''
+	try:
+		resname = res.getName()
+		model.getResourcesPtr().addChild(res)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('EditResource0: %r %s' % (e, str(e)))
+		return (False, { 'errors': [ 'Error configuring resource %s %s: ' % (resname, str(e)) ] })
+	return (True, { 'res_name': resname })
+
+def validate_fdom(model, request):
+	errors = list()
+	fvar = GetReqVars(request, [ 'clustername', 'name', 'oldname' ])
+
+	name = fvar['name']
+	if name is None:
+		errors.append('No name was given for this failover domain')
+
+	prioritized = False
+	try:
+		prioritized = request.form.has_key('prioritized')
+	except:
+		prioritized = False
+
+	restricted = False
+	try:
+		restricted = request.form.has_key('restricted')
+	except:
+		restricted = False
+
+	nofailback = False
+	try:
+		nofailback = request.form.has_key('nofailback')
+	except:
+		nofailback = False
+
+	oldname = fvar['oldname']
+
+	if oldname is None or oldname != name:
+		if model.getFailoverDomainByName(name) is not None:
+			errors.append('A failover domain named "%s" already exists' % name)
+
+	fdom = None
+	if oldname is not None:
+		fdom = model.getFailoverDomainByName(oldname)
+		if fdom is None:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('validateFdom1: No fdom named %s exists' % oldname)
+			errors.append('No failover domain named "%s" exists' % oldname)
+		else:
+			fdom.addAttribute('name', name)
+			fdom.children = list()
+	else:
+		fdom = FailoverDomain()
+		fdom.addAttribute('name', name)
+
+	if fdom is None or len(errors) > 0:
+		return (False, {'errors': errors })
+
+	if prioritized:
+		fdom.addAttribute('ordered', '1')
+	else:
+		fdom.addAttribute('ordered', '0')
+
+	if restricted:
+		fdom.addAttribute('restricted', '1')
+	else:
+		fdom.addAttribute('restricted', '0')
+
+	if nofailback:
+		fdom.addAttribute('nofailback', '1')
+	else:
+		fdom.addAttribute('nofailback', '0')
+
+	for i in model.getNodeNames():
+		if request.form.has_key(i):
+			fdn = FailoverDomainNode()
+			fdn.addAttribute('name', i)
+			if prioritized:
+				priority = 1
+				try:
+					priority = int(request.form['__PRIORITY__%s' % i].strip())
+					if priority < 1:
+						priority = 1
+				except Exception, e:
+					priority = 1
+				fdn.addAttribute('priority', str(priority))
+			fdom.addChild(fdn)
+
+	try:
+		fdom_ptr = model.getFailoverDomainPtr()
+		if not oldname:
+			fdom_ptr.addChild(fdom)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('validateFdom2: %r %s' % (e, str(e)))
+		errors.append('Unable to update the cluster configuration')
+
+	if len(errors) > 0:
+		return (False, { 'errors': errors })
+
+	if oldname:
+		action = FDOM
+		status_msg = 'Updating failover domain "%s"' % oldname
+	else:
+		action = FDOM_ADD
+		status_msg = 'Creating failover domain "%s"' % name
+
+	return (True, { 'msg': status_msg, 'action': action })
+
+def validate_config_mcast(model, form):
+	gulm_ptr = model.getGULMPtr()
+	if gulm_ptr:
+		return (False, { 'errors': ['Multicast cannot be used with GULM locking']})
+	errors = list()
+	try:
+		mcast_val = form['mcast'].strip().lower()
+		if mcast_val != 'true' and mcast_val != 'false':
+			raise KeyError, mcast_val
+		if mcast_val == 'true':
+			mcast_manual = True
+		else:
+			mcast_manual = False
+	except KeyError, e:
+		errors.append('An invalid multicast selection was made')
+		return (False, {'errors': errors})
+
+	mcast_interface = None
+	if form.has_key('mcast_interface'):
+		mcast_interface = form['mcast_interface'].strip()
+
+	if mcast_manual is True and form.has_key('cluster_version') and form['cluster_version'].strip() == 'rhel4' and not mcast_interface:
+		errors.append('No multicast interface was specified')
+		return (False, {'errors': errors})
+
+	if mcast_manual is True:
+		import socket
+		try:
+			addr_str = form['mcast_address'].strip()
+			socket.inet_pton(socket.AF_INET, addr_str)
+		except KeyError, e:
+			addr_str = None
+			errors.append('No multicast address was given')
+		except socket.error, e:
+			try:
+				socket.inet_pton(socket.AF_INET6, addr_str)
+			except socket.error, e:
+				addr_str = None
+				errors.append('An invalid multicast address was given: %s')
+	else:
+		addr_str = None
+
+	try:
+		if not addr_str:
+			if mcast_interface:
+				errors.append('A multicast interface was specified, but no multicast address was given')
+				return (False, {'errors': errors})
+			model.del_cluster_multicast()
+		else:
+			model.set_cluster_multicast(addr_str, mcast_if=mcast_interface)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug('Error updating mcast properties: %r %s' \
+				% (e, str(e)))
+		errors.append('Unable to update cluster multicast properties')
+
+	if len(errors) > 0:
+		return (False, {'errors': errors})
+
+	return (True, {})
+
+def validate_config_qdisk(model, form):
+	errors = list()
+
+	gulm_ptr = model.getGULMPtr()
+	if gulm_ptr is not None:
+		return (False, { 'errors': ['Quorum disk cannot be used with GULM locking']})
+
+	try:
+		qdisk_val = form['quorumd'].strip().lower()
+		if qdisk_val != 'true' and qdisk_val != 'false':
+			raise KeyError(qdisk_val)
+		if qdisk_val == 'true':
+			qdisk_val = 1
+		else:
+			qdisk_val = 0
+	except KeyError, e:
+		return (False, {'errors': ['An invalid quorum partition selection was made']})
+
+	cp = model.getClusterPtr()
+	qdp = model.getQuorumdPtr()
+
+	if not qdisk_val:
+		if qdp:
+			try:
+				cp.removeChild(qdp)
+			except Exception, e:
+				return (False, {'errors': [ 'Error disabling quorum partition: %s' % str(e) ] })
+		return (True, {})
+
+	try:
+		interval = int(form['interval'])
+		if interval < 0:
+			raise ValueError, 'Interval must be 0 or greater'
+	except KeyError, e:
+		errors.append('No Interval value was given')
+	except ValueError, e:
+		errors.append('An invalid Interval value was given: %s' % str(e))
+
+	try:
+		votes = int(form['votes'])
+		if votes < 1:
+			raise ValueError, 'Votes must be greater than 0'
+	except KeyError, e:
+		errors.append('No Votes value was given')
+	except ValueError, e:
+		errors.append('An invalid Votes value was given: %s' % str(e))
+
+	try:
+		tko = int(form['tko'])
+		if tko < 0:
+			raise ValueError, 'TKO must be 0 or greater'
+	except KeyError, e:
+		errors.append('No TKO value was given')
+	except ValueError, e:
+		errors.append('An invalid TKO value was given: %s' % str(e))
+
+	try:
+		min_score = int(form['min_score'])
+		if min_score < 1:
+			raise ValueError('Minimum Score must be greater than 0')
+	except KeyError, e:
+		errors.append('No Minimum Score value was given')
+	except ValueError, e:
+		errors.append('An invalid Minimum Score value was given: %s' % str(e))
+
+	# Either device or label must be present
+	device = None
+	try:
+		device = form['device'].strip()
+	except:
+		device = None
+
+	label = None
+	try:
+		label = form['label'].strip()
+	except:
+		label = None
+
+	if not device and not label:
+		errors.append('No Device or Label value was given')
+
+	num_heuristics = 0
+	try:
+		num_heuristics = int(form['num_heuristics']) + 1
+		if num_heuristics < 1:
+			raise ValueError, form['num_heuristics']
+	except KeyError, e:
+		errors.append('No number of heuristics was given')
+	except ValueError, e:
+		errors.append('An invalid number of heuristics was given: %s' % str(e))
+
+	heuristics = list()
+	for i in xrange(num_heuristics):
+		try:
+			h = form['heuristic%d' % i]
+			if not h or len(h) != 3 or not (h[0].strip() and h[1].strip() and h[2].strip()):
+				continue
+		except:
+			continue
+
+		try:
+			hprog = h[0]
+			if not hprog:
+				raise Exception, 'no hprog'
+		except Exception, e:
+			errors.append('No program was given for heuristic %d' % (i + 1))
+		try:
+			hint = int(h[1])
+			if hint < 1:
+				raise ValueError, 'Heuristic interval values must be greater than 0'
+		except KeyError, e:
+			errors.append('No interval was given for heuristic %d' % (i + 1))
+		except ValueError, e:
+			errors.append('An invalid interval was given for heuristic %d: %s' \
+				% ((i + 1), str(e)))
+
+		try:
+			hscore = int(h[2])
+			if hscore < 1:
+				raise ValueError, 'Heuristic scores must be greater than 0'
+		except KeyError, e:
+			errors.append('No score was given for heuristic %d' % (i + 1))
+		except ValueError, e:
+			errors.append('An invalid score was given for heuristic %d: %s' \
+				% ((i + 1), str(e)))
+
+		heuristics.append([ hprog, hint, hscore ])
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	qd = QuorumD()
+	qd.addAttribute('interval', str(interval))
+	qd.addAttribute('votes', str(votes))
+	qd.addAttribute('tko', str(tko))
+	qd.addAttribute('min_score', str(min_score))
+
+	if device:
+		qd.addAttribute('device', str(device))
+	else:
+		qd.addAttribute('label', str(label))
+
+	if qdp:
+		try:
+			cp.removeChild(qdp)
+		except:
+			pass
+	cp.addChild(qd)
+
+	for h in heuristics:
+		new_h = Heuristic()
+		new_h.addAttribute('program', str(h[0]))
+		new_h.addAttribute('interval', str(h[1]))
+		new_h.addAttribute('score', str(h[2]))
+		qd.addChild(new_h)
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	return (True, {})
+
+def validate_config_fence(model, form):
+	errors = list()
+
+	if model.getGULMPtr() is not None:
+		return (False, {'errors': [ 'GULM clusters do not support fenced' ]})
+
+	try:
+		post_fail_delay = int(form['post_fail_delay'])
+		if post_fail_delay < 0:
+			raise ValueError('post fail delay values must be 0 or greater')
+	except KeyError, e:
+		errors.append('No post fail delay was given')
+	except ValueError, e:
+		errors.append('Invalid post fail delay: %s' % str(e))
+
+	try:
+		post_join_delay = int(form['post_join_delay'])
+		if post_join_delay < 0:
+			raise ValueError('post join delay values must be 0 or greater')
+	except KeyError, e:
+		errors.append('No post join delay was given')
+	except ValueError, e:
+		errors.append('Invalid post join delay: %s' % str(e))
+
+	run_xvmd = form.has_key('run_xvmd')
+
+	if run_xvmd is True and not model.hasFenceXVM():
+		fenceXVMd = FenceXVMd()
+		model.addFenceXVM(fenceXVMd)
+	elif not run_xvmd:
+		model.delFenceXVM()
+
+	try:
+		fd = model.getFenceDaemonPtr()
+		old_pj_delay = fd.getPostJoinDelay()
+		old_pf_delay = fd.getPostFailDelay()
+
+		if post_join_delay == old_pj_delay and post_fail_delay == old_pf_delay:
+			errors.append('No fence daemon properties were changed')
+		else:
+			fd.setPostJoinDelay(str(post_join_delay))
+			fd.setPostFailDelay(str(post_fail_delay))
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('Unable to update fence daemon properties: %r %s' % (e, str(e)))
+		errors.append('An error occurred while attempting to update fence daemon properties: %s' % str(e))
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	return (True, {})
+
+def validate_config_gulm(model, form):
+	gulm_ptr = model.getGULMPtr()
+	if not gulm_ptr:
+		return (False, {'errors': [ 'This cluster is not using GULM locking' ]})
+
+	node_list = map(lambda x: x.getName(), gulm_ptr.getChildren())
+	for i in model.getNodeNames():
+		if not i in node_list:
+			node_list.append(i)
+
+	gulm_lockservers = list()
+	for node in node_list:
+		if form.has_key(node) and form[node] == 'on':
+			ls = Lockserver()
+			ls.addAttribute('name', node)
+			gulm_lockservers.append(ls)
+
+	try:
+		xlockservers = filter(lambda x: x.strip(), form['__GULM__'])
+	except:
+		xlockservers = list()
+
+	for i in xlockservers:
+		if not i in node_list:
+			ls = Lockserver()
+			ls.addAttribute('name', i)
+			gulm_lockservers.append(ls)
+
+	num_ls = len(gulm_lockservers)
+	if not num_ls in (1, 3, 5):
+		return (False, {'errors': [ 'You must have exactly 1, 3, or 5 GULM lock servers. You submitted %d lock servers' % num_ls ]})
+
+	model.GULM_ptr.children = gulm_lockservers
+	return (True, {})
+
+def validate_config_general(model, form):
+	errors = list()
+
+	try:
+		cp = model.getClusterPtr()
+		old_name = model.getClusterAlias()
+		old_ver = int(cp.getConfigVersion())
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('getConfigVersion: %s' % str(e))
+		errors.append('unable to determine the current configuration version')
+		return (False, {'errors': errors})
+
+	try:
+		cluster_name = form['cluname'].strip()
+		if not cluster_name:
+			raise KeyError('cluname')
+	except KeyError, e:
+		errors.append('No cluster name was given')
+
+	if len(cluster_name) > 15:
+		errors.append('A cluster\'s name must be less than 16 characters long')
+
+	try:
+		version_num = int(form['cfgver'])
+		if version_num < old_ver:
+			raise ValueError, 'configuration version number must be %d or greater' % old_ver
+	except KeyError, e:
+		errors.append('No cluster configuration version was given')
+	except ValueError, e:
+		errors.append('An invalid configuration version was given: %s' % str(e))
+
+	if len(errors) < 1:
+		try:
+			if cluster_name != old_name:
+				cp.addAttribute('alias', cluster_name)
+			cp.setConfigVersion(str(version_num))
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('unable to update general properties: %r %s' % (e, str(e)))
+			errors.append('Unable to update the cluster configuration')
+
+	try:
+		cluster_version = form['cluster_version'].strip()
+		if cluster_version != 'rhel5':
+			raise Exception, 'not rhel5'
+	except:
+		if len(errors) > 0:
+			return (False, {'errors': errors})
+		return (True, {})
+
+	totem = model.getTotemPtr()
+	if totem is None:
+		totem = model.addTotemPtr()
+
+	try:
+		token = form['token'].strip()
+		if not token:
+			raise KeyError, 'token'
+		token = int(token)
+		if token < 1:
+			raise ValueError, '%d is an invalid value for token timeout' % token
+		totem.addAttribute('token', str(token))
+	except KeyError, e:
+		try:
+			totem.removeAttribute('token')
+		except:
+			pass
+	except Exception, e:
+		errors.append(str(e))
+
+	try:
+		trblc = form['token_retransmits_before_loss_const'].strip()
+		if not trblc:
+			raise KeyError, 'token_retransmits_before_loss_const'
+		trblc = int(trblc)
+		if trblc < 1:
+			raise ValueError, '%d is an invalid value for number of token retransmits before loss' % trblc
+		totem.addAttribute('token_retransmits_before_loss_const', str(trblc))
+	except KeyError, e:
+		try:
+			totem.removeAttribute('token_retransmits_before_loss_const')
+		except:
+			pass
+	except Exception, e:
+		errors.append(str(e))
+
+	try:
+		join = form['join'].strip()
+		if not join:
+			raise KeyError, 'join'
+		join = int(join)
+		if join < 1:
+			raise ValueError, '%d is an invalid value for join timeout' % join
+		totem.addAttribute('join', str(join))
+	except KeyError, e:
+		try:
+			totem.removeAttribute('join')
+		except:
+			pass
+	except Exception, e:
+		errors.append(str(e))
+
+	try:
+		consensus = form['consensus'].strip()
+		if not consensus:
+			raise KeyError, 'consensus'
+		consensus = int(consensus)
+		if consensus < 1:
+			raise ValueError, '%d is an invalid value for consensus timeout' % consensus
+		totem.addAttribute('consensus', str(consensus))
+	except KeyError, e:
+		try:
+			totem.removeAttribute('consensus')
+		except:
+			pass
+	except Exception, e:
+		errors.append(str(e))
+
+	if len(errors) > 0:
+		return (False, {'errors': errors})
+	return (True, {})
+
+def validate_cluster_daemon_form(self, request):
+	errors = list()
+
+	fvar = GetReqVars(request, [ 'nodename' ])
+	nodename = fvar['nodename']
+	if nodename is None:
+		errors.append('Unable to determine the current node name')
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('VDP1: no nodename was given')
+
+	disable_list = list()
+	enable_list = list()
+
+	for i in request.form.items():
+		try:
+			if i[0][:11] == '__daemon__:':
+				daemon_prop = i[1]
+				if len(daemon_prop) == 2:
+					if daemon_prop[1] == '1':
+						disable_list.append(daemon_prop[0])
+				else:
+					if daemon_prop[1] == '0' and daemon_prop[2] == 'on':
+						enable_list.append(daemon_prop[0])
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('VDP3: error: %s: %r %s' \
+					% (str(i), e, str(e)))
+
+	if len(enable_list) < 1 and len(disable_list) < 1:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('VDP4: no changes made')
+		errors.append('No changes to daemon properies were made on node "%s"' \
+			% nodename)
+
+	if len(errors) > 0:
+		return (False, {'errors': errors})
+
+	return (True, { 'enable_list': enable_list, 'disable_list': disable_list })
+
+def validate_vmsvc_form(model, request):
+	errors = list()
+
+	fvar = GetReqVars(request, [ 'vmname', 'oldname', 'vmpath', 'recovery', 'domain', ])
+
+	vm_name = fvar['vmname']
+	if vm_name is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('validateVM2: no vm name')
+		errors.append('No virtual machine name was given')
+
+	vm_path = fvar['vmpath']
+	if vm_path is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('validateVM3: no vm path')
+		errors.append('No path to the virtual machine configuration directory was given for VM service "%s"' % vm_name)
+
+	autostart = 1
+	if request.form.has_key('autostart'):
+		autostart = 1
+	else:
+		autostart = 0
+
+	exclusive = 0
+	if request.form.has_key('exclusive'):
+		exclusive = 1
+	else:
+		exclusive = 0
+
+	recovery = fvar['recovery']
+	if recovery is not None and recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+		errors.append('You entered an invalid recovery option "%s" for VM service "%s". Valid options are "restart" "relocate" and "disable"' % (recovery, vm_name))
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	isNew = False
+	old_name = fvar['oldname']
+	if old_name is None:
+		isNew = True
+
+	delete_vm = False
+	if request.form.has_key('delete'):
+		try:
+			xvm = model.retrieveVMsByName(old_name)
+			if not xvm:
+				raise Exception, 'not found'
+			rmptr = model.getResourceManagerPtr()
+			rmptr.removeChild(xvm)
+			delete_vm = True
+		except:
+			return (False, { 'errors': [ 'No virtual machine service named "%s" exists' % old_name ]})
+	else:
+		if isNew is True:
+			xvm = Vm()
+			xvm.addAttribute('name', vm_name)
+			xvm.addAttribute('path', vm_path)
+			rmptr = model.getResourceManagerPtr()
+			rmptr.addChild(xvm)
+		else:
+			try:
+				xvm = model.retrieveVMsByName(old_name)
+				if not xvm:
+					raise Exception, 'not found'
+			except:
+				return (False, { 'errors': [ 'No virtual machine service named "%s" exists' % old_name ]})
+			xvm.addAttribute('name', vm_name)
+			xvm.addAttribute('path', vm_path)
+
+	xvm.addAttribute('autostart', str(autostart))
+	xvm.addAttribute('exclusive', str(exclusive))
+
+	fdom = fvar['domain']
+	if fdom:
+		xvm.addAttribute('domain', fdom)
+	else:
+		try:
+			xvm.removeAttribute('domain')
+		except:
+			pass
+
+	if recovery:
+		xvm.addAttribute('recovery', recovery)
+	else:
+		try:
+			xvm.removeAttribute('recovery')
+		except:
+			pass
+
+	if delete_vm is True:
+		action = VM_CONFIG
+		status_msg = 'Deleting virtual machine service "%s"' % vm_name
+	elif isNew is True:
+		action = VM_ADD
+		status_msg = 'Creating virtual machine service "%s"' % vm_name
+	else:
+		action = VM_CONFIG
+		status_msg = 'Configuring virtual machine service "%s"' % vm_name
+
+	return (True, { 'action_type': action, 'action_msg': status_msg })
+
+def validate_fence_del(model, request):
+	fvar = GetReqVars(request, [ 'orig_name' ])
+
+	fencedev_name = fvar['orig_name']
+	if fencedev_name is None:
+		return (False, { 'errors': [ 'No fence device name in form submission' ] })
+
+	try:
+		fdev = model.getFenceDeviceByName(fencedev_name)
+		if fdev:
+			if model.deleteFenceDevice(fdev) is not True:
+				raise Exception, 'failed to remove %s' % fdev.getName()
+			model.removeFenceInstancesForFenceDevice(fencedev_name)
+		else:
+			raise Exception, 'no fence device named "%s" was found' \
+					% fencedev_name
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('DFD3: %s: %r %s' \
+				% (fencedev_name, e, str(e)))
+		return (False, { 'errors': [ 'Error removing fence device %s: %s' \
+										% (fencedev_name, str(e)) ]})
+	return (True, { 'name': fencedev_name })


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]