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

[Cluster-devel] conga ./.cvsignore ./download_files luci/TODO ...



CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	rmccabe sourceware org	2007-03-01 00:31:21

Modified files:
	.              : .cvsignore download_files 
	luci           : TODO load_site.py pack.py 
	luci/cluster   : fence_device.js form-chooser form-macros 
	                 index_html resource-form-macros 
	                 resource_form_handlers.js 
	                 validate_config_general.js 
	                 validate_config_qdisk.js validate_fence.js 
	luci/homebase  : form-macros homebase_common.js 
	                 luci_homebase.css validate_cluster_add.js 
	luci/site/luci/Extensions: Cluster.py Clusterfs.py 
	                           FailoverDomain.py FenceHandler.py 
	                           Fs.py Ip.py ModelBuilder.py 
	                           NFSExport.py Netfs.py Samba.py 
	                           Script.py clui_constants.py 
	                           cluster_adapters.py 
	                           conga_constants.py 
	                           homebase_adapters.py ricci_bridge.py 
	                           ricci_communicator.py 
	luci/site/luci/var: Data.fs 
	luci/utils     : luci_admin luci_cleanup luci_manage 
	ricci          : ricci.spec.in.in 
	ricci/docs     : cluster_api.html modules.html rpm_api.html 
	                 service_api.html 
	ricci/modules/cluster: ClusterStatus.cpp 
	ricci/modules/log: LogParser.cpp 
	ricci/modules/rpm: PackageHandler.cpp 
	ricci/modules/service: ServiceManager.cpp ServiceManager.h 
	                       ServiceModule.cpp 
Added files:
	.              : Plone-2.5.2-1_CMFPlone.patch 
	luci/cluster   : validate_config_gulm.js validate_create_gulm.js 
	                 validate_fdom.js 
	luci/site/luci/Extensions: Apache.py FenceXVMd.py LVM.py 
	                           MySQL.py OpenLDAP.py Postgres8.py 
	                           Tomcat5.py Totem.py 
	luci/test      : CGA_0160_Add_User.py 
	                 CGA_0170_Online_Documentation_Portlet.py 
	                 CGA_0200_Create_cluster.py cleaner.py 
	                 congaDemoTests.py conga_Helpers.py 
	                 conga_suite.py loggerObject.py tests_README.txt 
	ricci/test_suite: README cacert.config generate_certs.sh 
	                  send_to_ricci 
	ricci/test_suite/cluster: fence_node.xml get_cluster.conf.xml 
	                          is_virtual.xml restart_service.xml 
	                          start_node.xml start_service.xml 
	                          status.xml stop_node.xml 
	                          stop_service.xml 
	ricci/test_suite/log: get_all.xml get_cluster.xml 
	                      get_piranha.xml get_rgmanager.xml 
	                      get_selinux.xml get_storage.xml 
	                      get_storage_and_selinux.xml 
	ricci/test_suite/reboot: reboot_now.xml 
	ricci/test_suite/ricci: authenticate.xml list_modules.xml 
	                        unauthenticate.xml 
	ricci/test_suite/rpm: install.xml install_enable_start.xml 
	                      list_all.xml list_installed.xml 
	                      list_repo.xml list_upgradeable.xml 
	                      query.xml repo_avail.xml 
	ricci/test_suite/service: disable.xml disable_and_stop.xml 
	                          enable.xml enable_and_start.xml 
	                          list.xml query.xml restart.xml 
	                          start.xml stop.xml 
	ricci/test_suite/storage: report.xml 
Removed files:
	.              : Plone-2.5_CMFPlone.patch 
	luci/site/luci/Extensions: CommandError.py CommandHandler.py 
	                           MessageLibrary.py ValidationError.py 
	                           Xenvm.py 

Log message:
	sync up with the RHEL4 branch to address the issues listed in bz 230466

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/Plone-2.5.2-1_CMFPlone.patch.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/.cvsignore.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/download_files.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/Plone-2.5_CMFPlone.patch.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/TODO.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/load_site.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.14.2.1&r2=1.14.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/pack.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.1&r2=1.4.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_config_gulm.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.3.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_create_gulm.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_fdom.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.3.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/fence_device.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2.2.4&r2=1.2.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-chooser.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.12.2.3&r2=1.12.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.90.2.18&r2=1.90.2.19
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/index_html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.6&r2=1.20.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/resource-form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.21.2.3&r2=1.21.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/resource_form_handlers.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.3&r2=1.20.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_config_general.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_config_qdisk.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.1&r2=1.4.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/validate_fence.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.44.2.7&r2=1.44.2.8
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/homebase_common.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.13.2.2&r2=1.13.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/luci_homebase.css.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.28.2.4&r2=1.28.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/validate_cluster_add.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.1&r2=1.4.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Apache.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/FenceXVMd.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LVM.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/MySQL.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/OpenLDAP.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Postgres8.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Tomcat5.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Totem.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Cluster.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Clusterfs.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/FailoverDomain.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/FenceHandler.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.3&r2=1.4.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Fs.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Ip.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ModelBuilder.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.8.2.6&r2=1.8.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/NFSExport.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Netfs.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Samba.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Script.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/clui_constants.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/cluster_adapters.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.120.2.20&r2=1.120.2.21
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/conga_constants.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.19.2.7&r2=1.19.2.8
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/homebase_adapters.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.34.2.11&r2=1.34.2.12
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_bridge.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.30.2.17&r2=1.30.2.18
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_communicator.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.9.2.9&r2=1.9.2.10
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/CommandError.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/CommandHandler.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/MessageLibrary.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ValidationError.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Xenvm.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/var/Data.fs.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.15.2.9&r2=1.15.2.10
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/CGA_0160_Add_User.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.7.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/CGA_0170_Online_Documentation_Portlet.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/CGA_0200_Create_cluster.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/cleaner.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/congaDemoTests.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.11.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/conga_Helpers.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.14.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/conga_suite.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.11.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/loggerObject.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/test/tests_README.txt.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/utils/luci_admin.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.50.2.2&r2=1.50.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/utils/luci_cleanup.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/utils/luci_manage.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.2.1&r2=1.1.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/ricci.spec.in.in.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.12&r2=1.12.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/docs/cluster_api.html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/docs/modules.html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/docs/rpm_api.html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/docs/service_api.html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/ClusterStatus.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.15.2.1&r2=1.15.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/log/LogParser.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.2&r2=1.6.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/rpm/PackageHandler.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.9.2.2&r2=1.9.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/service/ServiceManager.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.1&r2=1.5.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/service/ServiceManager.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/service/ServiceModule.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/README.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cacert.config.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/generate_certs.sh.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/send_to_ricci.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/fence_node.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/get_cluster.conf.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/is_virtual.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/restart_service.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/start_node.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/start_service.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/status.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/stop_node.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/cluster/stop_service.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_all.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_cluster.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_piranha.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_rgmanager.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_selinux.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_storage.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/log/get_storage_and_selinux.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/reboot/reboot_now.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/ricci/authenticate.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/ricci/list_modules.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/ricci/unauthenticate.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/install.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/install_enable_start.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/list_all.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/list_installed.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/list_repo.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/list_upgradeable.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/query.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/rpm/repo_avail.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/disable.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/disable_and_stop.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/enable.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/enable_and_start.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/list.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/query.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/restart.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/start.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/service/stop.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/storage/report.xml.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.4.1

/cvs/cluster/conga/Plone-2.5.2-1_CMFPlone.patch,v  -->  standard output
revision 1.1.4.1
--- conga/Plone-2.5.2-1_CMFPlone.patch
+++ -	2007-03-01 00:31:22.167341000 +0000
@@ -0,0 +1,111 @@
+diff -ur Plone-2.5.2-1.orig/CMFPlone/exportimport/configure.zcml Plone-2.5.2-1/CMFPlone/exportimport/configure.zcml
+--- Plone-2.5.2-1.orig/CMFPlone/exportimport/configure.zcml	2007-01-16 22:26:49.000000000 -0500
++++ Plone-2.5.2-1/CMFPlone/exportimport/configure.zcml	2007-01-23 16:24:53.000000000 -0500
+@@ -32,12 +32,6 @@
+      />
+ 
+   <adapter
+-     factory="Products.CMFCore.exportimport.content.StructureFolderWalkingAdapter"
+-     provides="Products.GenericSetup.interfaces.IFilesystemImporter"
+-     for="Products.ATContentTypes.interface.IATContentType"
+-     />
+-
+-  <adapter
+      factory=".propertiestool.SimpleItemWithPropertiesXMLAdapter"
+      provides="Products.GenericSetup.interfaces.IBody"
+      for="Products.CMFCore.interfaces.IMemberDataTool
+@@ -51,19 +45,6 @@
+           Products.GenericSetup.interfaces.ISetupEnviron"
+      />
+ 
+-  <!-- Mark ATCT objects as IDAVAware so CMFSetup can export/import them -->
+-  <five:implements
+-     class="Products.ATContentTypes.content.document.ATDocument"
+-     interface="Products.GenericSetup.interfaces.IDAVAware"
+-     />
+-
+-  <!-- XXX: Temporarily disable ATTopic exporting until we have an
+-       actual exporter or Marshaller -->
+-  <five:implements
+-     class="Products.ATContentTypes.content.topic.ATTopic"
+-     interface="Products.CMFPlone.exportimport.content.IDisabledExport"
+-     />
+-
+   <adapter
+      factory=".content.NullExporterAdapter"
+      provides="Products.GenericSetup.interfaces.IFilesystemExporter"
+diff -ur Plone-2.5.2-1.orig/CMFPlone/MembershipTool.py Plone-2.5.2-1/CMFPlone/MembershipTool.py
+--- Plone-2.5.2-1.orig/CMFPlone/MembershipTool.py	2007-01-16 22:26:49.000000000 -0500
++++ Plone-2.5.2-1/CMFPlone/MembershipTool.py	2007-01-23 16:20:22.000000000 -0500
+@@ -1,4 +1,3 @@
+-import PIL
+ from cStringIO import StringIO
+ from DateTime import DateTime
+ from Products.CMFCore.utils import getToolByName, _checkPermission
+@@ -587,6 +586,7 @@
+             if portrait_data == '':
+                 continue
+             try:
++                import PIL
+                 img = PIL.Image.open(StringIO(portrait_data))
+             except ConflictError:
+                 pass
+diff -ur Plone-2.5.2-1.orig/CMFPlone/setup/dependencies.py Plone-2.5.2-1/CMFPlone/setup/dependencies.py
+--- Plone-2.5.2-1.orig/CMFPlone/setup/dependencies.py	2007-01-16 22:26:49.000000000 -0500
++++ Plone-2.5.2-1/CMFPlone/setup/dependencies.py	2007-01-23 16:20:55.000000000 -0500
+@@ -107,7 +107,8 @@
+ except ImportError:
+     log(("PIL not found. Plone needs PIL 1.1.5 or newer. "
+          "Please download it from http://www.pythonware.com/products/pil/ or "
+-         "http://effbot.org/downloads/#Imaging";))
++         "http://effbot.org/downloads/#Imaging";),
++        severity=logging.INFO, optional=1)
+ 
+ try:
+     from elementtree import ElementTree
+diff -ur Plone-2.5.2-1.orig/CMFPlone/utils.py Plone-2.5.2-1/CMFPlone/utils.py
+--- Plone-2.5.2-1.orig/CMFPlone/utils.py	2007-01-16 22:26:50.000000000 -0500
++++ Plone-2.5.2-1/CMFPlone/utils.py	2007-01-23 16:24:11.000000000 -0500
+@@ -3,8 +3,6 @@
+ from os.path import join, abspath, split
+ from cStringIO import StringIO
+ 
+-from PIL import Image
+-
+ import zope.interface
+ from zope.interface import implementedBy
+ from zope.component import getMultiAdapter
+@@ -41,15 +39,6 @@
+ DANGEROUS_CHARS_REGEX = re.compile(r"[?&/:\\#]+")
+ EXTRA_DASHES_REGEX = re.compile(r"(^\-+)|(\-+$)")
+ 
+-# Settings for member image resize quality
+-PIL_SCALING_ALGO = Image.ANTIALIAS
+-PIL_QUALITY = 88
+-MEMBER_IMAGE_SCALE = (75, 100)
+-IMAGE_SCALE_PARAMS = {'scale': MEMBER_IMAGE_SCALE,
+-                      'quality': PIL_QUALITY,
+-                      'algorithm': PIL_SCALING_ALGO,
+-                      'default_format': 'PNG'}
+-
+ _marker = []
+ 
+ class BrowserView(BaseView):
+@@ -632,6 +621,17 @@
+     return security
+ 
+ def scale_image(image_file, max_size=None, default_format=None):
++    from PIL import Image
++
++    # Settings for member image resize quality
++    PIL_SCALING_ALGO = Image.ANTIALIAS
++    PIL_QUALITY = 88
++    MEMBER_IMAGE_SCALE = (75, 100)
++    IMAGE_SCALE_PARAMS = {'scale': MEMBER_IMAGE_SCALE,
++                          'quality': PIL_QUALITY,
++                          'algorithm': PIL_SCALING_ALGO,
++                          'default_format': 'PNG'}
++
+     """Scales an image down to at most max_size preserving aspect ratio
+     from an input file
+ 
--- conga/.cvsignore	2006/09/25 17:35:13	1.3
+++ conga/.cvsignore	2007/03/01 00:31:08	1.3.2.1
@@ -1,12 +1,10 @@
-Plone-2.5.tar.gz
-Zope-2.9.3.tgz
-Zope-2.9.4-final.tgz
+Plone-*.tar.gz
+Zope-*.tgz
 conga.spec.in
 conga.spec
 clustermon.spec.in
 clustermon.spec
-clustermon-*.src.rpm
+clustermon-*.rpm
 clustermon-*.tar.gz
-conga-*.src.rpm
+conga-*.rpm
 conga-*.tar.gz
-
--- conga/download_files	2006/09/25 17:35:13	1.3
+++ conga/download_files	2007/03/01 00:31:08	1.3.2.1
@@ -1,23 +1,16 @@
 # define archive info for Zope and Plone
 # URLs is a space delimited list of urls to download from
 
+ZOPE_ARCHIVE=Zope-2.9.6-final
+ZOPE_ARCHIVE_TAR=Zope-2.9.6-final.tgz
+ZOPE_MD5SUM=a87008a9e78248072ea5908e1006b269
+ZOPE_URLs="http://www.zope.org/Products/Zope/2.9.6/Zope-2.9.6-final.tgz";
 
-#ZOPE_ARCHIVE=Zope-2.9.3
-#ZOPE_ARCHIVE_TAR=Zope-2.9.3.tgz
-#ZOPE_MD5SUM=4e8b4e076cadd6eb62dd4513748cb9f9
-#ZOPE_URLs="http://www.zope.org/Products/Zope/2.9.3/Zope-2.9.3.tgz";
 
-
-ZOPE_ARCHIVE=Zope-2.9.4-final
-ZOPE_ARCHIVE_TAR=Zope-2.9.4-final.tgz
-ZOPE_MD5SUM=7d7ffe62eabc84d0c438e450e344c29f
-ZOPE_URLs="http://www.zope.org/Products/Zope/2.9.4/Zope-2.9.4-final.tgz";
-
-
-
-PLONE_ARCHIVE=Plone-2.5
-PLONE_ARCHIVE_TAR=Plone-2.5.tar.gz
-PLONE_MD5SUM=0a385a1a4afbf940bb4e094ce5dcb583
-PLONE_URLs="http://superb-west.dl.sourceforge.net/sourceforge/plone/Plone-2.5.tar.gz \
-	    http://superb-east.dl.sourceforge.net/sourceforge/plone/Plone-2.5.tar.gz \
-	    http://easynews.dl.sourceforge.net/sourceforge/plone/Plone-2.5.tar.gz";
+PLONE_ARCHIVE=Plone-2.5.2-1
+PLONE_ARCHIVE_TAR=Plone-2.5.2-1.tar.gz
+PLONE_MD5SUM=b4891a3f11a0eacb13b234d530ba9af1
+PLONE_URLs="http://plone.googlecode.com/files/Plone-2.5.2-1.tar.gz \
+	http://superb-west.dl.sourceforge.net/sourceforge/plone/Plone-2.5.2-1.tar.gz \
+	    http://superb-east.dl.sourceforge.net/sourceforge/plone/Plone-2.5.2-1.tar.gz \
+	    http://easynews.dl.sourceforge.net/sourceforge/plone/Plone-2.5.2-1.tar.gz";
--- conga/luci/TODO	2006/07/18 20:33:04	1.3
+++ conga/luci/TODO	2007/03/01 00:31:08	1.3.2.1
@@ -7,7 +7,6 @@
 
 
 Cluster:
- - deploy-node/cluster
 
 
 
--- conga/luci/load_site.py	2006/11/16 19:34:52	1.14.2.1
+++ conga/luci/load_site.py	2007/03/01 00:31:08	1.14.2.2
@@ -3,6 +3,7 @@
 ##############################################################################
 #
 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (C) 2006-2007 Red Hat, Inc.
 #
 # This software is subject to the provisions of the Zope Public License,
 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
--- conga/luci/pack.py	2006/11/16 19:34:52	1.4.2.1
+++ conga/luci/pack.py	2007/03/01 00:31:08	1.4.2.2
@@ -1,5 +1,7 @@
 #!/usr/bin/python
 
+# Copyright (C) 2006-2007 Red Hat, Inc.
+
 import os, sys, string
 
 sys.path.extend((
/cvs/cluster/conga/luci/cluster/validate_config_gulm.js,v  -->  standard output
revision 1.3.4.1
--- conga/luci/cluster/validate_config_gulm.js
+++ -	2007-03-01 00:31:22.946186000 +0000
@@ -0,0 +1,23 @@
+function validate_form(form) {
+	var errors = new Array();
+	var lscount = 0;
+
+	var elem = form.getElementsByTagName('input');
+	for (var i = 0 ; i < elem.length ; i++) {
+		if (elem[i].type == 'text' && !str_is_blank(elem[i].value))
+			lscount++;
+		else if (elem[i].type == 'checkbox' && elem[i].checked)
+			lscount++;
+	}
+
+	if (lscount != 1 && lscount != 3 && lscount != 5)
+		errors.push('You must have exactly 1, 3, or 5 GULM lockservers.');
+
+	if (error_dialog(errors))
+		return (-1);
+
+	if (confirm('Update GULM properties?'))
+		form.submit();
+
+	return (0);
+}
/cvs/cluster/conga/luci/cluster/validate_create_gulm.js,v  -->  standard output
revision 1.1.4.1
--- conga/luci/cluster/validate_create_gulm.js
+++ -	2007-03-01 00:31:23.032171000 +0000
@@ -0,0 +1,65 @@
+var lockservers = new Array();
+
+function toggle_gulm(form, lock_type) {
+	var gulm_div = document.getElementById('gulm_lockservers');
+	if (!gulm_div)
+		return (-1);
+
+	var ielem = gulm_div.getElementsByTagName('input');
+
+	if (lock_type != 'gulm') {
+		lockservers = new Array();
+		for (var i = 0 ; i < ielem.length ; i++) {
+			lockservers[i] = ielem[i].value;
+			ielem[i].value = null;
+			ielem[i].disabled = 'disabled';
+		}
+		gulm_div.className = 'invisible';
+	} else {
+		for (var i = 0 ; i < ielem.length ; i++)
+			ielem[i].disabled = null;
+		for (var i = 0 ; i < lockservers.length ; i++)
+			ielem[i].value = lockservers[i];
+		gulm_div.className = null;
+		lockservers = new Array();
+	}
+}
+
+function check_gulm_lkserv() {
+	var errors = new Array();
+	var gulm_div = document.getElementById('gulm_lockservers');
+	if (!gulm_div) {
+		errors.push('Exactly 1, 3, or 5 GULM lock servers must be given.');
+		return (errors);
+	}
+
+	var lcount = 0;
+	var ielem = gulm_div.getElementsByTagName('input');
+	if (!ielem) {
+		errors.push('Exactly 1, 3, or 5 GULM lock servers must be given.');
+		return (errors);
+	}
+
+	for (var i = 0 ; i < ielem.length ; i++) {
+		if (ielem[i]) {
+			if (str_is_blank(ielem[i].value))
+				ielem[i].value = null;
+			else
+				lcount++;
+		}
+	}
+
+	if (lcount != 1 && lcount != 3 && lcount != 5)
+		errors.push('Exactly 1, 3, or 5 GULM lock servers must be given.');
+
+	return (errors);
+}
+
+function validate_cluster_create(form) {
+	if (form.lockmanager && !form.lockmanager[0].checked) {
+		var errors = check_gulm_lkserv();
+		if (error_dialog(errors))
+			return (-1);
+	}
+	return validateForm(form);
+}
/cvs/cluster/conga/luci/cluster/validate_fdom.js,v  -->  standard output
revision 1.3.4.1
--- conga/luci/cluster/validate_fdom.js
+++ -	2007-03-01 00:31:23.114893000 +0000
@@ -0,0 +1,40 @@
+function fdom_set_prioritized(form, state) {
+	var prilist = form.getElementsByTagName('input');
+	if (!prilist)
+		return (-1);
+	for (var i = 0 ; i < prilist.length ; i++) {
+		if (prilist[i].type == 'text' && prilist[i].className == 'fdom_priority')
+			prilist[i].disabled = !state || !form[prilist[i].id][0].checked;
+	}
+}
+
+function fdom_set_member(form, name, state) {
+	var prioritized = document.getElementById('prioritized');
+	if (!prioritized)
+		return (-1);
+	prioritized = prioritized.checked;
+	var member_pri_elem = document.getElementById(name);
+	if (!member_pri_elem)
+		return (-1);
+	member_pri_elem.disabled = !prioritized || !state;
+}
+
+function validate_add_fdom(form) {
+	var errors = new Array();
+
+	if (!form.name || str_is_blank(form.name.value)) {
+		set_form_err(form.name);
+		errors.append('No name was given for this failover domain.');
+	} else
+		clr_form_err(form.name);
+
+	if (error_dialog(errors))
+		return (-1);
+
+	var confirm_msg = 'Add this failover domain?';
+	if (form.oldname)
+		confirm_msg = 'Update this failover domain?';
+
+	if (confirm(confirm_msg))
+		form.submit();
+}
--- conga/luci/cluster/fence_device.js	2007/01/17 03:53:35	1.2.2.4
+++ conga/luci/cluster/fence_device.js	2007/03/01 00:31:08	1.2.2.5
@@ -190,48 +190,3 @@
 	container.appendChild(div_elem);
 	num_fences_level[fence_level - 1]++;
 }
-
-function validate_fence(master_form, container_id) {
-	var errors = new Array();
-	var div_elem = document.getElementById(container_id);
-	if (!div_elem)
-		return (-1);
-	var form_xml = '';
-
-	var form = div_elem.getElementsByTagName('form');
-	for (var i = 0 ; i < form.length ; i++) {
-		var input_elem = form[i].getElementsByTagName('input');
-		var temp = '';
-		for (var j = 0 ; j < input_elem.length ; j++) {
-			var res_type = input_elem[j].type;
-			if (res_type == 'hidden' || res_type == 'text' ||
-				res_type == 'password')
-			{
-				temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" value="' + input_elem[j].value + '" />';
-			} else if (res_type == 'checkbox' || res_type == 'radio') {
-				if (input_elem[j].checked) {
-					temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '"';
-					if (res_type == 'checkbox')
-						temp += ' value="1"';
-					else if (res_type == 'radio')
-						temp += ' value="' + input_elem[j].value + '"';
-					temp += ' />';
-				} else if (res_type == 'checkbox') {
-					temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" value="0" />';
-				}
-			}
-		}
-
-		var select_elem = form[i].getElementsByTagName('select');
-		for (var j = 0 ; j < select_elem.length ; j++) {
-			temp += '<input type="text" name="' + select_elem[j].name + '" value="' + select_elem[j].options[select_elem[j].options.selectedIndex].value + '" />';
-		}
-
-		form_xml += '<form id="' + form[i].getAttribute('name') + '">' + temp + '</form>';
-	}
-
-	master_form.fence_xml.value = '<formlist>' + form_xml + '</formlist>';
-
-	if (confirm('Update this node\'s fence configuration?'))
-		master_form.submit();
-}
--- conga/luci/cluster/form-chooser	2006/12/22 17:50:16	1.12.2.3
+++ conga/luci/cluster/form-chooser	2007/03/01 00:31:08	1.12.2.4
@@ -57,10 +57,10 @@
      <div metal:use-macro="here/form-macros/macros/nodelogs-form"/>
     </span>
     <span tal:omit-tag="" tal:condition="python: ptype == '18'">
-     <div metal:use-macro="here/form-macros/macros/xenvmadd-form"/>
+     <div metal:use-macro="here/form-macros/macros/vmadd-form"/>
     </span>
     <span tal:omit-tag="" tal:condition="python: ptype == '19'">
-     <div metal:use-macro="here/form-macros/macros/xenvmconfig-form"/>
+     <div metal:use-macro="here/form-macros/macros/vmconfig-form"/>
     </span>
     <span tal:omit-tag="" tal:condition="python: ptype == '20'">
      <div metal:use-macro="here/form-macros/macros/servicelist-form"/>
@@ -92,9 +92,6 @@
     <span tal:omit-tag="" tal:condition="python: ptype == '28'">
      <div metal:use-macro="here/form-macros/macros/servicerestart"/>
     </span>
-    <span tal:omit-tag="" tal:condition="python: ptype == '29'">
-     <div metal:use-macro="here/form-macros/macros/xenvmprocess"/>
-    </span>
     <span tal:omit-tag="" tal:condition="python: ptype == '30'">
      <div metal:use-macro="here/resource-form-macros/macros/resources-form"/>
     </span>
--- conga/luci/cluster/form-macros	2007/01/16 17:38:06	1.90.2.18
+++ conga/luci/cluster/form-macros	2007/03/01 00:31:08	1.90.2.19
@@ -92,7 +92,7 @@
 		</td>
 
 		<td class="cluster cluster_action">
-			<form method="post" onSubmit="return dropdown(this.gourl)">
+			<form method="post">
 				<select name="gourl" id="cluster_action" class="cluster">
 					<option class="cluster running"
 						tal:condition="python: 'running' in cstatus and cstatus['running'] != 'true'"
@@ -116,7 +116,8 @@
 						Delete this cluster
 					</option>
 				</select>
-				<input class="cluster" type="submit" value="Go" />
+				<input class="cluster" type="button" value="Go"
+					onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 			</form>
 		</td>
 	</tr>
@@ -201,6 +202,8 @@
 	<script type="text/javascript"
 		src="/luci/homebase/validate_cluster_add.js">
 	</script>
+	<script type="text/javascript"
+		src="validate_create_gulm.js">
 	<script type="text/javascript">
 		set_page_title('Luci — cluster — Deploy a cluster');
 	</script>
@@ -208,7 +211,7 @@
 	<tal:block tal:omit-tag=""
 		tal:define="global sessionObj python: request.SESSION.get('checkRet')" />
 
-	<h1>Add a cluster</h1>
+	<h1>Create a new cluster</h1>
 
 	<form name="create_cluster" action="" method="post"
 		tal:define="
@@ -222,14 +225,14 @@
 
 		<table id="systemsTable" class="systemsTable" cellspacing="0">
 			<thead class="systemsTable">
-                <tr class="systemsTable"><td class="systemsTable" colspan="2">
-                    <div class="systemsTableTop">
-                        <strong>Cluster Name</strong>
-                        <input class="hbInputSys" type="text"
+				<tr class="systemsTable"><td class="systemsTable" colspan="2">
+					<div class="systemsTableTop">
+						<strong>Cluster Name</strong>
+						<input class="hbInputSys" type="text"
 							id="clusterName" name="clusterName"
 							tal:attributes="value add_cluster/name | nothing" />
-                    </div>
-                </td></tr>
+					</div>
+				</td></tr>
 				<tr class="systemsTable">
 					<th class="systemsTable">Node Hostname</th>
 					<th class="systemsTable">Root Password</th>
@@ -242,31 +245,40 @@
 			</thead>
 
 			<tfoot class="systemsTable">
+				<tr class="systemsTable"><td class="systemsTable" colspan="2">
+					<div class="systemsTableEnd">
+						<input type="button" value="Add a cluster node"
+							onClick="addSystem(this.form)" />
+					</div>
+				</td></tr>
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<input type="hidden" name="trust_shown" value="1"
 						tal:condition="add_cluster" />
 					<ul class="vanilla deploy">
 						<li class="vanilla">
-							<input type="radio" name="download_pkgs"
-								value="1" checked="checked" />
+							<input type="radio" name="download_pkgs" value="1"
+								tal:attributes="checked python: (not add_cluster or not 'download_pkgs' in add_cluster or add_cluster['download_pkgs'] != 0) and 'checked' or ''" />
 							Download packages
 						</li>
 						<li class="vanilla">
-							<input type="radio" name="download_pkgs"
-								value="0" />
+							<input type="radio" name="download_pkgs" value="0"
+								tal:attributes="checked python: (add_cluster and 'download_pkgs' in add_cluster and add_cluster['download_pkgs'] == 0) and 'checked' or ''" />
 							Use locally installed packages.
 						</li>
 					</ul>
 				</td></tr>
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
-					<input type="checkbox" name="enable_storage" />
+					<input type="checkbox" name="enable_storage"
+						tal:attributes="
+							checked add_cluster/shared_storage | nothing" />
 					Enable Shared Storage Support
 				</td></tr>
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<ul class="vanilla">
 						<li class="vanilla">
 							<input name="check_certs" type="checkbox"
-								tal:attributes="checked python: (add_cluster and add_cluster['check_certs']) and 'checked'" />
+								id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)" />
 							View system certificates before sending any passwords.
 						</li>
 						<li class="vanilla">
@@ -280,12 +292,94 @@
 						</li>
 					</ul>
 				</td></tr>
-				<tr class="systemsTable"><td class="systemsTable" colspan="2">
-					<div class="systemsTableEnd">
-						<input type="button" value="Add another entry"
-							onClick="addSystem(this.form)" />
-					</div>
-				</td></tr>
+
+				<tr class="systemsTable"
+					tal:condition="exists:add_cluster/gulm_support">
+					<td class="systemsTable" colspan="2">
+						<strong class="cluster">Lock Manager</strong>
+						<ul class="vanilla">
+							<li class="vanilla">
+								<input type="radio"
+									name="lockmanager" value="dlm"
+									onchange="toggle_gulm(this.form, this.value)"
+									tal:attributes="checked python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm'"
+								>DLM (preferred)
+							</li>
+							<li class="vanilla">
+								<input type="radio"
+									name="lockmanager" value="gulm"
+									onchange="toggle_gulm(this.form, this.value)"
+									tal:attributes="checked python: add_cluster and 'lockmanager' in add_cluster and add_cluster['lockmanager'] == 'gulm'"
+								>GULM
+							</li>
+							<div id="gulm_lockservers"
+								tal:attributes="class python: (add_cluster and 'lockmanager' in add_cluster and add_cluster['lockmanager'] != 'gulm') and 'invisible' or ''">
+								<fieldset>
+								<legend class="rescfg">GULM lock server properties</legend>
+								<p>You must enter exactly 1, 3, or 5 GULM lock servers.</p>
+
+								<table class="systemsTable">
+									<tr>
+										<td class="pad_right">Lock Server 1</td>
+										<td>
+											<input type="text"
+												name="__GULM__:server1"
+												class="hostname"
+												tal:attributes="
+													disabled python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm';
+													value add_cluster/gulm_lockservers/server1 | nothing" />
+										</td>
+									</tr>
+									<tr>
+										<td class="pad_right">Lock Server 2</td>
+										<td>
+											<input type="text"
+												name="__GULM__:server2"
+												class="hostname"
+												tal:attributes="
+													disabled python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm';
+													value add_cluster/gulm_lockservers/server2 | nothing" />
+										</td>
+									</tr>
+									<tr>
+										<td class="pad_right">Lock Server 3</td>
+										<td>
+											<input type="text"
+												name="__GULM__:server3"
+												class="hostname"
+												tal:attributes="
+													disabled python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm';
+													value add_cluster/gulm_lockservers/server3 | nothing" />
+										</td>
+									</tr>
+									<tr>
+										<td class="pad_right">Lock Server 4</td>
+										<td>
+											<input type="text"
+												name="__GULM__:server4"
+												class="hostname"
+												tal:attributes="
+													disabled python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm';
+													value add_cluster/gulm_lockservers/server4 | nothing" />
+										</td>
+									</tr>
+									<tr>
+										<td class="pad_right">Lock Server 5</td>
+										<td>
+											<input type="text"
+												name="__GULM__:server5"
+												class="hostname"
+												tal:attributes="
+													disabled python: not add_cluster or not 'lockmanager' in add_cluster or add_cluster['lockmanager'] != 'gulm';
+													value add_cluster/gulm_lockservers/server5 | nothing" />
+										</td>
+									</tr>
+								</table>
+								</fieldset>
+							</div>
+						<ul>
+					</td>
+				</tr>
 			</tfoot>
 
 			<tal:block tal:define="global cur_sysnum python:0" />
@@ -313,7 +407,7 @@
 								onChange="pwd0Change(this.form)"
 								autocomplete="off"
 								tal:attributes="
-									value sys/passwd | nothing;
+									value nothing;
 									class python: 'hbInputPass' + ('errors' in sys and ' error' or '');
 									id python: '__SYSTEM%d:Passwd' % cur_sysnum;
 									name python: '__SYSTEM%d:Passwd' % cur_sysnum" />
@@ -423,7 +517,7 @@
 
 		<div class="hbSubmit" id="hbSubmit">
 			<input type="button" name="Submit" value="Submit"
-				onClick="validateForm(this.form)" />
+				onClick="validate_cluster_create(this.form)" />
 		</div>
 	</form>
 
@@ -458,18 +552,28 @@
 				class python: 'configTab' + (configTabNum == 1 and ' configTabActive' or '');
 			">General</a>
 		</li>
-		<li class="configTab">
+		<li class="configTab"
+			tal:condition="not:clusterinfo/gulm">
 			<a tal:attributes="
 				href clusterinfo/fencedaemon_url | nothing;
 				class python: 'configTab' + (configTabNum == 2 and ' configTabActive' or '');
 			">Fence</a>
 		</li>
-		<li class="configTab">
+		<li class="configTab"
+			tal:condition="not:clusterinfo/gulm">
 			<a tal:attributes="
 				href clusterinfo/multicast_url | nothing;
 				class python: 'configTab' + (configTabNum == 3 and ' configTabActive' or '');
 			">Multicast</a>
 		</li>
+
+		<li class="configTab"
+			tal:condition="clusterinfo/gulm">
+			<a tal:attributes="
+				href clusterinfo/gulm_url | nothing;
+				class python: 'configTab' + (configTabNum == 5 and ' configTabActive' or '')">GULM</a>
+		</li>
+
 		<li class="configTab">
 			<a tal:attributes="
 				href clusterinfo/quorumd_url | nothing;
@@ -538,18 +642,62 @@
 					<table class="systemsTable">
 						<tr class="systemsTable">
 							<td class="systemsTable">
+								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#token', 55, 65);">Token Timeout</a> (ms)
+							</td>
+							<td class="systemsTable">
+								<input type="text" size="10" name="token"
+									tal:attributes="value clusterinfo/totem/token | string:10000" />
+							</td>
+						</tr>
+
+						<tr class="systemsTable">
+							<td class="systemsTable">
+								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#retransmits_before_loss', 55, 65);">Number of token retransmits before loss</a>
+							</td>
+							<td class="systemsTable">
+								<input type="text" size="10"
+									name="token_retransmits_before_loss_const"
+									tal:attributes="value clusterinfo/totem/token_retransmits_before_loss_const | string:20" />
+							</td>
+						</tr>
+
+						<tr class="systemsTable">
+							<td class="systemsTable">
+								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#join', 55, 65);">Join Timeout</a> (ms)
+							</td>
+							<td class="systemsTable">
+								<input type="text" size="10" name="join"
+									tal:attributes="value clusterinfo/totem/join | string:60" />
+							</td>
+						</tr>
+
+						<tr class="systemsTable">
+							<td class="systemsTable">
+								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#consensus', 55, 65);">Consensus Timeout</a> (ms)
+							</td>
+							<td class="systemsTable">
+								<input type="text" size="10"
+									name="consensus"
+									tal:attributes="value clusterinfo/totem/consensus | string:4800" />
+							</td>
+						</tr>
+
+<tal:comment tal:replace="nothing">
+						<tr class="systemsTable">
+							<td class="systemsTable">
 								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#secauth', 55, 65);">Secure Authentication</a>
 							</td>
 							<td class="systemsTable">
 								<input type="checkbox" name="secauth" checked="checked" />
 						</tr>
 
+
 						<tr class="systemsTable">
 							<td class="systemsTable">
 								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#rrp_mode', 55, 65);">Redundant Ring Protocol Mode</a>
 							</td>
 							<td class="systemsTable">
-								<select name="text" name="rrp_mode">
+								<select type="text" name="rrp_mode">
 									<option value="none">
 										None
 									</option>
@@ -601,16 +749,6 @@
 
 						<tr class="systemsTable">
 							<td class="systemsTable">
-								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#token', 55, 65);">Token Timeout</a> (ms)
-							</td>
-							<td class="systemsTable">
-								<input type="text" size="10" name="token"
-									tal:attributes="value string:5000" />
-							</td>
-						</tr>
-
-						<tr class="systemsTable">
-							<td class="systemsTable">
 								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#token_retransmit', 55, 65);">Token Retransmit</a> (ms)
 							</td>
 							<td class="systemsTable">
@@ -632,33 +770,11 @@
 
 						<tr class="systemsTable">
 							<td class="systemsTable">
-								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#retransmits_before_loss', 55, 65);">Number of retransmits before loss</a>
-							</td>
-							<td class="systemsTable">
-								<input type="text" size="10"
-									name="retransmits_before_loss"
-									tal:attributes="value string:4" />
-							</td>
-						</tr>
-
-						<tr class="systemsTable">
-							<td class="systemsTable">
-								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#join', 55, 65);">Join Timeout</a> (ms)
-							</td>
-							<td class="systemsTable">
-								<input type="text" size="10" name="join"
-									tal:attributes="value string:100" />
+								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#send_join', 55, 65);">Maximum time to wait before sending a join message</a> (ms)
 							</td>
-						</tr>
-
-						<tr class="systemsTable">
 							<td class="systemsTable">
-								<a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#consensus', 55, 65);">Consensus Timeout</a> (ms)
-							</td>
-							<td class="systemsTable">
-								<input type="text" size="10"
-									name="consensus"
-									tal:attributes="value string:100" />
+								<input type="text" size="10" name="send_join"
+									tal:attributes="value string:0" />
 							</td>
 						</tr>
 
@@ -782,6 +898,7 @@
 									tal:attributes="value string:47" />
 							</td>
 						</tr>
+</tal:comment>
 					</table>
 				</td></tr>
 			</table>
@@ -842,6 +959,14 @@
 							tal:attributes="value clusterinfo/pjd" />
 					</td>
 				</tr>
+				<tr class="systemsTable">
+					<td class="systemsTable">
+						<span class="cluster_help" title="Enable if you will be running a VM cluster on this physical cluster">Run XVM fence daemon</td>
+					<td class="systemsTable">
+						<input type="checkbox" name="run_xvmd"
+							tal:attributes="checked python: ('fence_xvmd' in clusterinfo and clusterinfo['fence_xvmd']) and 'checked' or ''" />
+					</td>
+				</tr>
 			</tbody>
 
 			<tfoot class="systemsTable">
@@ -891,7 +1016,12 @@
 							onClick="disable_mcast('mcast_address');"
 							tal:attributes="checked python: clusterinfo['is_mcast'] != 'True'"
 						/>
-						Let cluster choose the multicast address
+						<tal:block tal:condition="python:os_version == 'rhel4'">
+							Do not use multicast
+						</tal:block>
+						<tal:block tal:condition="python:os_version != 'rhel4'">
+							Let cluster choose the multicast address
+						</tal:block>
 					</td>
 				</tr>
 
@@ -902,12 +1032,20 @@
 							tal:attributes="checked python: clusterinfo['is_mcast'] == 'True'"
 
 						/>
-						Specify the multicast address manually
+						<tal:block tal:condition="python:os_version == 'rhel4'">
+							Use multicast
+						</tal:block>
+						<tal:block tal:condition="python:os_version != 'rhel4'">
+							Specify the multicast address manually
+						</tal:block>
 					</td>
 				</tr>
 
 				<tr class="systemsTable">
-					<td class="systemsTable" colspan="2">
+					<td class="systemsTable">
+						Multicast address
+					</td>
+					<td class="systemsTable">
 						<input type="text" name="mcast_address" id="mcast_address"
 							tal:attributes="
 								disabled python: clusterinfo['is_mcast'] != 'True' and '1' or '0';
@@ -959,14 +1097,14 @@
 				<tr class="systemsTable" id="st_row"><td class="systemsTable" id="st_col">
 					<input type="radio" name="quorumd" value="False"
 						onClick="disableChildrenInput('quorumdisk');"
-						tal:attributes="checked python: clusterinfo['is_quorumd'] != 'True'"/>
+						tal:attributes="checked python: (not clusterinfo['is_quorumd']) and 'checked' or ''" />
 					Do not use a Quorum Partition
 				</td></tr>
 
 				<tr class="systemsTable"><td class="systemsTable">
 					<input type="radio" name="quorumd" value="True"
 						onClick="enableChildrenInput('quorumdisk');"
-						tal:attributes="checked python: clusterinfo['is_quorumd'] == 'True'"/>
+						tal:attributes="checked python: (clusterinfo['is_quorumd']) and 'checked' or ''" />
 						Use a Quorum Partition
 				</td></tr>
 			</tbody>
@@ -981,48 +1119,48 @@
 			<tr class="systemsTable">
 				<td class="systemsTable">Interval</td>
 				<td class="systemsTable">
-					<input type="text" name="interval" value=""
-						tal:attributes="value clusterinfo/interval"/>
+					<input type="text" name="interval"
+						tal:attributes="value clusterinfo/interval | nothing" />
 				</td>
 			</tr>
 
 			<tr class="systemsTable">
 				<td class="systemsTable">Votes</td>
 				<td class="systemsTable">
-					<input type="text" name="votes" value=""
-						tal:attributes="value clusterinfo/votes"/>
+					<input type="text" name="votes"
+						tal:attributes="value clusterinfo/votes | nothing" />
 				</td>
 			</tr>
 
 			<tr class="systemsTable">
 				<td class="systemsTable">TKO</td>
 				<td class="systemsTable">
-					<input type="text" name="tko" value=""
-						tal:attributes="value clusterinfo/tko"/>
+					<input type="text" name="tko"
+						tal:attributes="value clusterinfo/tko | nothing" />
 				</td>
 			</tr>
 
 			<tr class="systemsTable">
 				<td class="systemsTable">Minimum Score</td>
 				<td class="systemsTable">
-					<input type="text" name="min_score" value=""
-						tal:attributes="value clusterinfo/min_score"/>
+					<input type="text" name="min_score"
+						tal:attributes="value clusterinfo/min_score | nothing" />
 				</td>
 			</tr>
 
 			<tr class="systemsTable">
 				<td class="systemsTable">Device</td>
 				<td class="systemsTable">
-					<input type="text" name="device" value=""
-						tal:attributes="value clusterinfo/device"/>
+					<input type="text" name="device"
+						tal:attributes="value clusterinfo/device | nothing" />
 				</td>
 			</tr>
 
 			<tr class="systemsTable">
 				<td class="systemsTable">Label</td>
 				<td class="systemsTable">
-					<input type="text" name="label" value=""
-						tal:attributes="value clusterinfo/label"/>
+					<input type="text" name="label"
+						tal:attributes="value clusterinfo/label | nothing" />
 				</td>
 			</tr>
 		</table>
@@ -1039,9 +1177,6 @@
 
 				<tr class="systemsTable">
 					<th class="systemsTable">
-						<div class="systemsTableTop">Name</div>
-					</th>
-					<th class="systemsTable">
 						<div class="systemsTableTop">Path to Program</div>
 					</th>
 					<th class="systemsTable">
@@ -1057,22 +1192,22 @@
 			</thead>
 
 			<tbody class="systemsTable" id="heuristicList"
-				tal:define="global heuristics clusterinfo/hlist">
+				tal:define="global heuristics clusterinfo/hlist | nothing">
 
-				<tal:block tal:condition="python: not len(heuristics)">
+				<tal:block tal:condition="python: not heuristics or not len(heuristics)">
 				<input type="hidden" name="num_heuristics" id="num_heuristics" value="0">
 				<tr class="systemsTable" id="heuristic0">
 					<td class="systemsTable">
-						<input class="qdname qdisk" type="text" name="heuristic0:hname" id="heuristic0:hname" value="">
-					</td>
-					<td class="systemsTable">
-						<input class="qdpath qdisk" type="text" name="heuristic0:hprog" id="heuristic0:hprog" value="">
+						<input class="qdpath qdisk" type="text"
+							name="heuristic0:hprog" id="heuristic0:hprog" />
 					</td>
 					<td class="systemsTable">
-						<input class="qdint qdisk" type="text" name="heuristic0:hinterval" id="heuristic0:hinterval" value="">
+						<input class="qdint qdisk" type="text"
+							name="heuristic0:hinterval" id="heuristic0:hinterval" />
 					</td>
 					<td class="systemsTable">
-						<input class="qdscore qdisk" type="text" name="heuristic0:hscore" id="heuristic0:hscore" value="">
+						<input class="qdscore qdisk" type="text"
+							name="heuristic0:hscore" id="heuristic0:hscore" />
 					</td>
 					<td class="systemsTable">
 						<img class="qdisk deleteRow"
@@ -1097,32 +1232,27 @@
 					tal:define="global curHeur python: curHeur + 1">
 
 					<td class="systemsTable">
-						<input class="qdname qdisk" type="text"
-							tal:attributes="
-								value heuristic/hname;
-								id python: 'heuristic' + str(curHeur) + ':hname';
-								name python: 'heuristic' + str(curHeur) + ':hname';"/>
-					</td>
-					<td class="systemsTable">
 						<input class="qdpath qdisk" type="text"
 							tal:attributes="
 								value heuristic/hprog;
 								id python: 'heuristic' + str(curHeur) + ':hprog';
-								name python: 'heuristic' + str(curHeur) + ':hprog';"/>
+								name python: 'heuristic' + str(curHeur) + ':hprog'" />
 					</td>
+
 					<td class="systemsTable">
 						<input class="qdint qdisk" type="text"
 							tal:attributes="
 								value heuristic/hinterval;
 								id python: 'heuristic' + str(curHeur) + ':hinterval';
-								name python: 'heuristic' + str(curHeur) + ':hinterval';"/>
+								name python: 'heuristic' + str(curHeur) + ':hinterval'" />
 					</td>
+
 					<td class="systemsTable">
 						<input class="qdscore qdisk" type="text"
 							tal:attributes="
 								value heuristic/hscore;
 								id python: 'heuristic' + str(curHeur) + ':hscore';
-								name python: 'heuristic' + str(curHeur) + ':hscore';"/>
+								name python: 'heuristic' + str(curHeur) + ':hscore'" />
 					</td>
 					<td class="systemsTable">
 						<img class="qdisk deleteRow"
@@ -1131,14 +1261,15 @@
 							onClick="delete_qdisk_heur(this, document.quorum_partition);"
 							tal:attributes="
 								id python: 'heuristic' + str(curHeur) + ':hdel';
-								name python: 'heuristic' + str(curHeur) + ':hdel';"/>
+								name python: 'heuristic' + str(curHeur) + ':hdel'" />
 					</td>
 				</tr>
 				</tal:block>
 			</tbody>
+
 			<tfoot>
 				<tr class="systemsTable"><td class="systemsTable">
-					<input class="addrow" type="button" value="Add another heuristic" onClick="addHeuristic('heuristicList');">
+					<input class="addrow" type="button" value="Add another heuristic" onClick="addHeuristic('heuristicList')">
 				</td></tr>
 			</tfoot>
 		</table>
@@ -1148,14 +1279,106 @@
 		<div class="spacing configTabContent"></div>
 		<div class="hbSubmit spacing configTabContent">
 			<input type="button" value="Apply"
-				onClick="validate_form(this.form);"
-			>
+				onClick="validate_form(this.form)" />
 		</div>
-		<script tal:condition="python: clusterinfo['is_quorumd'] != 'True'">
+		<script tal:condition="not: clusterinfo/is_quorumd">
 			disableChildrenInput('quorumdisk');
 		</script>
 		</form>
 	</div>
+
+	<tal:block tal:condition="clusterinfo/gulm">
+	<div id="configTabContent" tal:condition="python: configTabNum == 5">
+		<script type="text/javascript"
+			src="/luci/homebase/homebase_common.js">
+		</script>
+		<script type="text/javascript"
+			src="/luci/cluster/validate_config_gulm.js">
+		</script>
+
+		<form name="basecluster" action="" method="post">
+			<input type="hidden" name="cluster_version"
+				tal:attributes="value os_version | nothing" />
+			<input type="hidden" name="pagetype"
+				tal:attributes="value request/pagetype | request/form/pagetype"
+			/>
+			<input type="hidden" name="configtype" value="gulm" />
+			<input type="hidden" name="clustername"
+				tal:attributes="value request/clustername | clusterinfo/clustername | nothing" />
+
+		<strong class="cluster">GULM Configuration</strong><br/>
+		<table id="systemsTable" class="systemsTable" cellspacing="0">
+			<thead>
+				<tr class="systemsTable" align="left">
+					<th class="systemsTable">Node</th>
+					<th class="systemsTable">Lock Server</th>
+				</tr>
+			</thead>
+			<tbody>
+				<tal:block tal:repeat="c clusterinfo/gulm_lockservers">
+					<tr class="systemsTable">
+						<td class="systemsTable">
+							<span tal:replace="python:c[0]" />
+						</td>
+						<td class="systemsTable">
+							<input type="checkbox"
+								tal:attributes="
+									name python:c[0];
+									checked python:c[1]" />
+						</td>
+					</tr>
+				</tal:block>
+
+				<tr><td colspan="2">
+					<div class="spacing" />
+					<p><em class="cluster">You may have exactly 1, 3, or 5 GULM lock servers, in any combination of the hosts checked above and given below.</em></p>
+				</td></tr>
+
+				<tr>
+					<td class="pad_right">External Lock Server 1</td>
+					<td>
+						<input type="text" name="__GULM__:server1"
+							class="hostname" value="" />
+					</td>
+				</tr>
+				<tr>
+					<td class="pad_right">External Lock Server 2</td>
+					<td>
+						<input type="text" name="__GULM__:server2"
+							class="hostname" value="" />
+					</td>
+				</tr>
+				<tr>
+					<td class="pad_right">External Lock Server 3</td>
+					<td>
+						<input type="text" name="__GULM__:server3"
+							class="hostname" value="" />
+					</td>
+				</tr>
+				<tr>
+					<td class="pad_right">External Lock Server 4</td>
+					<td>
+						<input type="text" name="__GULM__:server4"
+							class="hostname" value="" />
+					</td>
+				</tr>
+				<tr>
+					<td class="pad_right">External Lock Server 5</td>
+					<td>
+						<input type="text" name="__GULM__:server5"
+							class="hostname" value="" />
+					</td>
+				</tr>
+			</tbody>
+		</table>
+
+		<div class="spacing configTabContent"></div>
+		<div class="hbSubmit spacing configTabContent">
+			<input type="button" value="Apply"
+				onClick="validate_form(this.form)"/>
+		</div>
+	</div>
+	</tal:block>
 </tal:block>
 </div>
 
@@ -1177,7 +1400,6 @@
 	<option name="fence_egenera" value="fence_egenera">Egenera SAN Controller</option>
 	<option name="fence_bladecenter" value="fence_bladecenter">IBM Blade Center</option>
 	<option name="fence_bullpap" value="fence_bullpap">Bull PAP</option>
-	<option name="fence_rps10" value="fence_rps10">RPS10 Serial Switch</option>
 	<option name="fence_xvm" value="fence_xvm">Virtual Machine Fencing</option>
 	<option name="fence_scsi" value="fence_scsi">SCSI Fencing</option>
 </div>
@@ -1223,7 +1445,7 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 	</div>
@@ -1271,14 +1493,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1329,14 +1562,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1378,14 +1622,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1428,14 +1683,25 @@
 				<td>Password</td>
 				<td>
 					<input name="passwd" type="password" autocomplete="off"
-						tal:attributes="value cur_fencedev/passwd | nothing" />
+						tal:attributes="value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1477,13 +1743,25 @@
 				<td>Password</td>
 				<td>
 					<input name="passwd" type="password" autocomplete="off"
-						tal:attributes="value cur_fencedev/passwd | nothing" />
+						tal:attributes="value nothing" />
 				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
+				</td>
+			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1525,14 +1803,25 @@
 				<td>Password</td>
 				<td>
 					<input name="passwd" type="password" autocomplete="off"
-						tal:attributes="value cur_fencedev/passwd | nothing" />
+						tal:attributes="value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1582,14 +1871,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1640,14 +1940,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1689,14 +2000,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1736,7 +2058,7 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1785,7 +2107,7 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1828,14 +2150,25 @@
 				<td>Password</td>
 				<td>
 					<input name="passwd" type="password" autocomplete="off"
-						tal:attributes="value cur_fencedev/passwd | nothing" />
+						tal:attributes="value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1886,14 +2219,25 @@
 					<input name="passwd" type="password" autocomplete="off"
 						tal:attributes="
 							disabled cur_fencedev/isShared | nothing;
-							value cur_fencedev/passwd | nothing" />
+							value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 		</table>
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1936,7 +2280,7 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -1966,12 +2310,12 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
 		<input type="hidden" name="sharable" value="1" />
-		<input type="hidden" name="fence_type" value="xvm" />
+		<input type="hidden" name="fence_type" value="fence_xvm" />
 	</div>
 </div>
 
@@ -1997,12 +2341,12 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
 		<input type="hidden" name="sharable" value="1" />
-		<input type="hidden" name="fence_type" value="scsi" />
+		<input type="hidden" name="fence_type" value="fence_scsi" />
 	</div>
 </div>
 
@@ -2040,7 +2384,18 @@
 				<td>Password</td>
 				<td>
 					<input name="passwd" type="password" autocomplete="off"
-						tal:attributes="value cur_fencedev/passwd | nothing" />
+						tal:attributes="value nothing" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<span title="Full path to a script to generate fence password">Password Script (optional)</span>
+				</td>
+				<td>
+					<input type="text" name="passwd_script"
+						tal:attributes="
+							disabled cur_fencedev/isShared | nothing;
+							value cur_fencedev/passwd_script | nothing" />
 				</td>
 			</tr>
 			<tr>
@@ -2067,7 +2422,7 @@
 
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 
@@ -2094,7 +2449,7 @@
 		</table>
 		<tal:block tal:condition="exists: cur_fencedev">
 			<input type="hidden" name="existing_device" value="1" />
-			<input type="hidden" name="old_name"
+			<input type="hidden" name="orig_name"
 				tal:attributes="value cur_fencedev/name | nothing" />
 		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_manual" />
@@ -2213,6 +2568,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_apc" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2255,6 +2611,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_egenera" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2290,6 +2647,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_wti" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2325,6 +2683,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_brocade" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2360,6 +2719,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_vixel" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2395,6 +2755,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_sanbox2" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2430,6 +2791,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_mcdata" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2465,6 +2827,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_gnbd" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2500,6 +2863,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_bladecenter" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2535,6 +2899,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_bullpap" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2557,6 +2922,7 @@
 			</tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_scsi" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2592,6 +2958,7 @@
 			</td></tr>
 		</table>
 
+		<input type="hidden" name="fence_type" value="fence_xvm" />
 		<input type="hidden" name="fence_instance" value="1" />
 		<input tal:condition="exists: cur_instance"
 			type="hidden" name="existing_instance" value="1" />
@@ -2630,62 +2997,62 @@
 <div metal:define-macro="fencedev-instance-cond-ladder"
 	tal:condition="exists: cur_fence_type">
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_apc'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_apc'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-apc" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_mcdata'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_mcdata'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-mcdata" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_wti'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_wti'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-wti" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_brocade'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_brocade'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-brocade" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_sanbox2'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_sanbox2'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-sanbox2" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_vixel'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_vixel'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-vixel" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_gnbd'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_gnbd'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-gnbd" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_egenera'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_egenera'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-egenera" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_bullpap'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_bullpap'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-bullpap" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_scsi'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_scsi'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-scsi" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_xvm'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_xvm'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-xvm" />
 	</tal:block>
 
-    <tal:block tal:condition="python: cur_fence_type == 'fence_bladecenter'">
+	<tal:block tal:condition="python: cur_fence_type == 'fence_bladecenter'">
 		<tal:block
 			metal:use-macro="here/form-macros/macros/fence-instance-form-bladecenter" />
 	</tal:block>
@@ -2698,6 +3065,9 @@
 	<script type="text/javascript"
 		src="/luci/cluster/fence_device.js">
 	</script>
+	<script type="text/javascript"
+		src="/luci/cluster/validate_fence.js">
+	</script>
 	<script type="text/javascript">
 		set_page_title('Luci — cluster — nodes — properties');
 	</script>
@@ -2730,7 +3100,7 @@
 
 			<td class="cluster node node_action"
 				tal:condition="python: nodeinfo['nodestate'] == '0' or nodeinfo['nodestate'] == '1'">
-				<form method="post" onSubmit="return dropdown(this.gourl)">
+				<form method="post">
 				<select name="gourl">
 					<option value="">Choose a Task...</option>
 					<option tal:attributes="value nodeinfo/jl_url"
@@ -2748,18 +3118,20 @@
 						tal:condition="python: not 'ricci_error' in nodeinfo">
 						Delete this node</option>
 				</select>
-				<input type="submit" value="Go"/>
+				<input type="button" value="Go"
+					onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 				</form>
 			</td>
 
 			<td class="cluster node node_action"
 				tal:condition="python: nodeinfo['nodestate'] != '0' and nodeinfo['nodestate'] != '1'">
-				<form method="post" onSubmit="return dropdown(this.gourl)">
+				<form method="post">
 				<select name="gourl">
 					<option value="">Choose a Task...</option>
 					<option tal:attributes="value nodeinfo/fence_url | nothing">Fence this node</option>
 				</select>
-				<input type="submit" value="Go"/>
+				<input type="button" value="Go"
+					onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 				</form>
 			</td>
 		</tr>
@@ -2770,7 +3142,13 @@
 				<span tal:attributes="class python: 'cluster node ' + status_class"
 					tal:content="python: cluster_node_status_str" />
 			</td>
+		</tr>
 
+		<tr class="cluster node info_middle"
+			tal:condition="nodeinfo/gulm_lockserver">
+			<td class="cluster node node_status" colspan="2">
+				This node is a GULM lock server.
+			</td>
 		</tr>
 
 		<tr class="cluster node info_bottom"
@@ -2803,7 +3181,8 @@
 		<tfoot class="systemsTable">
 			<tr class="systemsTable"><td class="systemsTable" colspan="3">
 				<div class="systemsTableEnd">
-					<input type="Submit" value="Update node daemon properties" />
+					<input type="button" value="Update node daemon properties"
+						onclick="if (confirm('Update daemon properties?')) this.form.submit()" />
 				</div>
 			</td></tr>
 		</tfoot>
@@ -3074,7 +3453,7 @@
 						<input type="hidden" name="pagetype" value="58" />
 						<input type="button"
 							value="Update main fence properties"
-							onclick="validate_fence(this.form, 'fence_list_level1')" />
+							onclick="validate_node_fence_form(this.form, 'fence_list_level1')" />
 					</form>
 				</div>
 			</td>
@@ -3090,7 +3469,7 @@
 						<input type="hidden" name="pagetype" value="58" />
 						<input type="button"
 							value="Update backup fence properties"
-							onclick="validate_fence(this.form, 'fence_list_level2')" />
+							onclick="validate_node_fence_form(this.form, 'fence_list_level2')" />
 					</form>
 				</div>
 			</td>
@@ -3138,7 +3517,7 @@
 				</td>
 
 				<td class="node node_action" tal:condition="python: nd['status'] == '0' or nd['status'] == '1'">
-					<form method="post" onSubmit="return dropdown(this.gourl)">
+					<form method="post">
 						<select class="node" name="gourl">
 							<option value="">Choose a Task...</option>
 							<option tal:attributes="value nd/jl_url">
@@ -3149,18 +3528,20 @@
 							<option tal:attributes="value nd/fence_it_url">Fence this node</option>
 							<option tal:attributes="value nd/reboot_url">Reboot this node</option>
 							<option value="">----------</option>
-							<option tal:attributes="value nd/delete_url">Delete</option>
+							<option tal:attributes="value nd/delete_url">Delete this node</option>
 						</select>
-						<input type="submit" value="Go"/>
+						<input type="button" value="Go"
+							onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 					</form>
 				</td>
 				<td class="node node_action" tal:condition="python: nd['status'] != '0' and nd['status'] != '1'">
-					<form method="post" onSubmit="return dropdown(this.gourl)">
+					<form method="post">
 						<select class="node" name="gourl">
 							<option value="">Choose a Task...</option>
 							<option tal:attributes="value nd/fence_it_url | nothing">Fence this node</option>
 						</select>
-						<input type="submit" value="Go"/>
+						<input type="button" value="Go"
+							onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 					</form>
 				</td>
 			</tr>
@@ -3172,6 +3553,13 @@
 				</td>
 			</tr>
 
+			<tr class="node info_middle"
+				tal:condition="nd/gulm_lockserver">
+				<td class="node node_status" colspan="2">
+					This node is a GULM lock server.
+				</td>
+			</tr>
+
 			<tr class="node info_bottom">
 				<td class="node node_services">
 					<strong class="cluster node">Services on this Node:</strong>
@@ -3262,6 +3650,9 @@
 			global cur_cluster_name add_cluster/name | request/clustername | request/form/clusterName | nothing">
 
 		<h2>Add a node to <span tal:replace="cur_cluster_name | string:this cluster" /></h2>
+
+		<input type="hidden" name="addnode" value="1" />
+
 		<input type="hidden" name="clusterName"
 			tal:attributes="value cur_cluster_name | string:[unknown]" />
 
@@ -3285,21 +3676,24 @@
 			</thead>
 
 			<tfoot class="systemsTable">
+				<tr class="systemsTable"><td class="systemsTable" colspan="2">
+					<div class="systemsTableEnd">
+						<input type="button" value="Add another node"
+							onClick="addSystem(this.form)" />
+					</div>
+				</td></tr>
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<input type="hidden" name="trust_shown" value="1"
 						tal:condition="add_cluster" />
 					<ul class="vanilla deploy">
 						<li class="vanilla">
 							<input type="radio" name="download_pkgs" value="1"
-								tal:attributes="
-									checked add_system/download_pkgs | string:checked" />
+								tal:attributes="checked python: (not add_cluster or not 'download_pkgs' in add_cluster or add_cluster['download_pkgs'] != 0) and 'checked' or ''" />
 							Download packages
 						</li>
 						<li class="vanilla">
 							<input type="radio" name="download_pkgs" value="0"
-								tal:attributes="
-									checked not: add_system/download_pkgs | nothing" />
-							
+								tal:attributes="checked python: (add_cluster and 'download_pkgs' in add_cluster and add_cluster['download_pkgs'] == 0) and 'checked' or ''" />
 							Use locally installed packages.
 						</li>
 					</ul>
@@ -3307,14 +3701,15 @@
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<input type="checkbox" name="enable_storage"
 						tal:attributes="
-							checked add_system/shared_storage | nothing" />
+							checked add_cluster/shared_storage | nothing" />
 					Enable Shared Storage Support
 				</td></tr>
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<ul class="vanilla">
 						<li class="vanilla">
 							<input name="check_certs" type="checkbox"
-								tal:attributes="checked python: (add_cluster and add_cluster['check_certs']) and 'checked'" />
+								id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)" />
 							View system certificates before sending any passwords.
 						</li>
 						<li class="vanilla"
@@ -3328,12 +3723,6 @@
 						</li>
 					</ul>
 				</td></tr>
-				<tr class="systemsTable"><td class="systemsTable" colspan="2">
-					<div class="systemsTableEnd">
-						<input type="button" value="Add another entry"
-							onClick="addSystem(this.form)" />
-					</div>
-				</td></tr>
 			</tfoot>
 
 			<tal:block tal:define="global cur_sysnum python:0" />
@@ -3361,7 +3750,7 @@
 								autocomplete="off"
 								onChange="pwd0Change(this.form)"
 								tal:attributes="
-									value sys/passwd | nothing;
+									value nothing;
 									class python: 'hbInputPass' + ('errors' in sys and ' error' or '');
 									id python: '__SYSTEM%d:Passwd' % cur_sysnum;
 									name python: '__SYSTEM%d:Passwd' % cur_sysnum" />
@@ -3492,10 +3881,13 @@
 						href svc/cfgurl;
 						class python: 'cluster service ' + (running and 'running' or 'stopped')"
 						tal:content="svc/name" />
+					<tal:block tal:condition="exists:svc/virt">
+						(virtual service)
+					</tal:block>
 				</td>
 
 				<td class="cluster service service_action">
-					<form method="post" onSubmit="return dropdown(this.gourl)">
+					<form method="post">
 						<select name="gourl">
 							<option value="">Choose a Task...</option>
 							<option
@@ -3524,7 +3916,8 @@
 								tal:attributes="value svc/delurl | nothing"
 								tal:content="string:Delete this service" />
 						</select>
-						<input type="submit" value="Go"/>
+						<input type="button" value="Go"
+							onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 					</form>
 				</td>
 			</tr>
@@ -3554,30 +3947,170 @@
 	</tal:block>
 </div>
 
-<div metal:define-macro="xenvmadd-form">
-  <form method="get" action="" tal:attributes="action python:request['baseurl'] + '?clustername=' + request['clustername'] + '&pagetype=29'">
-  <h4>Path to configuration file: </h4><input type="text" name="xenvmpath" value=""/>
-  <h4>Name of configuration file: </h4><input type="text" name="xenvmname" value=""/>
-  <input type="submit" value="Create Xen VM"/>
-  </form>
-</div>
-
-<div metal:define-macro="xenvmconfig-form">
-  <h4>Properties for Xen VM <font color="green"><span tal:content="request/servicename"/></font></h4>
-  <span tal:define="global xeninfo python:here.getXenVMInfo(modelb, request)">
-  <form method="get" action="" tal:attributes="action python:request['baseurl'] + '?clustername=' + request['clustername'] + '&pagetype=29&servicename=' + request['servicename']">
-  <h4>Path to configuration file: </h4><input type="text" name="xenvmpath" value="" tal:attributes="value xeninfo/path"/>
-  <h4>Name of configuration file: </h4><input type="text" name="xenvmname" value="" tal:attributes="value xeninfo/name"/>
-  <input type="button" value="Delete"/>
-  <input type="submit" value="Update"/>
-  </form>
- </span>
-</div>
+<div metal:define-macro="vmadd-form">
+<form method="post" action="">
+	<input type="hidden" name="clustername"
+		tal:attributes="value request/clustername | nothing" />
+
+	<input type="hidden" name="pagetype"
+		tal:attributes="value request/pagetype | nothing" />
 
-<div metal:define-macro="xenvmprocess">
-	<span tal:define="retrn python:here.processXenVM(request)"/>
+	<div class="service_comp_list">
+	<table class="systemsTable">
+		<thead class="systemsTable">
+			<tr class="systemsTable"><td class="systemsTable">
+				<p class="reshdr">Create a Virtual Machine Service</p>
+			</td></tr>
+		<tfoot class="systemsTable">
+			<tr class="systemsTable">
+				<td>Automatically start this service</td>
+				<td>
+					<input type="checkbox" name="autostart" checked="checked">
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Run exclusive</td>
+				<td>
+					<input type="checkbox" name="exclusive">
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Failover Domain</td>
+				<td>
+					<select name="domain">
+						<option value="" selected="selected">None</option>
+						<tal:block tal:repeat="f python:here.get_fdom_names(modelb)">
+							<option tal:content="f"
+								tal:attributes="value f" />
+						</tal:block>
+					</select>
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Recovery policy</td>
+				<td>
+					<select name="recovery">
+						<option value="">Select a recovery policy</option>
+						<option name="relocate" value="relocate">Relocate</option>
+						<option name="restart" value="restart">Restart</option>
+						<option name="disable" value="disable">Disable</option>
+					</select>
+				</td>
+			</tr>
+			<tr class="systemsTable"><td colspan="2">
+				<div class="hbSubmit">
+					<input type="submit" value="Create Virtual Machine Service" />
+				</div>
+			</td></tr>
+		</tfoot>
+		<tbody class="systemsTable">
+			<tr class="systemsTable">
+				<td><span class="cluster_help" title="e.g., guest1 if the VM config file is at /etc/xen/guest1">Virtual machine name</span></td>
+				<td><input type="text" name="vmname" value="" /></td>
+			</tr>
+			<tr class="systemsTable">
+				<td><span class="cluster_help" title="e.g., /etc/xen/">Path to VM configuration files</span></td>
+				<td><input type="text" name="vmpath" value="" /></td>
+			</tr>
+		</tbody>
+	</table>
+	</div>
+</form>
 </div>
 
+<div metal:define-macro="vmconfig-form">
+<form method="post" action=""
+	tal:define="vminfo python:here.getVMInfo(modelb, request)">
+
+	<input type="hidden" name="clustername"
+		tal:attributes="value request/clustername | nothing" />
+
+	<input type="hidden" name="pagetype"
+		tal:attributes="value request/pagetype | nothing" />
+
+	<input type="hidden" name="oldname"
+		tal:attributes="value vminfo/name | nothing" />
+
+	<div class="service_comp_list">
+	<table class="systemsTable">
+		<thead class="systemsTable">
+			<tr class="systemsTable"><td class="systemsTable">
+				<p class="reshdr">Properties for <tal:block tal:replace="vminfo/name | string:virtual machine service"/></p>
+			</td></tr>
+		<tfoot class="systemsTable">
+			<tr class="systemsTable">
+				<td>Automatically start this service</td>
+				<td>
+					<input type="checkbox" name="autostart"
+						tal:attributes="checked python: ('autostart' in vminfo and vminfo['autostart'] != '0') and 'checked' or ''" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Run exclusive</td>
+				<td>
+					<input type="checkbox" name="exclusive"
+						tal:attributes="checked python: ('exclusive' in vminfo and vminfo['exclusive'] != '0') and 'checked' or ''" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Failover Domain</td>
+				<td>
+					<select name="domain">
+						<option value="" tal:content="string:None"
+							tal:attributes="selected python: (not 'domain' in vminfo or not vminfo['domain']) and 'selected' or ''" />
+						<tal:block tal:repeat="f python:here.get_fdom_names(modelb)">
+							<option tal:content="f"
+								tal:attributes="
+									value f;
+									selected python: ('domain' in vminfo and vminfo['domain'] == f) and 'selected' or ''" />
+						</tal:block>
+					</select>
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Recovery policy</td>
+				<td>
+					<select name="recovery">
+						<option value="">Select a recovery policy</option>
+						<option name="relocate" value="relocate"
+							tal:content="string:Relocate"
+							tal:attributes="selected python: ('recovery' in vminfo and vminfo['recovery'] == 'relocate') and 'selected' or ''" />
+						<option name="restart" value="restart"
+							tal:content="string:Restart"
+							tal:attributes="selected python: ('recovery' in vminfo and vminfo['recovery'] == 'restart') and 'selected' or ''" />
+						<option name="disable" value="disable"
+							tal:content="string:Disable"
+							tal:attributes="selected python: ('recovery' in vminfo and vminfo['recovery'] == 'disable') and 'selected' or ''" />
+					</select>
+				</td>
+			</tr>
+			<tr class="systemsTable"><td colspan="2">
+				<div class="hbSubmit">
+					<input name="submit" type="submit" value="Update Virtual Machine Service" />
+					<input name="delete" type="submit" value="Delete Virtual Machine Service" />
+				</div>
+			</td></tr>
+		</tfoot>
+		<tbody class="systemsTable">
+			<tr class="systemsTable">
+				<td><span class="cluster_help" title="e.g., guest1 if the VM config file is at /etc/xen/guest1">Virtual machine name</span></td>
+				<td>
+					<input type="text" name="vmname"
+						tal:attributes="value vminfo/name | nothing" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td><span class="cluster_help" title="e.g., /etc/xen/">Path to VM configuration files</span></td>
+				<td>
+					<input type="text" name="vmpath"
+						tal:attributes="value vminfo/path | nothing" />
+				</td>
+			</tr>
+		</tbody>
+	</table>
+	</div>
+</form>
+</div>
 
 <div metal:define-macro="serviceadd-form">
 	<script type="text/javascript">
@@ -3586,6 +4119,8 @@
 	<tal:block metal:use-macro="here/form-macros/macros/service-config-head-macro" />
 
 	<h2>Add a Service</h2>
+	<tal:block tal:define="
+		global clusterinfo python: here.getClusterInfo(modelb, request)" />
 
 	<div id="resskel" class="invisible">
 		<tal:block metal:use-macro="here/resource-form-macros/macros/service-compose-macro" />
@@ -3610,6 +4145,35 @@
 						<input type="checkbox" name="autostart" checked="checked" />
 					</td>
 				</tr>
+				<tr class="systemsTable">
+					<td class="systemsTable">Run exclusive</td>
+					<td class="systemsTable">
+						<input type="checkbox" name="exclusive">
+					</td>
+				</tr>
+				<tr class="systemsTable">
+					<td class="systemsTable">Failover Domain</td>
+					<td class="systemsTable">
+						<select name="domain">
+							<option value="" selected="selected">None</option>
+							<tal:block tal:repeat="f sinfo/fdoms">
+								<option tal:content="f"
+									tal:attributes="value f" />
+							</tal:block>
+						</select>
+					</td>
+				</tr>
+				<tr class="systemsTable">
+					<td class="systemsTable">Recovery policy</td>
+					<td class="systemsTable">
+						<select name="recovery">
+							<option value="">Select a recovery policy</option>
+							<option name="relocate" value="relocate">Relocate</option>
+							<option name="restart" value="restart">Restart</option>
+							<option name="disable" value="disable">Disable</option>
+						</select>
+					</td>
+				</tr>
 			</table>
 		</form>
 	</div>
@@ -3618,8 +4182,6 @@
 
 	<div class="service_comp_list">
 		<form name="master" method="post">
-		<tal:block
-			tal:define="global clusterinfo python: here.getClusterInfo(modelb, request)" />
 		<input type="button" value="Add a resource to this service"
 			onclick="add_child_resource(this.form);" />
 		<input type="hidden" name="pagetype"
@@ -3634,6 +4196,9 @@
 		<input type="hidden" name="tree_level" value="-1" />
 		<input type="hidden" name="svc_name" value="" />
 		<input type="hidden" name="autostart" value="-1" />
+		<input type="hidden" name="exclusive" value="-1" />
+		<input type="hidden" name="recovery" />
+		<input type="hidden" name="domain" />
 		<input type="hidden" name="form_xml" />
 		<input type="hidden" name="action" value="add" />
 		</form>
@@ -3643,9 +4208,8 @@
 		<tal:block tal:repeat="gr global_resources">
 			<tal:block tal:define="
 				global res gr;
-				global type res/type;
+				global type python: 'tag_name' in res and res['tag_name'] or '';
 				global resourceIsRef python: True" />
-
 			<tal:block metal:use-macro="here/form-macros/macros/serviceconfig-type-macro" />
 		</tal:block>
 	</div>
@@ -3695,45 +4259,59 @@
 </div>
 
 <div metal:define-macro="serviceconfig-type-macro" tal:omit-tag="">
-	<tal:block tal:condition="python: type == 'ip' or type == 'IP Address: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/ip_macro" />
+	<tal:block tal:condition="python: type == 'ip'">
+		<div metal:use-macro="here/resource-form-macros/macros/ip_macro" />
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'fs' or type == 'File System: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/fs_macro" />
+	<tal:block tal:condition="python: type == 'fs'">
+		<div metal:use-macro="here/resource-form-macros/macros/fs_macro" />
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'gfs' or type == 'GFS: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
+	<tal:block tal:condition="python: type == 'gfs' or type == 'clusterfs'">
+		<div metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'nfsm' or type == 'NFS Mount: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/nfsm_macro" />
+	<tal:block tal:condition="python: type == 'nfsm'">
+		<div metal:use-macro="here/resource-form-macros/macros/nfsm_macro"/>
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'nfsx' or type == 'NFS Export: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/nfsx_macro" />
+	<tal:block tal:condition="python: type == 'nfsx'">
+		<div metal:use-macro="here/resource-form-macros/macros/nfsx_macro"/>
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'nfsc' or type == 'NFS Client: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/nfsc_macro" />
+	<tal:block tal:condition="python: type == 'nfsc'">
+		<div metal:use-macro="here/resource-form-macros/macros/nfsc_macro"/>
 	</tal:block>
 
-	<tal:block
-		tal:condition="python: type == 'smb' or type == 'Samba Service: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/smb_macro" />
+	<tal:block tal:condition="python: type == 'smb'">
+		<div metal:use-macro="here/resource-form-macros/macros/smb_macro" />
 	</tal:block>
 
-	<tal:block tal:condition="python: type == 'script' or type == 'Script: '">
-		<tal:block
-			metal:use-macro="here/resource-form-macros/macros/scr_macro" />
+	<tal:block tal:condition="python: type == 'script'">
+		<div metal:use-macro="here/resource-form-macros/macros/scr_macro" />
+	</tal:block>
+
+	<tal:block tal:condition="python: type == 'apache'">
+		<div metal:use-macro="here/resource-form-macros/macros/apache_macro" />
+	</tal:block>
+
+	<tal:block tal:condition="python: type == 'openldap'">
+		<div metal:use-macro="here/resource-form-macros/macros/openldap_macro" />
+	</tal:block>
+
+	<tal:block tal:condition="python: type == 'mysql'">
+		<div metal:use-macro="here/resource-form-macros/macros/mysql_macro" />
+	</tal:block>
+
+	<tal:block tal:condition="python: type == 'lvm'">
+		<div metal:use-macro="here/resource-form-macros/macros/lvm_macro" />
+	</tal:block>
+
+	<tal:block tal:condition="python: type == 'postgres-8'">
+		<div metal:use-macro="here/resource-form-macros/macros/postgres-8_macro" />
+	</tal:block>
+	<tal:block tal:condition="python: type == 'tomcat-5'">
+		<div metal:use-macro="here/resource-form-macros/macros/tomcat-5_macro" />
 	</tal:block>
 </div>
 
@@ -3778,7 +4356,7 @@
 			</td>
 			<td class="cluster service service_action"
 				tal:condition="python: sinfo and 'innermap' in sinfo">
-				<form method="post" onSubmit="return dropdown(this.gourl)">
+				<form method="post">
 					<input type="hidden" name="pagetype" tal:attributes="
 						value request/pagetype | request/form/pagetype | nothing" />
 					<select name="gourl"
@@ -3803,7 +4381,8 @@
 								tal:content="string:Delete this service" />
 						</tal:block>
 					</select>
-					<input type="submit" value="Go"/>
+					<input type="button" value="Go"
+						onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 				</form>
 			</td>
 		</tr>
@@ -3818,6 +4397,8 @@
 	<br/>
 
 	<h2>Service Composition</h2>
+	<tal:block tal:define="
+		global clusterinfo python: here.getClusterInfo(modelb, request)" />
 
 	<div id="resskel" class="invisible">
 		<tal:block metal:use-macro="here/resource-form-macros/macros/service-compose-macro" />
@@ -3834,7 +4415,7 @@
 			tal:replace="structure python: '<div class=nothing>'" />
 
 		<tal:block tal:define="
-			global type res/type;
+			global type python: 'tag_name' in res and res['tag_name'] or '';
 			global resourceIsRef res/ref_object | nothing" />
 
 		<tal:block metal:use-macro="here/form-macros/macros/serviceconfig-type-macro" />
@@ -3847,19 +4428,56 @@
 	<div class="service_comp_list">
 		<form name="service_name_form">
 			<table class="rescfg">
-				<tr><td>
-				Automatically start this service
-				</td>
-				<td><input type="checkbox" name="autostart"
-						tal:attributes="checked python: ('autostart' in sinfo and sinfo['autostart'].lower() != 'false') and 'checked'" /></td></tr>
+				<tr>
+					<td>Automatically start this service</td>
+					<td><input type="checkbox" name="autostart"
+							tal:attributes="checked python: ('autostart' in sinfo and sinfo['autostart'].lower() != 'false') and 'checked'" />
+					</td>
+				</tr>
+				<tr>
+					<td>Run exclusive</td>
+					<td><input type="checkbox" name="exclusive"
+							tal:attributes="checked python: ('exclusive' in sinfo and sinfo['exclusive'].lower() != 'false') and 'checked'" />
+					</td>
+				</tr>
+				<tr>
+					<td>Failover Domain</td>
+					<td>
+						<select name="domain">
+							<option value=""
+								tal:attributes="selected python: (not 'domain' in sinfo or not sinfo['domain']) and 'selected' or ''">None</option>
+							<tal:block tal:repeat="f sinfo/fdoms">
+								<option tal:content="f"
+									tal:attributes="
+										value f;
+										selected python: ('domain' in sinfo and sinfo['domain'] == f) and 'selected' or ''" />
+							</tal:block>
+						</select>
+					</td>
+				</tr>
+				<tr class="systemsTable">
+					<td>Recovery policy</td>
+					<td>
+						<select name="recovery">
+							<option value="">Select a recovery policy</option>
+							<option name="relocate" value="relocate"
+								tal:content="string:Relocate"
+								tal:attributes="selected python: ('recovery' in sinfo and sinfo['recovery'] == 'relocate') and 'selected' or ''" />
+							<option name="restart" value="restart"
+								tal:content="string:Restart"
+								tal:attributes="selected python: ('recovery' in sinfo and sinfo['recovery'] == 'restart') and 'selected' or ''" />
+							<option name="disable" value="disable"
+								tal:content="string:Disable"
+								tal:attributes="selected python: ('recovery' in sinfo and sinfo['recovery'] == 'disable') and 'selected' or ''" />
+						</select>
+					</td>
+				</tr>
 			</table>
 			<input type="hidden" name="service_name"
 				tal:attributes="value sinfo/name | string:1" />
 		</form>
 
 		<form name="master" method="post">
-		<tal:block
-			tal:define="global clusterinfo python: here.getClusterInfo(modelb, request)" />
 		<input type="hidden" name="pagetype"
 			tal:attributes="
 				value request/pagetype | request/form/pagetype | nothing" />
@@ -3874,6 +4492,9 @@
 		<input type="hidden" name="tree_level" value="-1" />
 		<input type="hidden" name="svc_name" value="" />
 		<input type="hidden" name="autostart" value="-1" />
+		<input type="hidden" name="exclusive" value="-1" />
+		<input type="hidden" name="recovery" />
+		<input type="hidden" name="domain" />
 		<input type="hidden" name="form_xml" />
 		<input type="hidden" name="action" value="edit" />
 		</form>
@@ -3883,9 +4504,8 @@
 		<tal:block tal:repeat="gr global_resources">
 			<tal:block tal:define="
 				global res gr;
-				global type res/type;
+				global type python: 'tag_name' in res and res['tag_name'] or '';
 				global resourceIsRef python: True" />
-
 			<tal:block metal:use-macro="here/form-macros/macros/serviceconfig-type-macro" />
 		</tal:block>
 	</div>
@@ -4003,23 +4623,119 @@
 	</div>
 </div>
 
+<tal:block metal:define-macro="fdom-macro">
+<script type="text/javascript"
+	src="/luci/homebase/homebase_common.js">
+</script>
+<script type="text/javascript"
+	src="/luci/cluster/validate_fdom.js">
+</script>
+
+<form method="post" action="">
+	<input type="hidden" name="clustername"
+		tal:attributes="value request/clustername | nothing" />
+	<input type="hidden" name="pagetype"
+		tal:attributes="value request/pagetype | nothing" />
+	<input type="hidden" name="oldname"
+		tal:condition="exists: fdom/name"
+		tal:attributes="value fdom/name | nothing" />
+	
+	<table class="systemsTable" width="100%">
+		<thead class="systemsTable">
+			<tr class="systemsTable">
+				<td><strong>Failover Domain Name</strong></td>
+				<td>
+					<input type="text" name="name"
+						tal:attributes="value fdom/name | nothing" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Prioritized</td>
+				<td>
+					<input type="checkbox" name="prioritized" id="prioritized"
+						onchange="fdom_set_prioritized(this.form, this.checked)"
+						tal:attributes="checked python: (fdom and 'prioritized' in fdom and fdom['prioritized'] == '1') and 'checked' or ''" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td>Restrict failover to this domain's members</td>
+				<td>
+					<input type="checkbox" name="restricted"
+						tal:attributes="checked python: (fdom and 'restricted' in fdom and fdom['restricted'] == '1') and 'checked' or ''" />
+				</td>
+			</tr>
+			<tr class="systemsTable">
+				<td class="systemsTable" colspan="2">
+					<p></p>
+					<p class="reshdr">Failover domain membership</p>
+				</td>
+			</tr>
+		</thead>
+
+		<tfoot class="systemsTable">
+			<tr class="systemsTable"><td>
+				<div class="hbSubmit">
+					<input type="button" name="add" value="Submit"
+						onclick="validate_add_fdom(this.form)" />
+				</div>
+			</td></tr>
+		</tfoot>
+
+		<tbody width="60%">
+			<tr class="systemsTable">
+				<th class="systemsTable" width="33%">Node</th>
+				<th class="systemsTable" width="10%">Member</th>
+				<th class="systemsTable" width="57%">Priority</th>
+			</tr>
+			<tal:block tal:repeat="n python:here.getnodes(modelb)">
+				<tr class="systemsTable">
+					<td class="systemsTable" width="33%">
+						<tal:block tal:replace="n" />
+					<td class="systemsTable" width="10%">
+						<input type="checkbox"
+							onchange="fdom_set_member(this.form, this.name, this.checked)"
+							tal:attributes="
+								checked python: ('members' in fdom and n in fdom['members']) and 'checked' or '';
+								name n" />
+					</td>
+					<td class="systemsTable" width="75%">
+						<input type="text" class="fdom_priority"
+							tal:attributes="
+								id n;
+								name python: '__PRIORITY__' + n;
+								value python: ('members' in fdom and n in fdom['members'] and 'priority' in fdom['members'][n]) and fdom['members'][n]['priority'] or '1';
+								disabled python: (not fdom or not 'prioritized' in fdom or fdom['prioritized'] != '1' or not 'members' in fdom or not n in fdom['members']) and 'disabled' or ''" />
+					</td>
+				</tr>
+			</tal:block>
+		</tbody>
+	</table>
+</form>
+
+</tal:block>
+
 <div metal:define-macro="fdomadd-form">
 	<script type="text/javascript">
 		set_page_title('Luci — cluster — failover domains — Add a failover domain');
 	</script>
-	<h2>Failover Domain Add Form</h2>
-  <tal:block tal:define="allnodes python:here.getFdomNodes(request)"/>
+
+	<h2>Add a Failover Domain</h2>
+	<tal:block tal:define="fdom python:{}">
+		<tal:block metal:use-macro="here/form-macros/macros/fdom-macro" />
+	</tal:block>
 </div>
 
 <div metal:define-macro="fdomconfig-form">
 	<script type="text/javascript">
 		set_page_title('Luci — cluster — failover domains — Configure a failover domain');
 	</script>
-	<h2>Failover Domain Configuration Form</h2>
 </div>
 
 <div metal:define-macro="fdom-form">
 	<h2>Failover Domain Form</h2>
+	<tal:block tal:define="fdom python:here.getFdomInfo(modelb, request)">
+		<tal:block metal:use-macro="here/form-macros/macros/fdom-macro" />
+	</tal:block>
 </div>
 
 <div metal:define-macro="fdomprocess-form">
@@ -4028,29 +4744,34 @@
 
 <div metal:define-macro="fencedevs-form">
 	<script type="text/javascript">
-		set_page_title('Luci — cluster — fence devices');
+		set_page_title('Luci — cluster — shared fence devices');
 	</script>
-	<h2>Shared Fence Devices for Cluster: <span tal:content="request/clustername"/></h2>
-  <tal:block tal:define="global fencedevinfo python: here.getFencesInfo(modelb, request)"/>
-<tal:block tal:define="global fencedevs python: fencedevinfo['fencedevs']"/>
-  <span tal:repeat="fencedev fencedevs">
-   <h3>Agent type: <span tal:content="fencedev/pretty_name"/></h3>
-   <h3>Name: <font style="color:green"><a class="running" tal:attributes="href fencedev/cfgurl"><span tal:content="fencedev/name"/></a></font></h3>
-   <h3>Nodes using this device for fencing:</h3>
-   <ul>
-     <tal:block tal:define="global usednodes python:fencedev['nodesused']"/>
-     <span tal:condition="python: len(usednodes) == 0">
-      <li>No nodes currently employ this fence device</li>
-     </span>
-    <span tal:repeat="usednode usednodes">
-     <li><font color="green">
-      <a class="runned" href="" tal:attributes="href usednode/nodeurl"><tal:block tal:content="usednode/nodename"/>
-      </a></font>
-     </li>
-    </span>
-   </ul>
-   <hr/>
-  </span>
+
+	<h2>Shared Fence Devices for Cluster: <span tal:replace="request/clustername" /></h2>
+
+	<tal:block tal:define="
+		global fencedevinfo python: here.getFencesInfo(modelb, request);
+		global fencedevs python: fencedevinfo['fencedevs']" />
+
+	<tal:block tal:repeat="fencedev fencedevs">
+		<h3>Agent type: <span tal:content="fencedev/pretty_name"/></h3>
+		<h3>Name: <a class="running" tal:attributes="href fencedev/cfgurl"><span tal:replace="fencedev/name" /></a></h3>
+		<h3>Nodes using this device for fencing:</h3>
+		<ul>
+			<tal:block tal:define="global usednodes python:fencedev['nodesused']"/>
+			<tal:block tal:condition="python: len(usednodes) == 0">
+				<li>No nodes currently employ this fence device</li>
+			</tal:block>
+
+			<tal:block tal:repeat="usednode usednodes">
+				<li><a class="cluster node"
+						tal:attributes="href usednode/nodeurl"
+						tal:content="usednode/nodename" />
+				</li>
+			</tal:block>
+		</ul>
+		<hr/>
+	</tal:block>
 </div>
 
 <div metal:define-macro="fencedevlist-form">
@@ -4064,6 +4785,15 @@
 	<script type="text/javascript"
 		src="/luci/cluster/fence_device.js">
 	</script>
+
+	<script type="text/javascript"
+		src="/luci/homebase/homebase_common.js">
+	</script>
+
+	<script type="text/javascript"
+		src="/luci/cluster/validate_fence.js">
+	</script>
+
 	<script type="text/javascript">
 		set_page_title('Luci — cluster — fence devices - Add a new fence device');
 	</script>
@@ -4101,10 +4831,13 @@
 					<div id="fence_container">
 					</div>
 					<div class="hbSubmit">
-						<input type="submit"
-							value="Add this shared fence device" />
+						<input type="button"
+							value="Add this shared fence device"
+							onclick="validate_fence_form(this.form)" />
+
 						<input type="hidden" name="pagetype"
 							value="51" id="pagetype" />
+
 						<input type="hidden" name="clustername" id="pagetype"
 							tal:attributes="value request/clustername" />
 				</form>
@@ -4130,12 +4863,12 @@
 
 	<tal:block tal:condition="exists: fencedevs/fencedevs">
 		<table class="systemsTable">
-	        <thead class="systemsTable">
+			<thead class="systemsTable">
 				<tr class="systemsTable">
 					<th class="systemsTable" width="100">Name</th>
 					<th class="systemsTable" width="100">Type</th>
 					<th class="systemsTable" width="75">Configure</th>
-            	</tr>
+				</tr>
 			</thead>
 			<tr class="systemsTable" tal:repeat="f fencedevs/fencedevs">
 				<td class="systemsTable" tal:content="f/name | string:[unknown]"/>
@@ -4226,13 +4959,25 @@
 		<tal:block metal:use-macro="here/form-macros/macros/fence-form-manual" />
 	</tal:block>
 
-    <tal:block tal:condition="exists:cur_fencedev/unknown">
+	<tal:block tal:condition="exists:cur_fencedev/unknown">
 		<tal:block metal:use-macro="here/form-macros/macros/fence-form-unknown" />
 	</tal:block>
 </div>
 
 
 <div metal:define-macro="fencedev-form">
+	<script type="text/javascript">
+		set_page_title('Luci — cluster — fence devices - Configure a fence device');
+	</script>
+
+	<script type="text/javascript"
+		src="/luci/homebase/homebase_common.js">
+	</script>
+
+	<script type="text/javascript"
+		src="/luci/cluster/validate_fence.js">
+	</script>
+
 	<h2>Fence Device Form</h2>
 
 	<div class="cluster fencedev fence">
@@ -4254,13 +4999,12 @@
 			<input type="hidden" name="pagetype" value="54" />
 			<input type="hidden" name="clustername"
 				tal:attributes="value request/clustername" />
-			<input type="hidden" name="orig_name"
-				tal:attributes="value request/fencename"/>
-  			<input type="hidden" name="fencename"
+			<input type="hidden" name="fencename"
 				tal:attributes="value request/fencename" />
 
 			<div class="hbSubmit">
-				<input type="submit" value="Update this fence device" />
+				<input type="button" value="Update this fence device"
+					onclick="validate_fence_form(this.form)" />
 			</div>
 		</form>
 
@@ -4273,7 +5017,8 @@
 			<input type="hidden" name="orig_name"
 				tal:attributes="value request/fencename" />
 			<div class="hbSubmit">
-				<input type="submit" value="Delete this fence device" />
+				<input type="button" value="Delete this fence device"
+					onclick="if (confirm('Delete this fence device?')) this.form.submit()" />
 			</div>
 		</form>
 	</div>
@@ -4286,22 +5031,28 @@
 <div metal:define-macro="conf_editor-form">
 	<h2>Edit cluster.conf</h2>
 	<form method="post"
-	      tal:attributes="action python: './?' + request['QUERY_STRING']"
-	      tal:define="ret python: here.process_cluster_conf_editor(request)">
-	  <span tal:content="structure python: ret['msg'].replace('\n', '<br/>')"/>
-	  <textarea name="new_cluster_conf"
-		    tal:attributes="rows python: len(ret['cluster_conf'].splitlines()) + 8"
-		    tal:content="structure ret/cluster_conf"></textarea>
-	  <input tal:attributes="type  string:hidden;
-	                         name  string:pagetype;
-	                         value python:request['pagetype']"/>
-	  <input tal:attributes="type  string:hidden;
-	                         name  string:clustername;
-	                         value python:request['clustername']"/>
-	  <input type="button" 
-	         value="Reset"
-	         tal:attributes="onclick python:'window.location.assign(\'./?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '\')'"/>
-	  <input type="submit" value="Propagate"/>
+		tal:attributes="action python: './?' + request['QUERY_STRING']"
+		tal:define="ret python: here.process_cluster_conf_editor(request)">
+
+	<span tal:content="structure python: ret['msg'].replace('\n', '<br/>')" />
+
+	<textarea name="new_cluster_conf"
+		tal:attributes="rows python: len(ret['cluster_conf'].splitlines()) + 8"
+		tal:content="structure ret/cluster_conf">
+	</textarea>
+
+	<input type="hidden" name="pagetype"
+		 tal:attributes="
+			value request/pagetype | nothing" />
+
+	<input type="hidden" name="clustername"
+		tal:attributes="
+			value request/clustername | nothing" />
+
+	<input type="button" value="Reset"
+		tal:attributes="onclick python:'window.location.assign(\'./?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '\')'" />
+
+	<input type="submit" value="Propagate" />
 	</form>
 </div>
 
--- conga/luci/cluster/index_html	2006/12/22 17:50:16	1.20.2.6
+++ conga/luci/cluster/index_html	2007/03/01 00:31:08	1.20.2.7
@@ -32,10 +32,6 @@
 			global ri_agent nothing;
 			global busywaiting python:None" />
 
-		<tal:block tal:condition="not: hascluster">
-		    <meta googaa="ooo"/>
-		</tal:block>
-
 		<tal:block tal:condition="hascluster">
 			<tal:block tal:define="
 				global ri_agent python:here.getRicciAgentForCluster(request);
@@ -45,6 +41,10 @@
 				global isBusy python:here.isClusterBusy(request);
 				global firsttime request/busyfirst |nothing" />
 
+			<tal:block tal:condition="ri_agent">
+				<tal:block tal:define="dummy python:request.SESSION.set('ricci', ri_agent)" />
+			</tal:block>
+
 			<tal:block tal:condition="firsttime">
 				<tal:block tal:define="global busywaiting python:True" />
 				<meta http-equiv="refresh"
--- conga/luci/cluster/resource-form-macros	2006/12/07 17:54:31	1.21.2.3
+++ conga/luci/cluster/resource-form-macros	2007/03/01 00:31:08	1.21.2.4
@@ -106,7 +106,10 @@
 		<form>
 		<select onChange="swap_div_elem(this.form.parentNode,
 									this.options[this.selectedIndex].value);">
-			<option name="blank" value="blank" checked>Select a resource type</option>
+			<option name="blank" value="blank" checked>
+				Select a resource type
+			</option>
+
 			<option name="IP" value="IP">IP address</option>
 			<option name="FS" value="FS">File system</option>
 			<option name="GFS" value="GFS">GFS file system</option>
@@ -115,6 +118,13 @@
 			<option name="NFSX" value="NFSX">NFS export</option>
 			<option name="SCR" value="SCR">Script</option>
 			<option name="SMB" value="SMB">Samba</option>
+
+			<option name="APACHE" value="APACHE">Apache</option>
+			<option name="LVM" value="LVM">LVM</option>
+			<option name="MYSQL" value="MYSQL">MySQL</option>
+			<option name="OPENLDAP" value="OPENLDAP">Open LDAP</option>
+			<option name="POSTGRES-8" value="POSTGRES-8">PostgreSQL 8</option>
+			<option name="TOMCAT-5" value="TOMCAT-5">Tomcat 5</option>
 		</select>
 		</form>
 	</p>
@@ -129,6 +139,12 @@
 		<div metal:use-macro="here/resource-form-macros/macros/nfsc_macro" />
 		<div metal:use-macro="here/resource-form-macros/macros/smb_macro" />
 		<div metal:use-macro="here/resource-form-macros/macros/scr_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/apache_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/mysql_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/lvm_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/openldap_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/postgres-8_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/tomcat-5_macro" />
 	</div>
 </div>
 
@@ -147,6 +163,13 @@
 			<option name="NFSX" value="NFSX">NFS export</option>
 			<option name="SCR" value="SCR">Script</option>
 			<option name="SMB" value="SMB">Samba</option>
+
+			<option name="APACHE" value="APACHE">Apache</option>
+			<option name="LVM" value="LVM">LVM</option>
+			<option name="MYSQL" value="MYSQL">MySQL</option>
+			<option name="OPENLDAP" value="OPENLDAP">Open LDAP</option>
+			<option name="POSTGRES-8" value="POSTGRES-8">PostgreSQL 8</option>
+			<option name="TOMCAT-5" value="TOMCAT-5">Tomcat 5</option>
 		</select>
 		</form>
 	</p>
@@ -184,6 +207,12 @@
 		<div metal:use-macro="here/resource-form-macros/macros/nfsc_macro" />
 		<div metal:use-macro="here/resource-form-macros/macros/smb_macro" />
 		<div metal:use-macro="here/resource-form-macros/macros/scr_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/apache_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/mysql_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/lvm_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/openldap_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/postgres-8_macro" />
+		<div metal:use-macro="here/resource-form-macros/macros/tomcat-5_macro" />
 	</div>
 </div>
 
@@ -199,7 +228,10 @@
 	</script>
 
 	<tal:block tal:define="
-		global res python: here.getResourceInfo(modelb, request);" />
+		global res python: here.getResourceInfo(modelb, request)" />
+
+	<tal:block tal:define="
+		global clusterinfo python: here.getClusterInfo(modelb, request)" />
 
 	<h2>Add a Resource</h2>
 
@@ -225,7 +257,7 @@
 		</thead>
 		<tr class="systemsTable">
 			<td class="systemsTable" tal:content="res/name" />
-			<td class="systemsTable" tal:content="res/tag_name" />
+			<td class="systemsTable" tal:content="res/type" />
 			<td>
 				<a class="cluster resource"
 					tal:content="string: configure"
@@ -235,7 +267,6 @@
 	</table>
 </div>
 
-
 <div metal:define-macro="resourceprocess-form">
 	<h2>Resource <span tal:replace="python: ('edit' in request and request['edit']) and 'Edited' or 'Added'" /></h2>
 
@@ -255,45 +286,17 @@
 	</script>
 
 	<tal:block tal:define="global resourcename request/resourcename | request/form/resourceName | nothing" />
+
 	<tal:block tal:condition="resourcename"
 		tal:define="
 			global res python: here.getResourceInfo(modelb, request);
 			global type python: 'tag_name' in res and res['tag_name'] or ''">
 
 	<h2>Configure <span tal:replace="res/name | string: resource" /></h2>
+	<br/>
 
 	<div class="reschoose">
-		<tal:block tal:condition="python: type == 'ip'">
-			<div metal:use-macro="here/resource-form-macros/macros/ip_macro" />
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'fs'">
-			<div metal:use-macro="here/resource-form-macros/macros/fs_macro" />
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'gfs' or type == 'clusterfs'">
-			<div metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'nfsm'">
-			<div metal:use-macro="here/resource-form-macros/macros/nfsm_macro"/>
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'nfsx'">
-			<div metal:use-macro="here/resource-form-macros/macros/nfsx_macro"/>
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'nfsc'">
-			<div metal:use-macro="here/resource-form-macros/macros/nfsc_macro"/>
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'smb'">
-			<div metal:use-macro="here/resource-form-macros/macros/smb_macro" />
-		</tal:block>
-
-		<tal:block tal:condition="python: type == 'script'">
-			<div metal:use-macro="here/resource-form-macros/macros/scr_macro" />
-		</tal:block>
+		<tal:block metal:use-macro="here/form-macros/macros/serviceconfig-type-macro" />
 	</div>
 	</tal:block>
 </div>
@@ -353,7 +356,7 @@
 				<input type="checkbox" name="monitorLink"
 					tal:attributes="
 						disabled python: editDisabled;
-						checked res/attrs/monitor_link | string: 1" />
+						checked res/attrs/monitor_link | string: checked" />
 			</td>
 		</tr>
 	</table>
@@ -421,10 +424,10 @@
 
 					<option name="ext3" value="ext3"
 						tal:content="string: ext3"
-						tal:attributes="checked python: fstype == 'ext3' and 'checked'" />
+						tal:attributes="selected python: fstype == 'ext3' and 'selected'" />
 					<option name="ext2" value="ext2"
 						tal:content="string: ext2"
-						tal:attributes="checked python: fstype == 'ext2' and 'checked'" />
+						tal:attributes="selected python: fstype == 'ext2' and 'selected'" />
 				</select>
 			</td>
 		</tr>
@@ -796,11 +799,569 @@
 				<input type="text" size="20" name="options"
 					tal:attributes="
 						disabled python: editDisabled;
-						value res/attrs/options | nothing"/>
+						value res/attrs/options | nothing" />
+			</td>
+		</tr>
+
+		<tr>
+			<td class="systemsTable">Allow Recover</td>
+			<td class="systemsTable">
+				<input type="checkbox" name="allow_recover"
+					tal:attributes="
+						disabled python: editDisabled;
+						checked res/attrs/allow_recover | nothing" />
+			</td>
+		</tr>
+	</table>
+
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="POSTGRES-8"
+	tal:attributes="id res/name | nothing" metal:define-macro="postgres-8_macro">
+	<p class="reshdr">PostgreSQL 8 Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
+
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="postgres-8" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Config File</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="config_file"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/config_file | string:/var/lib/pgsql/data/postgresql.conf" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Postmaster User</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="postmaster_user"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/postmaster_user | string:postgres" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Postmaster Options</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="postmaster_options"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/postmaster_options | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Shutdown Wait (seconds)</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="shutdown_wait"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/shutdown_wait | string:0" />
 			</td>
 		</tr>
 	</table>
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="APACHE"
+	tal:attributes="id res/name | nothing" metal:define-macro="apache_macro">
+	<p class="reshdr">Apache Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
 
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="apache" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Server Root</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="server_root"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/server_root | string:/etc/httpd" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Config File</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="config_file"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/config_file | string:conf/httpd.conf" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">httpd Options</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="httpd_options"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/httpd_options | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Shutdown Wait (seconds)</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="shutdown_wait"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/shutdown_wait | string:0" />
+			</td>
+		</tr>
+	</table>
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="OPENLDAP"
+	tal:attributes="id res/name | nothing" metal:define-macro="openldap_macro">
+	<p class="reshdr">Open LDAP Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
+
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="openldap" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Config File</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="config_file"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/config_file | string:/etc/openldap/slapd.conf" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">URL List</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="url_list"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/url_list | string:ldap:///"; />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">slapd Options</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="slapd_options"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/slapd_options | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Shutdown Wait (seconds)</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="shutdown_wait"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/shutdown_wait | string:0" />
+			</td>
+		</tr>
+	</table>
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="LVM"
+	tal:attributes="id res/name | nothing" metal:define-macro="lvm_macro">
+
+	<p class="reshdr">LVM Resource Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
+
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="lvm" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+		<tr class="systemsTable">
+			<td class="systemsTable">Volume Group Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="vg_name"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/vg_name | nothing" />
+			</td>
+		</tr>
+		<tr class="systemsTable">
+			<td class="systemsTable">Logical Volume Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="lv_name"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/lv_name | nothing" />
+			</td>
+		</tr>
+	</table>
+
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="MYSQL"
+	tal:attributes="id res/name | nothing" metal:define-macro="mysql_macro">
+	<p class="reshdr">MySQL Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
+
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="mysql" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Config File</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="config_file"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/config_file | string:/etc/my.cnf" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Listen Address</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="listen_address"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/listen_address | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">mysqld Options</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="mysqld_options"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/mysqld_options | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Shutdown Wait (seconds)</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="shutdown_wait"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/shutdown_wait | string:0" />
+			</td>
+		</tr>
+	</table>
+	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
+	</form>
+</div>
+
+<div class="rescfg" name="tomcat-5"
+	tal:attributes="id res/name | nothing" metal:define-macro="tomcat-5_macro">
+	<p class="reshdr">Tomcat 5 Configuration</p>
+
+	<form method="post"
+		tal:attributes="name res/parent_uuid | nothing"
+		tal:define="editDisabled resourceIsRef | nothing">
+
+	<input name="immutable" type="hidden" value="true"
+		tal:condition="editDisabled" />
+
+	<input name="edit" type="hidden" value="true"
+		tal:condition="python: ptype == '33' and True or False" />
+
+	<input name="pagetype" type="hidden"
+		tal:attributes="value python: ptype" />
+
+	<input name="global" type="hidden"
+		tal:attributes="value resourceIsRef | nothing" />
+
+	<input name="parent_uuid" type="hidden"
+		tal:attributes="value res/parent_uuid | nothing" />
+
+	<input name="uuid" type="hidden"
+		tal:attributes="value res/uuid | nothing" />
+
+	<input name="tree_level" type="hidden"
+		tal:attributes="value res/indent_ctr | string:0" />
+
+	<input name="clustername" type="hidden"
+		tal:attributes="
+			value request/clustername | request/form/clustername | nothing" />
+
+	<input name="oldname" type="hidden"
+		tal:attributes="value res/name | nothing" />
+
+	<input name="type" type="hidden" value="tomcat-5" />
+
+	<table class="systemsTable">
+		<tr class="systemsTable">
+			<td class="systemsTable">Name</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="resourceName"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/name | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Config File</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="config_file"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/config_file | string:/etc/tomcat5/tomcat5.conf" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Tomcat User</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="tomcat_user"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/tomcat_user | string:tomcat" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Catalina Options</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="catalina_options"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/catalina_options | nothing" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Catalina Base</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="catalina_base"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/catalina_base | string:/usr/share/tomcat5" />
+			</td>
+		</tr>
+
+		<tr class="systemsTable">
+			<td class="systemsTable">Shutdown Wait (seconds)</td>
+			<td class="systemsTable">
+				<input type="text" size="20" name="shutdown_wait"
+					tal:attributes="
+						disabled python: editDisabled;
+						value res/attrs/shutdown_wait | string:30" />
+			</td>
+		</tr>
+	</table>
 	<div metal:use-macro="here/resource-form-macros/macros/res_form_footer" />
 	</form>
 </div>
--- conga/luci/cluster/resource_form_handlers.js	2006/12/07 17:54:31	1.20.2.3
+++ conga/luci/cluster/resource_form_handlers.js	2007/03/01 00:31:08	1.20.2.4
@@ -98,6 +98,41 @@
 	return (errors);
 }
 
+function validate_apache(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_tomcat5(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_postgres8(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_mysql(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_lvm(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_openldap(form) {
+	var errors = new Array();
+	return (errors);
+}
+
+function validate_nfs_export(form) {
+	var errors = new Array();
+	return (errors);
+}
+
 function validate_nfs_mount(form) {
 	var errors = new Array();
 
@@ -121,11 +156,6 @@
 	return (errors);
 }
 
-function validate_nfs_export(form) {
-	var errors = new Array();
-	return (errors);
-}
-
 function validate_nfs_client(form) {
 	var errors = new Array();
 
@@ -211,6 +241,14 @@
 	return (errors);
 }
 
+var required_children = new Array();
+required_children['nfsx'] = [ 'nfsc' ];
+
+var forbidden_children = new Array();
+forbidden_children['ip'] = [ 'nfsc', 'nfsx' ];
+forbidden_children['netfs'] = [ 'nfsc', 'nfsx' ];
+forbidden_children['nfsx'] = [ 'nfsx' ];
+
 var form_validators = new Array();
 form_validators['ip'] = validate_ip;
 form_validators['nfsm'] = validate_nfs_mount;
@@ -220,6 +258,12 @@
 form_validators['gfs'] = validate_gfs;
 form_validators['scr'] = validate_script;
 form_validators['smb'] = validate_samba;
+form_validators['apache'] = validate_apache;
+form_validators['tomcat-5'] = validate_tomcat5;
+form_validators['postgres-8'] = validate_postgres8;
+form_validators['openldap'] = validate_openldap;
+form_validators['mysql'] = validate_mysql;
+form_validators['lvm'] = validate_lvm;
 
 function check_form(form) {
 	var valfn = form_validators[form.type.value];
@@ -241,7 +285,10 @@
 	var errors = check_form(form);
 	if (error_dialog(errors))
 		return (-1);
-	form.submit();
+
+	var confirm_str = form.edit ? 'Update this resource?' : 'Add this resource?';
+	if (confirm(confirm_str))
+		form.submit();
 }
 
 function delete_resource(form) {
@@ -382,6 +429,9 @@
 	var form_xml = '';
 	var svc_name = null;
 	var autostart = 1;
+	var domain = null;
+	var exclusive = 0;
+	var recovery = null;
 
 	var form = document.getElementsByTagName('form');
 	for (var i = 0 ; i < form.length ; i++) {
@@ -394,8 +444,26 @@
 				clr_form_err(form[i].service_name);
 				svc_name = form[i].service_name.value;
 			}
+
 			if (!form[i].autostart.checked)
 				autostart = 0;
+
+			if (!form[i].exclusive.checked)
+				exclusive = 0;
+			else
+				exclusive = 1;
+
+			if (form[i].recovery) {
+				recovery = form[i].recovery.options[form[i].recovery.options.selectedIndex].value;
+				if (str_is_blank(recovery))
+					recovery = null;
+			}
+
+			if (form[i].domain) {
+				domain = form[i].domain.options[form[i].domain.options.selectedIndex].value;
+				if (str_is_blank(domain))
+					domain = null;
+			}
 			continue;
 		}
 
@@ -415,11 +483,12 @@
 			{
 				temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" value="' + input_elem[j].value + '" />';
 			} else if (res_type == 'checkbox' || res_type == 'radio') {
-				if (input_elem[j].checked)
+				if (input_elem[j].checked) {
 					temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" checked="checked"';
-				if (res_type == 'radio')
-					temp += ' value="' + input_elem[j].value + '"';
-				temp += ' />';
+					if (res_type == 'radio')
+						temp += ' value="' + input_elem[j].value + '"';
+					temp += ' />';
+				}
 			}
 		}
 
@@ -438,13 +507,22 @@
 	if (!form_xml)
 		errors.push('No resource information was submitted.');
 
+	if (recovery && recovery != 'relocate' && recovery != 'restart' && recovery != 'disable') {
+		errors.push('You entered an invalid recovery option. Valid options are "relocate" "restart" and "disable"');
+	}
+
 	if (error_dialog(errors))
 		return (-1);
 
 	/* sort this out in the backend */
 	master_form.form_xml.value = '<formlist>' + form_xml + '</formlist>';
 	master_form.svc_name.value = svc_name;
+	if (domain)
+		master_form.domain.value = domain;
+	if (recovery)
+		master_form.recovery.value = recovery;
 	master_form.autostart.value = autostart;
+	master_form.exclusive.value = exclusive;
 
 	var confirm_msg = null;
 	if (master_form.action.value == 'add')
--- conga/luci/cluster/validate_config_general.js	2006/10/04 17:24:58	1.3
+++ conga/luci/cluster/validate_config_general.js	2007/03/01 00:31:08	1.3.2.1
@@ -8,7 +8,11 @@
 		set_form_err(form.cluname);
 	} else {
 		name = form.cluname.value;
-		clr_form_err(form.cluname);
+		if (name.length > 15) {
+			errors.push('A cluster\'s name must be less than 16 characters long.');
+			set_form_err(form.cluname);
+		} else
+			clr_form_err(form.cluname);
 	}
 
 	if (!form.cfgver || str_is_blank(form.cfgver.value)) {
--- conga/luci/cluster/validate_config_qdisk.js	2006/12/22 17:50:16	1.4.2.1
+++ conga/luci/cluster/validate_config_qdisk.js	2007/03/01 00:31:08	1.4.2.2
@@ -1,4 +1,4 @@
-var heuristic_names = [ ':hname', ':hprog', ':hinterval', ':hscore', ':hdel' ];
+var heuristic_names = [ ':hprog', ':hinterval', ':hscore', ':hdel' ];
 
 function clear_heuristic(form, heur_num) {
 	var str_prefix = 'heuristic' + heur_num;
@@ -82,26 +82,14 @@
 
 	var hstr = 'heuristic' + hnum;
 
-	var hname = document.getElementById(hstr + ':hname');
-	if (!hname || str_is_blank(hname.value)) {
-		++blank;
-		errors.push('No name was given for heuristic ' + (hnum + 1));
-		set_form_err(hname);
-	} else {
-		/* XXX sanity check the name */
-		hname = hname.value;
-		clr_form_err(hname);
-	}
-
-	var hpath = document.getElementById(hstr + ':hpath');
-	if (!hpath || str_is_blank(hpath.value)) {
+	var hprog = document.getElementById(hstr + ':hprog');
+	if (!hprog || str_is_blank(hprog.value)) {
 		++blank;
 		errors.push('No path was given for heuristic ' + (hnum + 1));
-		set_form_err(hpath);
+		set_form_err(hprog);
 	} else {
 		/* XXX sanity check the path */
-		hpath = hpath.value;
-		clr_form_err(hpath);
+		clr_form_err(hprog);
 	}
 
 	var hint = document.getElementById(hstr + ':hinterval');
@@ -110,8 +98,7 @@
 		errors.push('No interval was given for heuristic ' + (hnum + 1));
 		set_form_err(hint);
 	} else {
-		hint = hint.value;
-		if (!is_valid_int(hint, 1, null)) {
+		if (!is_valid_int(hint.value, 1, null)) {
 			errors.push('Heuristic interval values must be greater than 0.');
 			set_form_err(hint);
 		} else
@@ -124,18 +111,16 @@
 		errors.push('No score was given for heuristic ' + (hnum + 1));
 		set_form_err(hscore);
 	} else {
-		hscore = hscore.value;
-		if (!is_valid_int(hscore, 0, null)) {
+		if (!is_valid_int(hscore.value, 0, null)) {
 			errors.push('Heuristic score values must be 0 or greater.');
 			set_form_err(hscore);
 		} else
 			clr_form_err(hscore);
 	}
 
-	if (blank == 4) {
+	if (blank == 3) {
 		/* The entry is blank -- ignore it. */
-		clr_form_err(hname);
-		clr_form_err(hpath);
+		clr_form_err(hprog);
 		clr_form_err(hint);
 		clr_form_err(hscore);
 		return (null);
@@ -219,30 +204,15 @@
 				clr_form_err(form.min_score);
 		}
 
-		if (!form.device || str_is_blank(form.device.value)) {
-			errors.push('No device setting was given.');
-			set_form_err(form.device);
-		} else {
-			/* TODO: check this */
-			var device = form.device.value;
-			clr_form_err(form.device);
-		}
-
-		if (!form.label || str_is_blank(form.label.value)) {
-			errors.push('No label setting was given.');
-			set_form_err(form.label);
-		} else {
-			/* TODO: check this */
-			var label = form.device.label;
-			clr_form_err(form.label);
-		}
+		var no_dev = !form.device || str_is_blank(form.device.value);
+		var no_label = !form.label || str_is_blank(form.label.value);
+		if (no_dev && no_label)
+			errors.push('You must give either a label or a device.');
 
 		var hnum = document.getElementById('num_heuristics');
 		if (hnum) {
-			hnum = Number(hnum.value);
-			if (hnum === 0)
-				hnum++;
-			for (var i = 0 ; i < hnum ; i++) {
+			hnum = Number(hnum.value) + 1;
+			for (var i = 0 ; i <= hnum ; i++) {
 				var err = check_heuristic(i, form);
 				if (err)
 					errors = errors.concat(err);
@@ -252,6 +222,7 @@
 
 	if (error_dialog(errors))
 		return (-1);
+
 	if (confirm('Update quorum partition properties?'))
 		form.submit();
 }
@@ -275,15 +246,6 @@
 
 	var hstr = 'heuristic' + cur_hnum;
 
-	var name_td = document.createElement('td');
-	name_td.className = 'systemsTable';
-	var name_input = document.createElement('input');
-	name_input.className = 'qdname qdisk';
-	name_input.setAttribute('name', hstr + ':hname');
-	name_input.setAttribute('id', hstr + ':hname');
-	name_input.setAttribute('type', 'text');
-	name_td.appendChild(name_input);
-
 	var path_td = document.createElement('td');
 	path_td.className = 'systemsTable';
 	var path_input = document.createElement('input');
@@ -325,7 +287,6 @@
 	var tr = document.createElement('tr');
 	tr.className = 'systemsTable';
 	tr.setAttribute('id', 'heuristic' + cur_hnum);
-	tr.appendChild(name_td);
 	tr.appendChild(path_td);
 	tr.appendChild(interval_td);
 	tr.appendChild(score_td);
--- conga/luci/cluster/validate_fence.js	2006/10/04 17:25:20	1.1
+++ conga/luci/cluster/validate_fence.js	2007/03/01 00:31:08	1.1.2.1
@@ -1,48 +1,251 @@
-function validate_fence_apc(form) {
-	return (0);
-}
+var fence_inst_validator = new Array();
+fence_inst_validator['apc'] = [ 'port', 'switch' ];
+fence_inst_validator['bladecenter'] = [ 'blade' ];
+fence_inst_validator['brocade'] = [ 'port' ];
+fence_inst_validator['bullpap'] = [ 'domain' ];
+fence_inst_validator['egenera'] = [ 'lpan', 'pserver' ];
+fence_inst_validator['gndb'] = [ 'ipaddress' ];
+fence_inst_validator['mcdata'] = [ 'port' ];
+fence_inst_validator['sanbox2'] = [ 'port' ];
+fence_inst_validator['scsi'] = [ 'nodename' ];
+fence_inst_validator['vixel'] = [ 'port' ];
+fence_inst_validator['wti'] = [ 'port' ];
+fence_inst_validator['xvm'] = [ 'domain' ];
+
+var fence_validator = new Array();
+fence_validator['apc'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['bladecenter'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['brocade'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['bullpap'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['drac'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['egenera'] = [ 'cserver' ];
+fence_validator['gnbd'] = [ 'servers' ];
+fence_validator['ilo'] = [ 'hostname', 'login', 'passwd', 'passwd_script' ];
+fence_validator['ipmilan'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script', 'lanplus', 'auth' ];
+fence_validator['manual'] = [];
+fence_validator['mcdata'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['rps10'] = [ 'device', 'port'];
+fence_validator['rsa'] = [ 'hostname', 'login', 'passwd', 'passwd_script' ];
+fence_validator['sanbox2'] = [ 'ipaddr', 'login', 'passwd', 'passwd_script' ];
+fence_validator['scsi'] = [];
+fence_validator['unknown'] = [];
+fence_validator['vixel'] = [ 'ipaddr', 'passwd', 'passwd_script' ];
+fence_validator['wti'] = [ 'ipaddr', 'passwd', 'passwd_script' ];
+fence_validator['xvm'] = [];
+
+function validate_field_str(form, form_elem) {
+	var errors = new Array();
+
+	if (!form_elem || str_is_blank(form_elem.value)) {
+		if (!form_elem)
+			errors.push('No value was given for this field.');
+		else {
+			set_form_err(form_elem);
+			errors.push(form_elem.name + ' values must not be blank.');
+		}
+		return (errors);
+	}
 
-function validate_fence_wti(form) {
-	return (0);
+	clr_form_err(form_elem);
+	return (null);
 }
 
-function validate_fence_rsa(form) {
-	return (0);
+function validate_field_passwd(form, form_elem) {
+	if (form_elem.disabled) {
+		clr_form_err(form_elem);
+		return (null);
+	}
+
+	var errors = validate_field_str(form, form_elem);
+	if (errors && errors.length > 0 && form.passwd_script && !str_is_blank(form.passwd_script.value))
+	{
+		clr_form_err(form_elem);
+		return (null);
+	}
+	return errors;
+}
+
+/* Very loose checking for now -- just make sure it's not blank */
+function validate_field_host(form, form_elem) {
+	return (validate_field_str(form, form_elem));
+}
+
+function validate_field_noop(form, form_elem) {
+	if (form_elem)
+		clr_form_err(form_elem);
+	return (null);
 }
 
-function validate_fence_ilo(form) {
-	return (0);
+function validate_field_ipmilan_auth(form, form_elem) {
+	var errors = new Array();
+
+	if (!form_elem || str_is_blank(form_elem.value))
+		return (null);
+
+	var auth_type = form_elem.value;
+	if (auth_type != 'none' && auth_type != 'password' && auth_type != 'md5') {
+		errors.push('Auth type must be either \'none\' (or blank), \'md5\' or \'password\'');
+		set_form_err(form_elem);
+		return (errors);
+	}
+
+	clr_form_err(form_elem);
+	return (null);
 }
 
-function validate_fence_drac(form) {
-	return (0);
+var field_validator = new Array();
+field_validator['ipaddr'] = validate_field_host;
+field_validator['hostname'] = validate_field_host;
+field_validator['login'] = validate_field_str;
+field_validator['passwd'] = validate_field_passwd;
+field_validator['servers'] = validate_field_str;
+field_validator['cserver'] = validate_field_str;
+field_validator['device'] = validate_field_str;
+field_validator['port'] = validate_field_str;
+field_validator['passwd_script'] = validate_field_noop;
+
+/* IPMI fence device */
+field_validator['lanplus'] = validate_field_noop;
+field_validator['auth'] = validate_field_ipmilan_auth;
+
+/* APC instance switch */
+field_validator['switch'] = validate_field_noop;
+
+field_validator['ipaddress'] = validate_field_host;
+field_validator['blade'] = validate_field_str;
+field_validator['nodename'] = validate_field_host;
+field_validator['lpan'] = validate_field_str;
+field_validator['pserver'] = validate_field_str;
+field_validator['domain'] = validate_field_str;
+
+function validate_fence(form) {
+	var errors = new Array();
+
+	if (!form.fence_type || str_is_blank(form.fence_type.value))
+		errors.push('No fence device was selected.');
+
+	if (errors.length > 0)
+		return (errors);
+
+	if (!form.name || str_is_blank(form.name.value)) {
+		errors.push('A unique name must be given for all fence devices.');
+		set_form_err(form.name);
+	} else
+		clr_form_err(form.name);
+
+	if (errors.length > 0)
+		return (errors);
+
+	var fence_type = form.fence_type.value.replace(/^fence_/, '');
+	var fields = fence_validator[fence_type];
+	if (!fields)
+		errors.push('An unknown fence device type was given: \"' + fence_type + '.\"');
+
+	if (errors.length > 0)
+		return (errors);
+
+	for (var i = 0 ; i < fields.length ; i++) {
+		var field_name = fields[i];
+		if (form[field_name]) {
+			var err = field_validator[field_name](form, form[field_name]);
+			if (err)
+				errors = errors.concat(err);
+		}
+	}
+
+	return (errors);
 }
 
-function validate_fence_ipmilan(form) {
-	return (0);
+function validate_fence_form(form) {
+	var errors = validate_fence(form);
+
+	if (error_dialog(errors))
+		return (-1);
+
+	if (confirm('Update fence device properties?'))
+		form.submit();
 }
 
-var fence_validator = new Object();
-fence_validator['apc'] = validate_fence_apc;
-fence_validator['wti'] = validate_fence_wti;
-fence_validator['rsa'] = validate_fence_rsa;
-fence_validator['ilo'] = validate_fence_ilo;
-fence_validator['drac'] = validate_fence_drac;
-fence_validator['ipmilan'] = validate_fence_ipmilan;
+function validate_fence_instance(form) {
+	var errors = new Array();
 
-function validate_fence_common(form) {
-	return (null);
+	if (!form.fence_type || str_is_blank(form.fence_type.value))
+		errors.push('The fence device associated with this instance could not be determined.');
+
+	if (errors.length > 0)
+		return (errors);
+
+	var fence_type = form.fence_type.value.replace(/^fence_/, '');
+	var fields = fence_inst_validator[fence_type];
+	if (!fields)
+		errors.push('An unknown fence device type was given: \"' + fence_type + '.\"');
+
+	if (errors.length > 0)
+		return (errors);
+
+	for (var i = 0 ; i < fields.length ; i++) {
+		var field_name = fields[i];
+		if (form[field_name]) {
+			var err = field_validator[field_name](form, form[field_name]);
+			if (err)
+				errors = errors.concat(err);
+		}
+	}
+
+	return (errors);
 }
 
-function validate_fence(form) {
-	if (!form || !form.fence_type || !form.fence_type.value)
+function validate_node_fence_form(master_form, container_id) {
+	var errors = new Array();
+	var div_elem = document.getElementById(container_id);
+	if (!div_elem)
 		return (-1);
-	var errors = validate_fence_common(form);
-	var f = fence_validator[form.fence_type.value];
-	if (!f)
+	var form_xml = '';
+
+	var form = div_elem.getElementsByTagName('form');
+	for (var i = 0 ; i < form.length ; i++) {
+		var err = null;
+		if (form[i].fence_instance)
+			err = validate_fence_instance(form[i]);
+		else if (form[i].fence_type)
+			err = validate_fence(form[i]);
+		if (err)
+			errors = errors.concat(err);
+		var input_elem = form[i].getElementsByTagName('input');
+		var temp = '';
+		for (var j = 0 ; j < input_elem.length ; j++) {
+			var res_type = input_elem[j].type;
+			if (res_type == 'hidden' || res_type == 'text' ||
+				res_type == 'password')
+			{
+				temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" value="' + input_elem[j].value + '" />';
+			} else if (res_type == 'checkbox' || res_type == 'radio') {
+				if (input_elem[j].checked) {
+					temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '"';
+					if (res_type == 'checkbox')
+						temp += ' value="1"';
+					else if (res_type == 'radio')
+						temp += ' value="' + input_elem[j].value + '"';
+					temp += ' />';
+				} else if (res_type == 'checkbox') {
+					temp += '<input type="' + res_type + '" name="' + input_elem[j].name + '" value="0" />';
+				}
+			}
+		}
+
+		var select_elem = form[i].getElementsByTagName('select');
+		for (var j = 0 ; j < select_elem.length ; j++) {
+			temp += '<input type="text" name="' + select_elem[j].name + '" value="' + select_elem[j].options[select_elem[j].options.selectedIndex].value + '" />';
+		}
+
+		form_xml += '<form id="' + form[i].getAttribute('name') + '">' + temp + '</form>';
+	}
+
+	master_form.fence_xml.value = '<formlist>' + form_xml + '</formlist>';
+
+	if (error_dialog(errors))
 		return (-1);
-	var err = f(form);
-	if (err)
-		errors = errors.concat(err);
-	return (errors);
+
+	if (confirm('Update this node\'s fence configuration?'))
+		master_form.submit();
 }
--- conga/luci/homebase/form-macros	2007/01/04 00:22:13	1.44.2.7
+++ conga/luci/homebase/form-macros	2007/03/01 00:31:08	1.44.2.8
@@ -199,13 +199,15 @@
 		<span tal:condition="python:perms" tal:content="string:Select a User" /><br/>
 
 		<select tal:omit-tag="python: not perms" class="homebase" name="userList" onChange="document.location = this.form.baseURL.value + '&user=' + this.form.userList.options[this.form.userList.selectedIndex].text">
-			<tal:block tal:repeat="user python:perms">
+			<tal:block tal:define="userlist python: perms.keys().sort()">
+			<tal:block tal:repeat="user userlist">
 				<option class="homebase"
 					tal:content="python:user"
 					tal:attributes="value python:user;
 									selected python:user == curUser"
 				/>
 			</tal:block>
+			</tal:block>
 		</select>
 
 		<h3 class="homebase" tal:condition="python:systems[0] and len(systems[0]) > 0">
@@ -221,7 +223,7 @@
 					tal:define="global num_clusters python:num_clusters + 1"
 					tal:attributes="
 						checked python:perms[curUser]['cluster'][c] and 'checked' or None;
-						name python:'__CLUSTER:' + cfname;
+						name python:'__CLUSTER:X___' + cfname;
 						id python:'__CLUSTER' + str(num_clusters);
 						value python: c"
 				/>
@@ -237,7 +239,7 @@
 					tal:define="global num_systems python:num_systems + 1"
 					tal:attributes="
 						checked python:perms[curUser]['storage'][s] and 'checked' or None;
-						name python:'__SYSTEM:' + here.strFilter('[^0-9A-Za-z_-]', '_', s);
+						name python:'__SYSTEM:X___' + here.strFilter('[^0-9A-Za-z_-]', '_', s);
 						id python:'__SYSTEM' + str(num_systems);
 						value python:s"
 				/>
@@ -293,9 +295,11 @@
 
 	<h2 class="homebase">Manage Systems and Clusters</h2>
 
-	<h3>Reauthenticate to Storage or Cluster Systems</h3>
 
-	<form name="authform" method="post" action="">
+	<form name="authform" method="post" action="" class="form_border">
+		<fieldset>
+			<legend>Reauthenticate</legend>
+		<h3>Reauthenticate to Storage or Cluster Systems</h3><br/>
 		<table id="systemsTable" class="systemsTable" border="0" cellspacing="0"
 			tal:define="
 				new_systems request/SESSION/auth_systems | nothing;
@@ -369,7 +373,7 @@
 								tal:attributes="
 									id python: '__SYSTEM%d:Passwd' % cur_sysnum;
 									name python: '__SYSTEM%d:Passwd' % cur_sysnum;
-									value sys/passwd | nothing" />
+									value nothing" />
 						</td>
 						<td class="systemsTable">
 							<img 
@@ -409,7 +413,10 @@
 			<tfoot class="systemsTable">
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<ul class="vanilla">
-						<li class="vanilla"><input name="check_certs" type="checkbox">View system certificates before sending any passwords.</li>
+						<li class="vanilla">
+							<input name="check_certs" id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)"
+								type="checkbox">View system certificates before sending any passwords.</li>
 						<li class="vanilla"
 							tal:attributes="id python: cur_sysnum < 2 and 'allSameDiv' or ''">
 							<input type="checkbox" name="allSameCheckBox"
@@ -467,6 +474,7 @@
 				tal:define="x python: request.SESSION.delete('auth_status')" />
 			<div class="padding">&nbsp;</div>
 		</tal:block>
+	</fieldset>
 	</form>
 
 	<tal:block tal:define="
@@ -475,8 +483,10 @@
 		global num_clusters python:-1;
 		global num_systems python:-1" />
 
-	<form name="adminform" method="post" action=""
+	<form name="adminform" method="post" class="form_border" action=""
 		tal:condition="python:(systems[0] and len(systems[0]) > 0) or (systems[1] and len(systems[1]) > 0)">
+	<fieldset>
+		<legend>Remove clusters and systems</legend>
 
 		<tal:block tal:define="global blankForm python:0" />
 
@@ -497,13 +507,13 @@
 				<input type="checkbox" class="homebase"
 					tal:define="global num_clusters python:num_clusters + 1"
 					tal:attributes="
-						name python:'__CLUSTER:' + cfname;
+						name python:'__CLUSTER:X___' + cfname;
 						id python:'__CLUSTER' + str(num_clusters);
 						value python: c"
 				/>
 				<input type="hidden" value=""
 					tal:attributes="
-						name python:'__CLUSTER:' + cfname"
+						name python:'__CLUSTER:X___' + cfname"
 				/>
 				<span tal:omit-tag="" tal:content="python:c" />
 			</div>
@@ -518,13 +528,13 @@
 					<input type="checkbox" class="homebase"
 						tal:define="global num_systems python:num_systems + 1"
 						tal:attributes="
-							name python:'__SYSTEM:' + sfname;
+							name python:'__SYSTEM:X___' + sfname;
 							id python:'__SYSTEM' + str(num_systems);
 							value python:s"
 					/>
 
 					<input type="hidden" value=""
-						tal:attributes="name python:'__SYSTEM:' + sfname" />
+						tal:attributes="name python:'__SYSTEM:X___' + sfname" />
 					<span class="hbText" tal:omit-tag="" tal:content="python:s"/>
 				</div>
 			</tal:block>
@@ -540,6 +550,7 @@
 			<input type="button" name="Submit" value="Remove selected entries"
 				onClick="validateForm(this.form)" />
 		</div>
+	</fieldset>
 	</form>
 
 	<div tal:condition="python: blankForm">
@@ -658,7 +669,7 @@
 								tal:attributes="
 									id python: '__SYSTEM%d:Passwd' % cur_sysnum;
 									name python: '__SYSTEM%d:Passwd' % cur_sysnum;
-									value sys/passwd | nothing" />
+									value nothing" />
 									
 						</td>
 						<td class="systemsTable">
@@ -699,7 +710,10 @@
 			<tfoot class="systemsTable">
 				<tr class="systemsTable"><td colspan="2" class="systemsTable">
 					<ul class="vanilla">
-						<li class="vanilla"><input name="check_certs" type="checkbox">View system certificates before sending any passwords.</li>
+						<li class="vanilla">
+							<input name="check_certs" id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)"
+								type="checkbox">View system certificates before sending any passwords.</li>
 						<li class="vanilla"
 							tal:attributes="id python: cur_sysnum < 2 and 'allSameDiv' or ''"><input type="checkbox" name="allSameCheckBox" id="allSameCheckBox" onClick="allPasswdsSame(this.form);"/>Check if storage system passwords are identical.</li>
 					</ul>
@@ -796,7 +810,8 @@
 					<ul class="vanilla">
 						<li class="vanilla">
 							<input name="check_certs" type="checkbox"
-								tal:attributes="checked python: add_cluster['check_certs'] and 'checked'" />
+								id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)" />
 							View system certificates before sending any passwords.
 						</li>
 						<li class="vanilla" id="allSameDiv">
@@ -840,7 +855,7 @@
 								autocomplete="off"
 								onChange="pwd0Change(this.form)"
 								tal:attributes="
-									value sys/passwd | nothing;
+									value nothing;
 									class python: 'hbInputPass' + ('errors' in sys and ' error' or '');
 									id python: '__SYSTEM%d:Passwd' % cur_sysnum;
 									name python: '__SYSTEM%d:Passwd' % cur_sysnum" />
@@ -948,8 +963,11 @@
 						tal:condition="cur_sys" />
 
 					<ul class="vanilla">
-						<li class="vanilla"><input name="check_certs" type="checkbox">View system certificates before sending any passwords.</li>
-						<li class="vanilla"><input type="checkbox" name="allSameCheckBox" id="allSameCheckBox" onClick="allPasswdsSame(this.form);"/>Authenticate to all cluster nodes using the password provided above.</li>
+						<li class="vanilla">
+							<input name="check_certs" id="view_certs"
+								onchange="view_certs_only(this.form, this.checked)"
+								type="checkbox">View system certificates before sending any passwords.
+						</li>
 					</ul>
 				</td></tr>
 			</tfoot>
@@ -968,7 +986,7 @@
 							autocomplete="off"
 							id="__SYSTEM0:Passwd" name="__SYSTEM0:Passwd"
 							tal:attributes="
-								value cur_sys/passwd | nothing" />
+								value nothing" />
 					</td>
 					<tal:block tal:condition="cur_sys">
 						<td class="systemsTable">
--- conga/luci/homebase/homebase_common.js	2006/12/22 17:50:16	1.13.2.2
+++ conga/luci/homebase/homebase_common.js	2007/03/01 00:31:08	1.13.2.3
@@ -5,7 +5,7 @@
 
 function clr_form_err(ielem) {
 	if (ielem)
-		ielem.className = ielem.className.replace(/ formerror/, '');
+		ielem.className = ielem.className.replace(/( )?formerror/, '');
 }
 
 function toggle_visible(img_obj, elem_id, label_id) {
@@ -132,6 +132,26 @@
 	return (null);
 }
 
+function view_certs_only(form, state) {
+	var num_systems = form.numStorage.value;
+	if (!form.numStorage)
+		return (-1);
+
+	if (state) {
+		var cb = document.getElementById('allSameCheckBox');
+		if (cb && cb.checked)
+			cb.checked = false;
+	}
+
+	for (var i = 0 ; i < num_systems ; i++) {
+		var passwd = document.getElementById('__SYSTEM' + i + ':Passwd');
+		if (passwd) {
+			passwd.value = "";
+			passwd.disabled = state;
+		}
+	}
+}
+
 function allPasswdsSame(form) {
 	var cb = document.getElementById('allSameCheckBox');
 	if (!cb)
@@ -252,6 +272,12 @@
 	var added_storage = new Array();
 	var num_systems = form.numStorage.value;
 
+	var view_certs = document.getElementById('view_certs');
+	if (view_certs)
+		view_certs = view_certs.checked;
+	else
+		view_certs = false;
+
 	for (var i = 0 ; i < num_systems ; i++) {
 		var element = document.getElementById('__SYSTEM' + i + ':Addr');
 
@@ -260,18 +286,31 @@
 		element.disabled = false;
 
 		var pwdElem = document.getElementById('__SYSTEM' + i + ':Passwd');
-		if (!element.value) {
-			if (pwdElem.value) {
+		if (!element.value || str_is_blank(element.value)) {
+			if (pwdElem && pwdElem.value && !str_is_blank(pwdElem.value)) {
 				set_form_err(element);
-				if (!allSameCB.checked) {
+				if (!allSameCB || !allSameCB.checked) {
 					errors.push('You entered a password, but no hostname for system ' + (i + 1));
 					clr_form_err(pwdElem);
 				} else
 					pwdElem.value = '';
 			}
-			clr_form_err(pwdElem);
+			if (pwdElem)
+				clr_form_err(pwdElem);
+			continue;
+		}
+
+		if (view_certs) {
+			if (pwdElem) {
+				pwdElem.value = ' ';
+				pwdElem.disabled = false;
+			}
+			added_storage.push(element.value);
+			clr_form_err(element);
 			continue;
-		} else if (!pwdElem || !pwdElem.value) {
+		}
+
+		if (!pwdElem || !pwdElem.value) {
 			errors.push('No password was given for \"' + element.value + '\"');
 			set_form_err(pwdElem);
 		} else if (str_is_blank(pwdElem.value)) {
--- conga/luci/homebase/luci_homebase.css	2007/01/10 22:53:56	1.28.2.4
+++ conga/luci/homebase/luci_homebase.css	2007/03/01 00:31:08	1.28.2.5
@@ -18,6 +18,14 @@
 	margin-left: +.3333em;
 }
 
+td.pad_right {
+	padding-right: +.6666em;
+}
+
+form.form_border {
+	border-bottom: 1px solid #8cacbb;
+}
+
 div.fence {
 	max-width: 700px;
 	padding: .5em;
@@ -281,7 +289,7 @@
 	display: none;
 }
 
-input.hbInputSys {
+input.hbInputSys, input.hostname {
 	padding: .2em ! important;
 	width: 200px;
 }
@@ -328,13 +336,11 @@
 strong.cluster {
 	text-align: top;
 	font-size: 9pt;
-	letter-spacing: +.5px;
 }
 
 *.reshdr {
 	text-align: top;
-	font-size: 9pt;
-	letter-spacing: +.5px;
+	font-size: 10pt;
 	font-weight: 600;
 	padding-bottom: +1em;
 }
@@ -343,7 +349,6 @@
 strong.node_name,
 strong.cluster_name {
 	font-size: 10pt;
-	letter-spacing: +.5px;
 }
 
 td.service_name,
@@ -407,6 +412,10 @@
 	text-decoration: none ! important;
 }
 
+*.cluster_help:hover {
+	cursor: help;
+}
+
 a.cluster_help:hover {
 	text-decoration: none ! important;
 	cursor: help;
@@ -490,7 +499,7 @@
 	max-width: 700px;
 }
 
-div.rescfg {
+*.rescfg {
 	background: #dee7ec;
 }
 
--- conga/luci/homebase/validate_cluster_add.js	2006/12/11 23:58:00	1.4.2.1
+++ conga/luci/homebase/validate_cluster_add.js	2007/03/01 00:31:08	1.4.2.2
@@ -10,12 +10,17 @@
 		set_form_err(form.clusterName);
 	} else {
 		clusterName = clusterName.value;
-		var invalid_chars = str_is_valid(clusterName, '/[0-9A-Za-z_. -]/g');
-		if (invalid_chars) {
-			errors.push('The cluster name you gave contains the following invalid characters: "' + invalid_chars + '".');
+		if (clusterName.length > 15) {
+			errors.push('A cluster\'s name must be less than 16 characters long.');
 			set_form_err(form.clusterName);
-		} else
-			clr_form_err(form.clusterName);
+		} else {
+			var invalid_chars = str_is_valid(clusterName, '/[0-9A-Za-z_. -]/g');
+			if (invalid_chars) {
+				errors.push('The cluster name you gave contains the following invalid characters: "' + invalid_chars + '".');
+				set_form_err(form.clusterName);
+			} else
+				clr_form_err(form.clusterName);
+		}
 	}
 
 	var added_storage = validate_systems(form, errors);
@@ -29,13 +34,17 @@
 	if (error_dialog(errors))
 		return (-1);
 
-	var confirm_str = '';
-	if (form.addnode)
-		confirm_str = 'Add node' + (added_storage.length > 1 ? 's' : '') + ' to the \"' + clusterName + '\" cluster?';
-	else
-		confirm_str = 'Add the cluster \"' + clusterName + '\" to the Luci management interface?';
-
-	if (confirm(confirm_str))
+	var view_certs = document.getElementById('view_certs');
+	if (!view_certs || !view_certs.checked) {
+		var confirm_str = '';
+		if (form.addnode)
+			confirm_str = 'Add ' + (added_storage.length > 1 ? 'these nodes' : 'this node') + ' to the \"' + clusterName + '\" cluster?';
+		else
+			confirm_str = 'Add the cluster \"' + clusterName + '\" to the Luci management interface?';
+
+		if (confirm(confirm_str))
+			form.submit();
+	} else
 		form.submit();
 
 	return (0);
/cvs/cluster/conga/luci/site/luci/Extensions/Apache.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/site/luci/Extensions/Apache.py
+++ -	2007-03-01 00:31:24.542359000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "apache"
+RESOURCE_TYPE = _("Apache Server")
+
+class Apache(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/FenceXVMd.py,v  -->  standard output
revision 1.1.4.1
--- conga/luci/site/luci/Extensions/FenceXVMd.py
+++ -	2007-03-01 00:31:24.653224000 +0000
@@ -0,0 +1,14 @@
+import string
+from TagObject import TagObject
+
+TAG_NAME = "fence_xvmd"
+
+class FenceXVMd(TagObject):
+  def __init__(self):
+    TagObject.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    #Have autostart set by default
+
+  def getProperties(self):
+    stringbuf = ""
+    return stringbuf
/cvs/cluster/conga/luci/site/luci/Extensions/LVM.py,v  -->  standard output
revision 1.1.4.1
--- conga/luci/site/luci/Extensions/LVM.py
+++ -	2007-03-01 00:31:24.736506000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "lvm"
+RESOURCE_TYPE = _("LVM")
+
+class LVM(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/MySQL.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/site/luci/Extensions/MySQL.py
+++ -	2007-03-01 00:31:24.814177000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "mysql"
+RESOURCE_TYPE = _("MySQL Server")
+
+class MySQL(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/OpenLDAP.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/site/luci/Extensions/OpenLDAP.py
+++ -	2007-03-01 00:31:24.896526000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "openldap"
+RESOURCE_TYPE = _("Open LDAP Server")
+
+class OpenLDAP(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/Postgres8.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/site/luci/Extensions/Postgres8.py
+++ -	2007-03-01 00:31:24.976393000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "postgres-8"
+RESOURCE_TYPE = _("PostgreSQL 8 Server")
+
+class Postgres8(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/Tomcat5.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/site/luci/Extensions/Tomcat5.py
+++ -	2007-03-01 00:31:25.056957000 +0000
@@ -0,0 +1,15 @@
+import string
+from TagObject import TagObject
+from BaseResource import BaseResource
+
+import gettext
+_ = gettext.gettext
+
+TAG_NAME = "tomcat-5"
+RESOURCE_TYPE = _("Tomcat 5 Server")
+
+class Tomcat5(BaseResource):
+  def __init__(self):
+    BaseResource.__init__(self)
+    self.TAG_NAME = TAG_NAME
+    self.resource_type = RESOURCE_TYPE
/cvs/cluster/conga/luci/site/luci/Extensions/Totem.py,v  -->  standard output
revision 1.1.4.1
--- conga/luci/site/luci/Extensions/Totem.py
+++ -	2007-03-01 00:31:25.133529000 +0000
@@ -0,0 +1,9 @@
+import string
+from TagObject import TagObject
+
+TAG_NAME = "totem"
+
+class Totem(TagObject):
+  def __init__(self):
+    TagObject.__init__(self)
+    self.TAG_NAME = TAG_NAME 
--- conga/luci/site/luci/Extensions/Cluster.py	2006/10/16 20:46:55	1.4
+++ conga/luci/site/luci/Extensions/Cluster.py	2007/03/01 00:31:08	1.4.2.1
@@ -8,7 +8,7 @@
 ACTUAL_CLUSTER_NAME_DESC = "The Actual Cluster Name should be used for storage configuration, such as making a clustered file system"
 CLUSTER_POPULATION = "Number of Members: %d"
 DLM_TYPE = "Locking Type: Distributed"
-GULM_TYPE = "Locking Type: GuLM"
+GULM_TYPE = "Locking Type: GULM"
 LOCKSERVER = "Lock Server:"
 CONFIG_VERSION = "Config Version"
 MCAST_MODE = "Cluster Manager using Multicast Mode. \n   Multicast Address: %s"
--- conga/luci/site/luci/Extensions/Clusterfs.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/Clusterfs.py	2007/03/01 00:31:08	1.1.2.1
@@ -6,7 +6,7 @@
 _ = gettext.gettext
 
 TAG_NAME = "clusterfs"
-RESOURCE_TYPE = _("GFS: ")
+RESOURCE_TYPE = _("GFS")
 
 class Clusterfs(BaseResource):
   def __init__(self):
--- conga/luci/site/luci/Extensions/FailoverDomain.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/FailoverDomain.py	2007/03/01 00:31:08	1.1.2.1
@@ -22,7 +22,7 @@
   def getProperties(self):
     stringbuf = ""
     restricted_status = ""
-    ordereded_status = ""
+    ordered_status = ""
     string_restricted = ""
     string_ordered = ""
     string_num_kin = ""
--- conga/luci/site/luci/Extensions/FenceHandler.py	2007/01/15 18:21:50	1.4.2.3
+++ conga/luci/site/luci/Extensions/FenceHandler.py	2007/03/01 00:31:08	1.4.2.4
@@ -1,1562 +1,1138 @@
-import os
-from ValidationError import ValidationError
-import MessageLibrary
-import ModelBuilder
-#from FenceDevice import FenceDevice
+import re
+from Device import Device
 from conga_constants import FD_VAL_SUCCESS, FD_VAL_FAIL
 
-INSTALLDIR="/usr/share/system-config-cluster"
+FD_NEW_SUCCESS = 'New %s successfully added to cluster'
+FD_UPDATE_SUCCESS = 'Fence device %s successfully updated'
+FD_NEW_FAIL = 'No agent type %s in shared device list'
+
+FI_NEW_FAIL = 'No instance type %s in fence instance list'
+
+FD_PROVIDE_AGENT = 'A valid agent type must be provided for each Fence Device'
+FD_PROVIDE_NAME = 'A unique name must be provided for each Fence Device'
+FD_PROVIDE_PATH = 'An xCAT path must be provided for each xCAT Fence Device'
+FD_PROVIDE_SERVER = 'A server address must be provided for this Fence Device'
+FD_PROVIDE_CSERVER = 'A cserver address must be provided for this Egenera Fence Device'
+FD_PROVIDE_IP = 'An IP address must be provided for this Fence Device'
+FD_PROVIDE_HOSTNAME = 'A host name must be provided for this Fence Device'
+FD_PROVIDE_LOGIN = 'A login name must be provided for this Fence Device'
+FD_PROVIDE_PASSWD = 'A password must be provided for this Fence Device'
+FD_PROVIDE_DEVICE = 'A device must be provided for this Fence Device'
+FD_PROVIDE_PORT = 'A port must be provided for this Fence Device'
+FD_PROVIDE_IPMILAN_AUTH = 'Authentication type must be "none" (or blank), "md5", or "password"'
+
+FI_PROVIDE_PARENT = 'A Fence Device name must be provided for this Fence'
+FI_PROVIDE_SWITCH = 'A switch address must be provided for this Fence'
+FI_PROVIDE_PORT = 'A port value must be provided for this Fence'
+FI_PROVIDE_BLADE = 'A Blade must be specified for this Fence'
+FI_PROVIDE_DOMAIN = 'A Domain must be specified for this Fence'
+FI_PROVIDE_IPADDRESS = 'An IP address must be provided for this Fence'
+FI_PROVIDE_ELPAN = 'A LPAN value must be provided for this Egenera Fence'
+FI_PROVIDE_EPSERVER = 'A PServer value must be provided for this Egenera Fence'
+FI_PROVIDE_NODENAME = 'A Node Name value must be provided for this SCSI Fence'
+
+ILLEGAL_CHARS_REPLACED = 'Illegal characters were replaced by underscores. Feel free to set a new value.'
+
+# For every new fence added, there will be a fence instance and fence device
+# form needed. There will also be a populate and a validate method for each
+# form. The methods will need to be added to this file, and the four hash
+# tables (self.fi_populate, self.fi_validate, self.fd_populate,
+# self.fd_validate) must be updated. The methods will use fields in the
+# forms to set_text and to check.
+
+FENCE_OPTS = {
+	'fence_apc':			'APC Power Device',
+	'fence_wti':			'WTI Power Device',
+	'fence_brocade':		'Brocade Switch',
+	'fence_vixel':			'Vixel SAN Switch',
+	'fence_gnbd':			'Global Network Block Device',
+	'fence_sanbox2':		'QLogic SANBox2',
+	'fence_bladecenter':	'IBM Blade Center',
+	'fence_mcdata':			'McDATA SAN Switch',
+	'fence_egenera':		'Egenera SAN Controller',
+	'fence_bullpap':		'Bull PAP',
+	'fence_xvm':			'Virtual Machine Fencing',
+	'fence_scsi':			'SCSI Reservation',
+	'fence_ilo':			'HP ILO Device',
+	'fence_ipmilan':		'IPMI Lan',
+	'fence_drac':			'Dell DRAC',
+	'fence_rsa':			'IBM RSA II Device',
+	'fence_rps10':			'RPS10 Serial Switch',
+	'fence_manual':			'Manual Fencing'
+}
+
+FENCE_SHARED = {
+	'fence_apc':			True,
+	'fence_wti':			True,
+	'fence_brocade':		True,
+	'fence_vixel':			True,
+	'fence_gnbd':			True,
+	'fence_sanbox2':		True,
+	'fence_bladecenter':	True,
+	'fence_mcdata':			True,
+	'fence_egenera':		True,
+	'fence_bullpap':		True,
+	'fence_xvm':			True,
+	'fence_scsi':			True,
+	'fence_ilo':			False,
+	'fence_ipmilan':		False,
+	'fence_drac':			False,
+	'fence_rsa':			False,
+	'fence_rps10':			False,
+	'fence_manual':			False
+}
+
+PRETTY_NAME_ATTRS = {
+	'port':					'Port',
+	'blade':				'Blade',
+	'switch':				'Switch',
+	'ipaddr':				'IP Address',
+	'ipaddress':			'IP Address',
+	'nodename':				'Node Name',
+	'lpan':					'LPAN',
+	'lanplus':				'Lanplus',
+	'pserver':				'PServer',
+	'login':				'Login',
+	'passwd':				'Password',
+	'name':					'Name',
+	'server':				'Server',
+	'domain':				'Domain',
+	'hostname':				'Hostname',
+	'path':					'Path',
+	'cserver':				'CServer'
+}
+
+FENCE_FI_ATTRS = {
+	'fence_apc':			['port', 'switch'],
+	'fence_wti':			['port'],
+	'fence_brocade':		['port'],
+	'fence_vixel':			['port'],
+	'fence_gnbd':			['ipaddress'],
+	'fence_sanbox2':		['port'],
+	'fence_bladecenter':	['blade'],
+	'fence_mcdata':			['port'],
+	'fence_egenera':		['lpan', 'pserver'],
+	'fence_bullpap':		['domain'],
+	'fence_xvm':			['domain'],
+	'fence_scsi':			['nodename'],
+	'fence_ilo':			[],
+	'fence_ipmilan':		[],
+	'fence_drac':			[],
+	'fence_rsa':			[],
+	'fence_rps10':			[],
+	'fence_manual':			[]
+}
+
+FENCE_FD_ATTRS = {
+	'fence_apc': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_wti': ['name', 'ipaddr', 'passwd'],
+	'fence_brocade': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_vixel': ['name', 'ipaddr', 'passwd'],
+	'fence_gnbd': ['name', 'servers'],
+	'fence_sanbox2': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_bladecenter': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_mcdata': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_egenera': ['name', 'cserver'],
+	'fence_bullpap': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_xvm': ['name'],
+	'fence_scsi': ['name'],
+	'fence_ilo': ['name', 'hostname', 'login', 'passwd'],
+	'fence_ipmilan': ['name', 'ipaddr', 'login', 'passwd', 'lanplus', 'auth'],
+	'fence_drac': ['name', 'ipaddr', 'login', 'passwd'],
+	'fence_rsa': ['name', 'hostname', 'login', 'passwd'],
+	'fence_rps10': ['name', 'device', 'port'],
+	'fence_manual': ['name']
+}
+
+ILLEGAL_CHARS = re.compile(':| ')
+
+def makeNCName(name):
+	### name must conform to relaxNG ID type ##
+	return ILLEGAL_CHARS.sub('_', name)
+
+def check_unique_fd_name(model, name):
+	fds = model.getFenceDevices()
+	for fd in fds:
+		if fd.getName() == name:
+			return False
+	return True
+
+def validateNewFenceDevice(form, model):
+	from FenceDevice import FenceDevice
+	fencedev = FenceDevice()
+
+	try:
+		ret = validate_fencedevice(form, model, fencedev)
+		if len(ret) < 1:
+			fencedevptr = model.getFenceDevicePtr()
+			fencedevptr.addChild(fencedev)
+			model.setModified(True)
+			return (FD_VAL_SUCCESS, fencedev.getAttribute('name'))
+	except Exception, e:
+		ret = [ FD_PROVIDE_AGENT ]
+
+	return (FD_VAL_FAIL, ret)
+
+def validateFenceDevice(form, model):
+	from FenceDevice import FenceDevice
+	try:
+		old_fence_name = form['orig_name'].strip()
+		if not old_fence_name:
+			raise Exception, 'blank'
+	except Exception, e:
+		return (FD_VAL_FAIL, [ FD_PROVIDE_NAME ])
+
+	fencedev = None
+	try:
+		fencedevs = model.getFenceDevices()
+		for fd in fencedevs:
+			if fd.getName().strip() == old_fence_name:
+				fencedev = fd
+				break
+		if fencedev is None:
+			raise Exception, 'fencedev is None'
+	except Exception, e:
+		return (FD_VAL_FAIL, [ FD_PROVIDE_NAME ])
+
+	try:
+		ret = validate_fencedevice(form, model, fencedev, fence_edit=True)
+		if len(ret) < 1:
+			model.setModified(True)
+			return (FD_VAL_SUCCESS, fencedev.getAttribute('name'))
+	except Exception, e:
+		ret = [ FD_PROVIDE_NAME ]
+
+	return (FD_VAL_FAIL, ret)
+
+def val_apc_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_wti_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	return errors
+
+def val_brocade_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_vixel_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	return errors
+
+def val_mcdata_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_gnbd_fd(form, fencedev):
+	errors = list()
+
+	try:
+		server = form['servers'].strip()
+		if not server:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_SERVER)
+
+	fencedev.addAttribute('servers', server)
+	return errors
+
+def val_egenera_fd(form, fencedev):
+	errors = list()
+
+	try:
+		cserver = form['cserver'].strip()
+		if not cserver:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_CSERVER)
+
+	fencedev.addAttribute('cserver', cserver)
+	return errors
+
+def val_sanbox2_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_bladecenter_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_bullpap_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_noop_fd(dummy, _dummy):
+	return []
+
+# non-shared devices
+
+def val_rsa_fd(form, fencedev):
+	errors = list()
+
+	try:
+		hostname = form['hostname'].strip()
+		if not hostname:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_HOSTNAME)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('hostname', hostname)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_drac_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_rps10_fd(form, fencedev):
+	errors = list()
+
+	try:
+		device = form['device'].strip()
+		if not device:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_DEVICE)
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_PORT)
+
+	fencedev.addAttribute('device', device)
+	fencedev.addAttribute('port', port)
+	return errors
+
+def val_ipmilan_fd(form, fencedev):
+	errors = list()
+
+	try:
+		ip = form['ipaddr'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_IP)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	try:
+		auth_type = form['auth_type'].strip().lower()
+		if not auth_type or auth_type == 'none':
+			fencedev.removeAttribute('auth_type')
+		elif auth_type == 'password' or auth_type == 'md5':
+			fencedev.setAttribute('auth_type', auth_type)
+		else:
+			errors.append(FD_PROVIDE_IPMILAN_AUTH)
+	except KeyError, e:
+		fencedev.removeAttribute('auth_type')
+	except Exception, e:
+		errors.append(FD_PROVIDE_IPMILAN_AUTH)
+
+	try:
+		lanplus = form['lanplus'].strip().lower()
+		if not lanplus or lanplus == '0' or lanplus == 'false' or lanplus == 'off':
+			fencedev.removeAttribute('lanplus')
+		else:
+			fencedev.setAttribute('lanplus', '1')
+	except Exception, e:
+		fencedev.removeAttribute('lanplus')
+
+	fencedev.addAttribute('ipaddr', ip)
+	fencedev.addAttribute('login', log)
+	return errors
+
+def val_ilo_fd(form, fencedev):
+	errors = list()
+
+	try:
+		hostname = form['hostname'].strip()
+		if not hostname:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_HOSTNAME)
+
+	try:
+		log = form['login'].strip()
+		if not log:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FD_PROVIDE_LOGIN)
+
+	has_passwd = False
+	try:
+		pwd = form['passwd'].strip()
+		if not pwd:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd', pwd)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd')
+		except:
+			pass
+
+	try:
+		pwd_script = form['passwd_script'].strip()
+		if not pwd_script:
+			raise Exception, 'blank'
+		fencedev.addAttribute('passwd_script', pwd_script)
+		has_passwd = True
+	except Exception, e:
+		try:
+			fencedev.removeAttribute('passwd_script')
+		except:
+			pass
+
+	if not has_passwd:
+		errors.append(FD_PROVIDE_PASSWD)
+
+	fencedev.addAttribute('hostname', hostname)
+	fencedev.addAttribute('login', log)
+	return errors
+
+FD_VALIDATE = {
+	'fence_apc':			val_apc_fd,
+	'fence_wti':			val_wti_fd,
+	'fence_brocade':		val_brocade_fd,
+	'fence_vixel':			val_vixel_fd,
+	'fence_gnbd':			val_gnbd_fd,
+	'fence_sanbox2':		val_sanbox2_fd,
+	'fence_bladecenter':	val_bladecenter_fd,
+	'fence_mcdata':			val_mcdata_fd,
+	'fence_egenera':		val_egenera_fd,
+	'fence_bullpap':		val_bullpap_fd,
+	'fence_xvm':			val_noop_fd,
+	'fence_scsi':			val_noop_fd,
+	'fence_ilo':			val_ilo_fd,
+	'fence_ipmilan':		val_ipmilan_fd,
+	'fence_drac':			val_drac_fd,
+	'fence_rsa':			val_rsa_fd,
+	'fence_rps10':			val_rps10_fd,
+	'fence_manual':			val_noop_fd
+}
+
+def validate_fencedevice(form, model, fencedev, fence_edit=False):
+	try:
+		fence_name = form['name'].strip()
+		if not fence_name:
+			raise Exception, 'blank'
+		fence_name = makeNCName(fence_name)
+	except Exception, e:
+		return [ FD_PROVIDE_NAME ]
+
+	name_change = False
+	if fence_edit is True:
+		try:
+			old_fence_name = form['orig_name'].strip()
+			if not old_fence_name:
+				raise Exception, 'blank'
+		except Exception, e:
+			return [ FD_PROVIDE_NAME ]
+		if old_fence_name != fence_name:
+			if check_unique_fd_name(model, fence_name) is False:
+				return [ FD_PROVIDE_NAME ]
+			name_change = True
+	else:
+		if check_unique_fd_name(model, fence_name) is False:
+			return [ FD_PROVIDE_NAME ]
+
+	try:
+		fence_agent = form['fence_type'].strip()
+		if not fence_agent:
+			raise Exception, 'blank agent'
+	except Exception, e:
+		return [ FD_PROVIDE_AGENT ]
+
+	fencedev.addAttribute('name', fence_name)
+	fencedev.addAttribute('agent', fence_agent)
+
+	try:
+		ret = FD_VALIDATE[fence_agent](form, fencedev)
+		if len(ret) < 1 and name_change is True:
+			try:
+				model.rectifyNewFencedevicenameWithFences(old_fence_name, fence_name)
+			except:
+				return [ FD_NEW_FAIL % fence_agent ]
+		return ret
+	except:
+		return [ FD_NEW_FAIL % fence_agent ]
+
+# Validation Methods for Fence Instances
+
+def val_apc_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	try:
+		switch = form['switch'].strip()
+		if not switch:
+			raise KeyError, 'blank'
+		fenceinst.addAttribute('switch', switch)
+	except KeyError, e:
+		# switch is optional
+		fenceinst.removeAttribute('switch')
+	except Exception, e:
+		errors.append(FI_PROVIDE_SWITCH)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_wti_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_brocade_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_vixel_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_gnbd_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		ip = form['ipaddress'].strip()
+		if not ip:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_IPADDRESS)
+
+	fenceinst.addAttribute('ipaddress', ip)
+	return errors
+
+def val_sanbox2_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_bladecenter_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		blade = form['blade'].strip()
+		if not blade:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_BLADE)
+
+	fenceinst.addAttribute('blade', blade)
+	return errors
+
+def val_mcdata_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		port = form['port'].strip()
+		if not port:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_PORT)
+
+	fenceinst.addAttribute('port', port)
+	return errors
+
+def val_egenera_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		lpan = form['lpan'].strip()
+		if not lpan:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_ELPAN)
+
+	try:
+		pserver = form['pserver'].strip()
+		if not pserver:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_ELPAN)
+
+	fenceinst.addAttribute('lpan', lpan)
+	fenceinst.addAttribute('pserver', pserver)
+	return errors
+
+def val_bullpap_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		domain = form['domain'].strip()
+		if not domain:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_DOMAIN)
+
+	fenceinst.addAttribute('domain', domain)
+	return errors
+
+def val_xvm_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		domain = form['domain'].strip()
+		if not domain:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_DOMAIN)
+
+	fenceinst.addAttribute('domain', domain)
+	return errors
+
+def val_scsi_fi(form, fenceinst):
+	errors = list()
+
+	try:
+		nodename = form['nodename'].strip()
+		if not nodename:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append(FI_PROVIDE_NODENAME)
+
+	fenceinst.addAttribute('nodename', nodename)
+	return errors
+
+def val_noop_fi(dummy, _dummy):
+	return []
+
+FI_VALIDATE = {
+	'fence_apc':			val_apc_fi,
+	'fence_wti':			val_wti_fi,
+	'fence_brocade':		val_brocade_fi,
+	'fence_vixel':			val_vixel_fi,
+	'fence_gnbd':			val_gnbd_fi,
+	'fence_sanbox2':		val_sanbox2_fi,
+	'fence_bladecenter':	val_bladecenter_fi,
+	'fence_mcdata':			val_mcdata_fi,
+	'fence_egenera':		val_egenera_fi,
+	'fence_bullpap':		val_bullpap_fi,
+	'fence_xvm':			val_xvm_fi,
+	'fence_scsi':			val_scsi_fi,
+	'fence_ilo':			val_noop_fi,
+	'fence_ipmilan':		val_noop_fi,
+	'fence_drac':			val_noop_fi,
+	'fence_rsa':			val_noop_fi,
+	'fence_rps10':			val_noop_fi,
+	'fence_manual':			val_noop_fi
+}
+
+def validate_fenceinstance(form, parent_name, fence_agent):
+	try:
+		if not parent_name.strip():
+			return (FD_VAL_FAIL, [ FI_PROVIDE_PARENT ])
+	except:
+		return (FD_VAL_FAIL, [ FI_PROVIDE_PARENT ])
+
+	fenceinst = Device()
+	fenceinst.addAttribute('name', parent_name)
+
+	try:
+		ret = FI_VALIDATE[fence_agent](form, fenceinst)
+		if len(ret) > 0:
+			return (FD_VAL_FAIL, ret)
+	except Exception, e:
+		return (FD_VAL_FAIL, [ FI_NEW_FAIL % fence_agent ])
 
-FD_NEW_SUCCESS = "New %s successfully added to cluster"
-FD_UPDATE_SUCCESS = "Fence device %s successfully updated"
-FD_NEW_FAIL = "No agent type %s in shared device list"
-FD_PROVIDE_NAME = "A unique name must be provided for each Fence Device"
-
-FD_PROVIDE_PATH = "An xCAT path must be provided for each xCAT Fence Device"
-FD_PROVIDE_SERVER = "A server address must be provided for this Fence Device"
-FD_PROVIDE_CSERVER = "A cserver address must be provided for this Egenera Fence Device"
-FD_PROVIDE_IP = "An IP address must be provided for this Fence Device"
-FD_PROVIDE_HOSTNAME = "A host name must be provided for this Fence Device"
-FD_PROVIDE_LOGIN = "A login name must be provided for this Fence Device"
-FD_PROVIDE_PASSWD = "A password must be provided for this Fence Device"
-FI_PROVIDE_XCATNODENAME = "An xCAT Nodename must be provided for this Fence"
-FI_PROVIDE_SWITCH = "A switch address must be provided for this Fence"
-FI_PROVIDE_PORT = "A port value must be provided for this Fence"
-FI_PROVIDE_BLADE = "A Blade must be specified for this Fence"
-FI_PROVIDE_DOMAIN = "A Domain must be specified for this Fence"
-FI_PROVIDE_IPADDRESS = "An IP address must be provided for this Fence"
-FI_PROVIDE_ELPAN = "A LPAN value must be provided for this Egenera Fence"
-FI_PROVIDE_EPSERVER = "A PServer value must be provided for this Egenera Fence"
-
-ILLEGAL_CHARS_REPLACED = "Illegal characters were replaced by underscores. Feel free to set a new value."
-ILLEGAL_CHARS = [':', ' ']
-
-#ADDING A NEW FENCE: fence instance form should be named the same as its agent
-#in gladefile. Then add agent name to this list.
-#
-#In Glade File, fence device form should be added to 'fence_device_container'
-#and fence instance form to fence_instance_container
-#
-#For every new fence added, there will be a fence instance and fence device
-#form needed. There will also be a populate and a validate method for each
-#form. The methods will need to be added to this file, and the four hash
-#tables (self.fi_populate, self.fi_validate, self.fd_populate, 
-#self.fd_validate) must be updated. The methods will use fields in the
-#forms to set_text and to check.
-
-FENCE_OPTS = {"fence_apc":"APC Power Device",
-              "fence_wti":"WTI Power Device",
-              "fence_brocade":"Brocade Switch",
-              "fence_vixel":"Vixel SAN Switch",
-              "fence_gnbd":"Global Network Block Device",
-              "fence_ilo":"HP ILO Device",
-              "fence_rsa":"IBM RSA II Device",
-              "fence_sanbox2":"QLogic SANBox2",
-              "fence_bladecenter":"IBM Blade Center",
-              "fence_mcdata":"McDATA SAN Switch",
-              "fence_egenera":"Egenera SAN Controller",
-              "fence_bullpap":"Bull PAP",
-              "fence_drac":"DRAC",
-              "fence_xvm":"Virtual Machine Fencing",
-              "fence_scsi":"SCSI Reservation",
-              "fence_ipmilan":"IPMI Lan",
-              "fence_manual":"Manual Fencing" }
-
-FENCE_SHARED = {"fence_apc":True,
-              "fence_wti":True,
-              "fence_brocade":True,
-              "fence_vixel":True,
-              "fence_gnbd":True,
-              "fence_ilo":False,
-              "fence_rsa":False,
-              "fence_sanbox2":True,
-              "fence_bladecenter":True,
-              "fence_mcdata":True,
-              "fence_egenera":True,
-              "fence_bullpap":True,
-              "fence_drac":False,
-              "fence_xvm":True,
-              "fence_scsi":True,
-              "fence_ipmilan":False,
-              "fence_manual":False }
-
-FENCE_FD_ATTRS = {"fence_apc":["name","ipaddr","login","passwd"],
-              "fence_wti":["name","ipaddr","passwd"],
-              "fence_brocade":["name","ipaddr","login","passwd"],
-              "fence_vixel":["name","ipaddr","passwd"],
-              "fence_gnbd":["name","server"],
-              "fence_ilo":["name","hostname","login","passwd"],
-              "fence_sanbox2":["name","ipaddr","login","passwd"],
-              "fence_bladecenter":["name","ipaddr","login","passwd"],
-              "fence_mcdata":["name","ipaddr","login","passwd"],
-              "fence_egenera":["name","cserver"],
-              "fence_ipmilan":["name","ipaddr","login","passwd"],
-              "fence_bullpap":["name","ipaddr","login","passwd"],
-              "fence_manual":["name"] }
-
-FENCE_FI_ATTRS = {"fence_apc":["port","switch"],
-              "fence_wti":["port"],
-              "fence_brocade":["port"],
-              "fence_vixel":["port"],
-              "fence_gnbd":["ipaddress"],
-              "fence_ilo":[],
-              "fence_sanbox2":["port"],
-              "fence_bladecenter":["blade"],
-              "fence_mcdata":["port"],
-              "fence_egenera":["lpan","pserver"],
-              "fence_ipmilan":[],
-              "fence_bullpap":["domain"],
-              "fence_manual":[] }
-
-PRETTY_NAME_ATTRS = {"port":"Port",
-                     "blade":"Blade", 
-                     "switch":"Switch",
-                     "ipaddr":"IP Address",
-                     "nodename":"Nodename",
-                     "lpan":"LPAN",
-                     "pserver":"PServer",
-                     "login":"Login",
-                     "passwd":"Password",
-                     "name":"Name",
-                     "server":"Server",
-                     "domain":"Domain",
-                     "hostname":"Hostname",
-                     "path":"Path",
-                     "cserver":"CServer" }  
-
-class FenceHandler:
-  def __init__(self, fi_proxy_widget, fd_proxy_widget, model_builder):
-    self.fi_proxy_widget = fi_proxy_widget
-    self.fd_proxy_widget = fd_proxy_widget
-    self.model_builder = model_builder
-    gladepath = "fence.glade"
-    if not os.path.exists(gladepath):
-      gladepath = "%s/%s" % (INSTALLDIR,gladepath)
-                                                                                
-    #gtk.glade.bindtextdomain(PROGNAME)
-    self.fence_xml = gtk.glade.XML (gladepath, domain="NULL")
-
-    #Generate hash table for agent --> fence instance form
-    self.fi_hash = { }
-    fence_opt_keys = FENCE_OPTS.keys()
-    for fence in fence_opt_keys:
-      self.fi_hash[fence] = self.fence_xml.get_widget(fence)
-
-    #Generate hash table for agent --> fence device form
-    self.fd_hash = { }
-    fence_opt_keys = FENCE_OPTS.keys()
-    for fence in fence_opt_keys:
-      self.fd_hash[fence] = self.fence_xml.get_widget(fence + "_d")
-
-    self.pretty_agentname_hash = FENCE_OPTS
-
-    self.fi_container = self.fence_xml.get_widget('fence_instance_container')
-    children = self.fi_container.get_children()
-    for child in children:
-      child.reparent(self.fi_proxy_widget)
-    
-    self.fi_container2 = self.fence_xml.get_widget('fence_instance_container2')
-    children2 = self.fi_container2.get_children()
-    for child in children2:
-      child.reparent(self.fi_proxy_widget)
-    
-    self.fd_container = self.fence_xml.get_widget('fence_device_container')
-    children = self.fd_container.get_children()
-    for child in children:
-      child.reparent(self.fd_proxy_widget)
-    
-    self.fd_container2 = self.fence_xml.get_widget('fence_device_container2')
-    children2 = self.fd_container2.get_children()
-    for child in children2:
-      child.reparent(self.fd_proxy_widget)
-    
-    #For testing...
-    #self.fence_xml.get_widget('fi_wti').show()
-
-    self.fi_populate = {"fence_apc":self.pop_apc,
-              "fence_wti":self.pop_wti,
-              "fence_brocade":self.pop_brocade,
-              "fence_vixel":self.pop_vixel,
-              "fence_gnbd":self.pop_gnbd,
-              "fence_ilo":self.pop_ilo,
-              "fence_sanbox2":self.pop_sanbox2,
-              "fence_bladecenter":self.pop_bladecenter,
-              "fence_mcdata":self.pop_mcdata,
-              "fence_egenera":self.pop_egenera,
-              "fence_ipmilan":self.pop_ipmilan,
-              "fence_bullpap":self.pop_bullpap,
-              "fence_manual":self.pop_manual }
-
-    self.fd_populate = {"fence_apc":self.pop_apc_fd,
-              "fence_wti":self.pop_wti_fd,
-              "fence_brocade":self.pop_brocade_fd,
-              "fence_vixel":self.pop_vixel_fd,
-              "fence_gnbd":self.pop_gnbd_fd,
-              "fence_ilo":self.pop_ilo_fd,
-              "fence_sanbox2":self.pop_sanbox2_fd,
-              "fence_bladecenter":self.pop_bladecenter_fd,
-              "fence_mcdata":self.pop_mcdata_fd,
-              "fence_egenera":self.pop_egenera_fd,
-              "fence_ipmilan":self.pop_ipmilan_fd,
-              "fence_bullpap":self.pop_bullpap_fd,
-              "fence_manual":self.pop_manual_fd }
-
-    self.fi_validate = {"fence_apc":self.val_apc,
-              "fence_wti":self.val_wti,
-              "fence_brocade":self.val_brocade,
-              "fence_vixel":self.val_vixel,
-              "fence_gnbd":self.val_gnbd,
-              "fence_ilo":self.val_ilo,
-              "fence_sanbox2":self.val_sanbox2,
-              "fence_bladecenter":self.val_bladecenter,
-              "fence_mcdata":self.val_mcdata,
-              "fence_egenera":self.val_egenera,
-              "fence_ipmilan":self.val_ipmilan,
-              "fence_bullpap":self.val_bullpap,
-              "fence_manual":self.val_manual }
-
-    self.fd_validate = {"fence_apc":self.val_apc_fd,
-              "fence_wti":self.val_wti_fd,
-              "fence_brocade":self.val_brocade_fd,
-              "fence_vixel":self.val_vixel_fd,
-              "fence_gnbd":self.val_gnbd_fd,
-              "fence_ilo":self.val_ilo_fd,
-              "fence_sanbox2":self.val_sanbox2_fd,
-              "fence_bladecenter":self.val_bladecenter_fd,
-              "fence_mcdata":self.val_mcdata_fd,
-              "fence_egenera":self.val_egenera_fd,
-              "fence_ipmilan":self.val_ipmilan_fd,
-              "fence_bullpap":self.val_bullpap_fd,
-              "fence_manual":self.val_manual_fd }
-
-    self.process_widgets()
-
-  def get_fence_instance_hash(self):
-    return self.fi_hash
-
-  def get_fence_device_hash(self):
-    return self.fd_hash
-
-  def populate_fi_form(self, agent_type, *attrs):
-    apply(self.fi_populate[agent_type], attrs)
-
-  def populate_fd_form(self, agent_type, *attrs):
-    apply(self.fd_populate[agent_type], attrs)
-
-  def pop_apc(self, attrs):
-    self.apc_port.set_text(attrs["port"]) 
-    self.apc_switch.set_text(attrs["switch"]) 
- 
-  def pop_wti(self, attrs):
-    self.wti_port.set_text(attrs["port"])
- 
-  def pop_brocade(self, attrs):
-    self.brocade_port.set_text(attrs["port"])
- 
-  def pop_ilo(self, attrs):
-    pass
- 
-  def pop_vixel(self, attrs):
-    self.vixel_port.set_text(attrs["port"])
- 
-  def pop_mcdata(self, attrs):
-    self.mcdata_port.set_text(attrs["port"])
- 
-  def pop_manual(self, attrs):
-    pass
- 
-  def pop_gnbd(self, attrs):
-    self.gnbd_ip.set_text(attrs["ipaddress"])
- 
-  def pop_egenera(self, attrs):
-    self.egenera_lpan.set_text(attrs["lpan"])
-    self.egenera_pserver.set_text(attrs["pserver"])
- 
-  def pop_sanbox2(self, attrs):
-    self.sanbox2_port.set_text(attrs["port"])
-
-  def pop_bladecenter(self, attrs):
-    self.bladecenter_blade.set_text(attrs["blade"])
-
-  def pop_bullpap(self, attrs):
-    self.bullpap_domain.set_text(attrs["domain"])
-
-  def pop_ipmilan(self, attrs):
-    pass
- 
-  def clear_fi_forms(self):
-    self.apc_port.set_text("") 
-    self.apc_switch.set_text("") 
-    self.wti_port.set_text("") 
-    self.brocade_port.set_text("")
-    self.vixel_port.set_text("")
-    self.gnbd_ip.set_text("") 
-    self.sanbox2_port.set_text("")
-    self.bladecenter_blade.set_text("")
-    self.mcdata_port.set_text("")
-    self.egenera_lpan.set_text("")
-    self.egenera_pserver.set_text("")
-    self.bullpap_domain.set_text("")
-
-
-  def clear_fd_forms(self):
-    self.apc_fd_name.set_text("") 
-    self.apc_fd_ip.set_text("")
-    self.apc_fd_login.set_text("")
-    self.apc_fd_passwd.set_text("")
-    self.wti_fd_ip.set_text("")
-    self.wti_fd_name.set_text("")
-    self.wti_fd_passwd.set_text("")
-    self.brocade_fd_name.set_text("")
-    self.brocade_fd_ip.set_text("")
-    self.brocade_fd_login.set_text("")
-    self.brocade_fd_passwd.set_text("")
-    self.ilo_fd_name.set_text("")
-    self.ilo_fd_login.set_text("")
-    self.ilo_fd_passwd.set_text("")
-    self.ilo_fd_hostname.set_text("")
-    self.vixel_fd_name.set_text("")
-    self.vixel_fd_ip.set_text("")
-    self.vixel_fd_passwd.set_text("")
-    self.manual_fd_name.set_text("")
-    self.mcdata_fd_name.set_text("")
-    self.mcdata_fd_ip.set_text("")
-    self.mcdata_fd_login.set_text("")
-    self.mcdata_fd_passwd.set_text("")
-    self.gnbd_fd_name.set_text("")
-    self.gnbd_fd_server.set_text("")
-    self.egenera_fd_name.set_text("")
-    self.egenera_fd_cserver.set_text("")
-    self.sanbox2_fd_name.set_text("")
-    self.sanbox2_fd_ip.set_text("")
-    self.sanbox2_fd_login.set_text("")
-    self.sanbox2_fd_passwd.set_text("")
-    self.bladecenter_fd_name.set_text("")
-    self.bladecenter_fd_ip.set_text("")
-    self.bladecenter_fd_login.set_text("")
-    self.bladecenter_fd_passwd.set_text("")
-    self.ipmilan_fd_name.set_text("")
-    self.ipmilan_fd_login.set_text("")
-    self.ipmilan_fd_passwd.set_text("")
-    self.ipmilan_fd_ip.set_text("")
-    self.bullpap_fd_name.set_text("")
-    self.bullpap_fd_login.set_text("")
-    self.bullpap_fd_passwd.set_text("")
-    self.bullpap_fd_ip.set_text("")
-
-  #Populate form methods for Fence Devices
-  def pop_apc_fd(self, attrs):
-    self.apc_fd_name.set_text(attrs["name"]) 
-    self.apc_fd_ip.set_text(attrs["ipaddr"])
-    self.apc_fd_login.set_text(attrs["login"])
-    self.apc_fd_passwd.set_text(attrs["passwd"])
-
- 
-  def pop_wti_fd(self, attrs):
-    self.wti_fd_ip.set_text(attrs["ipaddr"])
-    self.wti_fd_name.set_text(attrs["name"])
-    self.wti_fd_passwd.set_text(attrs["passwd"])
- 
-  def pop_brocade_fd(self, attrs):
-    self.brocade_fd_name.set_text(attrs["name"])
-    self.brocade_fd_ip.set_text(attrs["ipaddr"])
-    self.brocade_fd_login.set_text(attrs["login"])
-    self.brocade_fd_passwd.set_text(attrs["passwd"])
-
- 
-  def pop_ilo_fd(self, attrs):
-    self.ilo_fd_name.set_text(attrs["name"])
-    self.ilo_fd_login.set_text(attrs["login"])
-    self.ilo_fd_passwd.set_text(attrs["passwd"])
-    self.ilo_fd_hostname.set_text(attrs["hostname"])
-
- 
-  def pop_vixel_fd(self, attrs):
-    self.vixel_fd_name.set_text(attrs["name"])
-    self.vixel_fd_ip.set_text(attrs["ipaddr"])
-    self.vixel_fd_passwd.set_text(attrs["passwd"])
-
- 
-  def pop_mcdata_fd(self, attrs):
-    self.mcdata_fd_name.set_text(attrs["name"])
-    self.mcdata_fd_ip.set_text(attrs["ipaddr"])
-    self.mcdata_fd_login.set_text(attrs["login"])
-    self.mcdata_fd_passwd.set_text(attrs["passwd"])
-
- 
-  def pop_manual_fd(self, attrs):
-    self.manual_fd_name.set_text(attrs["name"])
- 
-  def pop_gnbd_fd(self, attrs):
-    self.gnbd_fd_name.set_text(attrs["name"])
-    self.gnbd_fd_server.set_text(attrs["server"])
-
- 
-  def pop_egenera_fd(self, attrs):
-    self.egenera_fd_name.set_text(attrs["name"])
-    self.egenera_fd_cserver.set_text(attrs["cserver"])
-
- 
-  def pop_sanbox2_fd(self, attrs):
-    self.sanbox2_fd_name.set_text(attrs["name"])
-    self.sanbox2_fd_ip.set_text(attrs["ipaddr"])
-    self.sanbox2_fd_login.set_text(attrs["login"])
-    self.sanbox2_fd_passwd.set_text(attrs["passwd"])
-
-  def pop_bladecenter_fd(self, attrs):
-    self.bladecenter_fd_name.set_text(attrs["name"])
-    self.bladecenter_fd_ip.set_text(attrs["ipaddr"])
-    self.bladecenter_fd_login.set_text(attrs["login"])
-    self.bladecenter_fd_passwd.set_text(attrs["passwd"])
-
-  def pop_ipmilan_fd(self, attrs):
-    self.ipmilan_fd_name.set_text(attrs["name"])
-    self.ipmilan_fd_login.set_text(attrs["login"])
-    self.ipmilan_fd_passwd.set_text(attrs["passwd"])
-    self.ipmilan_fd_ip.set_text(attrs["ipaddr"])
-
-  def pop_bullpap_fd(self, attrs):
-    self.bullpap_fd_name.set_text(attrs["name"])
-    self.bullpap_fd_login.set_text(attrs["login"])
-    self.bullpap_fd_passwd.set_text(attrs["passwd"])
-    self.bullpap_fd_ip.set_text(attrs["ipaddr"])
-
-
-  def process_widgets(self):
-    ##Fence Instance Form Fields
-    self.apc_port = self.fence_xml.get_widget('entry1') 
-    self.apc_switch = self.fence_xml.get_widget('entry2') 
-    self.wti_port = self.fence_xml.get_widget('entry3') 
-    self.brocade_port = self.fence_xml.get_widget('entry4') 
-    self.vixel_port = self.fence_xml.get_widget('entry5') 
-    self.gnbd_ip = self.fence_xml.get_widget('entry6') 
-    self.ilo_port = self.fence_xml.get_widget('entry7') 
-    self.sanbox2_port = self.fence_xml.get_widget('entry8') 
-    self.bladecenter_blade = self.fence_xml.get_widget('entry41') 
-    self.mcdata_port = self.fence_xml.get_widget('entry9') 
-    self.egenera_lpan = self.fence_xml.get_widget('entry10') 
-    self.egenera_pserver = self.fence_xml.get_widget('entry11')
-    self.bullpap_domain = self.fence_xml.get_widget('entry51') 
-
-    ##Fence Device Forms
-    self.apc_fd_name = self.fence_xml.get_widget('entry12')
-    self.apc_fd_ip = self.fence_xml.get_widget('entry13')
-    self.apc_fd_login = self.fence_xml.get_widget('entry14')
-    self.apc_fd_passwd = self.fence_xml.get_widget('entry15')
-
-    self.wti_fd_ip = self.fence_xml.get_widget('entry17')
-    self.wti_fd_name = self.fence_xml.get_widget('entry16')
-    self.wti_fd_passwd = self.fence_xml.get_widget('entry18')
-
-    self.brocade_fd_name = self.fence_xml.get_widget('entry19')
-    self.brocade_fd_ip = self.fence_xml.get_widget('entry20')
-    self.brocade_fd_login = self.fence_xml.get_widget('entry21')
-    self.brocade_fd_passwd = self.fence_xml.get_widget('entry22')
-
-    self.vixel_fd_name = self.fence_xml.get_widget('entry23')
-    self.vixel_fd_ip = self.fence_xml.get_widget('entry24')
-    self.vixel_fd_passwd = self.fence_xml.get_widget('entry25')
-
-    self.gnbd_fd_name = self.fence_xml.get_widget('entry26')
-    self.gnbd_fd_server = self.fence_xml.get_widget('entry27')
-
-    self.ilo_fd_name = self.fence_xml.get_widget('entry28')
-    self.ilo_fd_login = self.fence_xml.get_widget('entry29')
-    self.ilo_fd_passwd = self.fence_xml.get_widget('entry30')
-    self.ilo_fd_hostname = self.fence_xml.get_widget('entry31')
-
-    self.sanbox2_fd_name = self.fence_xml.get_widget('entry32')
-    self.sanbox2_fd_ip = self.fence_xml.get_widget('entry33')
-    self.sanbox2_fd_login = self.fence_xml.get_widget('entry46')
-    self.sanbox2_fd_passwd = self.fence_xml.get_widget('entry47')
-
-    self.bladecenter_fd_name = self.fence_xml.get_widget('entry42')
-    self.bladecenter_fd_ip = self.fence_xml.get_widget('entry43')
-    self.bladecenter_fd_login = self.fence_xml.get_widget('entry44')
-    self.bladecenter_fd_passwd = self.fence_xml.get_widget('entry45')
-
-    self.mcdata_fd_name = self.fence_xml.get_widget('entry34')
-    self.mcdata_fd_ip = self.fence_xml.get_widget('entry35')
-    self.mcdata_fd_login = self.fence_xml.get_widget('entry36')
-    self.mcdata_fd_passwd = self.fence_xml.get_widget('entry37')
-
-    self.egenera_fd_name = self.fence_xml.get_widget('entry38')
-    self.egenera_fd_cserver = self.fence_xml.get_widget('entry39')
-
-    self.manual_fd_name = self.fence_xml.get_widget('entry40')
-
-    self.ipmilan_fd_name = self.fence_xml.get_widget('entry55')
-    self.ipmilan_fd_ip = self.fence_xml.get_widget('entry48')
-    self.ipmilan_fd_login = self.fence_xml.get_widget('entry49')
-    self.ipmilan_fd_passwd = self.fence_xml.get_widget('entry50')
-
-    self.bullpap_fd_name = self.fence_xml.get_widget('entry56')
-    self.bullpap_fd_ip = self.fence_xml.get_widget('entry52')
-    self.bullpap_fd_login = self.fence_xml.get_widget('entry53')
-    self.bullpap_fd_passwd = self.fence_xml.get_widget('entry54')
-
-  #####  Validation Methods
-  def validate_fencedevice(self, agent_type, name=None):
-    try:
-      args = list()
-      args.append(name)
-      returnlist = apply(self.fd_validate[agent_type], args)
-    except ValidationError, e:
-      MessageLibrary.errorMessage(e.getMessage())
-      return None
-
-    return returnlist
-
-    
-  def val_apc_fd(self, name):
-    rectify_fence_name = False
-    if self.apc_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.apc_fd_name)
-    if name != self.apc_fd_name.get_text():
-      res = self.check_unique_fd_name(self.apc_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-    
-    if self.apc_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-    if self.apc_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.apc_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.apc_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.apc_fd_name.get_text()
-    fields["ipaddr"] = self.apc_fd_ip.get_text()
-    fields["login"] = self.apc_fd_login.get_text()
-    fields["passwd"] = self.apc_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_wti_fd(self, name):
-    rectify_fence_name = False
-    if self.wti_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.wti_fd_name)
-    if name != self.wti_fd_name.get_text():
-      res = self.check_unique_fd_name(self.wti_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.wti_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-    if self.wti_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.wti_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.wti_fd_name.get_text()
-    fields["ipaddr"] = self.wti_fd_ip.get_text()
-    fields["passwd"] = self.wti_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_brocade_fd(self, name):
-    rectify_fence_name = False
-    if self.brocade_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.brocade_fd_name)
-    if name != self.brocade_fd_name.get_text():
-      res = self.check_unique_fd_name(self.brocade_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.brocade_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-    if self.brocade_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.brocade_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.brocade_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.brocade_fd_name.get_text()
-    fields["ipaddr"] = self.brocade_fd_ip.get_text()
-    fields["login"] = self.brocade_fd_login.get_text()
-    fields["passwd"] = self.brocade_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_ilo_fd(self, name):
-    rectify_fence_name = False
-    if self.ilo_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.ilo_fd_name)
-    if name != self.ilo_fd_name.get_text():
-      res = self.check_unique_fd_name(self.ilo_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.ilo_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.ilo_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-    if self.ilo_fd_hostname.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_HOSTNAME)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.ilo_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.ilo_fd_name.get_text()
-    fields["hostname"] = self.ilo_fd_hostname.get_text()
-    fields["login"] = self.ilo_fd_login.get_text()
-    fields["passwd"] = self.ilo_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_vixel_fd(self, name):
-    rectify_fence_name = False
-    if self.vixel_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.vixel_fd_name)
-    if name != self.vixel_fd_name.get_text():
-      res = self.check_unique_fd_name(self.vixel_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.vixel_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-    if self.vixel_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.vixel_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.vixel_fd_name.get_text()
-    fields["ipaddr"] = self.vixel_fd_ip.get_text()
-    fields["passwd"] = self.vixel_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_mcdata_fd(self, name):
-    rectify_fence_name = False
-    if self.mcdata_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.mcdata_fd_name)
-    if name != self.mcdata_fd_name.get_text():
-      res = self.check_unique_fd_name(self.mcdata_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.mcdata_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-    if self.mcdata_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.mcdata_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.mcdata_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.mcdata_fd_name.get_text()
-    fields["ipaddr"] = self.mcdata_fd_ip.get_text()
-    fields["login"] = self.mcdata_fd_login.get_text()
-    fields["passwd"] = self.mcdata_fd_passwd.get_text()
-
-    return fields
- 
-  def val_manual_fd(self, name):
-    rectify_fence_name = False
-    if self.manual_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.manual_fd_name)
-    if name != self.manual_fd_name.get_text():
-      res = self.check_unique_fd_name(self.manual_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.manual_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.manual_fd_name.get_text()
-
-    return fields
- 
-  def val_gnbd_fd(self, name):
-    rectify_fence_name = False
-    if self.gnbd_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.gnbd_fd_name)
-    if name != self.gnbd_fd_name.get_text():
-      res = self.check_unique_fd_name(self.gnbd_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.gnbd_fd_server.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_SERVER)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.gnbd_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.gnbd_fd_name.get_text()
-    fields["server"] = self.gnbd_fd_server.get_text()
-
-    return fields
- 
-  def val_egenera_fd(self, name):
-    rectify_fence_name = False
-    if self.egenera_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.egenera_fd_name)
-    if name != self.egenera_fd_name.get_text():
-      res = self.check_unique_fd_name(self.egenera_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.egenera_fd_cserver.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_CSERVER)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.egenera_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.egenera_fd_name.get_text()
-    fields["cserver"] = self.egenera_fd_cserver.get_text()
-
-    return fields
-
- 
-  def val_sanbox2_fd(self, name):
-    rectify_fence_name = False
-    if self.sanbox2_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.sanbox2_fd_name)
-    if name != self.sanbox2_fd_name.get_text():
-      res = self.check_unique_fd_name(self.sanbox2_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.sanbox2_fd_ip.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_IP)
-
-    if self.sanbox2_fd_login.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-
-    if self.sanbox2_fd_passwd.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.sanbox2_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.sanbox2_fd_name.get_text()
-    fields["ipaddr"] = self.sanbox2_fd_ip.get_text()
-    fields["login"] = self.sanbox2_fd_login.get_text()
-    fields["passwd"] = self.sanbox2_fd_passwd.get_text()
-
-    return fields
-
-  def val_bladecenter_fd(self, name):
-    rectify_fence_name = False
-    if self.bladecenter_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.bladecenter_fd_name)
-    if name != self.bladecenter_fd_name.get_text():
-      res = self.check_unique_fd_name(self.bladecenter_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.bladecenter_fd_ip.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_IP)
-
-    if self.bladecenter_fd_login.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-
-    if self.bladecenter_fd_passwd.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.bladecenter_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.bladecenter_fd_name.get_text()
-    fields["ipaddr"] = self.bladecenter_fd_ip.get_text()
-    fields["login"] = self.bladecenter_fd_login.get_text()
-    fields["passwd"] = self.bladecenter_fd_passwd.get_text()
-
-    return fields
-
-  def val_ipmilan_fd(self, name):
-    rectify_fence_name = False
-    if self.ipmilan_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.ipmilan_fd_name)
-    if name != self.ipmilan_fd_name.get_text():
-      res = self.check_unique_fd_name(self.ipmilan_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.ipmilan_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.ipmilan_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-    if self.ipmilan_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.ipmilan_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.ipmilan_fd_name.get_text()
-    fields["ipaddr"] = self.ipmilan_fd_ip.get_text()
-    fields["login"] = self.ipmilan_fd_login.get_text()
-    fields["passwd"] = self.ipmilan_fd_passwd.get_text()
-
-    return fields
- 
- 
-  def val_bullpap_fd(self, name):
-    rectify_fence_name = False
-    if self.bullpap_fd_name.get_text() == "":
-      raise ValidationError('FATAL', FD_PROVIDE_NAME)
-    self.validateNCName(self.bullpap_fd_name)
-    if name != self.bullpap_fd_name.get_text():
-      res = self.check_unique_fd_name(self.bullpap_fd_name.get_text())
-      if res == False:  #name is already used
-        raise ValidationError('FATAL', FD_PROVIDE_NAME)
-      rectify_fence_name = True
-
-    if self.bullpap_fd_login.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_LOGIN)
-    if self.bullpap_fd_passwd.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_PASSWD)
-    if self.bullpap_fd_ip.get_text() == "":
-        raise ValidationError('FATAL', FD_PROVIDE_IP)
-
-    if rectify_fence_name == True:
-      self.model_builder.rectifyNewFencedevicenameWithFences(name,self.bullpap_fd_name.get_text())
-
-    fields = {}
-    fields["name"] = self.bullpap_fd_name.get_text()
-    fields["ipaddr"] = self.bullpap_fd_ip.get_text()
-    fields["login"] = self.bullpap_fd_login.get_text()
-    fields["passwd"] = self.bullpap_fd_passwd.get_text()
-
-    return fields
- 
- 
-  #Validation Methods for Fence Instances 
-  def validate_fenceinstance(self, agent_type):
-    try:
-      returnlist = apply(self.fi_validate[agent_type])
-    except ValidationError, e:
-      MessageLibrary.errorMessage(e.getMessage())
-      return None
-
-    return returnlist
-
-  def val_apc(self):
-    if self.apc_port.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-    if self.apc_switch.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_SWITCH)
-
-    fields = {}
-    fields["port"] = self.apc_port.get_text()
-    fields["switch"] = self.apc_switch.get_text()
-
-    return fields
-
-  def val_wti(self):
-    if self.wti_port.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-
-    fields = {}
-    fields["port"] = self.wti_port.get_text()
-
-    return fields
-
-  def val_brocade(self):
-    if self.brocade_port.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-
-    fields = {}
-    fields["port"] = self.brocade_port.get_text()
-
-    return fields
-
-  def val_vixel(self):
-    if self.vixel_port.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-
-    fields = {}
-    fields["port"] = self.vixel_port.get_text()
-
-    return fields
-
-  def val_gnbd(self):
-    if self.gnbd_ip.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_IPADDRESS)
-
-    fields = {}
-    fields["ipaddress"] = self.gnbd_ip.get_text()
-
-    return fields
-
-  def val_ilo(self):
-
-    fields = {}
-
-    return fields
-
-  def val_sanbox2(self):
-    if self.sanbox2_port.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-
-    fields = {}
-    fields["port"] = self.sanbox2_port.get_text()
-
-    return fields
-
-  def val_bladecenter(self):
-    if self.bladecenter_blade.get_text() == "": 
-      raise ValidationError('FATAL', FI_PROVIDE_BLADE)
-
-    fields = {}
-    fields["blade"] = self.bladecenter_blade.get_text()
-
-    return fields
-
-  def val_mcdata(self):
-    if self.mcdata_port.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_PORT)
-
-    fields = {}
-    fields["port"] = self.mcdata_port.get_text()
-
-    return fields
-
-  def val_egenera(self):
-    if self.egenera_lpan.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_ELPAN)
-    if self.egenera_pserver.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_EPSERVER)
-
-    fields = {}
-    fields["lpan"] = self.egenera_lpan.get_text()
-    fields["pserver"] = self.egenera_pserver.get_text()
-
-    return fields
-
-  def val_manual(self): 
-
-    fields = {}
-    return fields
-
-  def val_ipmilan(self):
-
-    fields = {}
-
-    return fields
-
-  def val_bullpap(self):
-    if self.bullpap_domain.get_text() == "":
-      raise ValidationError('FATAL', FI_PROVIDE_DOMAIN)
-
-    fields = {}
-    fields["domain"] = self.bullpap_domain.get_text()
-
-    return fields
-
-  def check_unique_fd_name(self, name):
-    fds = self.model_builder.getFenceDevices()
-    for fd in fds:
-      if fd.getName() == name:
-        return False
-
-    return True
-
-  def getFENCE_OPTS(self):
-    return FENCE_OPTS
-
-  def set_model(self, model_builder):
-    self.model_builder = model_builder
-
-
-
-  ### name must conform to relaxNG ID type ##
-  def isNCName(self, name):
-    for ch in ILLEGAL_CHARS:
-      if ch in name:
-        return False
-    return True
-  
-  def makeNCName(self, name):
-    new_name = ''
-    for ch in name:
-      if ch in ILLEGAL_CHARS:
-        new_name = new_name + '_'
-      else:
-        new_name = new_name + ch
-    return new_name
-
-  def validateNCName(self, gtkentry):
-    name = gtkentry.get_text().strip()
-    gtkentry.set_text(name)
-    if not self.isNCName(name):
-      name = self.makeNCName(name)
-      gtkentry.set_text(name)
-      # select text
-      raise ValidationError('FATAL', ILLEGAL_CHARS_REPLACED)
-
-def validateNewFenceDevice(form, model): 
-  from FenceDevice import FenceDevice
-  try:
-    agent_type = form['fence_type']
-  except KeyError, e:
-    return (FD_VAL_FAIL, "No agent type in form submission")
-
-  ##Now that we have an agent type, we should check the fencedev name
-  ##before wasting any time checking other fields.
-  try:
-    fencedev_name = form['name']
-    fencedev_name = fencedev_name.strip()
-  except KeyError, e:
-    return (FD_VAL_FAIL, "No device name in form submission")
-
-  if fencedev_name == "":
-    return (1, "A unique name is required for every fence device")
-
-  fencedevs = model.getFenceDevices()
-  for fd in fencedevs:
-    if fd.getName().strip() == fencedev_name:
-      return (FD_VAL_FAIL, FD_PROVIDE_NAME)
-
-  if agent_type == "fence_apc":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_wti":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_brocade":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_vixel":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-
-  elif agent_type == "fence_mcdata":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-
-  elif agent_type == "fence_gnbd":
-    try:
-      server = form['server']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_SERVER)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("server",server)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_egenera":
-    try:
-      cserver = form['cserver']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_CSERVER)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("cserver",cserver)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-
-  elif agent_type == "fence_sanbox2":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_bladecenter":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_bullpap":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-
-  elif agent_type == "fence_xvm":
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  elif agent_type == "fence_scsi":
-
-    fencedev = FenceDevice()
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedevptr = model.getFenceDevicePtr()
-    fencedevptr.addChild(fencedev)
-    return (FD_VAL_SUCCESS, FD_NEW_SUCCESS % FENCE_OPTS[agent_type])
-
-  #Oh-oh...no agent match
-  else:
-    return (FD_VAL_FAIL, FD_NEW_FAIL % agent_type)
-  
-def validateFenceDevice(form, model): 
-  from FenceDevice import FenceDevice
-  namechange = False
-
-  try:
-    agent_type = form['fence_type']
-  except KeyError, e:
-    return (FD_VAL_FAIL, "No agent type in form submission")
-
-  ##Now that we have an agent type, we should check the fencedev name
-  ##before wasting any time checking other fields.
-  try:
-    fencedev_name = form['name']
-    fencedev_name = fencedev_name.strip()
-  except KeyError, e:
-    return (FD_VAL_FAIL, "No device name in form submission")
-
-  if fencedev_name == "":
-    return (1, "No device name in form submission")
-
-  try:
-    orig_name = form['orig_name']
-  except KeyError, e:
-    return (FD_VAL_FAIL, "Cannot retrieve original fence device")
-
-  if orig_name != fencedev_name:
-    namechange = True
-
-    fencedevs = model.getFenceDevices()
-    for fd in fencedevs:
-      if fd.getName().strip() == fencedev_name:
-        return (FD_VAL_FAIL, FD_PROVIDE_NAME)
-  else:
-    fencedevs = model.getFenceDevices()
-
-  #Now we know name is unique...find device now
-  fencedev = None
-  for fd in fencedevs:
-    if fd.getName().strip() == orig_name:
-      fencedev = fd
-      break
-
-  if fencedev == None:
-    return (FD_VAL_FAIL, "Could not find fencedevice in current configuration")
-
-  if agent_type == "fence_apc":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_wti":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_brocade":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_vixel":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-
-  elif agent_type == "fence_mcdata":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-
-  elif agent_type == "fence_gnbd":
-    try:
-      server = form['server']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_SERVER)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("server",server)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_egenera":
-    try:
-      cserver = form['cserver']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_CSERVER)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("cserver",cserver)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-
-  elif agent_type == "fence_sanbox2":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_bladecenter":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_bullpap":
-    try:
-      ip = form['ipaddr']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_IP)
-    try:
-      log = form['login']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_LOGIN)
-    try:
-      pwd = form['passwd']
-    except KeyError, e:
-      return (FD_VAL_FAIL, FD_PROVIDE_PASSWD)
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    fencedev.addAttribute("ipaddr",ip)
-    fencedev.addAttribute("login",log)
-    fencedev.addAttribute("passwd",pwd)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-
-  elif agent_type == "fence_xvm":
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  elif agent_type == "fence_scsi":
-
-    fencedev.addAttribute("agent",agent_type)
-    fencedev.addAttribute("name",fencedev_name)
-    if namechange:
-      model.rectifyNewFencedevicenameWithFences(orig_name,fencedev_name)
-    return (FD_VAL_SUCCESS, FD_UPDATE_SUCCESS % orig_name)
-
-  #Oh-oh...no agent match
-  else:
-    return (FD_VAL_FAIL, FD_NEW_FAIL % agent_type)
+	return (FD_VAL_SUCCESS, fenceinst)
--- conga/luci/site/luci/Extensions/Fs.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/Fs.py	2007/03/01 00:31:08	1.1.2.1
@@ -6,7 +6,7 @@
 _ = gettext.gettext
 
 TAG_NAME = "fs"
-RESOURCE_TYPE = _("File System: ")
+RESOURCE_TYPE = _("File System")
 
 class Fs(BaseResource):
   def __init__(self):
--- conga/luci/site/luci/Extensions/Ip.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/Ip.py	2007/03/01 00:31:08	1.1.2.1
@@ -6,7 +6,7 @@
 _ = gettext.gettext
 
 TAG_NAME = "ip"
-RESOURCE_TYPE=_("IP Address: ")
+RESOURCE_TYPE=_("IP Address")
 
 class Ip(BaseResource):
   def __init__(self):
--- conga/luci/site/luci/Extensions/ModelBuilder.py	2007/01/15 21:29:09	1.8.2.6
+++ conga/luci/site/luci/Extensions/ModelBuilder.py	2007/03/01 00:31:08	1.8.2.7
@@ -17,6 +17,7 @@
 from Method import Method
 from Device import Device
 from Cman import Cman
+from Totem import Totem
 from Gulm import Gulm
 from Lockserver import Lockserver
 from Ip import Ip
@@ -25,8 +26,15 @@
 from NFSExport import NFSExport
 from Fs import Fs
 from Samba import Samba
+from Apache import Apache
+from LVM import LVM
+from MySQL import MySQL
+from OpenLDAP import OpenLDAP
+from Postgres8 import Postgres8
+from Tomcat5 import Tomcat5
 from Multicast import Multicast
 from FenceDaemon import FenceDaemon
+from FenceXVMd import FenceXVMd
 from Netfs import Netfs
 from Clusterfs import Clusterfs
 from Resources import Resources
@@ -40,11 +48,9 @@
 from FailoverDomainNode import FailoverDomainNode
 from Rm import Rm
 from Heuristic import Heuristic
-from CommandHandler import CommandHandler
-from CommandError import CommandError
 from GeneralError import GeneralError
 from clui_constants import *
-import MessageLibrary
+
 TAGNAMES={ 'cluster':Cluster,
            'clusternodes':ClusterNodes,
            'clusternode':ClusterNode,
@@ -53,11 +59,13 @@
            'fencedevices':FenceDevices,
            'method':Method,
            'cman':Cman,
+           'totem':Totem,
            'gulm':Gulm,
            'lockserver':Lockserver,
            'rm':Rm,
            'service':Service,
            'vm':Vm,
+           'fence_xvmd':FenceXVMd,
            'resources':Resources,
            'failoverdomain':FailoverDomain,
            'failoverdomains':FailoverDomains,
@@ -65,6 +73,12 @@
            'ip':Ip,
            'fs':Fs,
            'smb':Samba,
+           'apache':Apache,
+           'lvm':LVM,
+           'mysql':MySQL,
+           'openldap':OpenLDAP,
+           'postgres-8':Postgres8,
+           'tomcat-5':Tomcat5,
            'fence_daemon':FenceDaemon,
            'multicast':Multicast,
            'clusterfs':Clusterfs,
@@ -87,14 +101,16 @@
 FENCEDAEMON_PTR_STR="fence_daemon"
 SERVICE="service"
 VM="vm"
+FENCE_XVMD_STR="fence_xvmd"
 GULM_TAG_STR="gulm"
 MCAST_STR="multicast"
 CMAN_PTR_STR="cman"
+TOTEM_PTR_STR="totem"
 QUORUMD_PTR_STR="quorumd"
 ###-----------------------------------
 
 
-INVALID_GULM_COUNT="GuLM locking mechanism may consist of 1, 3, 4 or 5 locking servers. You have configured %d. Fix the error and try saving again."
+INVALID_GULM_COUNT="GULM locking mechanism may consist of 1, 3, or 5 locking servers. You have configured %d. Fix the error and try saving again."
 
 
 class ModelBuilder:
@@ -112,16 +128,17 @@
     self.cluster_ptr = None
     self.GULM_ptr = None
     self.CMAN_ptr = None
+    self.TOTEM_ptr = None
     self.clusternodes_ptr = None
     self.failoverdomains_ptr = None
     self.fencedevices_ptr = None
     self.resourcemanager_ptr = None
     self.resources_ptr = None
     self.fence_daemon_ptr = None
-    self.command_handler = CommandHandler()
     self.isModified = False
     self.quorumd_ptr = None
     self.usesQuorumd = False
+    self.fence_xvmd_ptr = None
     self.unusual_items = list()
     self.isVirtualized = False
     if mcast_addr == None:
@@ -218,8 +235,12 @@
         self.lock_type = GULM_TYPE
       elif parent_node.nodeName == CMAN_PTR_STR:
         self.CMAN_ptr = new_object
+      elif parent_node.nodeName == TOTEM_PTR_STR:
+        self.TOTEM_ptr = new_object
       elif parent_node.nodeName == MCAST_STR:
         self.usesMulticast = True
+      elif parent_node.nodeName == FENCE_XVMD_STR:
+        self.fence_xvmd_ptr = new_object
 
     else:
       return None
@@ -280,15 +301,13 @@
 
     obj_tree.addAttribute("name","alpha_cluster")
     obj_tree.addAttribute("config_version","1")
-    fdp = FenceDaemon()
-    obj_tree.addChild(fdp)
-    self.fence_daemon_ptr = fdp
     cns = ClusterNodes()
     obj_tree.addChild(cns)
     self.clusternodes_ptr = cns
 
     gulm = Gulm()
     self.GULM_ptr = gulm
+    self.fence_daemon_ptr = None
     obj_tree.addChild(gulm)
 
     fds = FenceDevices()
@@ -521,9 +540,6 @@
   def getFilepath(self):
     return self.filename
 
-  def isClusterMember(self):
-    return self.command_handler.isClusterMember()
-
   def setIsVirtualized(self,isVirtualized):
     if isVirtualized == None:
       self.isVirtualized = False
@@ -549,7 +565,7 @@
   def deleteNode(self, clusternode):
     #1) delete node
     #2) delete failoverdomainnodes with same name
-    #3) delete lockserver nodes if GuLM
+    #3) delete lockserver nodes if GULM
 
     name = clusternode.getName()
 
@@ -591,13 +607,40 @@
 
     raise GeneralError('FATAL',"Couldn't find service name in current list")
 
-  def retrieveXenVMsByName(self, name):
-    vms = self.getXENVMs()
+  def retrieveVMsByName(self, name):
+    vms = self.getVMs()
     for v in vms:
       if v.getName() == name:
         return v
 
-    raise GeneralError('FATAL',"Couldn't find xen vm name %s in current node list" % name)
+    raise GeneralError('FATAL',"Couldn't find VM name %s in current list" % name)
+
+  def del_totem(self):
+    if self.TOTEM_ptr is not None:
+      self.cluster_ptr.removeChild(self.TOTEM_ptr)
+      self.TOTEM_ptr = None
+
+  def add_totem(self, obj):
+    self.del_totem()
+    if self.TOTEM_ptr is None:
+      self.cluster_ptr.addChild(obj)
+      self.TOTEM_ptr = obj
+
+  def hasFenceXVM(self):
+    return self.fence_xvmd_ptr is not None
+
+  # Right now the fence_xvmd tag is empty, but allow the object
+  # to be passed in case attributes are added in the future.
+  def addFenceXVM(self, obj):
+    if self.fence_xvmd_ptr is not None:
+      self.cluster_ptr.removeChild(self.fence_xvmd_ptr)
+    self.cluster_ptr.addChild(obj)
+    self.fence_xvmd_ptr = obj
+
+  def delFenceXVM(self):
+    if self.fence_xvmd_ptr is not None:
+      self.cluster_ptr.removeChild(self.fence_xvmd_ptr)
+      self.fence_xvmd_ptr = None
 
   def getFenceDevices(self):
     if self.fencedevices_ptr == None:
@@ -613,10 +656,17 @@
       return list()
     else:
       return self.failoverdomains_ptr.getChildren()
-        
+
   def getFailoverDomainPtr(self):
     return self.failoverdomains_ptr
 
+  def getFailoverDomainByName(self, fdom_name):
+    fdoms = self.getFailoverDomains()
+    for i in fdoms:
+      if i.getName() == fdom_name:
+        return i
+    return None
+
   def getFailoverDomainsForNode(self, nodename):
     matches = list()
     faildoms = self.getFailoverDomains()
@@ -707,7 +757,7 @@
       self.resourcemanager_ptr.addChild(rcs)
       self.resources_ptr = rcs
         
-    if self.fence_daemon_ptr == None:
+    if self.GULM_ptr is None and self.fence_daemon_ptr is None:
       fdp = FenceDaemon()
       self.cluster_ptr.addChild(fdp)
       self.fence_daemon_ptr = fdp
@@ -730,7 +780,7 @@
 
     return None
         
-  def getXENVMs(self):
+  def getVMs(self):
     rg_list = list()
     if self.resourcemanager_ptr != None:
       kids = self.resourcemanager_ptr.getChildren()
@@ -775,6 +825,12 @@
   def getGULMPtr(self):
     return self.GULM_ptr
 
+  def getCMANPtr(self):
+    return self.CMAN_ptr
+
+  def getTotemPtr(self):
+    return self.TOTEM_ptr
+
   def getLockServer(self, name):
     children = self.GULM_ptr.getChildren()
     for child in children:
@@ -792,7 +848,7 @@
 
   def isNodeLockserver(self,name):
     gptr = self.getGULMPtr()
-    if gptr == None:  #Obviously not GuLM
+    if gptr == None:  #Obviously not GULM
       return False
     children = gptr.getChildren()
     for child in children:
@@ -803,7 +859,7 @@
 
   def removeLockserver(self, clusternode):
     gptr = self.getGULMPtr()
-    if gptr == None:  #Obviously not GuLM
+    if gptr == None:  #Obviously not GULM
       return
     children = gptr.getChildren()
     for child in children:
@@ -818,6 +874,8 @@
     if self.lock_type == DLM_TYPE:
       #remove <cman>
       self.cluster_ptr.removeChild(self.CMAN_ptr)
+      if self.TOTEM_ptr is not None:
+        self.del_totem()
       self.CMAN_ptr = None
 
       #add gulm tag
@@ -938,7 +996,7 @@
     
 
   def check_fence_daemon(self):
-    if self.fence_daemon_ptr == None:
+    if self.GULM_ptr is None and self.fence_daemon_ptr is None:
       self.fence_daemon_ptr = FenceDaemon()
       self.cluster_ptr.addChild(self.fence_daemon_ptr)
 
@@ -1031,8 +1089,7 @@
   def check_gulm_count(self):
     if self.getLockType() == GULM_TYPE:
       gulm_count = len(self.getGULMPtr().getChildren())
-      if not (gulm_count in (1, 3, 4, 5)):
-        MessageLibrary.errorMessage(INVALID_GULM_COUNT % gulm_count)
+      if not (gulm_count in (1, 3, 5)):
         return False
     return True
 
--- conga/luci/site/luci/Extensions/NFSExport.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/NFSExport.py	2007/03/01 00:31:08	1.1.2.1
@@ -5,7 +5,7 @@
 import gettext
 _ = gettext.gettext
 
-RESOURCE_TYPE = _("NFS Export: ")
+RESOURCE_TYPE = _("NFS Export")
 TAG_NAME = "nfsexport"
 
 class NFSExport(BaseResource):
--- conga/luci/site/luci/Extensions/Netfs.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/Netfs.py	2007/03/01 00:31:08	1.1.2.1
@@ -6,7 +6,7 @@
 _ = gettext.gettext
 
 TAG_NAME = "netfs"
-RESOURCE_TYPE = _("NFS Mount: ")
+RESOURCE_TYPE = _("NFS Mount")
 
 class Netfs(BaseResource):
   def __init__(self):
--- conga/luci/site/luci/Extensions/Samba.py	2006/07/20 21:30:33	1.1
+++ conga/luci/site/luci/Extensions/Samba.py	2007/03/01 00:31:08	1.1.2.1
@@ -6,7 +6,7 @@
 _ = gettext.gettext
 
 TAG_NAME = "smb"
-RESOURCE_TYPE = _("Samba Service: ")
+RESOURCE_TYPE = _("Samba Service")
 
 class Samba(BaseResource):
   def __init__(self):
--- conga/luci/site/luci/Extensions/Script.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/Script.py	2007/03/01 00:31:08	1.1.2.1
@@ -5,7 +5,7 @@
 import gettext
 _ = gettext.gettext
 
-RESOURCE_TYPE = _("Script: ")
+RESOURCE_TYPE = _("Script")
 TAG_NAME = "script"
 
 class Script(BaseResource):
--- conga/luci/site/luci/Extensions/clui_constants.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/clui_constants.py	2007/03/01 00:31:08	1.1.2.1
@@ -66,7 +66,7 @@
 
 XML_CONFIG_ERROR=_("A problem was encountered while reading configuration file %s . Details or the error appear below. Click the \'Cancel\' button to quit the application. Click the \'New\' button to create a new configuration file. To continue anyway (Not Recommended!), click the \'Ok\' button.") 
 
-SWITCH_TO_GULM=_("Change to GuLM Lockserver")
+SWITCH_TO_GULM=_("Change to GULM Lockserver")
 SWITCH_TO_DLM=_("Change to Distributed Lock Manager")
 SWITCH_TO_BROADCAST=_("Change to Broadcast Mode for Cluster Manager")
 SWITCH_TO_MULTICAST=_("Change to Multicast Mode for Cluster Manager")
--- conga/luci/site/luci/Extensions/cluster_adapters.py	2007/01/17 22:26:27	1.120.2.20
+++ conga/luci/site/luci/Extensions/cluster_adapters.py	2007/03/01 00:31:08	1.120.2.21
@@ -11,23 +11,33 @@
 from Ip import Ip
 from Clusterfs import Clusterfs
 from Fs import Fs
+from FailoverDomain import FailoverDomain
+from FailoverDomainNode import FailoverDomainNode
 from RefObject import RefObject
 from ClusterNode import ClusterNode
 from NFSClient import NFSClient
 from NFSExport import NFSExport
 from Service import Service
+from Lockserver import Lockserver
 from Netfs import Netfs
+from Apache import Apache
+from MySQL import MySQL
+from Postgres8 import Postgres8
+from Tomcat5 import Tomcat5
+from OpenLDAP import OpenLDAP
 from Vm import Vm
+from FenceXVMd import FenceXVMd
 from Script import Script
 from Samba import Samba
+from LVM import LVM
 from QuorumD import QuorumD
 from Heuristic import Heuristic
 from clusterOS import resolveOSType
 from Fence import Fence
 from Method import Method
-from FenceDevice import FenceDevice
+from Totem import Totem
 from Device import Device
-from FenceHandler import validateNewFenceDevice, FENCE_OPTS, validateFenceDevice
+from FenceHandler import validateNewFenceDevice, FENCE_OPTS, validateFenceDevice, validate_fenceinstance
 from GeneralError import GeneralError
 from homebase_adapters import manageCluster, createClusterSystems, havePermCreateCluster, setNodeFlag, delNodeFlag, userAuthenticated, getStorageNode, getClusterNode, delCluster, parseHostForm
 from LuciSyslog import LuciSyslog
@@ -119,7 +129,7 @@
 
 	system_list, incomplete, errors, messages = parseHostForm(request, check_certs)
 	add_cluster['nodes'] = system_list
-	
+
 	for i in system_list:
 		cur_system = system_list[i]
 
@@ -150,13 +160,13 @@
 			try:
 				if prev_auth:
 					messages.append('Host %s is already authenticated.' \
-						% cur_host) 
+						% cur_host)
 				else:
 					rc.auth(cur_passwd)
 
 				if not rc.authed():
 					raise Exception, 'authentication failed'
-			except:
+			except Exception, e:
 				cur_system['errors'] = True
 				incomplete = True
 				errors.append('Error authenticating to %s: %s' \
@@ -227,6 +237,49 @@
 	add_cluster, incomplete, errors, messages = parseClusterNodes(self, request, cluster_os)
 	clusterName = add_cluster['name']
 
+	if len(clusterName) > 15:
+		errors.append('A cluster\'s name must be less than 16 characters long.')
+
+	try:
+		cluster_os = add_cluster['cluster_os']
+	except:
+		pass
+
+	lockmanager = 'dlm'
+	if cluster_os == 'rhel4':
+		add_cluster['gulm_support'] = True
+		if not request.form.has_key('lockmanager'):
+			# The user hasn't been presented with the RHEL4
+			# lock manager options yet.
+			incomplete = True
+		else:
+			try:
+				lockmanager = request.form['lockmanager'].strip()
+			except:
+				lockmanager = 'dlm'
+
+	lockservers = None
+	if lockmanager == 'gulm':
+		add_cluster['lockmanager'] = 'gulm'
+		try:
+			lockservers = filter(lambda x: x.strip(), request.form['__GULM__'])
+			if not lockservers or len(lockservers) < 1:
+				raise Exception, 'blank'
+			num_lockservers = len(lockservers)
+			if not num_lockservers in (1, 3, 5):
+				errors.append('You must have exactly 1, 3, or 5 GULM lock servers. You submitted %d lock servers.' % num_lockservers)
+		except:
+			errors.append('No lock servers were given.')
+
+		if len(errors) > 0:
+			try:
+				ls_hash = {}
+				for i in xrange(num_lockservers):
+					ls_hash['server%d' % (i + 1)] = lockservers[i]
+				add_cluster['gulm_lockservers'] = ls_hash
+			except:
+				pass
+
 	if incomplete or len(errors) > 0:
 		request.SESSION.set('create_cluster', add_cluster)
 		return (False, { 'errors': errors, 'messages': messages })
@@ -240,7 +293,8 @@
 					True,
 					add_cluster['shared_storage'],
 					False,
-					add_cluster['download_pkgs'])
+					add_cluster['download_pkgs'],
+					lockservers)
 
 	if not batchNode:
 		request.SESSION.set('create_cluster', add_cluster)
@@ -258,7 +312,7 @@
 		try:
 			rc = RicciCommunicator(i)
 			if not rc:
-				raise 'rc is None'
+				raise Exception, 'rc is None'
 		except Exception, e:
 			msg = 'Unable to connect to the ricci agent on %s: %s' % (i, str(e))
 			errors.append(msg)
@@ -271,7 +325,9 @@
 		try:
 			resultNode = rc.process_batch(batchNode, async=True)
 			batch_id_map[i] = resultNode.getAttribute('batch_id')
-		except:
+		except Exception, e:
+			luci_log.debug_verbose('validateCreateCluster0: %s: %s' \
+				% (i, str(e)))
 			errors.append('An error occurred while attempting to add cluster node \"%s\"' % i)
 			if len(batch_id_map) == 0:
 				request.SESSION.set('create_cluster', add_cluster)
@@ -327,7 +383,7 @@
 		except Exception, e:
 			luci_log.debug_verbose('VACN1: %s: %s' % (clusterName, str(e)))
 			return (False, { 'errors': [ 'The database object for %s is missing.' % clusterName ] })
-		
+
 		try:
 			cluster_os = cluster_folder.manage_getProperty('cluster_os')
 			if not cluster_os:
@@ -369,7 +425,7 @@
 
 	system_list, incomplete, errors, messages = parseHostForm(request, check_certs)
 	add_cluster['nodes'] = system_list
-	
+
 	for i in system_list:
 		cur_system = system_list[i]
 
@@ -396,16 +452,17 @@
 
 			prev_auth = rc.authed()
 			cur_system['prev_auth'] = prev_auth
+
 			try:
 				if prev_auth:
 					messages.append('Host %s is already authenticated.' \
-						% cur_host) 
+						% cur_host)
 				else:
 					rc.auth(cur_passwd)
 
 				if not rc.authed():
 					raise Exception, 'authentication failed'
-			except:
+			except Exception, e:
 				cur_system['errors'] = True
 				incomplete = True
 				errors.append('Error authenticating to %s: %s' \
@@ -508,7 +565,8 @@
 								True,
 								shared_storage,
 								False,
-								download_pkgs)
+								download_pkgs,
+								model.GULM_ptr is not None)
 				if not batch_node:
 					raise Exception, 'batch is blank'
 				system_list[x]['batch'] = batch_node
@@ -540,8 +598,6 @@
 			request.SESSION.set('add_node', add_cluster)
 			return (False, { 'errors': errors, 'messages': messages })
 
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf_str = str(model.exportModelAsString())
 		if not conf_str:
@@ -566,7 +622,7 @@
 				break
 			if code == -1:
 				errors.append(batch_ret[1])
-				raise Exception, batch_ret[1]
+				raise Exception, str(batch_ret[1])
 			if code == False:
 				time.sleep(0.5)
 	except Exception, e:
@@ -724,6 +780,25 @@
 	if len(errors) > 0:
 		return (False, {'errors': errors})
 
+	fdom = None
+	try:
+		fdom = request.form['domain'].strip()
+		if not fdom:
+			raise Exception, 'blank'
+	except:
+		fdom = None
+
+	recovery = None
+	try:
+		recovery = request.form['recovery'].strip()
+		if not recovery:
+			recovery = None
+		else:
+			if recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+				errors.append('You entered an invalid recovery option: \"%s\" Valid options are \"restart\" \"relocate\" and \"disable\"')
+	except:
+		recovery = None
+
 	try:
 		service_name = request.form['svc_name'].strip()
 	except Exception, e:
@@ -738,6 +813,15 @@
 		autostart = None
 		luci_log.debug_verbose('vSA5a: error getting autostart: %s' % 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 GeneralError, e:
@@ -776,6 +860,11 @@
 
 	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
 
@@ -788,8 +877,6 @@
 		return (False, {'errors': [ 'Unable to determine cluster name' ]})
 
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf = model.exportModelAsString()
 		if not conf:
@@ -855,11 +942,18 @@
 		return (False, {'errors': errors})
 
 	return (True, {'messages': ['Resource added successfully']})
-	
+
 ## Cluster properties form validation routines
 
 # rhel5 cluster version
 def validateMCastConfig(model, form):
+	try:
+		gulm_ptr = model.getGULMPtr()
+		if gulm_ptr:
+			return (False, {'errors': ['Multicast cannot be used with GULM locking.']})
+	except:
+		pass
+
 	errors = list()
 	try:
 		mcast_val = form['mcast'].strip().lower()
@@ -919,8 +1013,16 @@
 	except KeyError, e:
 		return (False, {'errors': ['An invalid quorum partition selection was made']})
 
+	cp = model.getClusterPtr()
+	qdp = model.getQuorumdPtr()
+
 	if not qdisk_val:
-		return (True, {'messages': ['Changes accepted. - FILL ME IN']})
+		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'])
@@ -960,22 +1062,25 @@
 
 	#Either device or label must be present
 	device = None
-	label = None
 	try:
 		device = form['device'].strip()
+	except:
+		device = None
+
+	label = None
+	try:
 		label = form['label'].strip()
-		if not device and not label:
-			raise KeyError, 'device and label are both none'
-	except KeyError, e:
+	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'])
-		if num_heuristics < 0:
-			raise ValueError, 'invalid number of heuristics: %s' % form['num_heuristics']
-		if num_heuristics == 0:
-			num_heuristics = 1
+		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:
@@ -983,65 +1088,67 @@
 
 	heuristics = list()
 	for i in xrange(num_heuristics):
-		prefix = 'heuristic' + str(i) + ':'
 		try:
-			hname = form[prefix + 'hname'].strip()
-			if not hname:
-				raise KeyError(prefix + 'hname')
-		except KeyError, e:
-			if ((not prefix + 'hpath' in form or not form['hpath'].strip()) and
-				(not prefix + 'hint' in form or not form['hint'].strip()) and
-				(not prefix + 'hscore' in form or not form['hscore'].strip())):
-				# The row is blank; ignore it.
+			h = form['heuristic%d' % i]
+			if not h or len(h) != 3:
 				continue
-			errors.append('No heuristic name was given for heuristic #%d' % i + 1)
+		except:
+			continue
 
 		try:
-			hpath = form[prefix + 'hpath']
-		except KeyError, e:
-			errors.append('No heuristic path was given for heuristic #%d' % i + 1)
-
+			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(form[prefix + 'hint'])
+			hint = int(h[1])
 			if hint < 1:
 				raise ValueError, 'Heuristic interval values must be greater than 0'
 		except KeyError, e:
-			errors.append('No heuristic interval was given for heuristic #%d' % i + 1)
+			errors.append('No interval was given for heuristic #%d' % i + 1)
 		except ValueError, e:
-			errors.append('An invalid heuristic interval was given for heuristic #%d: %s' % (i + 1, str(e)))
+			errors.append('An invalid interval was given for heuristic %d: %s' \
+				% (i + 1, str(e)))
 
 		try:
-			hscore = int(form[prefix + 'score'])
+			hscore = int(h[2])
 			if hscore < 1:
 				raise ValueError, 'Heuristic scores must be greater than 0'
 		except KeyError, e:
-			errors.append('No heuristic score was given for heuristic #%d' % i + 1)
+			errors.append('No score was given for heuristic %d' % i + 1)
 		except ValueError, e:
-			errors.append('An invalid heuristic score was given for heuristic #%d: %s' % (i + 1, str(e)))
-		heuristics.append([ hname, hpath, hint, hscore ])
+			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', interval)
-	qd.addAttribute('votes', votes)
-	qd.addAttribute('tko', tko)
-	qd.addAttribute('min_score', min_score)
+	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', device)
+		qd.addAttribute('device', str(device))
 	else:
-		qd.addAttribute('label', label)
+		qd.addAttribute('label', str(label))
 
-	cp = model.getClusterPtr()
+	if qdp:
+		try:
+			cp.removeChild(qdp)
+		except:
+			pass
 	cp.addChild(qd)
 
 	for h in heuristics:
 		new_h = Heuristic()
-		new_h.addAttribute('program', h[1])
-		new_h.addAttribute('interval', h[2])
-		new_h.addAttribute('score', h[3])
+		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:
@@ -1068,12 +1175,16 @@
 	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
-		# we'll increment the cluster version before propagating it.
-		version_num -= 1
+		if version_num != old_ver:
+			# we'll increment the cluster version before propagating it.
+			version_num -= 1
 	except KeyError, e:
 		errors.append('No cluster configuration version was given.')
 	except ValueError, e:
@@ -1088,6 +1199,85 @@
 			luci_log.debug_verbose('unable to update general properties: %s' % 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:
+		cp = model.getClusterPtr()
+		totem = Totem()
+		cp.addChild(totem)
+
+	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:
+		token_retransmits_before_loss_const = form['token_retransmits_before_loss_const'].strip()
+		if not token_retransmits_before_loss_const:
+			raise KeyError, 'token_retransmits_before_loss_const'
+		token_retransmits_before_loss_const = int(token_retransmits_before_loss_const)
+		if token_retransmits_before_loss_const < 1:
+			raise ValueError, '%d is an invalid value for number of token retransmits before loss' % token_retransmits_before_loss_const
+		totem.addAttribute('token_retransmits_before_loss_const', str(token_retransmits_before_loss_const))
+	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, {})
@@ -1095,6 +1285,9 @@
 def validateFenceConfig(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:
@@ -1113,6 +1306,18 @@
 	except ValueError, e:
 		errors.append('Invalid post join delay: %s' % str(e))
 
+	run_xvmd = False
+	try:
+		run_xvmd = form.has_key('run_xvmd')
+	except:
+		pass
+
+	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()
@@ -1132,11 +1337,47 @@
 
 	return (True, {})
 
+def validateGULMConfig(model, form):
+	gulm_ptr = model.getGULMPtr()
+	if not gulm_ptr:
+		return (False, {'errors': [ 'This cluster appears not to be using GULM locking.' ]})
+
+	node_list = map(lambda x: x.getName(), gulm_ptr.getChildren())
+	for i in map(lambda x: x.getName(), model.getNodes()):
+		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, {})
+
 configFormValidators = {
 	'general': validateGeneralConfig,
 	'mcast': validateMCastConfig,
 	'fence': validateFenceConfig,
-	'qdisk': validateQDiskConfig
+	'qdisk': validateQDiskConfig,
+	'gulm': validateGULMConfig
 }
 
 def validateConfigCluster(self, request):
@@ -1215,7 +1456,7 @@
       raise Exception, 'cluster name from model.getClusterName() is blank'
   except Exception, e:
     luci_log.debug_verbose('VCC5: error: getClusterName: %s' % str(e))
-    errors.append('Unable to determine cluster name from model') 
+    errors.append('Unable to determine cluster name from model')
 
   if len(errors) > 0:
     return (retcode, {'errors': errors, 'messages': messages})
@@ -1251,7 +1492,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1266,12 +1507,12 @@
       except:
         luci_log.debug_verbose('VFE: no model, no cluster name')
         return (False, {'errors': ['No cluster model was found.']})
-                                                                                
+
     try:
       model = getModelForCluster(self, cluname)
     except:
       model = None
-                                                                                
+
     if model is None:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1290,20 +1531,15 @@
     luci_log.debug_verbose('VFE: no form was submitted')
     return (False, {'errors': ['No form was submitted']})
 
-  #fencehandler = FenceHandler()
-  error_code, error_string = validateNewFenceDevice(form, model)
+  error_code, retobj = validateNewFenceDevice(form, model)
   if error_code == FD_VAL_SUCCESS:
-    messages.append(error_string)
     try:
-      cp = model.getClusterPtr()
-      cp.incrementConfigVersion()
-      model.setModified(True)
       conf_str = model.exportModelAsString()
       if not conf_str:
         raise Exception, 'conf_str is none'
     except Exception, e:
       luci_log.debug_verbose('VFE: export model as string failed: %s' \
-      % str(e))
+        % str(e))
       errors.append('Unable to store the new cluster configuration')
 
     try:
@@ -1312,7 +1548,7 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
@@ -1330,14 +1566,13 @@
       else:
         try:
           set_node_flag(self, clustername, rc.hostname(), batch_id,
-          CLUSTER_CONFIG, 'Updating cluster configuration')
+            CLUSTER_CONFIG, 'Adding new fence device \"%s\"' % retobj)
         except:
           pass
 
-    response.redirect(request['URL'] + "?pagetype=" + FENCEDEV + "&clustername=" + clustername + "&fencename=" + form['name'] + '&busyfirst=true')
-    return (True, {'errors': errors, 'messages': messages})
+    response.redirect(request['URL'] + "?pagetype=" + FENCEDEV + "&clustername=" + clustername + "&fencename=" + retobj + '&busyfirst=true')
   else:
-    errors.append(error_string)
+    errors.extend(retobj)
     return (False, {'errors': errors, 'messages': messages})
 
 
@@ -1345,7 +1580,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1360,12 +1595,12 @@
       except:
         luci_log.debug_verbose('VFE: no model, no cluster name')
         return (False, {'errors': ['No cluster model was found.']})
-                                                                                
+
     try:
       model = getModelForCluster(self, cluname)
     except:
       model = None
-                                                                                
+
     if model is None:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1388,19 +1623,15 @@
   #entry for this fence device.
   #
   #pass form and model to validation method, then save changes if it passes.
-  error_code, error_string = validateFenceDevice(form, model)
+  error_code, retobj = validateFenceDevice(form, model)
   if error_code == FD_VAL_SUCCESS:
-    messages.append(error_string)
     try:
-      cp = model.getClusterPtr()
-      cp.incrementConfigVersion()
-      model.setModified(True)
       conf_str = model.exportModelAsString()
       if not conf_str:
         raise Exception, 'conf_str is none'
     except Exception, e:
       luci_log.debug_verbose('VFE: export model as string failed: %s' \
-      % str(e))
+        % str(e))
       errors.append('Unable to store the new cluster configuration')
 
     try:
@@ -1409,35 +1640,36 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
       if not rc:
         luci_log.debug_verbose('VFA: unable to find a ricci agent for the %s cluster' % clustername)
         errors.append('Unable to contact a ricci agent for cluster %s' \
-        % clustername)
+          % clustername)
 
     if rc:
       batch_id, result = setClusterConf(rc, str(conf_str))
       if batch_id is None or result is None:
         luci_log.debug_verbose('VFA: setClusterConf: batchid or result is None')
         errors.append('Unable to propagate the new cluster configuration for %s' \
-        % clustername)
+          % clustername)
       else:
         try:
           set_node_flag(self, clustername, rc.hostname(), batch_id,
-          CLUSTER_CONFIG, 'Updating cluster configuration')
+            CLUSTER_CONFIG, 'Updating fence device \"%s\"' % retobj)
         except:
           pass
 
-    response.redirect(request['URL'] + "?pagetype=" + FENCEDEV + "&clustername=" + clustername + "&fencename=" + request['fencename'] + '&busyfirst=true')
-    return (True, {'errors': errors, 'messages': messages})
+    response.redirect(request['URL'] + "?pagetype=" + FENCEDEV + "&clustername=" + clustername + "&fencename=" + retobj + '&busyfirst=true')
   else:
-    errors.append(error_string)
+    errors.extend(retobj)
     return (False, {'errors': errors, 'messages': messages})
 
 def validateNodeFenceConfig(self, request):
+	errors = list()
+
 	try:
 		form_xml = request['fence_xml']
 		if not form_xml:
@@ -1519,10 +1751,10 @@
 				break
 		if delete_target is not None:
 			try:
-				node.getChildren()[0].removeChild(l)
+				node.getChildren()[0].removeChild(delete_target)
 			except Exception, e:
 				luci_log.debug_verbose('vNFC6a: %s: %s' % (method_id, str(e)))
-				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]}) 
+				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]})
 		else:
 			return (True, {'messages': ['No changes were made.'] })
 
@@ -1563,7 +1795,7 @@
 				return (False, {'errors': [ 'Unable to determine what device the current instance uses.' ]})
 
 			try:
-				parent_form = form_hash[parent][1].append(dummy_form)
+				form_hash[parent][1].append(dummy_form)
 				del dummy_form['fence_instance']
 			except Exception, e:
 				luci_log.debug_verbose('vNFC10: no parent for instance')
@@ -1576,7 +1808,6 @@
 	for i in fh_keys:
 		fencedev_name = None
 		fencedev_unknown = False
-		fencedev_obj = None
 
 		try:
 			fence_form, instance_list = form_hash[i]
@@ -1588,140 +1819,70 @@
 			fence_type = fence_form['fence_type']
 			if not fence_type:
 				raise Exception, 'fence type is blank'
-			fence_form['agent'] = fence_type
 		except Exception, e:
 			luci_log.debug_verbose('vNFC12: %s %s' % (i, str(e)))
 			fence_type = None
 
-		try:
-			del fence_form['fence_type']
-		except:
-			pass
-
 		if 'existing_device' in fence_form:
-			del fence_form['existing_device']
-
 			try:
 				fencedev_name = fence_form['name']
 				if not fencedev_name.strip():
 					raise Exception, 'no fence name'
 			except Exception, e:
-				return (False, {'errors': [ 'You must provide a unique name for all fence devices.' ]})
+				errors.append('You must provide a unique name for all fence devices.')
+				continue
 
 			if fence_type is None:
-				# An unknown device. Pull the data out of
+				# 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 'sharable' in fence_form:
+				if not 'sharable' in fence_form:
 					# 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.
-					del fence_form['sharable']
-				else:
-					# An existing non-shared device; build up the device
-					# from scratch since the user could have edited it.
-					try:
-						old_name = fence_form['old_name']
-						if not old_name:
-							raise Exception, 'old name is blank'
-						del fence_form['old_name']
-					except Exception, e:
-						luci_log.debug_verbose('vNFC12: no old name for %s %s' \
-							% (fence_form['name'], str(e)))
-						return (False, {'errors': [ 'Unable to determine the original name for the device now named %s' % fencedev_name ]})
-
-					fencedev_obj = None
-					fence_dev_list = model.getFenceDevices()
-					for fd in fence_dev_list:
-						if fd.getAttribute('name') == old_name:
-							fencedev_obj = fd
-							break
-
-					if fencedev_obj is None:
-						luci_log.debug_verbose('vNFC14: no fence device named %s was found' % old_name)
-						return (False, {'errors': ['No fence device named %s was found' % old_name ] })
+					# 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:
-						try:
-							model.fencedevices_ptr.removeChild(fd)
-						except Exception, e:
-							luci_log.debug_verbose('VNFC8a: %s: %s' \
-								% (old_name, str(e)))
-							return (False, {'errors': [ 'Unable to remove old fence device %s' % old_name ]})
-
-					for k in fence_form.keys():
-						if fence_form[k]:
-							fencedev_obj.addAttribute(k, str(fence_form[k]))
+						fencedev_name = retmsg
 
 					# Add back the tags under the method block
 					# for the fence instance
 					instance_list.append({'name': fencedev_name })
 		else:
 			# The user created a new fence device.
-			try:
-				fencedev_name = fence_form['name']
-				if not fencedev_name.strip():
-					raise Exception, 'no fence name'
-			except Exception, e:
-				return (False, {'errors': [ 'You must provide a unique name for all fence devices.' ]})
-
-			fencedev_obj = FenceDevice()
-			for k in fence_form.keys():
-				if fence_form[k]:
-					fencedev_obj.addAttribute(k, str(fence_form[k]))
+			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 'sharable' in fence_form:
 				instance_list.append({'name': fencedev_name })
-			else:
-				del fence_form['sharable']
-
-		if fencedev_obj is not None:
-			# If a device with this name exists in the model
-			# already, replace it with the current object. If
-			# this block is not executed, we don't need to make
-			# any changes to the fencedevices block for this
-			# device
-			fence_dev_list = model.getFenceDevices()
-			for fd in fence_dev_list:
-				if fencedev_name == fd.getAttribute('name'):
-					luci_log.debug_verbose('vNFC15: fence ident %s already in use' % fencedev_name)
-					return (False, {'errors': ['There is already a fence device named %s' % fencedev_name ] })
-			model.fencedevices_ptr.addChild(fencedev_obj)
 
 		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:
-			try:
-				del inst['parent_fencedev']
-			except:
-				pass
-			try:
-				del inst['new_instance']
-			except:
-				pass
-			try:
-				del inst['name']
-			except:
-				pass
-			try:
-				del inst['existing_instance']
-			except:
-				pass
-
-			device_obj = Device()
-			device_obj.setAgentType(fence_type)
-			device_obj.addAttribute('name', fencedev_name)
-			for k in inst.keys():
-				if inst[k]:
-					device_obj.addAttribute(k, str(inst[k]))
-			fence_method.addChild(device_obj)
+			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
@@ -1741,9 +1902,10 @@
 			fence_node.addChild(fence_method)
 			node.addChild(fence_node)
 
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf = str(model.exportModelAsString())
 		if not conf:
@@ -1777,7 +1939,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1792,12 +1954,12 @@
       except:
         luci_log.debug_verbose('VFE: no model, no cluster name')
         return (False, {'errors': ['No cluster model was found.']})
-                                                                                
+
     try:
       model = getModelForCluster(self, cluname)
     except:
       model = None
-                                                                                
+
     if model is None:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1844,18 +2006,16 @@
   except:
     error_code = FD_VAL_FAIL
     error_string = "Fence device %s could not be removed from configuration" % fencedev_name
- 
+
   try:
     model.removeFenceInstancesForFenceDevice(fencedev_name)
   except:
     luci_log.debug_verbose('VFD: Could not remove fence instances for')
-     
+
 
   if error_code == FD_VAL_SUCCESS:
     messages.append(error_string)
     try:
-      cp = model.getClusterPtr()
-      cp.incrementConfigVersion()
       model.setModified(True)
       conf_str = model.exportModelAsString()
       if not conf_str:
@@ -1871,7 +2031,7 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
@@ -1889,7 +2049,7 @@
       else:
         try:
           set_node_flag(self, clustername, rc.hostname(), batch_id,
-          CLUSTER_CONFIG, 'Updating cluster configuration')
+            CLUSTER_CONFIG, 'Removing fence device \"%s\"' % fencedev_name)
         except:
           pass
 
@@ -1960,7 +2120,7 @@
 		luci_log.debug_verbose('VDP5: RC %s: %s' % (nodename_resolved, str(e)))
 		errors.append('Unable to connect to the ricci agent on %s to update cluster daemon properties' % nodename_resolved)
 		return (False, {'errors': errors})
-		
+
 	batch_id, result = updateServices(rc, enable_list, disable_list)
 	if batch_id is None or result is None:
 		luci_log.debug_verbose('VDP6: setCluserConf: batchid or result is None')
@@ -1982,76 +2142,375 @@
 
 	response.redirect(request['URL'] + "?pagetype=" + NODE + "&clustername=" + clustername + '&nodename=' + nodename + '&busyfirst=true')
 
-formValidators = {
-	6: validateCreateCluster,
-	7: validateConfigCluster,
-	15: validateAddClusterNode,
-	21: validateServiceAdd,
-	24: validateServiceAdd,
-	31: validateResourceAdd,
-	33: validateResourceAdd,
-	51: validateFenceAdd,
-	54: validateFenceEdit,
-	55: validateDaemonProperties,
-	57: deleteFenceDevice,
-	58: validateNodeFenceConfig
-}
+def validateFdom(self, request):
+	errors = list()
 
-def validatePost(self, request):
 	try:
-		pagetype = int(request.form['pagetype'])
+		model = request.SESSION.get('model')
+		if not model:
+			raise Exception, 'no model'
 	except Exception, e:
-		luci_log.debug_verbose('VP0: error: %s' % str(e))
-		return None
+		luci_log.debug_verbose('validateFdom0: no model: %s' % str(e))
+		return (False, {'errors': [ 'Unable to retrieve cluster information.' ]})
 
-	if not pagetype in formValidators:
-		luci_log.debug_verbose('VP1: no handler for page type %d' % pagetype)
-		return None
-	else:
-		return formValidators[pagetype](self, request)
+	prioritized = False
+	try:
+		prioritized = request.form.has_key('prioritized')
+	except:
+		prioritized = False
 
+	restricted = False
+	try:
+		restricted = request.form.has_key('restricted')
+	except:
+		restricted = False
 
-def createCluChooser(self, request, systems):
-  dummynode = {}
+	clustername = None
+	try:
+		clustername = request.form['clustername'].strip()
+		if not clustername:
+			raise Exception, 'blank'
+	except:
+		try:
+			clustername = model.getClusterName()
+			if not clustername:
+				raise Exception, 'blank'
+		except:
+			clustername = None
 
-  if request.REQUEST_METHOD == 'POST':
-    ret = validatePost(self, request)
-    try:
-      request.SESSION.set('checkRet', ret[1])
-    except:
-      request.SESSION.set('checkRet', {})
-  else:
-    try:
-      request.SESSION.set('checkRet', {})
-    except:
-      pass
+	if not clustername:
+		errors.append('Unable to determine this cluster\'s name.')
 
-  #First, see if a cluster is chosen, then
-  #check that the current user can access that system
-  cname = None
-  try:
-    cname = request[CLUNAME]
-  except:
-    cname = ""
+	try:
+		name = request.form['name'].strip()
+		if not name:
+			raise Exception, 'blank'
+	except Exception, e:
+		errors.append('No name was given for this failover domain.')
+		luci_log.debug_verbose('validateFdom0: %s' % str(e))
 
-  try:
-    url = request['URL']
-  except:
-    url = "/luci/cluster/index_html"
+	oldname = None
+	try:
+		oldname = request.form['oldname'].strip()
+		if not oldname:
+			raise Exception, 'blank'
+	except:
+		pass
 
-  try:
-    pagetype = request[PAGETYPE]
-  except:
-    pagetype = '3'
+	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:
+			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 })
 
-  cldata = {}
-  cldata['Title'] = "Cluster List"
-  cldata['cfg_type'] = "clusters"
-  cldata['absolute_url'] = url + "?pagetype=" + CLUSTERLIST
-  cldata['Description'] = "Clusters available for configuration"
-  if pagetype == CLUSTERLIST:
-    cldata['currentItem'] = True
+	if prioritized:
+		fdom.addAttribute('ordered', '1')
+	else:
+		fdom.addAttribute('ordered', '0')
+
+	if restricted:
+		fdom.addAttribute('restricted', '1')
+	else:
+		fdom.addAttribute('restricted', '0')
+
+	cluster_nodes = map(lambda x: str(x.getName()), model.getNodes())
+
+	for i in cluster_nodes:
+		if request.form.has_key(i):
+			fdn = FailoverDomainNode()
+			fdn.addAttribute('name', i)
+			if prioritized:
+				priority = 1
+				try:
+					priority = int(request.form['__PRIORITY__' + 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)
+		model.setModified(True)
+		conf = str(model.exportModelAsString())
+	except Exception, e:
+		luci_log.debug_verbose('validateFdom2: %s' % str(e))
+		errors.append('Unable to update the cluster configuration.')
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	rc = getRicciAgent(self, clustername)
+	if not rc:
+		luci_log.debug_verbose('validateFdom3: unable to find a ricci agent for cluster %s' % clustername)
+		return (False, {'errors': ['Unable to find a ricci agent for the %s cluster' % clustername ]})
+	ragent = rc.hostname()
+
+	batch_number, result = setClusterConf(rc, conf)
+	if batch_number is None or result is None:
+		luci_log.debug_verbose('validateFdom4: missing batch and/or result')
+		return (False, {'errors': [ 'An error occurred while constructing the new cluster configuration.' ]})
+
+	try:
+		if oldname:
+			set_node_flag(self, clustername, ragent, str(batch_number), FDOM, 'Updating failover domain \"%s\"' % oldname)
+		else:
+			set_node_flag(self, clustername, ragent, str(batch_number), FDOM_ADD, 'Creating failover domain \"%s\"' % name)
+	except Exception, e:
+		luci_log.debug_verbose('validateFdom5: failed to set flags: %s' % str(e))
+
+	response = request.RESPONSE
+	response.redirect(request['URL'] + "?pagetype=" + FDOM + "&clustername=" + clustername + '&fdomname=' + name + '&busyfirst=true')
+
+def validateVM(self, request):
+	errors = list()
+
+	model = request.SESSION.get('model')
+
+	try:
+		vm_name = request.form['vmname'].strip()
+		if not vm_name:
+			raise Exception, 'blank'
+	except Exception, e:
+		luci_log.debug_verbose('validateVM0: no vm name: %s' % str(e))
+		errors.append('No virtual machine name was given.')
+
+	try:
+		vm_path = request.form['vmpath'].strip()
+		if not vm_path:
+			raise Exception, 'blank'
+	except Exception, e:
+		luci_log.debug_verbose('validateVM1: no vm path: %s' % str(e))
+		errors.append('No path to the virtual machine configuration file was given.')
+
+	autostart = 1
+	try:
+		if request.form.has_key('autostart'):
+			autostart = 1
+		else:
+			autostart = 0
+	except:
+		autostart = 1
+
+	exclusive = 0
+	try:
+		if request.form.has_key('exclusive'):
+			exclusive = 1
+		else:
+			exclusive = 0
+	except:
+		exclusive = 0
+
+	recovery = None
+	try:
+		recovery = request.form['recovery'].strip()
+		if not recovery:
+			recovery = None
+		else:
+			if recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+				errors.append('You entered an invalid recovery option: \"%s\" Valid options are \"restart\" \"relocate\" and \"disable\"')
+	except:
+		recovery = None
+
+	fdom = None
+	try:
+		fdom = request.form['domain'].strip()
+		if not fdom:
+			raise Exception, 'blank'
+	except:
+		fdom = None
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	isNew = False
+	try:
+		old_name = request.form['oldname'].strip()
+		if not old_name:
+			raise KeyError, 'oldname'
+	except KeyError, e:
+		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))
+	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
+
+	try:
+		model.setModified(True)
+		stringbuf = str(model.exportModelAsString())
+		if not stringbuf:
+			raise Exception, 'model is blank'
+	except Exception, e:
+		luci_log.debug_verbose('validateVM2: %s' % str(e))
+		errors.append('Unable to update the cluster model')
+
+	try:
+		clustername = model.getClusterName()
+		if not clustername:
+			raise Exception, 'cluster name from model.getClusterName() is blank'
+	except Exception, e:
+		luci_log.debug_verbose('validateVM3: %s' % str(e))
+		errors.append('Unable to determine the cluster name.')
+
+	if len(errors) > 0:
+		return (False, {'errors': errors })
+
+	rc = getRicciAgent(self, clustername)
+	if not rc:
+		luci_log.debug_verbose('validateVM4: no ricci for %s' % clustername)
+		return (False, {'errors': ['Unable to contact a ricci agent for this cluster.']})
+
+	batch_number, result = setClusterConf(rc, stringbuf)
+	if batch_number is None or result is None:
+		luci_log.debug_verbose('validateVM5: missing batch and/or result')
+		return (False, {'errors': [ 'Error creating virtual machine %s.' % vm_name ]})
+
+	try:
+		if delete_vm is True:
+			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_CONFIG, "Deleting virtual machine service \'%s\'" % vm_name)
+		elif isNew is True:
+			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_ADD, "Creating virtual machine service \'%s\'" % vm_name)
+		else:
+			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_CONFIG, "Configuring virtual machine service \'%s\'" % vm_name)
+	except Exception, e:
+		luci_log.debug_verbose('validateVM6: failed to set flags: %s' % str(e))
+
+	response = request.RESPONSE
+	response.redirect(request['URL'] + "?pagetype=" + SERVICES + "&clustername=" + clustername + '&busyfirst=true')
+
+formValidators = {
+	6: validateCreateCluster,
+	7: validateConfigCluster,
+	15: validateAddClusterNode,
+	18: validateVM,
+	19: validateVM,
+	21: validateServiceAdd,
+	24: validateServiceAdd,
+	31: validateResourceAdd,
+	33: validateResourceAdd,
+	41: validateFdom,
+	44: validateFdom,
+	51: validateFenceAdd,
+	54: validateFenceEdit,
+	55: validateDaemonProperties,
+	57: deleteFenceDevice,
+	58: validateNodeFenceConfig
+}
+
+def validatePost(self, request):
+	try:
+		pagetype = int(request.form['pagetype'])
+	except Exception, e:
+		luci_log.debug_verbose('VP0: error: %s' % str(e))
+		return None
+
+	if not pagetype in formValidators:
+		luci_log.debug_verbose('VP1: no handler for page type %d' % pagetype)
+		return None
+	else:
+		return formValidators[pagetype](self, request)
+
+
+def createCluChooser(self, request, systems):
+  dummynode = {}
+
+  if request.REQUEST_METHOD == 'POST':
+    ret = validatePost(self, request)
+    try:
+      request.SESSION.set('checkRet', ret[1])
+    except:
+      request.SESSION.set('checkRet', {})
+  else:
+    try:
+      request.SESSION.set('checkRet', {})
+    except:
+      pass
+
+  #First, see if a cluster is chosen, then
+  #check that the current user can access that system
+  cname = None
+  try:
+    cname = request[CLUNAME]
+  except:
+    cname = ""
+
+  try:
+    url = request['URL']
+  except:
+    url = "/luci/cluster/index_html"
+
+  try:
+    pagetype = request[PAGETYPE]
+  except:
+    pagetype = '3'
+
+
+  cldata = {}
+  cldata['Title'] = "Cluster List"
+  cldata['cfg_type'] = "clusters"
+  cldata['absolute_url'] = url + "?pagetype=" + CLUSTERLIST
+  cldata['Description'] = "Clusters available for configuration"
+  if pagetype == CLUSTERLIST:
+    cldata['currentItem'] = True
   else:
     cldata['currentItem'] = False
 
@@ -2115,12 +2574,11 @@
   return dummynode
 
 def getnodes(self, model):
-  mb = model
-  nodes = mb.getNodes()
-  names = list()
-  for node in nodes:
-    names.append(node.getName())
-  return names
+	try:
+		return map(lambda x: str(x.getName()), model.getNodes())
+	except Exception, e:
+		luci_log.debug_verbose('getnodes0: %s' % str(e))
+	return []
 
 def createCluConfigTree(self, request, model):
   dummynode = {}
@@ -2248,10 +2706,10 @@
   if model.getIsVirtualized() == True:
     vmadd = {}
     vmadd['Title'] = "Add a Virtual Service"
-    vmadd['cfg_type'] = "xenvmadd"
-    vmadd['absolute_url'] = url + "?pagetype=" + XENVM_ADD + "&clustername=" + cluname
+    vmadd['cfg_type'] = "vmadd"
+    vmadd['absolute_url'] = url + "?pagetype=" + VM_ADD + "&clustername=" + cluname
     vmadd['Description'] = "Add a Virtual Service to this cluster"
-    if pagetype == XENVM_ADD:
+    if pagetype == VM_ADD:
       vmadd['currentItem'] = True
     else:
       vmadd['currentItem'] = False
@@ -2271,7 +2729,6 @@
     svcfg['currentItem'] = False
 
   services = model.getServices()
-  xenvms = model.getXENVMs()
   serviceable = list()
   for service in services:
     servicename = service.getName()
@@ -2294,19 +2751,20 @@
 
     serviceable.append(svc)
 
-  for xenvm in xenvms:
-    xenname = xenvm.getName()
+  vms = model.getVMs()
+  for vm in vms:
+    name = vm.getName()
     svc = {}
-    svc['Title'] = xenname
-    svc['cfg_type'] = "xenvm"
-    svc['absolute_url'] = url + "?pagetype=" + XENVM_CONFIG + "&servicename=" + xenname + "&clustername=" + cluname
+    svc['Title'] = name
+    svc['cfg_type'] = "vm"
+    svc['absolute_url'] = url + "?pagetype=" + VM_CONFIG + "&servicename=" + name + "&clustername=" + cluname
     svc['Description'] = "Configure this Virtual Service"
-    if pagetype == XENVM_CONFIG:
+    if pagetype == VM_CONFIG:
       try:
         xname = request['servicename']
       except KeyError, e:
         xname = ""
-      if xenname == xname:
+      if name == xname:
         svc['currentItem'] = True
       else:
         svc['currentItem'] = False
@@ -2716,7 +3174,7 @@
 		except Exception, e:
 			luci_log.debug_verbose('GRA4b: %s' % str(e))
 			cur_alias = None
-			
+
 		if (cur_name is not None and cluname != cur_name) and (cur_alias is not None and cluname != cur_alias):
 			try:
 				luci_log.debug('GRA5: %s reports it\'s in cluster %s:%s; we expect %s' \
@@ -2922,6 +3380,10 @@
 			vals['name'] = node.getAttribute('name')
 			vals['nodename'] = node.getAttribute('nodename')
 			vals['running'] = node.getAttribute('running')
+			try:
+				vals['is_vm'] = node.getAttribute('vm').lower() == 'true'
+			except:
+				vals['is_vm'] = False
 			vals['failed'] = node.getAttribute('failed')
 			vals['autostart'] = node.getAttribute('autostart')
 			results.append(vals)
@@ -2954,14 +3416,29 @@
 		if item['type'] == "service":
 			itemmap = {}
 			itemmap['name'] = item['name']
+
 			if item['running'] == "true":
 				itemmap['running'] = "true"
 				itemmap['nodename'] = item['nodename']
+				itemmap['disableurl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + item['name'] + "&pagetype=" + SERVICE_STOP
+				itemmap['restarturl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + item['name'] + "&pagetype=" + SERVICE_RESTART
+			else:
+				itemmap['enableurl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + item['name'] + "&pagetype=" + SERVICE_START
+
 			itemmap['autostart'] = item['autostart']
-			itemmap['cfgurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + SERVICE
-			itemmap['delurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + SERVICE_DELETE
 
-			svc = model.retrieveServiceByName(item['name'])
+			try:
+				svc = model.retrieveServiceByName(item['name'])
+				itemmap['cfgurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + SERVICE
+				itemmap['delurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + SERVICE_DELETE
+			except:
+				try:
+					svc = model.retrieveVMsByName(item['name'])
+					itemmap['virt'] = True
+					itemmap['cfgurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + VM_CONFIG 
+					itemmap['delurl'] = baseurl + "?" + "clustername=" + cluname + "&servicename=" + item['name'] + "&pagetype=" + VM_CONFIG
+				except:
+					continue
 			dom = svc.getAttribute("domain")
 			if dom is not None:
 				itemmap['faildom'] = dom
@@ -2972,6 +3449,9 @@
 	map['services'] = maplist
 	return map
 
+def get_fdom_names(model):
+	return map(lambda x: x.getName(), model.getFailoverDomains())
+
 def getServiceInfo(self, status, model, req):
 	#set up struct for service config page
 	hmap = {}
@@ -2985,6 +3465,11 @@
 		baseurl = '/luci/cluster/index_html'
 
 	try:
+		hmap['fdoms'] = get_fdom_names(model)
+	except:
+		hmap['fdoms'] = list()
+
+	try:
 		cluname = req['clustername']
 		if not cluname:
 			raise KeyError, 'is blank'
@@ -3049,6 +3534,24 @@
 	#Now build hashes for resources under service.
 	#first get service by name from model
 	svc = model.getService(servicename)
+	try:
+		hmap['domain'] = svc.getAttribute('domain')
+	except:
+		hmap['domain'] = None
+
+	try:
+		hmap['recovery'] = svc.getAttribute('recovery')
+	except:
+		hmap['recovery'] = None
+
+	try:
+		if int(svc.getAttribute('exclusive')):
+			hmap['exclusive'] = 'true' 
+		else:
+			hmap['exclusive'] = 'false'
+	except:
+		hmap['exclusive'] = 'false'
+
 	resource_list = list()
 	if svc is not None:
 		indent_ctr = 0
@@ -3072,9 +3575,11 @@
 	#Note: Final version needs all resource attrs
 	if child.isRefObject() == True:
 		rc_map['ref_object'] = True
+		rc_map['tag_name'] = child.getObj().TAG_NAME
 		rc_map['type'] = child.getObj().getResourceType()
 		rc_map['attrs'] = child.getObj().getAttributes()
 	else:
+		rc_map['tag_name'] = child.TAG_NAME
 		rc_map['type'] = child.getResourceType()
 		rc_map['attrs'] = child.getAttributes()
 
@@ -3176,7 +3681,7 @@
 	if batch_number is None or result is None:
 		luci_log.debug_verbose('serviceRestart2: %s failed' % svcname)
 		return None
-				
+
 	try:
 		set_node_flag(self, cluname, rc.hostname(), str(batch_number), SERVICE_RESTART, "Restarting service \'%s\'" % svcname)
 	except Exception, e:
@@ -3225,6 +3730,39 @@
 	response = req.RESPONSE
 	response.redirect(req['URL'] + "?pagetype=" + SERVICE_LIST + "&clustername=" + cluname + '&busyfirst=true')
 
+def getFdomInfo(self, model, request):
+	fhash = {}
+	fhash['members'] = {}
+
+	try:
+		fdom = model.getFailoverDomainByName(request['fdomname'])
+	except Exception, e:
+		luci_log.debug_verbose('getFdomInfo0: %s' % str(e))
+		return fhash
+
+	fhash['name'] = fdom.getName()
+
+	ordered_attr = fdom.getAttribute('ordered')
+	if ordered_attr is not None and (ordered_attr == "true" or ordered_attr == "1"):
+		fhash['prioritized'] = '1'
+	else:
+		fhash['prioritized'] = '0'
+
+	restricted_attr = fdom.getAttribute('restricted')
+	if restricted_attr is not None and (restricted_attr == "true" or restricted_attr == "1"):
+		fhash['restricted'] = '1'
+	else:
+		fhash['restricted'] = '0'
+
+	nodes = fdom.getChildren()
+	for node in nodes:
+		try:
+			priority = node.getAttribute('priority')
+		except:
+			priority = '1'
+		fhash['members'][node.getName()] = { 'priority': priority }
+	return fhash
+
 def getFdomsInfo(self, model, request, clustatus):
   slist = list()
   nlist = list()
@@ -3241,7 +3779,7 @@
   for fdom in fdoms:
     fdom_map = {}
     fdom_map['name'] = fdom.getName()
-    fdom_map['cfgurl'] = baseurl + "?pagetype=" + FDOM_LIST + "&clustername=" + clustername
+    fdom_map['cfgurl'] = baseurl + "?pagetype=" + FDOM + "&clustername=" + clustername + '&fdomname=' + fdom.getName()
     ordered_attr = fdom.getAttribute('ordered')
     restricted_attr = fdom.getAttribute('restricted')
     if ordered_attr is not None and (ordered_attr == "true" or ordered_attr == "1"):
@@ -3326,6 +3864,7 @@
 	if not model:
 		return 'Unable to get the model object for %s' % cluname
 
+	redirect_page = NODES
 	if task == CLUSTER_STOP:
 		clusterStop(self, model)
 	elif task == CLUSTER_START:
@@ -3333,13 +3872,15 @@
 	elif task == CLUSTER_RESTART:
 		clusterRestart(self, model)
 	elif task == CLUSTER_DELETE:
-		clusterStop(self, model, delete=True)
+		ret = clusterDelete(self, model)
+		if ret is not None:
+			redirect_page = ret
 	else:
 		return 'An unknown cluster task was requested.'
 
 	response = request.RESPONSE
 	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], NODES, model.getClusterName()))
+		% (request['URL'], redirect_page, model.getClusterName()))
 
 def getClusterInfo(self, model, req):
   try:
@@ -3354,6 +3895,7 @@
         luci_log.debug_verbose('GCI0: unable to determine cluster name')
         return {}
 
+  clumap = {}
   if model is None:
     try:
       model = getModelForCluster(self, cluname)
@@ -3363,9 +3905,12 @@
     except Exception, e:
       luci_log.debug_verbose('GCI1: unable to get model for cluster %s: %s' % (cluname, str(e)))
       return {}
+  else:
+    totem = model.getTotemPtr()
+    if totem:
+      clumap['totem'] = totem.getAttributes()
 
   prop_baseurl = req['URL'] + '?' + PAGETYPE + '=' + CLUSTER_CONFIG + '&' + CLUNAME + '=' + cluname + '&'
-  clumap = {}
   basecluster_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_GENERAL_TAB
   #needed:
   clumap['basecluster_url'] = basecluster_url
@@ -3377,33 +3922,52 @@
   #-------------
   #new cluster params - if rhel5
   #-------------
-  #Fence Daemon Props
-  fencedaemon_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_FENCE_TAB
-  clumap['fencedaemon_url'] = fencedaemon_url
-  fdp = model.getFenceDaemonPtr()
-  pjd = fdp.getAttribute('post_join_delay')
-  if pjd is None:
-    pjd = "6"
-  pfd = fdp.getAttribute('post_fail_delay')
-  if pfd is None:
-    pfd = "0"
-  #post join delay
-  clumap['pjd'] = pjd
-  #post fail delay
-  clumap['pfd'] = pfd
-  #-------------
-  #if multicast
-  multicast_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_MCAST_TAB
-  clumap['multicast_url'] = multicast_url
-  #mcast addr
-  is_mcast = model.isMulticast()
-  #clumap['is_mcast'] = is_mcast
-  if is_mcast:
-    clumap['mcast_addr'] = model.getMcastAddr()
-    clumap['is_mcast'] = "True"
-  else:
-    clumap['is_mcast'] = "False"
-    clumap['mcast_addr'] = "1.2.3.4"
+
+  clumap['fence_xvmd'] = model.hasFenceXVM()
+  gulm_ptr = model.getGULMPtr()
+  if not gulm_ptr:
+    #Fence Daemon Props
+    fencedaemon_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_FENCE_TAB
+    clumap['fencedaemon_url'] = fencedaemon_url
+    fdp = model.getFenceDaemonPtr()
+    pjd = fdp.getAttribute('post_join_delay')
+    if pjd is None:
+      pjd = "6"
+    pfd = fdp.getAttribute('post_fail_delay')
+    if pfd is None:
+      pfd = "0"
+    #post join delay
+    clumap['pjd'] = pjd
+    #post fail delay
+    clumap['pfd'] = pfd
+
+    #-------------
+    #if multicast
+    multicast_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_MCAST_TAB
+    clumap['multicast_url'] = multicast_url
+    #mcast addr
+    is_mcast = model.isMulticast()
+    if is_mcast:
+      clumap['mcast_addr'] = model.getMcastAddr()
+      clumap['is_mcast'] = "True"
+    else:
+      clumap['is_mcast'] = "False"
+      clumap['mcast_addr'] = "1.2.3.4"
+    clumap['gulm'] = False
+  else:
+    #-------------
+    #GULM params (rhel4 only)
+    lockserv_list = list()
+    clunodes = model.getNodes()
+    gulm_lockservs = map(lambda x: x.getName(), gulm_ptr.getChildren())
+    lockserv_list = map(lambda x: (x, True), gulm_lockservs)
+    for node in clunodes:
+      n = node.getName()
+      if not n in gulm_lockservs:
+        lockserv_list.append((n, False))
+    clumap['gulm'] = True
+    clumap['gulm_url'] = prop_baseurl + PROPERTIES_TAB + '=' + PROP_GULM_TAB
+    clumap['gulm_lockservers'] = lockserv_list
 
   #-------------
   #quorum disk params
@@ -3448,27 +4012,21 @@
       clumap['label'] = label
 
     heuristic_kids = qdp.getChildren()
-    h_ctr = 0
+
     for kid in heuristic_kids:
       hmap = {}
-      hname = kid.getAttribute('name')
-      if hname is None:
-        hname = h_ctr
-        h_ctr = h_ctr + 1
       hprog = kid.getAttribute('program')
-      hscore = kid.getAttribute('score')
-      hinterval = kid.getAttribute('interval')
       if hprog is None:
         continue
-      if hname is not None:
-        hmap['hname'] = hname
-      else:
-        hmap['hname'] = ""
+
+      hscore = kid.getAttribute('score')
       hmap['hprog'] = hprog
       if hscore is not None:
         hmap['hscore'] = hscore
       else:
         hmap['hscore'] = ""
+
+      hinterval = kid.getAttribute('interval')
       if hinterval is not None:
         hmap['hinterval'] = hinterval
       else:
@@ -3528,7 +4086,12 @@
       svcname = svc['name']
       svc_dict['name'] = svcname
       svc_dict['srunning'] = svc['running']
-      svcurl = baseurl + "?" + PAGETYPE + "=" + SERVICE + "&" + CLUNAME + "=" + clustername + "&servicename=" + svcname
+
+      if svc.has_key('is_vm') and svc['is_vm'] is True:
+        target_page = VM_CONFIG
+      else:
+        target_page = SERVICE
+      svcurl = baseurl + "?" + PAGETYPE + "=" + target_page + "&" + CLUNAME + "=" + clustername + "&servicename=" + svcname
       svc_dict['servicename'] = svcname
       svc_dict['svcurl'] = svcurl
       svc_dict_list.append(svc_dict)
@@ -3644,18 +4207,18 @@
 			rc = RicciCommunicator(nodename_resolved)
 		except Exception, e:
 			luci_log.debug_verbose('CStop0: [%d] RC %s: %s' \
-				% (delete, nodename_resolved, str(e)))
+				% (delete is True, str(nodename_resolved), str(e)))
 			errors += 1
 			continue
 
 		if delete is True:
 			if nodeDelete(self, rc, model, clustername, nodename, nodename_resolved, delete_cluster=True) is None:
-				luci_log.debug_verbose('CStop1: nodeDelete failed')
+				luci_log.debug_verbose('CStop1: [1] nodeDelete failed')
 				errors += 1
 		else:
 			if nodeLeave(self, rc, clustername, nodename_resolved) is None:
-				luci_log.debug_verbose('CStop2: nodeLeave %s' \
-					% (delete, nodename_resolved))
+				luci_log.debug_verbose('CStop2: [0] nodeLeave %s' \
+					% (nodename_resolved))
 				errors += 1
 	return errors
 
@@ -3670,13 +4233,13 @@
 
 def clusterDelete(self, model):
 	num_errors = clusterStop(self, model, delete=True)
-	if num_errors < 1:
-		try:
-			clustername = model.getClusterName()
-		except Exception, e:
-			luci_log.debug_verbose('clusterDelete0: unable to get cluster name')
-			return None
+	try:
+		clustername = model.getClusterName()
+	except Exception, e:
+		luci_log.debug_verbose('clusterDelete0: unable to get cluster name')
+		return None
 
+	if num_errors < 1:
 		try:
 			delCluster(self, clustername)
 		except Exception, e:
@@ -3691,6 +4254,7 @@
 		except Exception, e:
 			luci_log.debug_verbose('clusterDelete2: %s %s' \
 				% (clustername, str(e)))
+		return CLUSTERLIST
 	else:
 		luci_log.debug_verbose('clusterDelete2: %s: %d errors' \
 			% (clustername, num_errors))
@@ -3882,8 +4446,6 @@
 				% (delete_target.getName(), str(e)))
 
 		try:
-			cp = model.getClusterPtr()
-			cp.incrementConfigVersion()
 			model.setModified(True)
 			str_buf = model.exportModelAsString()
 			if not str_buf:
@@ -4100,7 +4662,13 @@
   infohash['currentservices'] = svc_dict_list
 
   fdom_dict_list = list()
+  gulm_cluster = False
   if model:
+    gulm_cluster = model.getGULMPtr() is not None
+    try:
+      infohash['gulm_lockserver'] = model.isNodeLockserver(nodename)
+    except:
+      infohash['gulm_lockserver'] = False
     #next is faildoms
     fdoms = model.getFailoverDomainsForNode(nodename)
     for fdom in fdoms:
@@ -4109,6 +4677,8 @@
       fdomurl = baseurl + "?" + PAGETYPE + "=" + FDOM_CONFIG + "&" + CLUNAME + "=" + clustername + "&fdomname=" + fdom.getName()
       fdom_dict['fdomurl'] = fdomurl
       fdom_dict_list.append(fdom_dict)
+  else:
+    infohash['gulm_lockserver'] = False
 
   infohash['fdoms'] = fdom_dict_list
 
@@ -4132,8 +4702,11 @@
     if rc is not None:
       dlist = list()
       dlist.append("ccsd")
-      dlist.append("cman")
-      dlist.append("fenced")
+      if not gulm_cluster:
+        dlist.append("cman")
+        dlist.append("fenced")
+      else:
+        dlist.append("lock_gulmd")
       dlist.append("rgmanager")
       states = getDaemonStates(rc, dlist)
       infohash['d_states'] = states
@@ -4174,13 +4747,17 @@
         except:
           luci_log.debug_verbose('GNI0: unable to determine cluster name')
           return {}
-      
- 
+
   for item in nodelist:
     map = {}
     name = item['name']
     map['nodename'] = name
     try:
+      map['gulm_lockserver'] = model.isNodeLockserver(name)
+    except:
+      map['gulm_lockserver'] = False
+
+    try:
       baseurl = req['URL']
     except:
       baseurl = '/luci/cluster/index_html'
@@ -4285,7 +4862,7 @@
               clustername = model.getClusterName()
               node_hash = {}
               node_hash['nodename'] = node.getName().strip()
-              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE 
+              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
               nodes_used.append(node_hash)
 
       map['nodesused'] = nodes_used
@@ -4299,7 +4876,7 @@
       return fd
 
   raise
-  
+
 def getFenceInfo(self, model, request):
   if not model:
     luci_log.debug_verbose('getFenceInfo00: model is None')
@@ -4342,12 +4919,12 @@
       luci_log.debug_verbose('getFenceInfo2: unable to extract nodename: %s' \
           % str(e))
       return {}
-    
+
   #Here we need to get fences for a node - just the first two levels
   #Each level has its own list of fence devs used in that level
   #For each fence dev, a list of instance structs is appended
   #In addition, for each level, a list of available but unused fence devs
-  #is returned. 
+  #is returned.
   try:
     node = model.retrieveNodeByName(nodename)
   except GeneralError, e:
@@ -4396,7 +4973,7 @@
             if kee == "name":
               continue #Don't duplicate name attr
             fencedev[kee] = kidattrs[kee]
-          #This fencedev struct is complete, and needs to be placed on the 
+          #This fencedev struct is complete, and needs to be placed on the
           #level1 Q. Because it is non-shared, we should set last_kid_fd
           #to none.
           last_kid_fd = None
@@ -4425,7 +5002,7 @@
               fencedev['unknown'] = True
               fencedev['prettyname'] = fd.getAgentType()
             fencedev['isShared'] = True
-            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV 
+            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
             fencedev['id'] = str(major_num)
             major_num = major_num + 1
             inlist = list()
@@ -4441,7 +5018,7 @@
               if kee == "name":
                 continue
               instance_struct[kee] = kidattrs[kee]
-            inlist.append(instance_struct) 
+            inlist.append(instance_struct)
             level1.append(fencedev)
             last_kid_fd = fencedev
             continue
@@ -4503,7 +5080,7 @@
             if kee == "name":
               continue #Don't duplicate name attr
             fencedev[kee] = kidattrs[kee]
-          #This fencedev struct is complete, and needs to be placed on the 
+          #This fencedev struct is complete, and needs to be placed on the
           #level2 Q. Because it is non-shared, we should set last_kid_fd
           #to none.
           last_kid_fd = None
@@ -4532,7 +5109,7 @@
               fencedev['unknown'] = True
               fencedev['prettyname'] = fd.getAgentType()
             fencedev['isShared'] = True
-            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV 
+            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
             fencedev['id'] = str(major_num)
             major_num = major_num + 1
             inlist = list()
@@ -4548,7 +5125,7 @@
               if kee == "name":
                 continue
               instance_struct[kee] = kidattrs[kee]
-            inlist.append(instance_struct) 
+            inlist.append(instance_struct)
             level2.append(fencedev)
             last_kid_fd = fencedev
             continue
@@ -4576,8 +5153,8 @@
         shared2.append(shared_struct)
     map['shared2'] = shared2
 
-  return map    
-      
+  return map
+
 def getFencesInfo(self, model, request):
   map = {}
   if not model:
@@ -4591,13 +5168,16 @@
 
   #Get list of fence devices
   fds = model.getFenceDevices()
-  nodes_used = list() #This section determines which nodes use the dev
   for fd in fds:
+    #This section determines which nodes use the dev
     #create fencedev hashmap
+    nodes_used = list()
+
     if fd.isShared() == True:
       fencedev = {}
       attr_hash = fd.getAttributes()
       kees = attr_hash.keys()
+
       for kee in kees:
         fencedev[kee] = attr_hash[kee] #copy attrs over
       try:
@@ -4605,6 +5185,7 @@
       except:
         fencedev['unknown'] = True
         fencedev['pretty_name'] = fd.getAgentType()
+
       fencedev['agent'] = fd.getAgentType()
       #Add config url for this fencedev
       fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
@@ -4625,7 +5206,7 @@
                 continue
               node_hash = {}
               node_hash['nodename'] = node.getName().strip()
-              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE 
+              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
               nodes_used.append(node_hash)
 
       fencedev['nodesused'] = nodes_used
@@ -4634,7 +5215,6 @@
   map['fencedevs'] = fencedevs
   return map
 
-    
 def getLogsForNode(self, request):
 	try:
 		nodename = request['nodename']
@@ -4693,70 +5273,43 @@
 
 	return getNodeLogs(rc)
 
-def processXenVM(self, req):
-  model = req.SESSION.get('model')
-  isNew = False
+def getVMInfo(self, model, request):
+  map = {}
+  baseurl = request['URL']
+  clustername = request['clustername']
+  svcname = None
+
   try:
-    xenvmname = req['servicename']
+    svcname = request['servicename']
   except KeyError, e:
-    isNew = True
-  
-  if isNew == True:
-    xvm = Vm()
-    xvm.addAttribute("name", req.form['xenvmname'])
-    xvm.addAttribute("path", req.form['xenvmpath'])
-    rmptr = model.getResourceManagerPtr()
-    rmptr.addChild(xvm)
-  else:
-    xvm = model.retrieveXenVMsByName(self, xenvmname)
-    xvm.addAttribute("name", req.form['xenvmname'])
-    xvm.addAttribute("path", req.form['xenvmpath'])
+    svcname = None
+  urlstring = baseurl + "?" + clustername + "&pagetype=29"
+  if svcname != None:
+    urlstring = urlstring + "&servicename=" + svcname
 
-  try:
-    cp = model.getClusterPtr()
-    cp.incrementConfigVersion()
-    model.setModified(True)
-    stringbuf = model.exportModelAsString()
-    if not stringbuf:
-      raise Exception, 'model is blank'
-  except Exception, e:
-    luci_log.debug_verbose('exportModelAsString error: %s' % str(e))
-    return None
+  map['formurl'] = urlstring
 
   try:
-    clustername = model.getClusterName()
-    if not clustername:
-      raise Exception, 'cluster name from model.getClusterName() is blank'
-  except Exception, e:
-    luci_log.debug_verbose('error: getClusterName: %s' % str(e))
-    return None
-
-  rc = getRicciAgent(self, clustername)
-  if not rc:
-    luci_log.debug_verbose('Unable to find a ricci agent for the %s cluster' % clustername)
-    return None
-
-  setClusterConf(rc, stringbuf)
-
-def getXenVMInfo(self, model, request):
-	try:
-		xenvmname = request['servicename']
-	except:
-		try:
-			xenvmname = request.form['servicename']
-		except:
-			luci_log.debug_verbose('servicename is missing from request')
-			return {}
+    vmname = request['servicename']
+  except:
+    try:
+      vmname = request.form['servicename']
+    except:
+      luci_log.debug_verbose('servicename is missing from request')
+      return map
 
-	try:
-		xenvm = model.retrieveXenVMsByName(xenvmname)
-	except:
-		luci_log.debug('An error occurred while attempting to get VM %s' \
-			% xenvmname)
-		return {}
+  try:
+    vm = model.retrieveVMsByName(vmname)
+  except:
+    luci_log.debug('An error occurred while attempting to get VM %s' \
+      % vmname)
+    return map
 
-	map = xenvm.getAttributes()
-	return map
+  attrs = vm.getAttributes()
+  keys = attrs.keys()
+  for key in keys:
+    map[key] = attrs[key]
+  return map
 
 def isClusterBusy(self, req):
   items = None
@@ -4829,7 +5382,7 @@
       node_report = {}
       node_report['isnodecreation'] = True
       node_report['iserror'] = False  #Default value
-      node_report['desc'] = item[1].getProperty(FLAG_DESC) 
+      node_report['desc'] = item[1].getProperty(FLAG_DESC)
       batch_xml = None
       ricci = item[0].split("____") #This removes the 'flag' suffix
 
@@ -4885,7 +5438,7 @@
       if batch_xml is None:  #The job is done and gone from queue
         if redirect_message == False: #We have not displayed this message yet
           node_report['desc'] = REDIRECT_MSG
-          node_report['iserror'] = True 
+          node_report['iserror'] = True
           node_report['errormessage'] = ""
           nodereports.append(node_report)
           redirect_message = True
@@ -4984,7 +5537,7 @@
             luci_log.debug_verbose('ICB16: last_status err: %s %d: %s' \
               % (item[0], creation_status, str(e)))
           continue
-          
+
     else:
       node_report = {}
       node_report['isnodecreation'] = False
@@ -5084,6 +5637,7 @@
 		itemmap['name'] = item.getName()
 		itemmap['attrs'] = item.attr_hash
 		itemmap['type'] = item.resource_type
+		itemmap['tag_name'] = item.TAG_NAME
 		itemmap['cfgurl'] = baseurl + "?" + "clustername=" + cluname + "&resourcename=" + item.getName() + "&pagetype=" + RESOURCE_CONFIG
 		itemmap['url'] = baseurl + "?" + "clustername=" + cluname + "&resourcename=" + item.getName() + "&pagetype=" + RESOURCE
 		itemmap['delurl'] = baseurl + "?" + "clustername=" + cluname + "&resourcename=" + item.getName() + "&pagetype=" + RESOURCE_REMOVE
@@ -5199,8 +5753,6 @@
 		return (False, {'errors': [ '%s: error removing service %s.' % (errstr, name) ]})
 
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf = model.exportModelAsString()
 		if not conf:
@@ -5281,8 +5833,6 @@
 		return errstr + ': the specified resource was not found.'
 
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf = model.exportModelAsString()
 		if not conf:
@@ -5298,7 +5848,7 @@
 		return errstr
 
 	try:
-		set_node_flag(self, clustername, ragent, str(batch_number), RESOURCE_REMOVE, "Removing Resource \'%s\'" % request['resourcename'])
+		set_node_flag(self, clustername, ragent, str(batch_number), RESOURCE_REMOVE, "Removing resource \'%s\'" % request['resourcename'])
 	except Exception, e:
 		luci_log.debug_verbose('delResource7: failed to set flags: %s' % str(e))
 
@@ -5306,572 +5856,1254 @@
 	response.redirect(request['URL'] + "?pagetype=" + RESOURCES + "&clustername=" + clustername + '&busyfirst=true')
 
 def addIp(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addIp error: form is missing')
+		luci_log.debug_verbose('addIp0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addIp error: model is missing')
+		luci_log.debug_verbose('addIp1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank.'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No IP resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addIp error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this IP resource.')
 	else:
 		try:
 			res = Ip()
 			if not res:
-				raise Exception, 'apply(Ip) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addIp error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating an IP resource.')
+			luci_log.debug_verbose('addIp3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addIp error: res is none')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		addr = form['ip_address'].strip()
 		if not addr:
 			raise KeyError, 'ip_address is blank'
 		# XXX: validate IP addr
-		res.attr_hash['address'] = addr
+		res.addAttribute('address', addr)
 	except KeyError, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addIp error: %s' % err)
+		luci_log.debug_verbose('addIp4: %s' % err)
 
 	if 'monitorLink' in form:
-		res.attr_hash['monitor_link'] = '1'
+		res.addAttribute('monitor_link', '1')
 	else:
-		res.attr_hash['monitor_link'] = '0'
+		res.addAttribute('monitor_link', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addFs(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addFs error: form is missing')
+		luci_log.debug_verbose('addFs0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addFs error: model is missing')
+		luci_log.debug_verbose('addFs1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank.'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No filesystem resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addFs error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this filesystem resource.')
+			luci_log.debug_verbose('addFs3: %s' % str(e))
 	else:
 		try:
 			res = Fs()
 			if not res:
-				raise Exception, 'apply(Fs) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addFs error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a filesystem resource.')
+			luci_log.debug_verbose('addFs4: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addFs error: fs obj was not created')
-		return None
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
-		res.attr_hash['name'] = name
+		if not name:
+			raise Exception, 'No name was given for this filesystem resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs5: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for this filesystem resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs6: %s' % err)
 
 	try:
 		device = form['device'].strip()
-		res.attr_hash['device'] = device
+		if not device:
+			raise Exception, 'No device was given for this filesystem resource.'
+		res.addAttribute('device', device)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs7: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs8: %s' % err)
 
 	try:
 		fstype = form['fstype'].strip()
-		res.attr_hash['fstype'] = fstype
+		if not fstype:
+			raise Exception, 'No filesystem type was given for this filesystem resource.'
+		res.addAttribute('fstype', fstype)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs9: %s' % err)
 
 	try:
 		fsid = form['fsid'].strip()
-		res.attr_hash['fsid'] = fsid
+		if not fsid:
+			raise Exception, 'No filesystem ID was given for this filesystem resource.'
+		res.addAttribute('fsid', fsid)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs10: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if form.has_key('selffence'):
-		res.attr_hash['self_fence'] = '1'
+		res.addAttribute('self_fence', '1')
 	else:
-		res.attr_hash['self_fence'] = '0'
+		res.addAttribute('self_fence', '0')
 
 	if form.has_key('checkfs'):
-		res.attr_hash['force_fsck'] = '1'
+		res.addAttribute('force_fsck', '1')
 	else:
-		res.attr_hash['force_fsck'] = '0'
+		res.addAttribute('force_fsck', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addGfs(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addGfs error: form is missing')
+		luci_log.debug_verbose('addGfs0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addGfs error: model is missing')
+		luci_log.debug_verbose('addGfs1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
-			if not res:
-				luci_log.debug('resource %s was not found for editing' % oldname)
-				return None
+				raise Exception, 'oldname is blank'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No filesystem resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug('resource %s was not found for editing: %s' \
-				% (oldname, str(e)))
-			return None
+			errors.append('No original name was found for this cluster filesystem resource.')
+			luci_log.debug_verbose('addGfs2: %s' % str(e))
 	else:
 		try:
 			res = Clusterfs()
 			if not res:
-				raise Exception, 'apply(Clusterfs) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug('addGfs error: %s' % str(e))
-			return None
-		except:
-			luci_log.debug('addGfs error')
-			return None
+			errors.append('An error occurred while creating a cluster filesystem resource.')
+			luci_log.debug('addGfs3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this cluster filesystem resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs4: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for this cluster filesystem resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs5: %s' % err)
 
 	try:
 		device = form['device'].strip()
-		res.attr_hash['device'] = device
+		if not device:
+			raise Exception, 'No device was given for this cluster filesystem resource.'
+		res.addAttribute('device', device)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs6: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs7: %s' % err)
 
 	try:
 		fsid = form['fsid'].strip()
-		res.attr_hash['fsid'] = fsid
+		if not fsid:
+			raise Exception, 'No filesystem ID was given for this cluster filesystem resource.'
+		res.addAttribute('fsid', fsid)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs8: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
+
 	return [res, model, None]
 
 def addNfsm(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsm error: form is missing')
+		luci_log.debug_verbose('addNfsm0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsm error: model is missing')
+		luci_log.debug_verbose('addNfsm1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS mount resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsm error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this NFS mount resource.')
+			luci_log.debug_verbose('addNfsm2: %s' % str(e))
 	else:
 		try:
 			res = Netfs()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addNfsm error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a NFS mount resource.')
+			luci_log.debug_verbose('addNfsm3: %s' % str(e))
 
 	if not res:
-		return None
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS mount resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm4: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for NFS mount resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
-		
+		luci_log.debug_verbose('addNfsm5: %s' % err)
+
 	try:
 		host = form['host'].strip()
-		res.attr_hash['host'] = host
+		if not host:
+			raise Exception, 'No host server was given for this NFS mount resource.'
+		res.addAttribute('host', host)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm6 error: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm7: %s' % err)
 
 	try:
 		exportpath = form['exportpath'].strip()
-		res.attr_hash['exportpath'] = exportpath 
+		if not exportpath:
+			raise Exception, 'No export path was given for this NFS mount resource.'
+		res.addAttribute('exportpath', exportpath)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm8: %s' % err)
 
 	try:
 		nfstype = form['nfstype'].strip().lower()
 		if nfstype != 'nfs' and nfstype != 'nfs4':
-			raise KeyError, 'invalid nfs type: %s' % nfstype
-		res.attr_hash['nfstype'] = nfstype
+			raise Exception, 'An invalid NFS version \"%s\" was given.' % nfstype
+		res.addAttribute('nfstype', nfstype)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm9: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addNfsc(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsc error: form is missing')
+		luci_log.debug_verbose('addNfsc0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsc error: model is missing')
+		luci_log.debug_verbose('addNfsc1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS client resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsc error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this NFS client resource.')
+			luci_log.debug_verbose('addNfsc2: %s' % str(e))
 	else:
 		try:
 			res = NFSClient()
-		except:
-			luci_log.debug_verbose('addNfsc error: %s' % str(e))
-			return None
+			if not res:
+				raise Exception, 'res is None'
+		except Exception, e:
+			errors.append('An error occurred while creating a NFS client resource.')
+			luci_log.debug_verbose('addNfsc3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addNfsc error: res is none')
-		return None
+		return [None, None, errors]
 
-	errors = list()
+	# XXX: sanity check these fields
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS client resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc4: %s' % err)
 
 	try:
 		target = form['target'].strip()
-		res.attr_hash['target'] = target 
+		if not target:
+			raise Exception, 'No target was given for NFS client resource.'
+		res.addAttribute('target', target)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc5: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc6: %s' % err)
+
+	if form.has_key('allow_recover'):
+		res.addAttribute('allow_recover', '1')
+	else:
+		res.addAttribute('allow_recover', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addNfsx(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsx error: model is missing')
+		luci_log.debug_verbose('addNfsx0: model is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsx error: model is missing')
+		luci_log.debug_verbose('addNfsx0: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS export resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsx error: %s', str(e))
-			return None
+			errors.append('No original name was found for this NFS export resource.')
+			luci_log.debug_verbose('addNfsx2: %s', str(e))
 	else:
 		try:
 			res = NFSExport()
-		except:
-			luci_log.debug_verbose('addNfsx error: %s', str(e))
-			return None
+			if not res:
+				raise Exception, 'res is None'
+		except Exception, e:
+			errors.append('An error occurred while creating a NFS clientresource.')
+			luci_log.debug_verbose('addNfsx3: %s', str(e))
 
 	if not res:
-		luci_log.debug_verbose('addNfsx error: res is None')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS export resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsx error: %s', err)
+		luci_log.debug_verbose('addNfsx4: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addScr(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addScr error: form is missing')
+		luci_log.debug_verbose('addScr0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addScr error: model is missing')
+		luci_log.debug_verbose('addScr1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No script resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addScr error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this script resource.')
+			luci_log.debug_verbose('addScr2: %s' % str(e))
 	else:
 		try:
 			res = Script()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addScr error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a script resource.')
+			luci_log.debug_verbose('addScr3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addScr error: res is None')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this script resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addScr error: %s' % err)
+		luci_log.debug_verbose('addScr4: %s' % err)
 
 	try:
 		path = form['file'].strip()
 		if not path:
-			raise KeyError, 'file path is blank'
-		res.attr_hash['file'] = path
+			raise Exception, 'No path to a script file was given for this script resource.'
+		res.addAttribute('file', path)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addScr error: %s' % err)
+		luci_log.debug_verbose('addScr5: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addSmb(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addSmb error: form is missing')
+		luci_log.debug_verbose('addSmb0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addSmb error: model is missing')
+		luci_log.debug_verbose('addSmb1: model is missing')
 		return None
 
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No Samba resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addSmb error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this Samba resource.')
+			luci_log.debug_verbose('addSmb2: %s' % str(e))
 	else:
 		try:
 			res = Samba()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addSmb error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a Samba resource.')
+			luci_log.debug_verbose('addSmb3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addSmb error: res is None')
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this Samba resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addSmb4: %s' % err)
+
+	try:
+		workgroup = form['workgroup'].strip()
+		if not workgroup:
+			raise Exception, 'No workgroup was given for this Samba resource.'
+		res.addAttribute('workgroup', workgroup)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addSmb5: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addApache(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addApache0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addApache1: model is missing')
 		return None
 
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No Apache resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this Apache resource.')
+			luci_log.debug_verbose('addApache2: %s' % str(e))
+	else:
+		try:
+			res = Apache()
+			if not res:
+				raise Exception, 'could not create Apache object'
+		except Exception, e:
+			errors.append('An error occurred while creating an Apache resource.')
+			luci_log.debug_verbose('addApache3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this Apache resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache4: %s' % err)
+
+	try:
+		server_root = form['server_root'].strip()
+		if not server_root:
+			raise KeyError, 'No server root was given for this Apache resource.'
+		res.addAttribute('server_root', server_root)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache5: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not server_root:
+			raise KeyError, 'No path to the Apache configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache6: %s' % err)
+
+	try:
+		options = form['httpd_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('httpd_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('httpd_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', str(shutdown_wait))
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', '0')
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addMySQL(request, form=None):
 	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addMySQL0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addMySQL1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No MySQL resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this MySQL resource.')
+			luci_log.debug_verbose('addMySQL2: %s' % str(e))
+	else:
+		try:
+			res = MySQL()
+			if not res:
+				raise Exception, 'could not create MySQL object'
+		except Exception, e:
+			errors.append('An error occurred while creating a MySQL resource.')
+			luci_log.debug_verbose('addMySQL3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this MySQL resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addSmb error: %s' % err)
+		luci_log.debug_verbose('addMySQL4: %s' % err)
 
 	try:
-		workgroup = form['workgroup'].strip()
-		res.attr_hash['workgroup'] = workgroup
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the MySQL configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL5: %s' % err)
+
+	try:
+		listen_addr = form['listen_address'].strip()
+		if not listen_addr:
+			raise KeyError, 'No address was given for MySQL server to listen on.'
+		res.addAttribute('listen_address', listen_addr)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL6: %s' % err)
+
+	try:
+		options = form['mysql_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('mysql_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('mysql_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', str(shutdown_wait))
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', '0')
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addOpenLDAP(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addOpenLDAP0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addOpenLDAP1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No OpenLDAP resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this OpenLDAP resource.')
+			luci_log.debug_verbose('addOpenLDAP2: %s' % str(e))
+	else:
+		try:
+			res = OpenLDAP()
+			if not res:
+				raise Exception, 'could not create OpenLDAP object'
+		except Exception, e:
+			errors.append('An error occurred while creating an OpenLDAP resource.')
+			luci_log.debug_verbose('addOpenLDAP3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this OpenLDAP resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP4: %s' % err)
+
+	try:
+		url_list = form['url_list'].strip()
+		if not url_list:
+			raise KeyError, 'No URL list was given for this OpenLDAP resource.'
+		res.addAttribute('url_list', url_list)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP5: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the OpenLDAP configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP6: %s' % err)
+
+	try:
+		options = form['slapd_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('slapd_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('slapd_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', str(shutdown_wait))
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', '0')
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addSmb error: %s' % err)
+		luci_log.debug_verbose('addOpenLDAP7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addPostgres8(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addPostgreSQL80: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addPostgreSQL81: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No PostgreSQL 8 resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this PostgreSQL 8 resource.')
+			luci_log.debug_verbose('addPostgreSQL82: %s' % str(e))
+	else:
+		try:
+			res = Postgres8()
+			if not res:
+				raise Exception, 'could not create PostgreSQL 8 object'
+		except Exception, e:
+			errors.append('An error occurred while creating a PostgreSQL 8 resource.')
+			luci_log.debug_verbose('addPostgreSQL83: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this PostgreSQL 8 resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL84: %s' % err)
+
+	try:
+		user = form['postmaster_user'].strip()
+		if not user:
+			raise KeyError, 'No postmaster user was given for this PostgreSQL 8 resource.'
+		res.addAttribute('postmaster_user', user)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL85: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the PostgreSQL 8 configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL86: %s' % err)
+
+	try:
+		options = form['postmaster_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('postmaster_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('postmaster_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL87: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', str(shutdown_wait))
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', '0')
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL87: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addTomcat5(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addTomcat50: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addTomcat51: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No Tomcat 5 resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this Tomcat 5 resource.')
+			luci_log.debug_verbose('addTomcat52: %s' % str(e))
+	else:
+		try:
+			res = Tomcat5()
+			if not res:
+				raise Exception, 'could not create Tomcat5 object'
+		except Exception, e:
+			errors.append('An error occurred while creating a Tomcat 5 resource.')
+			luci_log.debug_verbose('addTomcat53: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this Tomcat 5 resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat54: %s' % err)
+
+	try:
+		user = form['tomcat_user'].strip()
+		if not user:
+			raise KeyError, 'No user was given for this Tomcat 5 resource.'
+		res.addAttribute('tomcat_user', user)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat55: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the Tomcat 5 configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat56: %s' % err)
+
+	try:
+		options = form['catalina_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('catalina_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('catalina_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat57: %s' % err)
+
+	try:
+		catalina_base = form['catalina_base'].strip()
+		if not catalina_base:
+			raise KeyError, 'No cataliny base directory was given for this Tomcat 5 resource.'
+		res.addAttribute('catalina_base', catalina_base)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat58: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', str(shutdown_wait))
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', '0')
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat59: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addLVM(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addLVM0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addLVM1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No LVM resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this LVM resource.')
+			luci_log.debug_verbose('addLVM2: %s' % str(e))
+	else:
+		try:
+			res = LVM()
+			if not res:
+				raise Exception, 'could not create LVM object'
+		except Exception, e:
+			errors.append('An error occurred while creating a LVM resource.')
+			luci_log.debug_verbose('addLVM3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this LVM resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addLVM4: %s' % err)
+
+	try:
+		vg_name = form['vg_name'].strip()
+		if not vg_name:
+			raise KeyError, 'No volume group name was given.'
+		res.addAttribute('vg_name', vg_name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addLVM5: %s' % err)
+
+	try:
+		lv_name = form['lv_name'].strip()
+		if not lv_name:
+			raise KeyError, 'No logical volume name was given.'
+		res.addAttribute('lv_name', lv_name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addLVM6: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
@@ -5885,7 +7117,13 @@
 	'nfsx': addNfsx,
 	'nfsc': addNfsc,
 	'scr': addScr,
-	'smb': addSmb
+	'smb': addSmb,
+	'tomcat-5': addTomcat5,
+	'postgres-8': addPostgres8,
+	'apache': addApache,
+	'openldap': addOpenLDAP,
+	'lvm': addLVM,
+	'mysql': addMySQL
 }
 
 def resolveClusterChanges(self, clusterName, model):
@@ -5962,7 +7200,7 @@
 			messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s,\". but it has not been added to the management interface for this cluster as a result of an error creating a database entry for it.' % (i, clusterName))
 			luci_log.debug_verbose('VCC5: addFolder: %s/%s: %s' \
 				% (clusterName, i, str(e)))
-	
+
 	return messages
 
 def addResource(self, request, model, res, res_type):
@@ -5983,8 +7221,6 @@
 		return 'Unable to add the new resource'
 
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
 		model.setModified(True)
 		conf = model.exportModelAsString()
 		if not conf:
@@ -6014,7 +7250,17 @@
 		res_name = res.attr_hash['address']
 
 	try:
-		set_node_flag(self, clustername, ragent, str(batch_number), RESOURCE_ADD, "Creating New Resource \'%s\'" % res_name)
+		try:
+			if request.form.has_key('edit'):
+				action_type = RESOURCE_CONFIG
+				action_str = 'Configuring resource \"%s\"' % res_name
+			else:
+				raise Exception, 'new'
+		except Exception, e:
+			action_type = RESOURCE_ADD
+			action_str = 'Creating new resource \"%s\"' % res_name
+
+		set_node_flag(self, clustername, ragent, str(batch_number), action_type, action_str)
 	except Exception, e:
 		luci_log.debug_verbose('addResource7: failed to set flags: %s' % str(e))
 
@@ -6049,7 +7295,7 @@
 		request.SESSION.set('model', model)
 	except:
 		luci_log.debug_verbose('Appending model to request failed')
-		return 'An error occurred while storing the cluster model.' 
+		return 'An error occurred while storing the cluster model.'
 
 def resolve_nodename(self, clustername, nodename):
 	path = str(CLUSTER_FOLDER_PATH + clustername)
@@ -6058,7 +7304,7 @@
 		clusterfolder = self.restrictedTraverse(path)
 		objs = clusterfolder.objectItems('Folder')
 	except Exception, e:
-		luci_log.info('RNN0: error for %s/%s: %s' \
+		luci_log.debug_verbose('RNN0: error for %s/%s: %s' \
 			% (nodename, clustername, str(e)))
 		return nodename
 
@@ -6069,7 +7315,7 @@
 		except:
 			continue
 
-	luci_log.info('RNN1: failed for %s/%s: nothing found' \
+	luci_log.debug_verbose('RNN1: failed for %s/%s: nothing found' \
 		% (nodename, clustername))
 	return nodename
 
@@ -6206,7 +7452,7 @@
 			msg += 'Fix the error and try again:\n'
 		else:
 			msg += 'PASSED\n'
-			
+
 			msg += 'Making sure no clustername change has accured - '
 			new_name = cc_xml.firstChild.getAttribute('name')
 			if new_name != clustername:
@@ -6214,13 +7460,13 @@
 				msg += 'Fix the error and try again:\n'
 			else:
 				msg += 'PASSED\n'
-				
+
 				msg += 'Increasing cluster version number - '
 				version = cc_xml.firstChild.getAttribute('config_version')
 				version = int(version) + 1
 				cc_xml.firstChild.setAttribute('config_version', str(version))
 				msg += 'DONE\n'
-				
+
 				msg += 'Propagating new cluster.conf'
 				rc = getRicciAgent(self, clustername)
 				if not rc:
@@ -6231,7 +7477,7 @@
 					if batch_id is None or result is None:
 						luci_log.debug_verbose('VFA: setClusterConf: batchid or result is None')
 						msg += '\nUnable to propagate the new cluster configuration for ' + clustername + '\n\n'
-					else:	
+					else:
 						msg += ' - DONE\n'
 						cc = cc_xml.toxml()
 						msg += '\n\nALL DONE\n\n'
--- conga/luci/site/luci/Extensions/conga_constants.py	2007/01/15 18:21:50	1.19.2.7
+++ conga/luci/site/luci/Extensions/conga_constants.py	2007/03/01 00:31:08	1.19.2.8
@@ -13,8 +13,8 @@
 NODE_ADD="15"
 NODE_PROCESS="16"
 NODE_LOGS="17"
-XENVM_ADD="18"
-XENVM_CONFIG="19"
+VM_ADD="18"
+VM_CONFIG="19"
 SERVICES="20"
 SERVICE_ADD="21"
 SERVICE_LIST="22"
@@ -24,7 +24,7 @@
 SERVICE_START="26"
 SERVICE_STOP="27"
 SERVICE_RESTART="28"
-XENVM_PROCESS="29"
+VM_PROCESS="29"
 RESOURCES="30"
 RESOURCE_ADD="31"
 RESOURCE_LIST="32"
@@ -73,6 +73,7 @@
 PROP_FENCE_TAB = '2'
 PROP_MCAST_TAB = '3'
 PROP_QDISK_TAB = '4'
+PROP_GULM_TAB = '5'
 
 PAGETYPE="pagetype"
 ACTIONTYPE="actiontype"
--- conga/luci/site/luci/Extensions/homebase_adapters.py	2007/01/10 22:53:56	1.34.2.11
+++ conga/luci/site/luci/Extensions/homebase_adapters.py	2007/03/01 00:31:08	1.34.2.12
@@ -278,7 +278,7 @@
 		if not cluster_info:
 			errmsg = 'An error occurred while attempting to retrieve the cluster.conf file from \"%s\"' % cur_host
 		else:
-			errmsg = '\"%s\" reports is not a member of any cluster.'
+			errmsg = '\"%s\" reports is not a member of any cluster.' % cur_host
 		return (False, { 'errors': [ errmsg ] })
 
 	cluster_name = cluster_info[0]
@@ -571,7 +571,7 @@
 				if not prev_auth:
 					try:
 						rc.unauth()
-					except:
+					except Exception, e:
 						luci_log.debug_verbose('VAC4: %s: %s' % (cur_host, str(e)))
 
 				errors.append(err_msg)
--- conga/luci/site/luci/Extensions/ricci_bridge.py	2007/01/08 19:49:20	1.30.2.17
+++ conga/luci/site/luci/Extensions/ricci_bridge.py	2007/03/01 00:31:08	1.30.2.18
@@ -47,7 +47,8 @@
 			install_services,
 			install_shared_storage,
 			install_LVS,
-			upgrade_rpms):
+			upgrade_rpms,
+			gulm):
 	
 	batch = '<?xml version="1.0" ?>'
 	batch += '<batch>'
@@ -63,7 +64,10 @@
 	batch += '"/>'
 	batch += '<var name="sets" type="list_xml">'
 	if install_base or install_services or install_shared_storage:
-		batch += '<set name="Cluster Base"/>'
+		if gulm:
+			batch += '<set name="Cluster Base - Gulm"/>'
+		else:
+			batch += '<set name="Cluster Base"/>'
 	if install_services:
 		batch += '<set name="Cluster Service Manager"/>'
 	if install_shared_storage:
@@ -80,7 +84,10 @@
 	batch += '<function_call name="disable">'
 	batch += '<var mutable="false" name="services" type="list_xml">'
 	if install_base or install_services or install_shared_storage:
-		batch += '<set name="Cluster Base"/>'
+		if gulm:
+			batch += '<set name="Cluster Base - Gulm"/>'
+		else:
+			batch += '<set name="Cluster Base"/>'
 	if install_services:
 		batch += '<set name="Cluster Service Manager"/>'
 	if install_shared_storage:
@@ -153,7 +160,8 @@
 		       install_services,
 		       install_shared_storage,
 		       install_LVS,
-		       upgrade_rpms):
+		       upgrade_rpms,
+		       gulm_lockservers):
 	
 	batch = '<?xml version="1.0" ?>'
 	batch += '<batch>'
@@ -169,7 +177,10 @@
 	batch += '"/>'
 	batch += '<var name="sets" type="list_xml">'
 	if install_base or install_services or install_shared_storage:
-		batch += '<set name="Cluster Base"/>'
+		if gulm_lockservers:
+			batch += '<set name="Cluster Base - Gulm"/>'
+		else:
+			batch += '<set name="Cluster Base"/>'
 	if install_services:
 		batch += '<set name="Cluster Service Manager"/>'
 	if install_shared_storage:
@@ -186,7 +197,10 @@
 	batch += '<function_call name="disable">'
 	batch += '<var mutable="false" name="services" type="list_xml">'
 	if install_base or install_services or install_shared_storage:
-		batch += '<set name="Cluster Base"/>'
+		if gulm_lockservers:
+			batch += '<set name="Cluster Base - Gulm"/>'
+		else:
+			batch += '<set name="Cluster Base"/>'
 	if install_services:
 		batch += '<set name="Cluster Service Manager"/>'
 	if install_shared_storage:
@@ -228,12 +242,19 @@
 			batch += '<clusternode name="' + i + '" votes="1" nodeid="' + str(x) + '" />'
 		x = x + 1
 	batch += '</clusternodes>'
-	if len(nodeList) == 2:
-		batch += '<cman expected_votes="1" two_node="1"/>'
-	else:
-		batch += '<cman/>'
+
+	if not gulm_lockservers:
+		if len(nodeList) == 2:
+			batch += '<cman expected_votes="1" two_node="1"/>'
+		else:
+			batch += '<cman/>'
 	batch += '<fencedevices/>'
 	batch += '<rm/>'
+	if gulm_lockservers:
+		batch += '<gulm>'
+		for i in gulm_lockservers:
+			batch += '<lockserver name="%s" />' % i
+		batch += '</gulm>'
 	batch += '</cluster>'
 	batch += '</var>'
 	batch += '</function_call>'
--- conga/luci/site/luci/Extensions/ricci_communicator.py	2007/01/04 00:22:13	1.9.2.9
+++ conga/luci/site/luci/Extensions/ricci_communicator.py	2007/03/01 00:31:08	1.9.2.10
@@ -165,7 +165,7 @@
             pass
 
         if not self.authed():
-            raise RicciError, 'not authenticated to host %s', self.__hostname
+            raise RicciError, 'not authenticated to host %s' % self.__hostname
         
         # construct request
         doc = minidom.Document()
Binary files /cvs/cluster/conga/luci/site/luci/var/Data.fs	2007/01/23 22:34:28	1.15.2.9 and /cvs/cluster/conga/luci/site/luci/var/Data.fs	2007/03/01 00:31:08	1.15.2.10 differ
rcsdiff: /cvs/cluster/conga/luci/site/luci/var/Data.fs: diff failed
/cvs/cluster/conga/luci/test/CGA_0160_Add_User.py,v  -->  standard output
revision 1.7.2.1
--- conga/luci/test/CGA_0160_Add_User.py
+++ -	2007-03-01 00:31:28.094711000 +0000
@@ -0,0 +1,219 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    CGA_0160_Add_User.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0
+Summary:        Test for Conga use case CGA-160 - Adding a new user 
+                http://sourceware.org/cluster/conga/usecases/cga-0160.html
+                
+                The sequence of actions is:
+                
+                As admin:
+                    Login
+                    Add systems
+                    Add users
+                    Assign user to a machine
+                    Logout
+  
+                As each user:  
+                    Login
+                    Verify user view machine storage
+                    Verify user cannot view other machines
+                    Logout
+  
+                As admin:
+                    Login
+                    Delete systems
+                    Delete users
+                    Logout
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from selenium import selenium
+import unittest, time, re
+from conga_Helpers import *
+import time
+import logging
+from loggerObject import loggerObject
+
+class CGA_0160_Add_User (unittest.TestCase):
+
+    def setUp(self): 
+        
+        # Set up logging      
+        self.theloggerObject = setupLogger (CONGA_DEBUG_LOG)
+        self.logger = self.theloggerObject.getLogger()
+        self.logger.info('-----------------------------------------------------------') 
+             
+        """Establish connection to selenium server, login to luci """
+        self.verificationErrors = []
+        self.selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)
+
+        """Test to create and delete storage systems"""
+        sel = self.selenium
+
+        # Create the storage systems
+        for systemName in CONGA_STORAGE_SYSTEMS:
+            createStorageSystem(sel, systemName, CONGA_STORAGE_SYSTEMS[systemName], self.logger)
+            # Validation - verify that the success message was displayed for each storage system
+            self.assertEqual("Do you really want to add the following Storage Systems:\n" + systemName, sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Added storage system "' + systemName + '" successfully'))               
+        
+        # Return to homebase page
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)     
+
+        # Create the users
+        for userName in CONGA_USERS.keys(): 
+            createUser (sel, userName, CONGA_USERS[userName], self.logger)
+            # Validation - verify that the success message was displayed for each user
+            self.assertEqual('Do you really want to add the user "' + userName + '"?', sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Added new user "' + userName + '" successfully')) 
+     
+        # Return to homebase page
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)    
+
+        # Assign permissions to users as defined in CONGA_USERS_SYSTEMS
+        for userName in CONGA_USERS_SYSTEMS:
+            # Temporary - 20061205 - only tng3-2, 3-3, and 3-5 are reliable systems right now
+            #if ((userName == 'user2') or (userName == 'user3') or (userName == 'user5') ):
+                systemName = CONGA_USERS_SYSTEMS[userName]
+                # Replace . with _ in system name to match HTML
+                systemNameMod = systemName.replace('.', '_')
+
+                sel.click("link=User Permissions")
+                sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                
+                sel.select("userList", "label=" + userName)
+                sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                sel.click("name=__SYSTEM:" + systemNameMod)
+                
+                sel.click("document.adminform.elements['Update Permissions']")
+                sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                # The following statement is failing - not clear why - is luci not displaying the confirm dialog?
+                #self.assertEqual('Modify permissions for ' + userName, sel.get_confirmation())  - why is this failing?
+                sel.get_confirmation()
+                #print "DEBUG = " + userName + " " + systemName
+                self.assertTrue (sel.is_text_present('Added permission for ' + userName + ' for system ' + systemName))
+ 
+        # Logout as admin
+        logout(self.selenium)
+
+    def test_create_users_systems(self):
+        """Test to verify user permissions - control of access to view systems"""
+        
+        self.logger.info('Starting test case CGA_0160_Add_User.test_create_users_systems') 
+        
+        # Validation: Two part test:
+        #   1) Verify that the loggedin user can see the systems for which they have authorization
+        #   2) Verify that the loggedin user cannot see any other systems
+        for loggedInUser in CONGA_USERS:
+            self.selenium = login (loggedInUser, CONGA_USERS[loggedInUser])
+            sel = self.selenium 
+            sel.click("link=storage")
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            
+            for userName in CONGA_USERS_SYSTEMS:
+                    #print "DEBUG - loggedInUser=" + loggedInUser + " userName=" + userName
+                    if (loggedInUser == userName):
+                        # Validation 1 - seeing authorized systems
+                        self.logger.info('Verify user ' + userName + ' is able to access authorized systems')
+                        self.assertTrue (sel.is_text_present(CONGA_USERS_SYSTEMS[loggedInUser]))
+                                               
+                        sel.click("link=" + CONGA_USERS_SYSTEMS[loggedInUser])
+                        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                        
+                        # Comment out this code - 20061206 - this is causing the Zope
+                        # server to crash - need to investigate - maybe an internal
+                        # Zope timer?
+                        loopCounter = 1
+                        while loopCounter < 6:
+                            try:
+                                sel.click("link=Hard Drives")
+                                sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                                self.assertTrue (sel.is_text_present('hda'))
+                                break
+                            except:
+                                self.logger.info('Failed to view hard disk - assume slow reponse - trying again')
+                            loopCounter = loopCounter +1    
+                            time.sleep (30)
+                        
+                    else:
+                        # Validation 2 - not seeing other systems
+                        self.logger.info('Verify user ' + loggedInUser + ' is not able to access unauthorized system ' + CONGA_USERS_SYSTEMS[userName])
+                        self.assertFalse (sel.is_text_present(CONGA_USERS_SYSTEMS[userName]))
+                        
+            logout(self.selenium)  
+                   
+            self.logger.info('Ending test case CGA_0160_Add_User.test_create_users_systems') 
+
+    def tearDown(self):        
+        # login as admin
+        self.selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)
+        sel = self.selenium 
+        
+        # Return to homebase page
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)     
+
+        # View the defined storage systems 
+        sel.select_window("null")
+        sel.click("link=Manage Systems")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+
+        # Delete the storage systems
+        for systemName in CONGA_STORAGE_SYSTEMS:
+            deleteStorageSystem(sel, systemName, self.logger)
+            # Validation - verify that the success message was displayed for each storage system
+            self.assertEqual("Do you really want to remove the following managed systems:\nStorage Systems:\n-" + systemName, sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Removed storage system "' + systemName + '" successfully'))
+ 
+        # Return to homebase page
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)     
+
+        # Delete the users 
+        for userName in CONGA_USERS.keys(): 
+            deleteUser (sel, userName, self.logger)
+            # Validation - verify that the success message was displayed for each user
+            self.assertEqual('Do you really want to remove the user "' + userName + '"?', sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('User "' + userName + '" has been deleted'))  
+       
+        """Logout and stop Selenium session"""
+        logout(self.selenium)
+        self.assertEqual([], self.verificationErrors)
+        closeLogger (self.theloggerObject)
+
+def suite():
+        suite = unittest.TestSuite()
+        suite.addTest(CGA_0160_Add_User('test_create_users_systems'))
+        return suite
+
+if __name__ == "__main__":
+    #unittest.main()
+    unittest.TextTestRunner( verbosity=2 ).run( suite() )
/cvs/cluster/conga/luci/test/CGA_0170_Online_Documentation_Portlet.py,v  -->  standard output
revision 1.1.4.1
--- conga/luci/test/CGA_0170_Online_Documentation_Portlet.py
+++ -	2007-03-01 00:31:28.173755000 +0000
@@ -0,0 +1,91 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    GA_0170_Online_Documentation_Portlet.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0
+Summary:        Test for Conga use case CGA-0170 - verify the online user documentation
+                Regression test for: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=212991
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from selenium import selenium
+import unittest, time, re
+from conga_Helpers import *
+import time
+import logging
+from loggerObject import loggerObject
+
+class CGA_0170_Online_Documentation_Portlet (unittest.TestCase):
+
+    def setUp(self):      
+               
+        # Set up logging      
+        self.theloggerObject = setupLogger (CONGA_DEBUG_LOG)
+        self.logger = self.theloggerObject.getLogger()
+        self.logger.info('-----------------------------------------------------------') 
+  
+        """Establish connection to selenium server, login to luci """
+        self.verificationErrors = []
+        self.selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)
+
+        """Test to create and delete storage systems"""
+        sel = self.selenium
+
+    def test_docs(self):
+        """Test to verify on-line Help docs"""
+        self.logger.info('Starting test case CGA_0170_Online_Documentation_Portlet.test_docs')
+        
+        sel = self.selenium
+        
+        # Access the on-line help
+        sel.click("link=help")
+        sel.wait_for_pop_up("Conga Help", "30000")        
+        sel.select_window('Conga Help')
+        
+        # Grab all the text       
+        theText = sel.get_html_source()
+
+        # Validation - check the offsets for the items in the HELP list             
+        for theItem in HELP_LIST:
+            self.logger.debug('Verify offset of help text "' + theItem + '" = ' + str(theText.index(theItem)))
+            self.assertEqual (theText.index(theItem), HELP_DICTIONARY[theItem])
+            
+        # Select the main window    
+        sel.select_window('null')
+        
+        self.logger.info('Ending test case CGA_0170_Online_Documentation_Portlet.test_docs')
+  
+    def tearDown(self):  
+        """Logout and stop Selenium session"""
+        logout(self.selenium)
+        self.assertEqual([], self.verificationErrors)
+        closeLogger (self.theloggerObject)
+
+def suite():
+        suite = unittest.TestSuite()
+        suite.addTest(CGA_0170_Online_Documentation_Portlet('test_docs'))
+        return suite
+
+if __name__ == "__main__":
+    #unittest.main()
+    unittest.TextTestRunner( verbosity=2 ).run( suite() )
/cvs/cluster/conga/luci/test/CGA_0200_Create_cluster.py,v  -->  standard output
revision 1.4.2.1
--- conga/luci/test/CGA_0200_Create_cluster.py
+++ -	2007-03-01 00:31:28.253255000 +0000
@@ -0,0 +1,141 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    CGA_0200_Create_cluster.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0 (http://www.openqa.org/selenium/)
+Summary:        Simple, demo/prototype test for Conga
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from conga_Helpers import *
+from selenium import selenium
+import unittest, time, re
+
+class CGA_0200_Create_cluster(unittest.TestCase):
+
+    def setUp(self):
+        # Set up logging      
+        self.theloggerObject = setupLogger (CONGA_DEBUG_LOG)
+        self.logger = self.theloggerObject.getLogger()
+        self.logger.info('-----------------------------------------------------------') 
+        
+        """Establish connection to selenium server, login to luci """
+        self.verificationErrors = []
+        self.selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)
+ 
+    def test_congaCluster(self):
+        """Test to create and delete a cluster"""
+
+        self.logger.info('Starting test case CGA_0200_Create_cluster.test_congaCluster')
+
+        # TODO - Need to generalize this function - but as of 20061129, note tng3-1 
+        # is not responding to the creation of a cluster
+        sel = self.selenium
+        sel.open("/luci/homebase")
+        sel.click("link=cluster")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=Create a New Cluster")
+
+        # Create the new "testCluster" cluster
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.type("clusterName", "testCluster")
+        self.logger.debug('Create cluster: testCluster')
+
+        # Add the nodes to the cluster
+        # Needed to generalize statements like this:
+        #     sel.type("__SYSTEM1:Addr", "tng3-2.lab.msp.redhat.com")
+        #     sel.type("__SYSTEM1:Passwd", "password")
+        #     sel.click("//input[ value='Add Another Row']")
+        systemCounter = 0
+        for systemName in CONGA_SMALL_CLUSTER_SYSTEMS.keys():
+            sel.type("__SYSTEM" + str(systemCounter) + ":Addr", systemName)
+            sel.type("__SYSTEM" + str(systemCounter) + ":Passwd", CONGA_SMALL_CLUSTER_SYSTEMS[systemName])
+            systemCounter = systemCounter + 1
+            if (systemCounter > 2):
+                sel.click("//input[ value='Add Another Row']")          
+        #sel.click("document.adminform.rhn_dl[1]")
+        sel.click("Submit")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+
+        self.assertEqual('Add the cluster "testCluster" to the Luci management interface?' , sel.get_confirmation())
+        #sel.click("link=testCluster")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+
+        # Wait 5 minutes for the cluster nodes to be rebooted
+        time.sleep (300)
+
+        # Validation - verify that the newly created cluster shows up in the cluster list        
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=Manage Systems")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        self.assertTrue (sel.is_text_present('testCluster'))
+        self.assertTrue (sel.is_element_present("name=__CLUSTER:testCluster"))
+        
+        # Then - delete the cluster
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=cluster")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.select("cluster_action", "label=Delete this cluster")
+        sel.click("//input[ value='Go']")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=Manage Systems")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)       
+
+        # Delete the storage systems created when the cluster was created
+        for systemName in CONGA_SMALL_CLUSTER_SYSTEMS:
+            deleteStorageSystem(sel, systemName, self.logger)
+           # Validation - verify that the success message was displayed for each storage system
+            self.assertEqual("Do you really want to remove the following managed systems:\nStorage Systems:\n-" + systemName, sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Removed storage system "' + systemName + '" successfully'))
+
+        # And the cluster reference in the storage system list too
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=Manage Systems")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("__CLUSTER0")
+        sel.click("document.adminform.Submit")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        self.assertEqual("Do you really want to remove the following managed systems:\nClusters:\n-testCluster", sel.get_confirmation())
+
+        self.logger.info('Ending test case CGA_0200_Create_cluster.test_congaCluster')
+
+    def tearDown(self):
+        """Logout and stop Selenium session"""
+        logout(self.selenium)
+        self.assertEqual([], self.verificationErrors)
+        closeLogger (self.theloggerObject)
+
+def suite():
+        suite = unittest.TestSuite()
+        suite.addTest(CGA_0200_Create_cluster('test_congaCluster'))
+        return suite
+
+if __name__ == "__main__":
+    #unittest.main()
+    unittest.TextTestRunner(verbosity=2).run(suite())
/cvs/cluster/conga/luci/test/cleaner.py,v  -->  standard output
revision 1.1.4.1
--- conga/luci/test/cleaner.py
+++ -	2007-03-01 00:31:28.334293000 +0000
@@ -0,0 +1,102 @@
+#! /usr/bin/env python
+
+'''
+Script name:    cleaner.py
+Creation date:  Feb 2007
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0
+Summary:        Script to clean up all Conga test suite related artifacts - this script will be 
+                before Conga use case tests
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from selenium import selenium
+import unittest, time, re
+from conga_Helpers import *
+import time
+import logging
+from loggerObject import loggerObject
+
+class cleaner:
+    
+    def cleanup(self):
+
+        selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)
+        sel = selenium
+        theloggerObject = setupLogger (CONGA_DEBUG_LOG)
+        logger = theloggerObject.getLogger()
+        
+        # Step 1 of 3 - Delete all clusters
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.click("link=cluster")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        
+        #####################
+            
+            
+        junk = sel.get_text("cluster_action")
+        print junk
+        print sel.get_body_text()
+        print '============================='
+        
+                
+        tempBool = sel.is_element_present("cluster_action")
+        if (tempBool == True):
+            sel.select("cluster_action", "label=Delete this cluster")
+            sel.click("//input[ value='Go']")
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            time.sleep(300)
+        else:
+            print 'No cluster to delete'
+           
+        sel.click("link=homebase")
+        
+        # Create the users
+#        for userName in CONGA_USERS.keys(): 
+#            createUser (sel, userName, CONGA_USERS[userName], logger)
+#            # Validation - verify that the success message was displayed for each user
+#            assertEqual('Do you really want to add the user "' + userName + '"?', sel.get_confirmation())
+#            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+#            assertTrue (sel.is_text_present('Added new user "' + userName + '" successfully')) 
+#     
+###############################################################################
+        # Delete the users 
+        for userName in CONGA_USERS.keys(): 
+            deleteUser (sel, userName, logger)
+            # Validation - verify that the success message was displayed for each user
+            try:
+                assertEqual('Do you really want to remove the user "' + userName + '"?', sel.get_confirmation())
+                sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                assertTrue (sel.is_text_present('User "' + userName + '" has been deleted'))  
+            except:
+                print 'Unable to delete user: ' + userName + ' does it exist?'
+    
+        
+#        # Create the storage systems
+#        for systemName in CONGA_STORAGE_SYSTEMS:
+#            createStorageSystem(sel, systemName, CONGA_STORAGE_SYSTEMS[systemName], logger)
+#            # Validation - verify that the success message was displayed for each storage system
+#            assertEqual("Do you really want to add the following Storage Systems:\n" + systemName, sel.get_confirmation())
+#            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+#            assertTrue (sel.is_text_present('Added storage system "' + systemName + '" successfully'))            
+#            
+
+        tempBool = sel.is_element_present("link=Manage Systems")
+        if (tempBool == True):
+             # Delete the storage systems
+            for systemName in CONGA_STORAGE_SYSTEMS:
+                deleteStorageSystem(sel, systemName, logger)
+                try:
+                    # Validation - verify that the success message was displayed for each storage system
+                    assertEqual("Do you really want to remove the following managed systems:\nStorage Systems:\n-" + systemName, sel.get_confirmation())
+                    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+                    assertTrue (sel.is_text_present('Removed storage system "' + systemName + '" successfully'))
+                except:
+                    print 'Unable to delete system: ' + systemName + ' does it exist?'
+        else:
+            print 'No systems to delete'
+           
+        sel = selenium.stop()
+             
\ No newline at end of file
/cvs/cluster/conga/luci/test/congaDemoTests.py,v  -->  standard output
revision 1.11.2.1
--- conga/luci/test/congaDemoTests.py
+++ -	2007-03-01 00:31:28.417350000 +0000
@@ -0,0 +1,128 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    congaDemoTests.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0 (http://www.openqa.org/selenium/)
+Summary:        Simple, demo/prototype test for Conga
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from conga_Helpers import *
+from selenium import selenium
+import unittest, time, re
+import logging
+from loggerObject import loggerObject
+from cleaner import *
+
+class congaDemoTests(unittest.TestCase):
+
+    def setUp(self):
+        
+        temp = cleaner()    
+        temp.cleanup()
+        
+        # Set up logging      
+        self.theloggerObject = setupLogger (CONGA_DEBUG_LOG)
+        self.logger = self.theloggerObject.getLogger()
+        self.logger.info('-----------------------------------------------------------') 
+        
+        """Establish connection to selenium server, login to luci """
+        self.verificationErrors = []
+        self.selenium = login (CONGA_ADMIN_USERNAME, CONGA_ADMIN_PASSWORD)     
+ 
+    def test_congaStorage(self):
+        """Test to create and delete storage systems"""
+        self.logger.info('Starting test case congaDemoTests.test_congaStorage')    
+        sel = self.selenium
+
+        # Create the storage systems
+        for systemName in CONGA_STORAGE_SYSTEMS:
+            createStorageSystem(sel, systemName, CONGA_STORAGE_SYSTEMS[systemName], self.logger)
+            # Validation - verify that the success message was displayed for each storage system
+            self.assertEqual("Do you really want to add the following Storage Systems:\n" + systemName, sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Added storage system "' + systemName + '" successfully'))            
+            
+        # View the defined storage systems 
+        sel.select_window("null")
+        sel.click("link=Manage Systems")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+
+        # Delete the storage systems
+        for systemName in CONGA_STORAGE_SYSTEMS:
+            deleteStorageSystem(sel, systemName, self.logger)
+           # Validation - verify that the success message was displayed for each storage system
+            self.assertEqual("Do you really want to remove the following managed systems:\nStorage Systems:\n-" + systemName, sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Removed storage system "' + systemName + '" successfully'))
+
+        self.logger.info('Ending test case congaDemoTests.test_congaStorage')
+        
+    def test_congaUsers(self):
+        """Test to create and delete conga users"""
+        self.logger.info('Starting test case congaDemoTests.test_congaUsers')        
+        sel = self.selenium
+
+        # Create the users
+        for userName in CONGA_USERS.keys(): 
+            createUser (sel, userName, CONGA_USERS[userName], self.logger)
+            # Validation - verify that the success message was displayed for each user
+            self.assertEqual('Do you really want to add the user "' + userName + '"?', sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('Added new user "' + userName + '" successfully')) 
+
+        # Return to homebase page
+        sel.click("link=homebase")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)     
+
+        # Delete the users 
+        for userName in CONGA_USERS.keys(): 
+            deleteUser (sel, userName, self.logger)
+            # Validation - verify that the success message was displayed for each user
+            self.assertEqual('Do you really want to remove the user "' + userName + '"?', sel.get_confirmation())
+            sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+            self.assertTrue (sel.is_text_present('User "' + userName + '" has been deleted'))  
+
+        self.logger.info('Ending test case congaDemoTests.test_congaUsers')
+
+    def tearDown(self):
+        """Logout and stop Selenium session"""
+        logout(self.selenium)
+        self.assertEqual([], self.verificationErrors)
+        closeLogger (self.theloggerObject)
+
+def suite():
+        suite = unittest.TestSuite()
+#        suite.addTest(congaDemoTests('test_congaStorage'))
+        suite.addTest(congaDemoTests('test_congaUsers'))
+        return suite
+
+if __name__ == "__main__":
+    #unittest.main()
+    unittest.TextTestRunner(verbosity=2).run(suite())
+    
+# To write pyunit-generated output to file
+#    tests = unittest.defaultTestLoader.loadTestsFromTestCase(congaDemoTests) 
+#    output = open("/var/tmp/output-file.txt", "w") 
+#    unittest.TextTestRunner(output).run(tests) 
+#    output.close() 
/cvs/cluster/conga/luci/test/conga_Helpers.py,v  -->  standard output
revision 1.14.2.1
--- conga/luci/test/conga_Helpers.py
+++ -	2007-03-01 00:31:28.493266000 +0000
@@ -0,0 +1,193 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    conga_Helpers.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0 (http://www.openqa.org/selenium/)
+Summary:        Common routines, global variables
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+from selenium import selenium
+import unittest, time, re
+import logging
+import logging.handlers
+from loggerObject import loggerObject
+
+# Define data to support tests - global for now
+
+CONGA_ADMIN_USERNAME = 'admin'
+CONGA_ADMIN_PASSWORD = 'password'
+CONGA_SERVER = 'http://tng3-5.lab.msp.redhat.com:8080'
+PAGE_DISPLAY_DELAY = '60000'
+CONGA_LOG = '/var/tmp/congaTest.log'
+CONGA_DEBUG_LOG = '/var/tmp/congaTest_debug.log'
+
+# 20061130 - Node tng3-1 isn't booting, node tng3-4 is having some problems too
+
+CONGA_STORAGE_SYSTEMS = { #'tng3-1.lab.msp.redhat.com':'password', 
+                         #'tng3-2.lab.msp.redhat.com':'password',
+                         'tng3-3.lab.msp.redhat.com':'password',
+                         'tng3-4.lab.msp.redhat.com':'password',
+                         'tng3-5.lab.msp.redhat.com':'password'}
+
+CONGA_SMALL_CLUSTER_SYSTEMS = {  #'tng3-1.lab.msp.redhat.com':'password', 
+                         #'tng3-2.lab.msp.redhat.com':'password', 
+                         'tng3-3.lab.msp.redhat.com':'password',
+                         'tng3-4.lab.msp.redhat.com':'password' }
+
+CONGA_LARGE_CLUSTER_SYSTEMS = {#'tng3-1.lab.msp.redhat.com':'password', 
+                         #'tng3-2.lab.msp.redhat.com':'password', 
+                         'tng3-3.lab.msp.redhat.com':'password',
+                         'tng3-4.lab.msp.redhat.com':'password',
+                         'tng3-5.lab.msp.redhat.com':'password'}
+
+CONGA_USERS =           {#'user1':'user1_password', 
+                         #'user2':'user2_password', 
+                         'user3':'user3_password', 
+                         'user4':'user4_password', 
+                         'user5':'user5_password', 
+                         'user6':'user6_password', 
+                         'user7':'user7_password', 
+                         'user8':'user8_password', 
+                         'user9':'user9_password', 
+                         'user10':'user10_password'}
+
+CONGA_USERS_SYSTEMS =   {#'user1':'tng3-1.lab.msp.redhat.com', 
+                         #'user2':'tng3-2.lab.msp.redhat.com', 
+                         'user3':'tng3-3.lab.msp.redhat.com', 
+                         'user4':'tng3-4.lab.msp.redhat.com', 
+                         'user5':'tng3-5.lab.msp.redhat.com'
+                         }
+   
+# Data used to verify the on-line help contents. The Dictionary contains
+# strings and offsets of the strings in the help as of 20061207   
+HELP_LIST = ['Conga User Manual',
+             'Introduction', 
+             'Conga Architecture', 
+             'Homebase Tab', 
+             'Cluster Tab', 
+             'Storage Tab']
+        
+HELP_DICTIONARY = {'Conga User Manual':77,
+                   'Introduction':200,
+                   'Conga Architecture':225,
+                   'Homebase Tab':4257,
+                   'Cluster Tab':12280,
+                   'Storage Tab':23833 }
+
+def createStorageSystem(sel, systemName, systemPassword, theLogger):
+    """Common code to create storage systems"""
+    theLogger.debug ('Create storage system: ' + systemName)
+    sel.click("link=Add a System")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+    sel.type("__SYSTEM0:Addr", systemName)        
+    sel.type("__SYSTEM0:Passwd", systemPassword)
+    sel.click("Submit")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+
+def deleteStorageSystem(sel, systemName, theLogger):
+    """Common code to delete storage systems"""
+    try:
+        theLogger.debug('Delete storage system: ' + systemName)
+        # Need to handle artifacts names - underscores in strings, not periods
+        systemNameMod = systemName.replace('.', '_')
+        sel.click("name=__SYSTEM:" + systemNameMod)
+        sel.click("document.adminform.Submit")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)          
+    except:
+        print 'Unable to delete system: ' + systemName
+
+def createUser(sel, userName, userPassword, theLogger):
+    """Common code to create users"""
+    theLogger.debug('Create user: ' + userName)
+    sel.click("link=Add a User")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+    sel.type("newUserName", userName)
+    sel.type("newPassword", userPassword)     
+    sel.type("newPasswordConfirm", userPassword)
+    sel.click("Submit")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+    
+def deleteUser(sel, userName, theLogger):
+    """Common code to delete users"""
+    try:
+        theLogger.debug('Delete user: ' + userName)
+        sel.click("link=Delete a User")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+        sel.select("deluserId", "label=" + userName)
+        sel.click("Submit")
+        sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)    
+    except:
+        print 'Unable to delete user: ' + userName
+        
+def login(userName, password):
+    """Establish connection to selenium server, login to luci """
+    sel = selenium("localhost", 4444, "*firefox", CONGA_SERVER)
+    sel.start()
+
+    #  Login to the luci web app
+    sel.open(CONGA_SERVER)
+
+    # Wait for "Redirecting, please wait to complete" - it seems like this should not be needed,
+    # but as of 20061130, it still is
+    time.sleep(10)
+    sel.type("__ac_name", userName)
+    sel.type("__ac_password", password)
+    sel.click("submit")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+    return sel
+
+def logout(sel):
+    """Logout and stop Selenium session"""
+    sel.click("link=Log out")
+    sel.wait_for_page_to_load(PAGE_DISPLAY_DELAY)
+    sel.stop()
+    
+def setupLogger (testName):   
+    """Create logger - use this message format:  2003-07-08 16:49:45,896 ERROR We have a problem
+    For now - 20061213 - just append all log messages to a single log file """
+    logger = logging.getLogger('congaTestLogger')
+    
+    # Why use a RotatingFileHandler? To keep track of previous test results - maybe?
+    #hdlr = logging.handlers.RotatingFileHandler(testName, 'a', 1024000, 10)
+    hdlr = logging.FileHandler(testName, 'a')
+    
+    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+    hdlr.setFormatter(formatter)
+    logger.addHandler(hdlr) 
+    #logger.setLevel(logging.WARNING)
+    logger.setLevel(logging.DEBUG)
+    
+    theloggerObject = loggerObject()
+    theloggerObject.setLogger(logger)
+    theloggerObject.setHandler(hdlr)
+    return theloggerObject
+    
+def closeLogger (theloggerObject):
+    """Close the logger - roll the logs"""
+    theLogger = theloggerObject.getLogger()
+    theHandler = theloggerObject.getHandler()
+    theLogger.removeHandler(theHandler)
+    theHandler.close()
+#    theHandler.doRollover()
+    
/cvs/cluster/conga/luci/test/conga_suite.py,v  -->  standard output
revision 1.11.2.1
--- conga/luci/test/conga_suite.py
+++ -	2007-03-01 00:31:28.570790000 +0000
@@ -0,0 +1,81 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    conga_suite.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0 (http://www.openqa.org/selenium/)
+Summary:        Simple, demo/prototype test for Conga
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+# Import the test suites
+import unittest
+import congaDemoTests
+from conga_Helpers import *
+import CGA_0160_Add_User
+import CGA_0170_Online_Documentation_Portlet
+import CGA_0200_Create_cluster
+
+# Tests planned - all not yet complete:   
+#   CGA-0160_Add_User.py
+#   CGA-0170_Online_Documenation_Portlet.py
+#   CGA-0180_Event_Portlet.py
+#   CGA-0200_Create_cluster.py
+#   CGA-0210_Add_cluster_to_Administer.py
+#   CGA-0220_Add_node_to_cluster.py
+#   CGA-0300_Initialize_Disk_or_Partition.py
+#   CGA-0310_Create_Volume_Group.py
+#   CGA-0311_Activate_Volume_Group.py
+#   CGA-0312_Deactivate_Volume_Group.py
+#   CGA-0313_Remove_Volume_Group.py
+#   CGA-0314_Add_Physical_Volume.py
+#   CGA-0315_Remove_Physical_Volume.py
+#   CGA-0320_Create_Logical_Volume.py
+#   CGA-0321_Remove_Logical_Volume.py
+#   CGA-0322_Extend_Logical_Volume.py
+#   CGA-0323_Reduce_Logical_Volume.py
+#   CGA-0330_Migrate_Data_off_Physical_Volume.py
+#   CGA-0331_Take_Snapshot_Volume.py
+#   CGA-0340_Set_logging_Params.py
+#   CGA-0341_Block_Device_Params.py
+#   CGA-0342_Backup_Archive_Params.py
+
+# Define the suite elements
+congaDemoSuite = congaDemoTests.suite()
+CGA_0160_Add_UserSuite = CGA_0160_Add_User.suite()
+CGA_0170_Online_Documentation_Portlet_Suite = CGA_0170_Online_Documentation_Portlet.suite()
+CGA_0200_Create_cluster_Suite = CGA_0200_Create_cluster.suite()
+
+# Assemble the suite
+suite = unittest.TestSuite()
+suite.addTest(congaDemoSuite)
+suite.addTest(CGA_0160_Add_UserSuite)
+suite.addTest(CGA_0170_Online_Documentation_Portlet_Suite)
+suite.addTest(CGA_0200_Create_cluster_Suite)
+
+# Run the test suite
+unittest.TextTestRunner(verbosity=2).run(suite)
+
+# Or, write all pyunit-generated messages to a log file
+#output = open(CONGA_LOG, "w") 
+#unittest.TextTestRunner(output).run(suite) 
+#output.close() 
/cvs/cluster/conga/luci/test/loggerObject.py,v  -->  standard output
revision 1.2.4.1
--- conga/luci/test/loggerObject.py
+++ -	2007-03-01 00:31:28.648286000 +0000
@@ -0,0 +1,50 @@
+#! /usr/bin/env python
+
+# Copyright Red Hat, Inc. 2006
+#
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by the
+#  Free Software Foundation; either version 2, or (at your option) any
+#  later version.
+#
+#  This program is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+
+'''
+Script name:    loggerObject.py
+Creation date:  Dec 2006
+Purpose:        Prototype automated GUI test for RHEL5 Conga (luci server web app) - automated
+                with Selenium RC (remote control) 0.9.0 (http://www.openqa.org/selenium/)
+Summary:        Simple object to let us get/set the logger and its handler
+'''
+
+__author__ = 'Len DiMaggio <ldimaggi redhat com>'
+
+
+class loggerObject:
+    theLogger = 'null'
+    theHandler = 'null'
+    
+    # constructor - not sure if we want this
+    # def __init__(self, value):
+    #   self.name = value
+
+    # getters and setters methods
+    def setLogger( self, value ):
+        self.theLogger = value
+        
+    def setHandler( self, value ):
+        self.theHandler = value
+        
+    def getLogger( self ):
+        return self.theLogger
+    
+    def getHandler( self ):
+        return self.theHandler
/cvs/cluster/conga/luci/test/tests_README.txt,v  -->  standard output
revision 1.2.2.1
--- conga/luci/test/tests_README.txt
+++ -	2007-03-01 00:31:28.725023000 +0000
@@ -0,0 +1,86 @@
+README for Running RHEL5 Conga Automated GUI Tests
+==================================================
+
+(Rev 1.0 - 20061211, ldimaggi redhat com)
+
+1) Install Selenium Core and Selenium RC (Remote Control)
+   a. wget http://release.openqa.org/selenium-core/0.8.1/selenium-core-0.8.1.zip
+   b. wget http://release.openqa.org/selenium-remote-control/0.9.0/selenium-remote-control-0.9.0.zip
+   c. Unzip someplace - I used /opt
+
+2) Make sure Firefox 1.5 or newer is installed - I'm using 1.5.0.8
+
+3) Make sure Java 1.5 is installed - I'm using Sun 1.5.0_09
+
+4) Add Firefox bin dir to PATH
+   a. export PATH=/usr/lib/firefox-1.5.0.8:$PATH
+
+5) Start up Selenium server:
+   a. cd /opt/selenium/selenium-remote-control-0.9.0/server/
+   b. java -jar selenium-server.jar
+
+6) On the luci server, modify config to not use SSL, edit /var/lib/luci/etc/zope.conf:
+   a. Change this:
+
+           <cgi-environment> 
+           HTTPS ON
+           <cgi-environment> 
+
+      to this:
+
+           <cgi-environment> 
+           HTTPS OFF
+           <cgi-environment> 
+
+   b. Change this:
+
+      <http-server>                                              
+      # valid keys are "address" and "force-connection-close"    
+      #address 8080                                              
+      address localhost:25639                               
+      # force-connection-close on                           
+      </http-server>             
+
+     to this:
+
+      <http-server>       
+      address 8080                            
+      </http-server> 
+
+   c. Restart luci service
+
+7) Get a local copy of the tests.
+
+   a. mkdir sandbox; cd sandbox
+   b. cvs -d :ext:ldimaggi sources redhat com:/cvs/cluster checkout conga
+   c. cd conga/luci/tests
+   
+8) Set up the test data to match your current test network node names
+   and passwords - edit conga_Helpers.py
+
+9) Run the tests individually:
+   a. python congaDemoTests.py
+   b. python CGA_0160_Add_User.py
+   c. python CGA_0170_Online_Documenation_Portlet.py
+   d. python CGA_0200_Create_cluster.py
+
+   Or, run all the tests as a suite:
+   a. python conga_suite.py
+
+   Look in the syslog and debug log on the luci server and in the selenium server log for errors if a test fails.
+
+Current Issues:
+===============
+
+   1) The tests that create a cluster (congaDemoTests.py,
+      CGA_0200_Create_cluster.py) don't yet fully cleanup after a test
+      run. The cluster is deleted in the luci database, but the
+      cluster.conf file and the service startup settings are not reset
+      on the cluster nodes.
+
+   2) The tests do not yet handle errors, other than expected failures. 
+
+
+
+
+
--- conga/luci/utils/luci_admin	2007/01/11 00:23:59	1.50.2.2
+++ conga/luci/utils/luci_admin	2007/03/01 00:31:19	1.50.2.3
@@ -1,5 +1,7 @@
 #!/usr/bin/python
 
+# Copyright (C) 2006-2007 Red Hat, Inc.
+
 import sys, os, stat, select, string, pwd
 from sys import stderr, argv
 import types
--- conga/luci/utils/luci_cleanup	2006/08/04 18:43:26	1.4
+++ conga/luci/utils/luci_cleanup	2007/03/01 00:31:19	1.4.2.1
@@ -1,5 +1,7 @@
 #!/usr/bin/python
 
+# Copyright (C) 2006-2007 Red Hat, Inc.
+
 import sys, os, pwd
 import types
 
@@ -34,7 +36,7 @@
 LUCI_BACKUP_DIR = '/var/lib/luci/var'
 LUCI_DB_PATH = '/var/lib/luci/var/Data.fs'
 
-null = file(os.devnull, 'rwb+', 0)
+null = file('/dev/null', 'rwb+', 0)
 orig_stderr = sys.stderr
 
 def restore_luci_db_fsattr():
--- conga/luci/utils/luci_manage	2007/01/08 19:27:35	1.1.2.1
+++ conga/luci/utils/luci_manage	2007/03/01 00:31:19	1.1.2.2
@@ -1,5 +1,7 @@
 #!/usr/bin/python
 
+# Copyright (C) 2006-2007 Red Hat, Inc.
+
 import sys, os, pwd
 import types
 
@@ -34,7 +36,7 @@
 LUCI_BACKUP_DIR = '/var/lib/luci/var'
 LUCI_DB_PATH = '/var/lib/luci/var/Data.fs'
 
-null = file(os.devnull, 'rwb+', 0)
+null = file('/dev/null', 'rwb+', 0)
 orig_stderr = sys.stderr
 
 def restore_luci_db_fsattr():
--- conga/ricci/ricci.spec.in.in	2006/05/26 22:17:35	1.12
+++ conga/ricci/ricci.spec.in.in	2007/03/01 00:31:19	1.12.2.1
@@ -85,7 +85,7 @@
 if [ ! -e /var/lib/ricci/certs/privkey.pem ]; then
 	/usr/bin/openssl genrsa -out /var/lib/ricci/certs/privkey.pem 2048 > /dev/null 2>&1
 	/usr/bin/openssl req -new -x509 -key /var/lib/ricci/certs/privkey.pem \
-	-out /var/lib/ricci/certs/cacert.pem -days 1095 -config /var/lib/ricci/certs/cacert.config
+	-out /var/lib/ricci/certs/cacert.pem -days 1825 -config /var/lib/ricci/certs/cacert.config
 	/bin/chown -R ricci:ricci /var/lib/ricci/certs/*
 	/bin/chmod 644 /var/lib/ricci/certs/*
 	/bin/chmod 400 /var/lib/ricci/certs/privkey.pem
--- conga/ricci/docs/cluster_api.html	2006/10/05 17:38:01	1.4
+++ conga/ricci/docs/cluster_api.html	2007/03/01 00:31:19	1.4.2.1
@@ -8,7 +8,7 @@
 	<META NAME="CHANGED" CONTENT="20060620;15340700">
 </HEAD>
 <BODY LANG="en-US" DIR="LTR">
-<P>Cluster module manages Redhat Cluster Suite. 
+<P>Cluster module manages Red Hat Cluster Suite. 
 </P>
 <P>Module name: “cluster” 
 </P>
--- conga/ricci/docs/modules.html	2006/06/05 19:54:40	1.4
+++ conga/ricci/docs/modules.html	2007/03/01 00:31:19	1.4.2.1
@@ -14,7 +14,7 @@
 <P>Management Modules:</P>
 <UL>
 	<LI><P><A HREF="cluster_api.html">Cluster Module</A> – Manages
-	Redhat Cluster Suite</P>
+	Red Hat Cluster Suite</P>
 	<LI><P><A HREF="rpm_api.html">Rpm Module</A> – Manages rpm
 	packages. Allows retrieval of currently installed rpms, querying
 	repositories, and installation/upgrade of rpms using repositories
@@ -35,4 +35,4 @@
 <P><BR><BR>
 </P>
 </BODY>
-</HTML>
\ No newline at end of file
+</HTML>
--- conga/ricci/docs/rpm_api.html	2006/10/12 19:13:11	1.2
+++ conga/ricci/docs/rpm_api.html	2007/03/01 00:31:19	1.2.2.1
@@ -36,10 +36,10 @@
 installed; and upgraded, if already installed. 
 </P>
 <P>There are couple of predefined rpm sets: <BR>- “Cluster Base”
-- base infrastructure of Redhat Cluster Suite (currently ccs, cman,
+- base infrastructure of Red Hat Cluster Suite (currently ccs, cman,
 dlm, fence, and respective kernel-... rpms) <BR>- “Cluster Base -
-Gulm” - base infrastructure of Redhat Cluster Suite using Gulm lock
-manager (currently ccs, gulm, fence and respective kernel-... rpms)
+Gulm” - base infrastructure of Red Hat Cluster Suite using GULM lock
+manager (currently ccs, gulm, and respective kernel-... rpms)
 <BR>- “Cluster Service Manager” - (currently rgmanager, magma,
 magma-plugins) <BR>- “Clustered Storage” - shared storage
 (currently GFS, lvm2-cluster and respective kernel-... rpms) <BR>-
--- conga/ricci/docs/service_api.html	2006/04/12 15:47:09	1.1
+++ conga/ricci/docs/service_api.html	2007/03/01 00:31:19	1.1.2.1
@@ -30,10 +30,10 @@
 running=&quot;true/false&quot;/&gt;<BR>“enabled” - enabled on
 boot; “running” - currently running.</P>
 <P>There are couple of predefined service sets: <BR>- “Cluster
-Base” - base infrastructure of Redhat Cluster Suite (currently
+Base” - base infrastructure of Red Hat Cluster Suite (currently
 ccsd, cman, fenced) <BR>- “Cluster Base - Gulm” - base
-infrastructure of Redhat Cluster Suite using Gulm lock manager
-(currently ccsd, lock_gulmd, fenced) <BR>- “Cluster Service
+infrastructure of Red Hat Cluster Suite using GULM lock manager
+(currently ccsd, lock_gulmd) <BR>- “Cluster Service
 Manager” - (currently rgmanager) <BR>- “Clustered Storage” -
 shared storage (currently clvmd, gfs)<BR>- “Linux Virtual Server”
 - (currently pulse, piranha-gui)</P>
@@ -117,6 +117,18 @@
 		generic ones might get returned. 
 		</P>
 	</UL>
+	<LI><P>restart</P>
+	<UL>
+		<P ALIGN=LEFT>Restart services/sets.</P>
+		<P>Input variables: <BR>- “services” (list_xml) – list of
+		services/sets to restart. For format see “query”. 
+		</P>
+		<P>No output variables. 
+		</P>
+		<P ALIGN=LEFT>On failure: <BR>- No special errors defined, only
+		generic ones might get returned. 
+		</P>
+	</UL>
 	<LI><P>stop</P>
 	<UL>
 		<P ALIGN=LEFT>Stop services/sets. It is not error to stop already
@@ -135,4 +147,4 @@
 <P ALIGN=LEFT><BR><BR>
 </P>
 </BODY>
-</HTML>
\ No newline at end of file
+</HTML>
--- conga/ricci/modules/cluster/ClusterStatus.cpp	2006/10/24 14:31:40	1.15.2.1
+++ conga/ricci/modules/cluster/ClusterStatus.cpp	2007/03/01 00:31:20	1.15.2.2
@@ -157,10 +157,11 @@
 {
   XMLObject cluster_conf(ClusterConf::get()); // bailout if cluster.conf not present
   XMLObject stat = status();
+  bool cman_cluster = ClusterConf::is_cman(cluster_conf);
   
   if (stat.get_attr("cluster_version") == "4") {
     run_initd("ccsd", true, false);
-    if (ClusterConf::is_cman(cluster_conf))
+    if (cman_cluster)
       try {
 	run_initd("cman", true, true);
       } catch ( ... ) {
@@ -197,7 +198,8 @@
     
     if (use_qdisk)
       run_initd("qdiskd", true, false);
-    run_initd("fenced", true, false);
+    if (cman_cluster)
+      run_initd("fenced", true, false);
     run_initd("clvmd", true, false);
     run_initd("gfs", true, false);
     run_initd("rgmanager", true, true);
@@ -205,18 +207,19 @@
     // enable them on boot
     
     run_chkconfig("ccsd", true);
-    if (ClusterConf::is_cman(cluster_conf)) {
+    if (cman_cluster) {
       run_chkconfig("cman", true);
       run_chkconfig("lock_gulmd", false);
+      run_chkconfig("fenced", true);
     } else {
       run_chkconfig("cman", false);
+      run_chkconfig("fenced", false);
       run_chkconfig("lock_gulmd", true);
     }
     if (use_qdisk)
       run_chkconfig("qdiskd", true);
     else
       run_chkconfig("qdiskd", false);
-    run_chkconfig("fenced", true);
     run_chkconfig("clvmd", true);
     run_chkconfig("gfs", true);
     run_chkconfig("rgmanager", true);
--- conga/ricci/modules/log/LogParser.cpp	2006/11/16 19:34:53	1.6.2.2
+++ conga/ricci/modules/log/LogParser.cpp	2007/03/01 00:31:20	1.6.2.3
@@ -43,6 +43,11 @@
 				"modclusterd",
 				"dlm",
 				"gulm",
+				"lock_gulmd",
+				"lock_gulmd_main",
+				"lock_gulmd_core",
+				"lock_gulmd_LT",
+				"lock_gulmd_LTPX",
 				"cman",
 				"cman_tool",
 				"ccs",
--- conga/ricci/modules/rpm/PackageHandler.cpp	2006/12/13 20:27:40	1.9.2.2
+++ conga/ricci/modules/rpm/PackageHandler.cpp	2007/03/01 00:31:20	1.9.2.3
@@ -26,6 +26,7 @@
 #include "File.h"
 
 #include <unistd.h>
+#include <sys/utsname.h>
 
 
 using namespace std;
@@ -154,10 +155,6 @@
     return true;
   
   if (RHEL4) {
-    
-    // TODO: fix up2date handling
-    throw String("RHEL4 not supported, yet");
-    
     String out, err;
     int status;
     vector<String> args;
@@ -416,7 +413,9 @@
     set.packages.push_back("dlm");
     set.packages.push_back("fence");
     
-    String kernel(utils::strip(File::open("/proc/sys/kernel/osrelease")));
+    struct utsname uts;
+    uname(&uts);
+    String kernel(uts.release);
     if (kernel.find("smp") != kernel.npos) {
       set.packages.push_back("cman-kernel-smp");
       set.packages.push_back("dlm-kernel-smp");
@@ -442,7 +441,6 @@
   if (RHEL4 || FC5) {
     set.packages.push_back("ccs");
     set.packages.push_back("gulm");
-    set.packages.push_back("fence");
   } else
     throw String("GULM not available in CS5");
   
@@ -464,7 +462,9 @@
 PackageSet
 PackageHandler::build_cluster_storage_set()
 {
-  String kernel(utils::strip(File::open("/proc/sys/kernel/osrelease")));
+  struct utsname uts;
+  uname(&uts);
+  String kernel(uts.release);
   
   PackageSet set("Clustered Storage");
   set.packages.push_back("lvm2-cluster");
@@ -523,10 +523,9 @@
       const Package& pack = iter->second;
       if (pack.version.empty())
 	set.installed = false;
-      if (pack.repo_version.empty()) {
+      if (pack.repo_version.empty())
 	set.in_repo = false;
-	set.upgradeable = false;
-      } else if (pack.repo_version > pack.version)
+      else if (pack.repo_version > pack.version)
 	set.upgradeable = true;
     }
   }
--- conga/ricci/modules/service/ServiceManager.cpp	2006/10/23 21:13:21	1.5.2.1
+++ conga/ricci/modules/service/ServiceManager.cpp	2007/03/01 00:31:20	1.5.2.2
@@ -172,7 +172,15 @@
 Service::start()
 {
   running();
-  run_service(name(), true);
+  run_service(name(), START);
+  *_running = true;
+}
+
+void 
+Service::restart()
+{
+  running();
+  run_service(name(), RESTART);
   *_running = true;
 }
 
@@ -180,7 +188,7 @@
 Service::stop()
 {
   running();
-  run_service(name(), false);
+  run_service(name(), STOP);
   *_running = false;
 }
 
@@ -217,7 +225,7 @@
 }
 
 void 
-Service::run_service(const String& name, bool on)
+Service::run_service(const String& name, ActionState state)
 {
   String path(INITD_DIR_PATH);
   path += name;
@@ -225,20 +233,27 @@
   String out, err;
   int status;
   vector<String> args;
-  if (on)
-    args.push_back("start");
-  else
-    args.push_back("stop");
+  switch (state) {
+    case START:
+      args.push_back("start");
+      break;
+    case STOP:
+      args.push_back("stop");
+      break;
+    case RESTART:
+      args.push_back("restart");
+      break;
+  }
   if (utils::execute(path, args, out, err, status, false) != 0)
     throw command_not_found_error_msg(path);
   if (status) {
     bool running = service_running(name);
-    if (on) {
+    if (state == START || state == RESTART) {
       if (!running)
-	throw String("service ") + name + " " + String(on?"start":"stop") + " failed";
+	throw String("service ") + name + " " + String(state == START ? "start" : "restart") + " failed";
     } else {
       if (running)
-	throw String("service ") + name + " " + String(on?"start":"stop") + " failed";
+	throw String("service ") + name + " stop failed";
     }
   }
 }
@@ -363,6 +378,19 @@
 }
 
 void 
+ServiceSet::restart()
+{
+  name();
+  try {
+    // ordered sequence: last started, first to be stoped
+    stop();
+    start();
+  } catch (String e) {
+    throw String("service set '") + name() + "' failed to restart";
+  }
+}
+
+void 
 ServiceSet::stop()
 {
   name();
@@ -440,11 +468,10 @@
   if (RHEL4 || FC5) {
     servs.clear();
     name = "Cluster Base - Gulm";
-    descr = "Cluster infrastructure: ccs, gulm, fence";
+    descr = "Cluster infrastructure: ccs, gulm";
     s = ServiceSet(name, descr);
     servs.push_back("ccsd");
     servs.push_back("lock_gulmd");
-    servs.push_back("fenced");
     if (populate_set(s, servs))
       sets[name] = s;
   }
@@ -590,6 +617,34 @@
 }
 
 void 
+ServiceManager::restart(const std::list<String>& services, 
+		     const std::list<String>& sets)
+{
+  // check
+  for (list<String>::const_iterator iter = services.begin();
+       iter != services.end();
+       iter++)
+    if (_servs.find(*iter) == _servs.end())
+      throw String("no such service: ") + *iter;
+  for (list<String>::const_iterator iter = sets.begin();
+       iter != sets.end();
+       iter++)
+    if (_sets.find(*iter) == _sets.end())
+      throw String("no such service set: ") + *iter;
+  
+  // apply
+  for (list<String>::const_iterator iter = services.begin();
+       iter != services.end();
+       iter++)
+    _servs[*iter].restart();
+  
+  for (list<String>::const_iterator iter = sets.begin();
+       iter != sets.end();
+       iter++)
+    _sets[*iter].restart();
+}
+
+void 
 ServiceManager::stop(const std::list<String>& services, 
 		     const std::list<String>& sets)
 {
--- conga/ricci/modules/service/ServiceManager.h	2006/08/10 22:53:09	1.2
+++ conga/ricci/modules/service/ServiceManager.h	2007/03/01 00:31:20	1.2.2.1
@@ -48,6 +48,7 @@
   
   void enable();
   void disable();
+  void restart();
   void start();
   void stop();
   
@@ -61,9 +62,15 @@
   mutable counting_auto_ptr<bool> _enabled;
   mutable counting_auto_ptr<bool> _running;
   
+  enum ActionState {
+    START,
+    STOP,
+    RESTART
+  };
+  
   static void enable_service(const String& name, bool on);
   static bool service_running(const String& name);
-  static void run_service(const String& name, bool on);
+  static void run_service(const String& name, ActionState state);
   
   friend class ServiceManager;
 
@@ -84,6 +91,7 @@
   void enable();
   void disable();
   void start();
+  void restart();
   void stop();
   
   std::list<Service> servs;
@@ -107,6 +115,7 @@
   void disable(const std::list<String>& services, const std::list<String>& sets);
   
   void start(const std::list<String>& services, const std::list<String>& sets);
+  void restart(const std::list<String>& services, const std::list<String>& sets);
   void stop(const std::list<String>& services, const std::list<String>& sets);
   
   void lists(std::list<Service>& services, 
--- conga/ricci/modules/service/ServiceModule.cpp	2006/08/10 22:53:09	1.3
+++ conga/ricci/modules/service/ServiceModule.cpp	2007/03/01 00:31:20	1.3.2.1
@@ -31,6 +31,7 @@
 static VarMap enable(const VarMap& args);
 static VarMap disable(const VarMap& args);
 static VarMap start(const VarMap& args);
+static VarMap restart(const VarMap& args);
 static VarMap stop(const VarMap& args);
 static VarMap lists(const VarMap& args);
 static VarMap query(const VarMap& args);
@@ -53,6 +54,7 @@
   api_1_0["enable"]     = enable;
   api_1_0["disable"]    = disable;
   api_1_0["start"]      = start;
+  api_1_0["restart"]	= restart;
   api_1_0["stop"]       = stop;
   api_1_0["list"]       = lists;
   api_1_0["query"]      = query;
@@ -149,6 +151,34 @@
 }
 
 VarMap 
+restart(const VarMap& args)
+{
+  list<XMLObject> serv_list;
+  try {
+    VarMap::const_iterator iter = args.find("services");
+    if (iter == args.end())
+      throw APIerror("missing services variable");
+    serv_list = iter->second.get_list_XML();
+  } catch ( String e ) {
+    throw APIerror(e);
+  }
+  
+  list<String> services, sets;
+  for (list<XMLObject>::const_iterator iter = serv_list.begin();
+       iter != serv_list.end();
+       iter++) {
+    if (iter->tag() == "service")
+      services.push_back(iter->get_attr("name"));
+    else if (iter->tag() == "set")
+      sets.push_back(iter->get_attr("name"));
+  }
+  
+  ServiceManager().restart(services, sets);
+  
+  return VarMap();
+}
+
+VarMap 
 stop(const VarMap& args)
 {
   list<XMLObject> serv_list;
/cvs/cluster/conga/ricci/test_suite/README,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/README
+++ -	2007-03-01 00:31:30.222645000 +0000
@@ -0,0 +1,14 @@
+1. make SSL certs
+	./generate_certs.sh
+	this step needs to be performed only once 
+	(cert can be used for multiple riccis - each requires authentication)
+2. modify ricci/authenticate.xml, writing root password of machine hosting ricci to 'password' attribute
+3. run ./ricci_test ricci_hostname ricci/authenticate.xml
+	you are authenticated to that ricci, and don't have to repeat authentication to it
+4. pick/modify one of XML files
+	check ../docs/ for API
+5. execute ./ricci_test ricci_hostname xml_file
+	ricci's response will be printed to stdout
+
+
+15. send ricci/unauthenticate.xml to unauthenticate from that ricci
/cvs/cluster/conga/ricci/test_suite/cacert.config,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cacert.config
+++ -	2007-03-01 00:31:30.300780000 +0000
@@ -0,0 +1,15 @@
+[ req ]
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = State or Province
+L                      = Locality
+O                      = Organization Name
+OU                     = Organizational Unit Name
+CN                     = Common Name
+emailAddress           = root localhost
+
+[ req_attributes ]
/cvs/cluster/conga/ricci/test_suite/generate_certs.sh,v  -->  standard output
revision 1.2.4.1
--- conga/ricci/test_suite/generate_certs.sh
+++ -	2007-03-01 00:31:30.378977000 +0000
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+/usr/bin/openssl genrsa -out privkey.pem 2048
+/usr/bin/openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1825 -config cacert.config
+chmod go-rwx *.pem
/cvs/cluster/conga/ricci/test_suite/send_to_ricci,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/send_to_ricci
+++ -	2007-03-01 00:31:30.460158000 +0000
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+import socket
+import sys, os
+import xml.dom
+import xml
+from xml.dom import minidom
+
+
+
+RICCI_PORT = 11111
+
+
+
+def send_to_ricci(hostname, msg):
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.settimeout(2.0)
+    s.connect((hostname, RICCI_PORT))
+    ss = socket.ssl(s, 'privkey.pem', 'cacert.pem')
+    s.settimeout(600.0)
+    
+    res1 = ss.read(1024)
+    ss.write(msg)
+    res2 = ''
+    while True:
+        buff = ss.read(10485760)
+        if buff == '':
+            break
+        res2 += buff
+        try:
+            minidom.parseString(res2)
+            break
+        except:
+            pass
+    return res1, res2
+
+
+def main(argv):
+    certs_present = True
+    if os.access('cacert.pem', os.R_OK) == False:
+        print 'cannot find cacert.pem'
+        certs_present = False
+    if os.access('privkey.pem', os.R_OK) == False:
+        print 'cannot find privkey.pem'
+        certs_present = False
+    
+    if len(argv) != 3 or not certs_present:
+        print 'sends <command_file> to ricci on <hostname>, and writes its response to stdout'
+        print '\t' + argv[0] + ' <hostname> <command_file>'
+        print '\t\thostname - host to send command to'
+        print '\t\txml_file - file with valid ricci request to be sent'
+        print '\t./ has to contain privkey.pem and cacert.pem'
+        sys.exit(1)
+
+    hostname = argv[1]
+    filename = argv[2]
+    res = send_to_ricci(hostname, open(filename).read(100000))
+    print res[1]
+    if res[1].find('success="5"') > -1:
+        print "not authenticated, send ricci/authenticate.xml with root password in it"
+
+
+
+
+# If called from the command line
+if __name__ == '__main__':
+    main(sys.argv)
+
/cvs/cluster/conga/ricci/test_suite/cluster/fence_node.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/fence_node.xml
+++ -	2007-03-01 00:31:30.536969000 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="fence_node">
+  <var mutable="false" name="nodename" type="string" value="blue"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/get_cluster.conf.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/get_cluster.conf.xml
+++ -	2007-03-01 00:31:30.618885000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="get_cluster.conf"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/is_virtual.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/is_virtual.xml
+++ -	2007-03-01 00:31:30.698135000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="virt_guest" />
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/restart_service.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/restart_service.xml
+++ -	2007-03-01 00:31:30.774610000 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="restart_service">
+  <var mutable="false" name="servicename" type="string" value="new_serv"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/start_node.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/start_node.xml
+++ -	2007-03-01 00:31:30.851876000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="start_node"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/start_service.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/start_service.xml
+++ -	2007-03-01 00:31:30.929014000 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="start_service">
+  <var mutable="false" name="servicename" type="string" value="new_serv"/>
+  <var mutable="false" name="nodename" type="string" value="blue"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/status.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/status.xml
+++ -	2007-03-01 00:31:31.006620000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="status"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/stop_node.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/stop_node.xml
+++ -	2007-03-01 00:31:31.084624000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="stop_node"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/cluster/stop_service.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/cluster/stop_service.xml
+++ -	2007-03-01 00:31:31.162519000 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="cluster">
+<request sequence="1254" API_version="1.0">
+<function_call name="stop_service">
+  <var mutable="false" name="servicename" type="string" value="new_serv"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/log/get_all.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_all.xml
+++ -	2007-03-01 00:31:31.243482000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value=""/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_cluster.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_cluster.xml
+++ -	2007-03-01 00:31:31.321978000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="cluster"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_piranha.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_piranha.xml
+++ -	2007-03-01 00:31:31.397653000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="lvs"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_rgmanager.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_rgmanager.xml
+++ -	2007-03-01 00:31:31.474861000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="cluster service manager"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_selinux.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_selinux.xml
+++ -	2007-03-01 00:31:31.553590000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="selinux"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_storage.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_storage.xml
+++ -	2007-03-01 00:31:31.629737000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="storage"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/log/get_storage_and_selinux.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/log/get_storage_and_selinux.xml
+++ -	2007-03-01 00:31:31.708682000 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="log">
+<request sequence="1254" API_version="1.0">
+<function_call name="get">
+  <var mutable="false" name="age" type="int" value="86400"/>
+  <var mutable="false" name="intersection" type="boolean" value="false"/>
+  <var mutable="false" name="tags" type="list_str">
+    <listentry value="storage"/>
+    <listentry value="selinux"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/reboot/reboot_now.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/reboot/reboot_now.xml
+++ -	2007-03-01 00:31:31.785967000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="reboot">
+<request sequence="1254" API_version="1.0">
+<function_call name="reboot_now"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/ricci/authenticate.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/ricci/authenticate.xml
+++ -	2007-03-01 00:31:31.862748000 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="authenticate" password="enter_password_here"/>
/cvs/cluster/conga/ricci/test_suite/ricci/list_modules.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/ricci/list_modules.xml
+++ -	2007-03-01 00:31:31.939173000 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="list_modules"/>
/cvs/cluster/conga/ricci/test_suite/ricci/unauthenticate.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/ricci/unauthenticate.xml
+++ -	2007-03-01 00:31:32.016019000 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="unauthenticate"/>
/cvs/cluster/conga/ricci/test_suite/rpm/install.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/install.xml
+++ -	2007-03-01 00:31:32.101278000 +0000
@@ -0,0 +1,21 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="install">
+  <var mutable="false" name="rpms" type="list_xml">
+    <rpm name="httpd"/>
+    <rpm name="xinetd"/>
+  </var>
+  <var mutable="false" name="sets" type="list_xml">
+    <set name="Cluster Base"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/install_enable_start.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/install_enable_start.xml
+++ -	2007-03-01 00:31:32.180354000 +0000
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="install">
+  <var mutable="false" name="rpms" type="list_xml">
+    <rpm name="httpd"/>
+  </var>
+  <var mutable="false" name="sets" type="list_xml">
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="enable">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="start">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/list_all.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/list_all.xml
+++ -	2007-03-01 00:31:32.258040000 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="list">
+  <var name="sets" type="boolean" value="true"/>
+  <var name="rpms" type="boolean" value="true"/>
+  <var name="installed" type="boolean" value="true"/>
+  <var name="upgradeable" type="boolean" value="true"/>
+  <var name="installable" type="boolean" value="true"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/list_installed.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/list_installed.xml
+++ -	2007-03-01 00:31:32.335590000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="list">
+  <var name="sets" type="boolean" value="true"/>
+  <var name="rpms" type="boolean" value="true"/>
+  <var name="installed" type="boolean" value="true"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/list_repo.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/list_repo.xml
+++ -	2007-03-01 00:31:32.415870000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="list">
+  <var name="sets" type="boolean" value="true"/>
+  <var name="rpms" type="boolean" value="true"/>
+  <var name="installable" type="boolean" value="true"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/list_upgradeable.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/list_upgradeable.xml
+++ -	2007-03-01 00:31:32.493384000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="list">
+  <var name="sets" type="boolean" value="true"/>
+  <var name="rpms" type="boolean" value="true"/>
+  <var name="upgradeable" type="boolean" value="true"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/query.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/query.xml
+++ -	2007-03-01 00:31:32.574535000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="query">
+  <var mutable="false" name="search" type="list_xml">
+    <rpm name="httpd"/>
+    <rpm name="xinetd"/>
+    <set name="Cluster Base"/>
+    <set name="Clustered Storage"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/rpm/repo_avail.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/rpm/repo_avail.xml
+++ -	2007-03-01 00:31:32.658792000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="rpm">
+<request sequence="1254" API_version="1.0">
+<function_call name="repository_configured"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+
/cvs/cluster/conga/ricci/test_suite/service/disable.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/disable.xml
+++ -	2007-03-01 00:31:32.737714000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="disable">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/disable_and_stop.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/disable_and_stop.xml
+++ -	2007-03-01 00:31:32.815216000 +0000
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="disable">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="stop">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="query">
+  <var mutable="false" name="search" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/enable.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/enable.xml
+++ -	2007-03-01 00:31:32.899422000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="enable">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/enable_and_start.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/enable_and_start.xml
+++ -	2007-03-01 00:31:32.976560000 +0000
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="start">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="enable">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="query">
+  <var mutable="false" name="search" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/list.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/list.xml
+++ -	2007-03-01 00:31:33.054319000 +0000
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="12dsa" API_version="1.0">
+<function_call name="list">
+  <var mutable="false" name="description" type="boolean" value="true"/>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/query.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/query.xml
+++ -	2007-03-01 00:31:33.132025000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="query">
+  <var mutable="false" name="description" type="boolean" value="true"/>
+  <var mutable="false" name="search" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+    <set name="Cluster Base"/>
+    <set name="Clustered Storage"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/restart.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/restart.xml
+++ -	2007-03-01 00:31:33.215255000 +0000
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="restart">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/start.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/start.xml
+++ -	2007-03-01 00:31:33.293298000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="start">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/service/stop.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/service/stop.xml
+++ -	2007-03-01 00:31:33.369594000 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="service">
+<request sequence="1254" API_version="1.0">
+<function_call name="stop">
+  <var mutable="false" name="services" type="list_xml">
+    <service name="httpd"/>
+    <service name="xinetd"/>
+  </var>
+</function_call>
+</request>
+</module>
+
+</batch>
+</ricci>
/cvs/cluster/conga/ricci/test_suite/storage/report.xml,v  -->  standard output
revision 1.1.4.1
--- conga/ricci/test_suite/storage/report.xml
+++ -	2007-03-01 00:31:33.447640000 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<ricci version="1.0" function="process_batch" async="false">
+<batch>
+
+<module name="storage">
+<request sequence="1254" API_version="1.0">
+<function_call name="report"/>
+</request>
+</module>
+
+</batch>
+</ricci>
+


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