* [Cluster-devel] conga/luci/site/luci/Extensions LuciValidation.py
@ 2007-12-12 15:43 rmccabe
0 siblings, 0 replies; 3+ messages in thread
From: rmccabe @ 2007-12-12 15:43 UTC (permalink / raw)
To: cluster-devel.redhat.com
CVSROOT: /cvs/cluster
Module name: conga
Changes by: rmccabe at 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 })
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Cluster-devel] conga/luci/site/luci/Extensions LuciValidation.py
@ 2008-07-31 18:46 rmccabe
0 siblings, 0 replies; 3+ messages in thread
From: rmccabe @ 2008-07-31 18:46 UTC (permalink / raw)
To: cluster-devel.redhat.com
CVSROOT: /cvs/cluster
Module name: conga
Branch: RHEL5
Changes by: rmccabe at sourceware.org 2008-07-31 18:46:40
Modified files:
luci/site/luci/Extensions: LuciValidation.py
Log message:
Fix the fix for bz429350
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciValidation.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.6&r2=1.6.2.7
--- conga/luci/site/luci/Extensions/LuciValidation.py 2008/07/23 19:55:41 1.6.2.6
+++ conga/luci/site/luci/Extensions/LuciValidation.py 2008/07/31 18:46:40 1.6.2.7
@@ -1134,13 +1134,6 @@
errors.append('Restart expire time must be a number greater than or equal to 0')
restart_expire_time = None
- 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')
-
-
migration_type = fvar['migration_type']
if migration_type is not None and migration_type != 'live' and migration_type != 'pause':
errors.append('Migration type must be either "live" or "pause"')
@@ -1194,7 +1187,6 @@
xvm.removeAttribute('domain')
except:
pass
-
if recovery:
xvm.addAttribute('recovery', recovery)
else:
@@ -1202,6 +1194,10 @@
xvm.removeAttribute('recovery')
except:
pass
+ if max_restarts is not None:
+ xvm.addAttribute('max_restarts', str(max_restarts))
+ if restart_expire_time is not None:
+ xvm.addAttribute('restart_expire_time', str(restart_expire_time))
if delete_vm is True:
action = VM_CONFIG
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Cluster-devel] conga/luci/site/luci/Extensions LuciValidation.py
@ 2010-08-05 19:32 rmccabe
0 siblings, 0 replies; 3+ messages in thread
From: rmccabe @ 2010-08-05 19:32 UTC (permalink / raw)
To: cluster-devel.redhat.com
CVSROOT: /cvs/cluster
Module name: conga
Branch: RHEL5
Changes by: rmccabe at sourceware.org 2010-08-05 19:32:58
Modified files:
luci/site/luci/Extensions: LuciValidation.py
Log message:
Fix rhbz#603114: Can't create KVM guest resources without a path to the XML file
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciValidation.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.13&r2=1.6.2.14
--- conga/luci/site/luci/Extensions/LuciValidation.py 2010/01/07 18:08:35 1.6.2.13
+++ conga/luci/site/luci/Extensions/LuciValidation.py 2010/08/05 19:32:58 1.6.2.14
@@ -1116,10 +1116,6 @@
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'):
@@ -1192,7 +1188,8 @@
if isNew is True:
xvm = Vm()
xvm.addAttribute('name', vm_name)
- xvm.addAttribute('path', vm_path)
+ if vm_path:
+ xvm.addAttribute('path', vm_path)
rmptr = model.getResourceManagerPtr()
rmptr.addChild(xvm)
else:
@@ -1203,7 +1200,11 @@
except:
return (False, { 'errors': [ 'No virtual machine service named "%s" exists' % old_name ]})
xvm.addAttribute('name', vm_name)
- xvm.addAttribute('path', vm_path)
+
+ if vm_path:
+ xvm.addAttribute('path', vm_path)
+ else:
+ xvm.removeAttribute('vm_path')
if nfslock is not None:
xvm.addAttribute('nfslock', '1')
@@ -1229,6 +1230,8 @@
hypervisor = fvar['hypervisor']
if hypervisor == 'xen':
xvm.addAttribute('hypervisor', 'xen')
+ if not vm_path:
+ errors.append('No path to the virtual machine configuration directory was given for VM service "%s"' % vm_name)
elif hypervisor == 'qemu':
xvm.addAttribute('hypervisor', 'qemu')
else:
@@ -1264,6 +1267,8 @@
action = VM_CONFIG
status_msg = 'Configuring virtual machine service "%s"' % vm_name
+ if len(errors) > 0:
+ return (False, {'errors': errors })
return (True, { 'action_type': action, 'action_msg': status_msg })
def validate_fence_del(model, request):
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-08-05 19:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-05 19:32 [Cluster-devel] conga/luci/site/luci/Extensions LuciValidation.py rmccabe
-- strict thread matches above, loose matches on Subject: below --
2008-07-31 18:46 rmccabe
2007-12-12 15:43 rmccabe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).