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

[Cluster-devel] conga/luci cluster/form-chooser cluster/form-m ...



CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	rmccabe sourceware org	2006-12-07 17:54:31

Modified files:
	luci/cluster   : form-chooser form-macros index_html 
	                 resource-form-macros resource_form_handlers.js 
	luci/homebase  : luci_homebase.css 
	luci/site/luci/Extensions: ClusterNode.py FenceDevice.py 
	                           LuciSyslog.py cluster_adapters.py 
	                           conga_constants.py ricci_bridge.py 

Log message:
	Related: bz217387, bz218040, bz212021

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-chooser.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.12.2.1&r2=1.12.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.90.2.6&r2=1.90.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/index_html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.4&r2=1.20.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/resource-form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.21.2.2&r2=1.21.2.3
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.2&r2=1.20.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.1&r2=1.28.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ClusterNode.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/FenceDevice.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciSyslog.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2.2.3&r2=1.2.2.4
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.12&r2=1.120.2.13
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.2&r2=1.19.2.3
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.10&r2=1.30.2.11

--- conga/luci/cluster/form-chooser	2006/11/16 19:34:52	1.12.2.1
+++ conga/luci/cluster/form-chooser	2006/12/07 17:54:31	1.12.2.2
@@ -80,6 +80,9 @@
     <span tal:omit-tag="" tal:condition="python: ptype == '25'">
      <div metal:use-macro="here/form-macros/macros/serviceprocess-form"/>
     </span>
+	<tal:block tal:condition="python: ptype == '56'">
+		<div metal:use-macro="here/form-macros/macros/servicedelete-form" />
+	</tal:block>
     <span tal:omit-tag="" tal:condition="python: ptype == '26'">
      <div metal:use-macro="here/form-macros/macros/servicestart"/>
     </span>
--- conga/luci/cluster/form-macros	2006/11/30 22:31:59	1.90.2.6
+++ conga/luci/cluster/form-macros	2006/12/07 17:54:31	1.90.2.7
@@ -77,7 +77,7 @@
 
 	<tal:block tal:condition="python: ricci_agent">
 		<tal:block tal:define="
-			global stat python: here.getClusterStatus(ricci_agent);
+			global stat python: here.getClusterStatus(request, ricci_agent);
 			global cstatus python: here.getClustersInfo(stat, request);
 			global cluster_status python: 'cluster ' + (('running' in cstatus and cstatus['running'] == 'true') and 'running' or 'stopped');"
 	 	/>
@@ -122,14 +122,22 @@
 		</td>
 	</tr>
 
+	<tr class="cluster">
+		<td tal:condition="exists: cstatus/error" class="cluster">
+			<span class="errmsgs">
+				An error occurred while attempting to get status information for this cluster. The information shown may be out of date.
+			</span>
+		</td>
+	</tr>
+
 	<tr class="cluster info_middle">
 		<td colspan="2" class="cluster cluster_quorum">
 			<ul class="cluster_quorum"
 				tal:condition="exists: cstatus/status">
 
-				<li><strong class="cluster">Status</strong>: <span tal:replace="cstatus/status"/></li>
-				<li><strong class="cluster">Total Cluster Votes</strong>: <span tal:replace="cstatus/votes"/></li>
-				<li><strong class="cluster">Minimum Required Quorum</strong>: <span tal:replace="cstatus/minquorum"/></li>
+				<li><strong class="cluster">Status</strong>: <span tal:replace="cstatus/status | string:[unknown]"/></li>
+				<li><strong class="cluster">Total Cluster Votes</strong>: <span tal:replace="cstatus/votes | string:[unknown]"/></li>
+				<li><strong class="cluster">Minimum Required Quorum</strong>: <span tal:replace="cstatus/minquorum | string:[unknown]"/></li>
 			</ul>
 		</td>
 	</tr>
@@ -1141,7 +1149,7 @@
 
 	<div id="fence_apc" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>APC Power Switch</td>
 			</tr>
@@ -1174,6 +1182,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-apc" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_apc" />
 	</div>
 </div>
@@ -1183,7 +1205,7 @@
 
 	<div id="fence_mcdata" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>McData SAN Switch</td>
 			</tr>
@@ -1216,6 +1238,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-mcdata" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_mcdata" />
 	</div>
 </div>
@@ -1225,7 +1261,7 @@
 
 	<div id="fence_wti" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>WTI Power Switch</td>
 			</tr>
@@ -1251,6 +1287,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-wti" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_wti" />
 	</div>
 </div>
@@ -1260,7 +1310,7 @@
 
 	<div id="fence_ilo" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>HP iLO</td>
 			</tr>
@@ -1293,6 +1343,11 @@
 				</td>
 			</tr>
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_ilo" />
 	</div>
 </div>
@@ -1302,7 +1357,7 @@
 
 	<div id="fence_drac" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Dell Drac</td>
 			</tr>
@@ -1334,6 +1389,11 @@
 						tal:attributes="value cur_fencedev/passwd | nothing" />
 				</td>
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_drac" />
 	</div>
 </div>
@@ -1343,7 +1403,7 @@
 
 	<div id="fence_rsa" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>IBM RSA II</td>
 			</tr>
@@ -1376,6 +1436,11 @@
 				</td>
 			</tr>
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_rsa" />
 	</div>
 </div>
@@ -1385,7 +1450,7 @@
 
 	<div id="fence_brocade" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Brocade Fabric Switch</td>
 			</tr>
@@ -1418,6 +1483,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-brocade" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_brocade" />
 	</div>
 </div>
@@ -1427,7 +1506,7 @@
 
 	<div id="fence_sanbox2" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>QLogic SANbox2</td>
 			</tr>
@@ -1457,6 +1536,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-sanbox2" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_sanbox2" />
 	</div>
 </div>
@@ -1466,7 +1559,7 @@
 
 	<div id="fence_vixel" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Vixel SAN Switch</td>
 			</tr>
@@ -1492,6 +1585,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-brocade" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_vixel" />
 	</div>
 </div>
@@ -1501,7 +1608,7 @@
 
 	<div id="fence_gnbd" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>GNBD</td>
 			</tr>
@@ -1520,6 +1627,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-gnbd" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_gnbd" />
 	</div>
 </div>
@@ -1529,7 +1650,7 @@
 
 	<div id="fence_egenera" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Egenera SAN Controller</td>
 			</tr>
@@ -1555,6 +1676,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-egenera" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_egenera" />
 	</div>
 </div>
@@ -1564,7 +1699,7 @@
 
 	<div id="fence_bladecenter" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>IBM Blade Center</td>
 			</tr>
@@ -1597,6 +1732,11 @@
 				</td>
 			</tr>
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_bladecenter" />
 	</div>
 </div>
@@ -1606,7 +1746,7 @@
 
 	<div id="fence_bullpap" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Bull PAP</td>
 			</tr>
@@ -1639,6 +1779,20 @@
 				</td>
 			</tr>
 		</table>
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-bullpap" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="sharable" value="1" />
 		<input type="hidden" name="fence_type" value="fence_bullpap" />
 	</div>
 </div>
@@ -1648,7 +1802,7 @@
 
 	<div id="fence_rps10" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>RPS10 Serial Switch</td>
 			</tr>
@@ -1670,11 +1824,16 @@
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value cur_fencedev/port| nothing" />
+						tal:attributes="value cur_fencedev/port | nothing" />
 				</td>
 			</tr>
 		</table>
-		<input type="hidden" name="fence_type" value="fence_rps10"/>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="fence_type" value="fence_rps10" />
 	</div>
 </div>
 
@@ -1682,8 +1841,8 @@
 	tal:attributes="id cur_fencedev/name | nothing">
 
 	<div id="fence_xvm" class="fencedev">
-	<table>
-			<tr tal:condition="exists: cur_fence_type">
+		<table>
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Virtual Machine Fencing</td>
 			</tr>
@@ -1694,7 +1853,22 @@
 						tal:attributes="value cur_fencedev/name | nothing" />
 				</td>
 			</tr>
-  </table>	
+		</table>	
+		<div name="instances">
+			<tal:block tal:condition="exists: cur_fence_instances">
+				<tal:block tal:repeat="cur_fence_instance cur_fence_instances">
+					<tal:block
+						metal:use-macro="here/form-macros/macros/fence-instance-form-xvm" />
+				</tal:block>
+			</tal:block>
+		</div>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_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" />
 	</div>
 </div>
 
@@ -1702,8 +1876,8 @@
 	tal:attributes="id cur_fencedev/name | nothing">
 
 	<div id="fence_scsi" class="fencedev">
-	<table>
-			<tr tal:condition="exists: cur_fence_type">
+		<table>
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>SCSI Reservation Fencing</td>
 			</tr>
@@ -1714,7 +1888,14 @@
 						tal:attributes="value cur_fencedev/name | nothing" />
 				</td>
 			</tr>
-  </table>	
+		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_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" />
 	</div>
 </div>
 
@@ -1723,7 +1904,7 @@
 
 	<div id="fence_ipmilan" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>IPMI Lan</td>
 			</tr>
@@ -1760,6 +1941,11 @@
 				<td><input name="auth_type" type="text" Title="Options are to leave blank for none, password, md2, or md5"/></td>
 			</tr>
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
 		<input type="hidden" name="fence_type" value="fence_ipmilan" />
 	</div>
 </div>
@@ -1769,7 +1955,7 @@
 
 	<div id="fence_manual" class="fencedev">
 		<table>
-			<tr tal:condition="exists: cur_fence_type">
+			<tr>
 				<td><strong class="cluster">Fence Type</strong></td>
 				<td>Manual Fencing</td>
 			</tr>
@@ -1780,8 +1966,13 @@
 						tal:attributes="value cur_fencedev/name | nothing" />
 				</td>
 			</tr>
-			<input type="hidden" name="fence_type" value="fence_manual" />
 		</table>
+		<tal:block tal:condition="exists: cur_fencedev">
+			<input type="hidden" name="existing_device" value="1" />
+			<input type="hidden" name="old_name"
+				tal:attributes="value cur_fencedev/name | nothing" />
+		</tal:block>
+		<input type="hidden" name="fence_type" value="fence_manual" />
 	</div>
 </div>
 
@@ -1863,172 +2054,206 @@
 </div>
 
 <div metal:define-macro="fence-instance-form-apc">
-	<div id="fence_apc_instance" class="fencedev">
+	<div id="fence_apc_instance" name="fence_apc" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
 			<tr>
 				<td>Switch</td>
 				<td>
 					<input name="switch" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/switch | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-egenera">
-	<div id="fence_egenera_instance" class="fencedev">
+	<div id="fence_egenera_instance" name="fence_egenera" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>lpan</td>
 				<td>
 					<input name="lpan" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/lpan | nothing" />
 				</td>
 			</tr>
 			<tr>
 				<td>pserver</td>
 				<td>
 					<input name="pserver" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/pserver | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-wti">
-	<div id="fence_wti_instance" class="fencedev">
+	<div id="fence_wti_instance" name="fence_wti" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-brocade">
-	<div id="fence_brocade_instance" class="fencedev">
+	<div id="fence_brocade_instance" name="fence_brocade" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-vixel">
-	<div id="fence_vixel_instance" class="fencedev">
+	<div id="fence_vixel_instance" name="fence_vixel" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-sanbox2">
-	<div id="fence_sanbox2_instance" class="fencedev">
+	<div id="fence_sanbox2_instance" name="fence_sanbox2" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-mcdata">
-	<div id="fence_mcdata_instance" class="fencedev">
+	<div id="fence_mcdata_instance" name="fence_mcdata" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Port</td>
 				<td>
 					<input name="port" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/port | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-gndb">
-	<div id="fence_gnbd_instance" class="fencedev">
+	<div id="fence_gnbd_instance" name="fence_gnbd" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>IP Address</td>
 				<td>
 					<input name="ipaddress" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/ipaddress | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-bladecenter">
-	<div id="fence_bladecenter_instance" class="fencedev">
+	<div id="fence_bladecenter_instance" name="fence_bladecenter" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Blade</td>
 				<td>
 					<input name="ipaddress" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/ipaddress | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-bullpap">
-	<div id="fence_bullpap_instance" class="fencedev">
+	<div id="fence_bullpap_instance" name="fence_bullpap" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Domain</td>
 				<td>
 					<input name="domain" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/domain | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
 
 <div metal:define-macro="fence-instance-form-xvm">
-	<div id="fence_xvm_instance" class="fencedev">
+	<div id="fence_xvm_instance" name="fence_xvm" class="fencedev_instance">
 		<table>
 			<tr>
 				<td>Domain</td>
 				<td>
 					<input name="domain" type="text"
-						tal:attributes="value nothing" />
+						tal:attributes="value cur_instance/domain | nothing" />
 				</td>
 			</tr>
+			<input tal:condition="exists: cur_instance"
+				type="hidden" name="existing_instance" value="1" />
+			<input type="hidden" name="parent_fencedev" value="" />
 		</table>
 	</div>
 </div>
+
 <div metal:define-macro="fence-instance-form-list">
 	<tal:block
 		metal:use-macro="here/form-macros/macros/fence-instance-form-apc" />
@@ -2071,7 +2296,7 @@
 		global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
 
 	<tal:block tal:define="
-		global nodestatus python: here.getClusterStatus(ricci_agent);
+		global nodestatus python: here.getClusterStatus(request, ricci_agent);
 		global nodeinfo python: here.getNodeInfo(modelb, nodestatus, request);
 		global status_class python: 'node_' + (nodeinfo['nodestate'] == '0' and 'active' or (nodeinfo['nodestate'] == '1' and 'inactive' or 'unknown'));
 		global cluster_node_status_str python: (nodeinfo['nodestate'] == '0' and 'Cluster member' or (nodeinfo['nodestate'] == '1' and 'Currently not a cluster participant' or 'This node is not responding'));
@@ -2214,79 +2439,91 @@
 
 	<hr/>
 
-	<div id="invisible" class="invisible">
+	<div class="invisible" id="fence_device_list">
 		<tal:block metal:use-macro="here/form-macros/macros/fence-form-list" />
 	</div>
 
-	<table id="fence_devices" class="cluster node fencedev">
-		<tfoot class="fencedev">
-		<tr class="cluster node fencedev"><td class="cluster node fencedev">
-			<input type="button" value="Update fence properties"
-				onClick="validate_fence_properties('fence_devices')" />
-		</td></tr>
+	<div class="invisible" id="shared_fence_devices">
+		<tal:block tal:repeat="cur_fencedev fencedevinfo/fencedevs">
+			<tal:block metal:use-macro="here/form-macros/macros/shared-fence-device-list" />
+		</tal:block>
+	</div>
+
+	<div class="invisible" id="fence_instances">
+		<tal:block metal:use-macro="here/form-macros/macros/fence-instance-form-list" />
+	</div>
+
+	<div id="fence_selection_block" class="invisible">
+		<form name="main_fence_form">
+			<select name="select_div">
+				<option value="fence-form-new-device">------ Use an existing Fence Device ------</option>
+				<tal:block tal:repeat="f fencedevinfo/fencedevs">
+					<option class="shared_fencedev"
+						tal:attributes="value f/name"
+						tal:content="python: f['name'] + ' (' + f['pretty_name'] + ')'"
+					/>
+				</tal:block>
+				<option value="fence-form-new-instance">------ Create a new Fence Device ------</option>
+				<tal:block metal:use-macro="here/form-macros/macros/fence-option-list" />
+			</select>
+			<input type="hidden" name="fence_level" value="" />
+			<input type="hidden" name="fence_num" value="" />
+		</form>
+	</div>
+
+	<table id="fence_devices" class="cluster node fence">
+		<tfoot class="fence">
+			<tr class="cluster node fence"><td class="cluster node fence">
+				<input type="button" value="Update fence properties"
+					onClick="validate_fence_properties('fence_devices')" />
+			</td></tr>
 		</tfoot>
-		<tbody class="fencedev">
-		<tr class="cluster node info_top fencedev">
-			<td class="cluster node fencedev">
-				<span class="fencedev">
+
+		<tbody class="fence">
+		<tr class="cluster node info_top fence">
+			<td class="cluster node fence">
+				<span class="fence">
 					<strong class="cluster node">Main Fencing Method</strong>
 				</span>
 			</td>
 			<td class="cluster node fence_backup">
-				<span class="fencedev">
+				<span class="fence">
 					<strong class="cluster node">Backup Fencing Method</strong>
 				</span>
 			</td>
 		</tr>
 
-		<tr class="cluster node info_top fencedev">
-			<td class="cluster node fence_main fencedev">
-				<tal:block tal:repeat="cur_fencedev fencedevinfo/fencedevs">
-					<div class="invisible" id="shared_fence_devices">
-						<tal:block metal:use-macro="here/form-macros/macros/shared-fence-device-list" />
-					</div>
-				</tal:block>
+		<tr class="cluster node info_top fence">
+			<td class="cluster node fence_main fence"><div class="fence_container">
+				<div id="fence_list_level1">
+					<tal:comment tal:replace="nothing">
+						XXX - fill in any existing fence devices for this node
+						and update the counter number for this level
+					</tal:comment>
+				</div>
 
-				<form name="main_fence_form">
-				<select name="select_div"
-					onChange="swap_fence_div('fence_container',
-								this.options[this.selectedIndex].value)">
-					<option value="fence-form-new-device">------ Use an existing Fence Device ------</option>
-					<tal:block tal:repeat="f fencedevinfo/fencedevs">
-						<option class="shared_fencedev"
-							tal:attributes="value f/name"
-							tal:content="python: f['name'] + ' (' + f['pretty_name'] + ')'"
-						/>
-					</tal:block>
-					<option value="fence-form-new-instance">------ Create a new Fence Device ------</option>
-					<tal:block metal:use-macro="here/form-macros/macros/fence-option-list" />
-				</select>
-				</form>
-				<div id="fence_container">
+				<div class="fence_control">
+					<input type="button" value="Add a fence to this level"
+						onclick="add_node_fence_device(1);" />
 				</div>
-			</td>
-			<td class="cluster node fence_main fencedev">
-				<form name="backup_fence_form">
-				<select name="select_div"
-					onChange="swap_fence_div('fence_container_backup',
-						this.options[this.selectedIndex].value)">
-					<option value="fence-form-new-device">------ Use an existing Fence Device ------</option>
-					<option value="fence-form-new-instance">------ Create a new Fence Device ------</option>
-					<tal:block metal:use-macro="here/form-macros/macros/fence-option-list" />
-				</select>
-				</form>
-				<div id="fence_container_backup">
+			</div></td>
+
+			<td class="cluster node fence_main fence"><div class="fence_container">
+				<div id="fence_list_level2">
+					<tal:comment tal:replace="nothing">
+						XXX - fill in any existing fence devices for this node
+						and update the counter number for this level
+					</tal:comment>
 				</div>
-			</td>
+
+				<div class="fence_control">
+					<input type="button" value="Add a fence to this level"
+						onclick="add_node_fence_device(2)" />
+				</div>
+			</div></td>
 		</tr>
 		</tbody>
 	</table>
-	<script type="text/javascript">
-		swap_fence_div('fence_container',
-			document.main_fence_form.select_div.options[document.main_fence_form.select_div.selectedIndex].value);
-		swap_fence_div('fence_container_backup',
-			document.backup_fence_form.select_div.options[document.backup_fence_form.select_div.selectedIndex].value);
-	</script>
 </div>
 
 <div metal:define-macro="nodes-form">
@@ -2302,7 +2539,7 @@
 		global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
 
 	<tal:block tal:define="
-		global status python: here.getClusterStatus(ricci_agent);
+		global status python: here.getClusterStatus(request, ricci_agent);
 		global nds python: here.getNodesInfo(modelb, status, request)" />
 
 	<div tal:repeat="nd nds">
@@ -2523,7 +2760,7 @@
 		global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
 
 	<tal:block tal:define="
-		global svcstatus python: here.getClusterStatus(ricci_agent);
+		global svcstatus python: here.getClusterStatus(request, ricci_agent);
 		global svcinf python: here.getServicesInfo(svcstatus,modelb,request);
 		global svcs svcinf/services" />
 
@@ -2546,9 +2783,31 @@
 					<form method="post" onSubmit="return dropdown(this.gourl)">
 						<select name="gourl">
 							<option value="">Choose a Task...</option>
-							<option value="" tal:attributes="value svc/cfgurl">Configure</option>
+							<option
+								tal:attributes="value svc/cfgurl | nothing"
+								tal:content="string:Configure this service" />
+
 							<option value="">----------</option>
-							<option value="">Delete</option>
+
+							<option
+								tal:condition="running"
+								tal:attributes="value svc/retstarturl| nothing"
+								tal:content="string:Restart this service" />
+
+							<option
+								tal:condition="running"
+								tal:attributes="value svc/disableurl | nothing"
+								tal:content="string:Stop this service" />
+
+							<option
+								tal:condition="not: running"
+								tal:attributes="value svc/enableurl | nothing"
+								tal:content="string:Start this service" />
+
+							<option
+								tal:condition="not: running"
+								tal:attributes="value svc/delurl | nothing"
+								tal:content="string:Delete this service" />
 						</select>
 						<input type="submit" value="Go"/>
 					</form>
@@ -2566,7 +2825,7 @@
 							This service is stopped
 						</tal:block>
 					</div>
-					<p>Autostart is <span tal:condition="not: autostart" tal:replace="string:not" /> enabled for this service</p>
+					<p>Autostart is <span tal:condition="python: autostart.lower() == 'false'" tal:replace="string:not" /> enabled for this service</p>
 				</td>
 			</tr>
 
@@ -2628,6 +2887,14 @@
 						<input type="text" length="20" name="service_name" value="" />
 					</td>
 				</tr>
+				<tr class="systemsTable">
+					<td class="systemsTable">
+						Automatically start this service
+					</td>
+					<td class="systemsTable">
+						<input type="checkbox" name="autostart" checked="checked" />
+					</td>
+				</tr>
 			</table>
 		</form>
 	</div>
@@ -2650,7 +2917,10 @@
 		<input type="hidden" name="uuid" value="toplevel" />
 		<input type="hidden" name="parent_uuid" value="_toplevel" />
 		<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="form_xml" />
+		<input type="hidden" name="action" value="add" />
 		</form>
 	</div>
 
@@ -2710,30 +2980,46 @@
 </div>
 
 <div metal:define-macro="serviceconfig-type-macro" tal:omit-tag="">
-	<span tal:omit-tag="" tal:condition="python: type == 'ip'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/ip_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'fs'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/fs_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'gfs'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'nfsm'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/nfsm_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'nfsx'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/nfsx_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'nfsc'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/nfsc_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'smb'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/smb_macro" />
-	</span>
-	<span tal:omit-tag="" tal:condition="python: type == 'script'">
-		<tal:block metal:use-macro="here/resource-form-macros/macros/scr_macro" />
-	</span>
+	<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: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:block tal:condition="python: type == 'gfs' or type == 'GFS: '">
+		<tal:block
+			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: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: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: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:block tal:condition="python: type == 'script' or type == 'Script: '">
+		<tal:block
+			metal:use-macro="here/resource-form-macros/macros/scr_macro" />
+	</tal:block>
 </div>
 
 <div metal:define-macro="service-config-head-macro" tal:omit-tag="">
@@ -2749,7 +3035,7 @@
 
 	<tal:block tal:define="
 		global global_resources python: here.getResourcesInfo(modelb, request);
-		global sstat python: here.getClusterStatus(ricci_agent);
+		global sstat python: here.getClusterStatus(request, ricci_agent);
 		global sinfo python: here.getServiceInfo(sstat, modelb, request);
 		global running sinfo/running | nothing;" />
 
@@ -2775,7 +3061,8 @@
 					tal:content="sinfo/name | nothing"
 					tal:attributes="class python: running and 'running' or 'stopped'" />
 			</td>
-			<td class="cluster service service_action">
+			<td class="cluster service service_action"
+				tal:condition="python: sinfo and 'innermap' in sinfo">
 				<form method="post" onSubmit="return dropdown(this.gourl)">
 					<input type="hidden" name="pagetype" tal:attributes="
 						value request/pagetype | request/form/pagetype | nothing" />
@@ -2790,14 +3077,15 @@
 							<option value="" tal:attributes="value innermap/disableurl">Disable this service</option>
 							<option value="">----------</option>
 							<option tal:repeat="starturl innermap/links" value="" tal:attributes="value starturl/url">Start this service on <span tal:replace="starturl/nodename"/></option>
-							<option value="">----------</option>
-							<option value="">Delete this service</option>
 						</tal:block>
 
 						<tal:block tal:condition="not: running">
 							<option value="">----------</option>
 							<option value="" tal:attributes="value innermap/enableurl">Enable this service</option>
 							<option value="">----------</option>
+							<option
+								tal:attributes="value innermap/delurl | nothing"
+								tal:content="string:Delete this service" />
 						</tal:block>
 					</select>
 					<input type="submit" value="Go"/>
@@ -2842,6 +3130,18 @@
 		</div>
 	</div>
 	<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>
+			</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)" />
@@ -2857,7 +3157,10 @@
 		<input type="hidden" name="uuid" value="toplevel" />
 		<input type="hidden" name="parent_uuid" value="_toplevel" />
 		<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="form_xml" />
+		<input type="hidden" name="action" value="edit" />
 		</form>
 	</div>
 
@@ -2881,6 +3184,11 @@
 	<h2>Service Process Form</h2>
 </div>
 
+<div metal:define-macro="servicedelete-form">
+	<h2>Service Delete Form</h2>
+	<tal:block tal:define="dummy python: here.delService(request)" />
+</div>
+
 <div metal:define-macro="resources-form">
 	<h2>Resources Form</h2>
 </div>
@@ -2918,7 +3226,7 @@
 		global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
 
 	<tal:block tal:define="
-		global sta python: here.getClusterStatus(ricci_agent);
+		global sta python: here.getClusterStatus(request, ricci_agent);
 		global fdominfo python: here.getFdomsInfo(modelb, request, sta);" />
 
 	<div class="cluster fdom" tal:repeat="fdom fdominfo">
@@ -3051,23 +3359,23 @@
 		<tal:block metal:use-macro="here/form-macros/macros/shared-fence-form-list" />
 	</div>
 
-	<table id="fence_devices" class="cluster node fencedev">
-		<tfoot class="fencedev">
-		<tr class="cluster node fencedev"><td class="cluster node fencedev">
+	<table id="fence_devices" class="cluster node fence">
+		<tfoot class="fence">
+		<tr class="cluster node fence"><td class="cluster node fence">
 			<input type="button" value="Add this shared fence device"
 				onClick="validate_fence_properties('fence_devices')" />
 		</td></tr>
 		</tfoot>
-		<tbody class="fencedev">
-		<tr class="cluster node info_top fencedev">
-			<td class="cluster node fencedev">
-				<span class="fencedev">
+		<tbody class="fence">
+		<tr class="cluster node info_top fence">
+			<td class="cluster node fence">
+				<span class="fence">
 					<strong class="cluster node">Fencing Type</strong>
 				</span>
 			</td>
 		</tr>
-		<tr class="cluster node info_top fencedev">
-			<td class="cluster node fence_main fencedev">
+		<tr class="cluster node info_top fence">
+			<td class="cluster node fence_main fence">
 				<form name="main_fence_form">
 				<select name="select_div"
 					onChange="swap_fence_div('fence_container',
@@ -3208,7 +3516,7 @@
 		<tal:block metal:use-macro="here/form-macros/macros/fence-form-manual" />
 	</tal:block>
 
-	<div class="fencedev">
+	<div class="fence_submit">
 		<input class="hbInput" type="button" value="Submit" name="Submit" />
 	</div>
 	</div>
--- conga/luci/cluster/index_html	2006/11/16 19:34:52	1.20.2.4
+++ conga/luci/cluster/index_html	2006/12/07 17:54:31	1.20.2.5
@@ -100,25 +100,6 @@
         window.open(href, windowname, 'width=500,height=500,scrollbars=yes');
         return false;
         }
-
-		function swap_fence_div(container_id, element_id) {
-			var container_element = document.getElementById(container_id)
-			if (!container_element) {
-				alert('Can\'t find element with id = ' + container_id);
-				return (-1);
-			}
-
-			var child_element = document.getElementById(element_id);
-			if (!child_element) {
-				alert('Can\'t find element with id = ' + element_id);
-				return (-1);
-			}
-			if (container_element.firstChild)
-				container_element.removeChild(container_element.firstChild);
-			var target = child_element.cloneNode(1);
-			target.id = null;
-			container_element.appendChild(target);
-		}
         //-->
        </SCRIPT>
       <metal:javascriptslot define-slot="javascript_head_slot" />
--- conga/luci/cluster/resource-form-macros	2006/11/16 19:34:53	1.21.2.2
+++ conga/luci/cluster/resource-form-macros	2006/12/07 17:54:31	1.21.2.3
@@ -271,7 +271,7 @@
 			<div metal:use-macro="here/resource-form-macros/macros/fs_macro" />
 		</tal:block>
 
-		<tal:block tal:condition="python: type == 'gfs'">
+		<tal:block tal:condition="python: type == 'gfs' or type == 'clusterfs'">
 			<div metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
 		</tal:block>
 
@@ -307,7 +307,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -368,7 +371,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -507,7 +513,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -609,7 +618,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -727,7 +739,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -799,7 +814,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -851,7 +869,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
@@ -913,7 +934,10 @@
 		tal:attributes="name res/parent_uuid | nothing"
 		tal:define="editDisabled resourceIsRef | nothing">
 
-	<input name="edit" type="hidden"
+	<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"
--- conga/luci/cluster/resource_form_handlers.js	2006/11/16 19:34:53	1.20.2.2
+++ conga/luci/cluster/resource_form_handlers.js	2006/12/07 17:54:31	1.20.2.3
@@ -380,21 +380,61 @@
 function forms_to_xml(master_form) {
 	var errors = new Array();
 	var form_xml = '';
+	var svc_name = null;
+	var autostart = 1;
 
 	var form = document.getElementsByTagName('form');
 	for (var i = 0 ; i < form.length ; i++) {
+		if (form[i].name == 'service_name_form') {
+			if (!form[i].service_name ||
+				str_is_blank(form[i].service_name.value))
+			{
+				set_form_err(form[i].service_name);
+			} else {
+				clr_form_err(form[i].service_name);
+				svc_name = form[i].service_name.value;
+			}
+			if (!form[i].autostart.checked)
+				autostart = 0;
+			continue;
+		}
+
 		if (form[i].name == 'master' || !form[i].uuid || !form[i].uuid.value)
 			continue;
+
 		var err = check_form(form[i]);
 		if (err)
-			errors.concat(err);
-		var temp = form[i].innerHTML.match(/<input [^>]+>/ig).toString().replace(/>(,|$)/g, '/>');
-		if (!temp)
-			continue;
+			errors = errors.concat(err);
+		var temp = '';
+
+		var input_elem = form[i].getElementsByTagName('input');
+		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 + '" checked="checked"';
+				if (res_type == 'radio')
+					temp += ' value="' + input_elem[j].value + '"';
+				temp += ' />';
+			}
+		}
+
+		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].uuid.value + '" parent="' +
 					form[i].parent_uuid.value + '">' + temp + '</form>';
 	}
 
+	if (!svc_name)
+		errors.push('No name was given for this service.');
+
 	if (!form_xml)
 		errors.push('No resource information was submitted.');
 
@@ -403,7 +443,15 @@
 
 	/* sort this out in the backend */
 	master_form.form_xml.value = '<formlist>' + form_xml + '</formlist>';
-	if (confirm('Save changes to this service?'))
+	master_form.svc_name.value = svc_name;
+	master_form.autostart.value = autostart;
+
+	var confirm_msg = null;
+	if (master_form.action.value == 'add')
+		confirm_msg = 'Create this service?';
+	else
+		confirm_msg = 'Save changes to this service?';
+	if (confirm(confirm_msg))
 		master_form.submit();
 	return (0);
 }
--- conga/luci/homebase/luci_homebase.css	2006/11/16 19:34:53	1.28.2.1
+++ conga/luci/homebase/luci_homebase.css	2006/12/07 17:54:31	1.28.2.2
@@ -14,27 +14,27 @@
 	background: #dee7ec;
 }
 
-div.fencedev {
+div.fence {
 	max-width: 700px;
 	padding: .5em;
 }
 
-*.fencedev {
+*.fence {
 	background: #dee7ec;
 }
 
-table.fencedev {
+table.fence {
 	padding: .618em;
 	width: 700px;
 }
 
-div.fencedev,
-td.fencedev {
+div.fence,
+td.fence {
 	padding-top: .309em;
 	padding-bottom: .309em;
 }
 
-td.fencedev {
+td.fence {
 	width: 50%;
 }
 
@@ -438,6 +438,21 @@
 	margin-bottom: .25em ! important;
 }
 
+div.fence_add {
+	margin-top: .25em ! important;
+	margin-bottom: .25em ! important;
+}
+
+div.fence_container {
+	border: thin solid #c9c9c9;
+}
+
+div.fence_control {
+	margin-top: 2em;
+	margin-bottom: .75em;
+	margin-left: .33em;
+}
+
 div.service_comp_list {
 	background: #dee7ec;
 	max-width: 700px;
--- conga/luci/site/luci/Extensions/ClusterNode.py	2006/05/30 20:17:21	1.1
+++ conga/luci/site/luci/Extensions/ClusterNode.py	2006/12/07 17:54:31	1.1.2.1
@@ -96,3 +96,10 @@
     except KeyError, e:
       return ""
 
+  def getVotes(self):
+    try:
+      return self.getAttribute('votes')
+    except KeyError, e:
+      return "1"
+    except:
+      return None
--- conga/luci/site/luci/Extensions/FenceDevice.py	2006/10/04 15:11:10	1.2
+++ conga/luci/site/luci/Extensions/FenceDevice.py	2006/12/07 17:54:31	1.2.2.1
@@ -19,7 +19,12 @@
 
 
   def getAgentType(self):
-    return self.attr_hash["agent"]
+    agent = self.attr_hash["agent"]
+    try:
+      return agent[agent.rfind('/') + 1:]
+    except:
+      pass
+    return agent
 
   def isShared(self):
     agent = self.getAgentType()
--- conga/luci/site/luci/Extensions/LuciSyslog.py	2006/11/16 19:34:53	1.2.2.3
+++ conga/luci/site/luci/Extensions/LuciSyslog.py	2006/12/07 17:54:31	1.2.2.4
@@ -78,6 +78,7 @@
 
 	def close(self):
 		try:
+			self.__init = 0
 			closelog()
 		except:
 			pass
--- conga/luci/site/luci/Extensions/cluster_adapters.py	2006/11/30 20:12:38	1.120.2.12
+++ conga/luci/site/luci/Extensions/cluster_adapters.py	2006/12/07 17:54:31	1.120.2.13
@@ -12,8 +12,10 @@
 from Ip import Ip
 from Clusterfs import Clusterfs
 from Fs import Fs
+from RefObject import RefObject
 from NFSClient import NFSClient
 from NFSExport import NFSExport
+from Service import Service
 from Netfs import Netfs
 from Vm import Vm
 from Script import Script
@@ -396,19 +398,31 @@
 	response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clusterName + '&busyfirst=true')
 
 def validateServiceAdd(self, request):
+	errors = list()
+
 	try:
 		form_xml = request['form_xml']
 		if not form_xml:
-			raise KeyError('form_xml must not be blank')
-	except KeyError, e:
+			raise KeyError, 'form_xml must not be blank'
+	except Exception, e:
+		luci_log.debug_verbose('vSA0: no form_xml: %s' % str(e))
 		return (False, {'errors': ['No resource data was supplied for this service.']})
 
 	try:
+		model = request.SESSION.get('model')
+		if not model:
+			raise Exception, 'model is None'
+	except Exception, e:
+		luci_log.debug_verbose('vSA0a: %s' % str(e))
+		return (False, {'errors': [ 'The cluster model is missing from the session object.' ]})
+
+	try:
 		doc = minidom.parseString(form_xml)
 		forms = doc.getElementsByTagName('form')
 		if len(forms) < 1:
 			raise
-	except:
+	except Exception, e:
+		luci_log.debug_verbose('vSA1: error: %s' % str(e))
 		return (False, {'errors': ['The resource data submitted for this service is not properly formed.']})
 
 	form_hash = {}
@@ -440,27 +454,145 @@
 			try:
 				dummy_form[str(i.getAttribute('name'))] = str(i.getAttribute('value'))
 			except Exception, e:
-				luci_log.debug_verbose('Error parsing service XML: %s' % str(e))
+				luci_log.debug_verbose('vSA2: parsing XML: %s' % str(e))
 				pass
 
 		try:
 			res_type = dummy_form['type'].strip()
-			if not res_type or not res_type in resourceAddHandler:
-				raise
-		except:
-			return (False, {'errors': ['An invalid resource type was specified: ' + res_type]})
+			if not res_type:
+				raise Exception, 'no resource type was given'
+			if not res_type in resourceAddHandler:
+				raise Exception, 'invalid resource type: %s' % res_type
+		except Exception, e:
+			luci_log.debug_verbose('vSA3: %s' % str(e))
+			return (False, {'errors': [ 'An invalid resource type was specified' ]})
 
 		try:
-			resObj = resourceAddHandler[res_type](request, dummy_form)
-		except:
-			luci_log('res type %d is invalid' % res_type)
+			if res_type == 'ip':
+				dummy_form['resourceName'] = dummy_form['ip_address']
+		except Exception, e:
+			luci_log.debug_verbose('vSA3a: type is ip but no addr: %s' % str(e))
+			return (False, {'errors': [ 'No IP address was given.' ]})
+
+		try:
+			if dummy_form.has_key('immutable'):
+				newRes = getResource(model, dummy_form['resourceName'])
+				resObj = RefObject(newRes)
+				resObj.setRef(newRes.getName())
+			else:
+				resObj = resourceAddHandler[res_type](request, dummy_form)[0]
+		except Exception, e:
 			resObj = None
+			luci_log.debug_verbose('vSA4: type %s: %s' % (res_type, str(e)))
 
 		if resObj is None:
-			return (False, {'errors': ['An error occurred while adding ' + res_type]})
+			return (False, {'errors': [ 'An error occurred while adding %s' % res_type ]})
 		form_hash[form_id]['obj'] = resObj
-			
-	return (True, {'messages': ['This service has been updated.']})
+
+	if len(errors) > 0:
+		return (False, {'errors': errors})
+
+	try:
+		service_name = request.form['svc_name'].strip()
+	except Exception, e:
+		luci_log.debug_verbose('vSA5: no service name: %s' % str(e))
+		return (False, {'errors': [ 'No service name was given.' ]})
+
+	autostart = "1"
+	try:
+		if not request.form.has_key('autostart') or request.form['autostart'] == "0":
+			autostart = "0"
+	except Exception, e:
+		autostart = None
+		luci_log.debug_verbose('vSA5a: error getting autostart: %s' % str(e))
+
+	try:
+		cur_service = model.retrieveServiceByName(service_name)
+	except GeneralError, e:
+		luci_log.debug_verbose('vSA5b: no service named %s found' % service_name)
+		cur_service = None
+	except Exception, e:
+		luci_log.debug_verbose('vSA5c: no service named %s found: %s' % (service_name, str(e)))
+		cur_service = None
+
+	try:
+		if request.form['action'] == 'edit':
+			if cur_service is None:
+				return (False, {'errors': [ 'The service %s could not be found for editing.' % service_name ]})
+			model.deleteService(service_name)
+		elif request.form['action'] == 'add':
+			if cur_service is not None:
+				return (False, {'errors': [ 'A service with the name %s already exists.' % service_name ]})
+		else:
+			luci_log.debug_verbose('vSA4a: unknown action %s' % request.form['action'])
+			return (False, {'errors': [ 'An unknown action was specified.' ]})
+	except Exception, e:
+		luci_log.debug_verbose('vSA5: no action type: %s' % str(e))
+
+	def buildSvcTree(parent, child_id_list):
+		for i in child_id_list:
+			try:
+				child = form_hash[i]['obj']
+				if not child:
+					raise Exception, 'No object for %s' % i
+			except Exception, e:
+				luci_log.debug_verbose('bST0: %s' % str(e))
+				continue
+			parent.addChild(child)
+			if 'kids' in form_hash[i]:
+				buildSvcTree(child, form_hash[i]['kids'])
+
+	new_service = Service()
+	new_service.addAttribute('name', service_name)
+	if autostart is not None:
+		new_service.attr_hash['autostart'] = autostart
+
+	buildSvcTree(new_service, form_hash['toplevel']['kids'])
+	model.resourcemanager_ptr.addChild(new_service)
+
+	clustername = model.getClusterName()
+	if not clustername:
+		luci_log.debug_verbose('vAS6: no cluname from mb')
+		return (False, {'errors': [ 'Unable to determine cluster name' ]})
+
+	try:
+		conf = model.exportModelAsString()
+		if not conf:
+			raise Exception, 'model string for %s is blank' % clustername
+	except Exception, e:
+		luci_log.debug_verbose('vAS6a: exportModelAsString : %s' \
+			% str(e))
+		return (False, {'errors': [ 'An error occurred while adding this service.' ]})
+
+	rc = getRicciAgent(self, clustername)
+	if not rc:
+		luci_log.debug_verbose('vAS6b: unable to find a ricci agent for cluster %s' % clustername)
+		return 'Unable to find a ricci agent for the %s cluster' % clustername
+
+	try:
+		ragent = rc.hostname()
+		if not ragent:
+			luci_log.debug_verbose('vAS7: missing ricci hostname')
+			raise Exception, 'unknown ricci agent hostname'
+
+		batch_number, result = setClusterConf(rc, str(conf))
+		if batch_number is None or result is None:
+			luci_log.debug_verbose('vAS8: missing batch_number or result')
+			raise Exception, 'unable to save the new cluster configuration.'
+	except Exception, e:
+		luci_log.debug_verbose('vAS9: %s' % str(e))
+		return 'An error occurred while propagating the new cluster.conf: %s' % str(e)
+
+	try:
+		if request.form['action'] == 'edit':
+			set_node_flag(self, clustername, ragent, str(batch_number), SERVICE_CONFIG, "Configuring service \'%s\'" % service_name)
+		else:
+			set_node_flag(self, clustername, ragent, str(batch_number), SERVICE_ADD, "Adding new service \'%s\'" % service_name)
+	except Exception, e:
+		luci_log.debug_verbose('vAS10: failed to set flags: %s' % str(e))
+
+	response = request.RESPONSE
+	response.redirect(request['URL'] + "?pagetype=" + SERVICES + "&clustername=" + clustername + '&busyfirst=true')
 
 def validateResourceAdd(self, request):
 	try:
@@ -1712,23 +1844,133 @@
 		return None
 	return getRicciAgent(self, clustername)
 
-def getClusterStatus(self, rc):
+def getClusterStatusModel(model):
+	results = list()
+	vals = {}
+
+	try:
+		clustername = model.getClusterName()
+		clusteralias = model.getClusterAlias()
+		vals['type'] = 'cluster'
+		vals['alias'] = clusteralias
+		vals['name'] = clustername
+		vals['error'] = True
+		vals['votes'] = '[unknown]'
+		vals['quorate'] = '[unknown]'
+		vals['minQuorum'] = '[unknown]'
+		results.append(vals)
+	except Exception, e:
+		luci_log.debug_verbose('GCSM0: %s' % str(e))
+		return None
+
+	try:
+		nodelist = model.getNodes()
+	except Exception, e:
+		luci_log.debug_verbose('GCSM1: %s' % str(e))
+		return None
+
+	for node in nodelist:
+		node_val = {}
+		node_val['type'] = 'node'
+		try:
+			node_name = node.getName()
+			if not node_name:
+				raise Exception, 'cluster node name is unknown'
+		except:
+			node_name = '[unknown]'
+
+		node_val['name'] = node_name
+		node_val['clustered'] = '[unknown]'
+		node_val['online'] = '[unknown]'
+		node_val['error'] = True
+
+		try:
+			votes = node.getVotes()
+			if not votes:
+				raise Exception, 'unknown unmber of votes'
+		except:
+			votes = '[unknown]'
+
+		node_val['votes'] = votes
+		results.append(node_val)
+	return results
+
+def getClusterStatusDB(self, clustername):
+	results = list()
+	vals = {}
+
+	vals['type'] = 'cluster'
+	vals['alias'] = clustername
+	vals['name'] = clustername
+	vals['error'] = True
+	vals['quorate'] = '[unknown]'
+	vals['votes'] = '[unknown]'
+	vals['minQuorum'] = '[unknown]'
+	results.append(vals)
+
+	try:
+		cluster_path = '%s/luci/systems/cluster/%s' % (CLUSTER_FOLDER_PATH, clustername)
+		nodelist = self.restrictedTraverse(cluster_path).objectItems('Folder')
+	except Exception, e:
+		luci_log.debug_verbose('GCSDB0: %s: %s' % (clustername, str(e)))
+		return results
+
+	for node in nodelist:
+		try:
+			node_val = {}
+			node_val['type'] = 'node'
+			node_val['name'] = node[0]
+			node_val['clustered'] = '[unknown]'
+			node_val['online'] = '[unknown]'
+			node_val['error'] = True
+			results.append(node_val)
+		except Exception, e:
+			luci_log.debug_verbose('GCSDB1: %s' % str(e))
+	return results
+
+def getClusterStatus(self, request, rc):
 	try:
 		doc = getClusterStatusBatch(rc)
+		if not doc:
+			raise Exception, 'doc is None'
 	except Exception, e:
 		luci_log.debug_verbose('GCS0: error: %s' % str(e))
 		doc = None
 
+	if doc is None:
+		try:
+			model = request.SESSION.get('model')
+			cinfo = getClusterStatusModel(model)
+			if not cinfo or len(cinfo) < 1:
+				raise Exception, 'cinfo is None'
+			return cinfo
+		except Exception, e:
+			luci_log.debug_verbose('GCS1: %s' % str(e))
+			doc = None
+
 	if not doc:
 		try:
-			luci_log.debug_verbose('GCS1: returned None for %s/%s' % rc.cluster_info())
-		except:
-			pass
+			clustername = None
+			try:
+				clustername = request['clustername']
+			except:
+				try:
+					clustername = request.form['clustername']
+				except:
+					pass
 
-		return {}
+			if not clustername:
+				raise Exception, 'unable to determine cluster name'
 
-	results = list()
+			cinfo = getClusterStatusDB(self, clustername)
+			if not cinfo or len(cinfo) < 1:
+				raise Exception, 'cinfo is None'
+			return cinfo
+		except Exception, e:
+			luci_log.debug_verbose('GCS1a: unable to get cluster info from DB: %s' % str(e))
+		return []
 
+	results = list()
 	vals = {}
 	vals['type'] = "cluster"
 
@@ -1796,6 +2038,7 @@
 				itemmap['nodename'] = item['nodename']
 			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 = modelb.retrieveServiceByName(item['name'])
 			dom = svc.getAttribute("domain")
@@ -1847,6 +2090,7 @@
 			if item['name'] == servicename:
 				hmap['name'] = servicename
 				starturls = list()
+				hmap['autostart'] = item['autostart']
 				if item['running'] == "true":
 					hmap['running'] = "true"
 					#In this case, determine where it can run...
@@ -1855,6 +2099,8 @@
 					innermap['current'] = "This service is currently running on %s" % nodename
 					innermap['disableurl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + servicename + "&pagetype=" + SERVICE_STOP
 					innermap['restarturl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + servicename + "&pagetype=" + SERVICE_RESTART
+					innermap['delurl'] = baseurl + "?" + "clustername=" + cluname +"&servicename=" + servicename + "&pagetype=" + SERVICE_DELETE
+
 					nodes = modelb.getNodes()
 					for node in nodes:
 						starturl = {}
@@ -1901,16 +2147,18 @@
 	if parent is not None:
 		rc_map['parent'] = parent
 	rc_map['name'] = child.getName()
+
+	#Note: Final version needs all resource attrs
 	if child.isRefObject() == True:
 		rc_map['ref_object'] = True
 		rc_map['type'] = child.getObj().getResourceType()
+		rc_map['attrs'] = child.getObj().getAttributes()
 	else:
 		rc_map['type'] = child.getResourceType()
+		rc_map['attrs'] = child.getAttributes()
 
 	rc_map['indent_ctr'] = indent_ctr
 
-	#Note: Final version needs all resource attrs
-	rc_map['attrs'] = child.getAttributes()
 	rc_map['uuid'] = make_uuid('resource')
 	rc_map['parent_uuid'] = parent_uuid
 
@@ -2186,39 +2434,31 @@
         return {}
 
   if model is None:
-    rc = getRicciAgent(self, cluname)
-    if not rc:
-      luci_log.debug_verbose('GCI1: unable to find a ricci agent for the %s cluster' % cluname)
-      return {}
     try:
-      model = getModelBuilder(None, rc, rc.dom0())
+      model = getModelForCluster(self, cluname)
       if not model:
         raise Exception, 'model is none'
-
-      try:
-        req.SESSION.set('model', model)
-      except Exception, e2:
-        luci_log.debug_verbose('GCI2 unable to set model in session: %s' % str(e2))
+      req.SESSION.set('model', model)
     except Exception, e:
-      luci_log.debug_verbose('GCI3: unable to get model for cluster %s: %s' % (cluname, str(e)))
+      luci_log.debug_verbose('GCI1: unable to get model for cluster %s: %s' % (cluname, str(e)))
       return {}
 
   prop_baseurl = req['URL'] + '?' + PAGETYPE + '=' + CLUSTER_CONFIG + '&' + CLUNAME + '=' + cluname + '&'
-  map = {}
+  clumap = {}
   basecluster_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_GENERAL_TAB
   #needed:
-  map['basecluster_url'] = basecluster_url
+  clumap['basecluster_url'] = basecluster_url
   #name field
-  map['clustername'] = model.getClusterAlias()
+  clumap['clustername'] = model.getClusterAlias()
   #config version
   cp = model.getClusterPtr()
-  map['config_version'] = cp.getConfigVersion()
+  clumap['config_version'] = cp.getConfigVersion()
   #-------------
   #new cluster params - if rhel5
   #-------------
   #Fence Daemon Props
   fencedaemon_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_FENCE_TAB
-  map['fencedaemon_url'] = fencedaemon_url
+  clumap['fencedaemon_url'] = fencedaemon_url
   fdp = model.getFenceDaemonPtr()
   pjd = fdp.getAttribute('post_join_delay')
   if pjd is None:
@@ -2227,35 +2467,35 @@
   if pfd is None:
     pfd = "0"
   #post join delay
-  map['pjd'] = pjd
+  clumap['pjd'] = pjd
   #post fail delay
-  map['pfd'] = pfd
+  clumap['pfd'] = pfd
   #-------------
   #if multicast
   multicast_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_MCAST_TAB
-  map['multicast_url'] = multicast_url
+  clumap['multicast_url'] = multicast_url
   #mcast addr
   is_mcast = model.isMulticast()
-  #map['is_mcast'] = is_mcast
+  #clumap['is_mcast'] = is_mcast
   if is_mcast:
-    map['mcast_addr'] = model.getMcastAddr()
-    map['is_mcast'] = "True"
+    clumap['mcast_addr'] = model.getMcastAddr()
+    clumap['is_mcast'] = "True"
   else:
-    map['is_mcast'] = "False"
-    map['mcast_addr'] = "1.2.3.4"
+    clumap['is_mcast'] = "False"
+    clumap['mcast_addr'] = "1.2.3.4"
 
   #-------------
   #quorum disk params
   quorumd_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_QDISK_TAB
-  map['quorumd_url'] = quorumd_url
+  clumap['quorumd_url'] = quorumd_url
   is_quorumd = model.isQuorumd()
-  map['is_quorumd'] = is_quorumd
-  map['interval'] = ""
-  map['tko'] = ""
-  map['votes'] = ""
-  map['min_score'] = ""
-  map['device'] = ""
-  map['label'] = ""
+  clumap['is_quorumd'] = is_quorumd
+  clumap['interval'] = ""
+  clumap['tko'] = ""
+  clumap['votes'] = ""
+  clumap['min_score'] = ""
+  clumap['device'] = ""
+  clumap['label'] = ""
 
   #list struct for heuristics...
   hlist = list()
@@ -2264,27 +2504,27 @@
     qdp = model.getQuorumdPtr()
     interval = qdp.getAttribute('interval')
     if interval is not None:
-      map['interval'] = interval
+      clumap['interval'] = interval
 
     tko = qdp.getAttribute('tko')
     if tko is not None:
-      map['tko'] = tko
+      clumap['tko'] = tko
 
     votes = qdp.getAttribute('votes')
     if votes is not None:
-      map['votes'] = votes
+      clumap['votes'] = votes
 
     min_score = qdp.getAttribute('min_score')
     if min_score is not None:
-      map['min_score'] = min_score
+      clumap['min_score'] = min_score
 
     device = qdp.getAttribute('device')
     if device is not None:
-      map['device'] = device
+      clumap['device'] = device
 
     label = qdp.getAttribute('label')
     if label is not None:
-      map['label'] = label
+      clumap['label'] = label
 
     heuristic_kids = qdp.getChildren()
     h_ctr = 0
@@ -2313,9 +2553,9 @@
       else:
         hmap['hinterval'] = ""
       hlist.append(hmap)
-  map['hlist'] = hlist
+  clumap['hlist'] = hlist
 
-  return map
+  return clumap
 
 def getClustersInfo(self, status, req):
   map = {}
@@ -2335,6 +2575,10 @@
   if len(clulist) < 1:
     return {}
   clu = clulist[0]
+  cluerror = False
+  if 'error' in clu:
+    cluerror = True
+    map['error'] = True
   clustername = clu['name']
   if clu['alias'] != "":
     map['clusteralias'] = clu['alias']
@@ -2349,6 +2593,7 @@
     map['running'] = "false"
   map['votes'] = clu['votes']
   map['minquorum'] = clu['minQuorum']
+
   map['clucfg'] = baseurl + "?" + PAGETYPE + "=" + CLUSTER_CONFIG + "&" + CLUNAME + "=" + clustername
 
   map['restart_url'] = baseurl + "?" + PAGETYPE + "=" + CLUSTER_PROCESS + "&" + CLUNAME + "=" + clustername + '&task=' + CLUSTER_RESTART
@@ -2370,6 +2615,7 @@
   map['currentservices'] = svc_dict_list
   node_dict_list = list()
   for item in nodelist:
+    node_error = 'error' in item
     nmap = {}
     name = item['name']
     nmap['nodename'] = name
@@ -2872,15 +3118,16 @@
 
   infohash['currentservices'] = svc_dict_list
 
-  #next is faildoms
-  fdoms = model.getFailoverDomainsForNode(nodename)
   fdom_dict_list = list()
-  for fdom in fdoms:
-    fdom_dict = {}
-    fdom_dict['name'] = fdom.getName()
-    fdomurl = baseurl + "?" + PAGETYPE + "=" + FDOM_CONFIG + "&" + CLUNAME + "=" + clustername + "&fdomname=" + fdom.getName()
-    fdom_dict['fdomurl'] = fdomurl
-    fdom_dict_list.append(fdom_dict)
+  if model:
+    #next is faildoms
+    fdoms = model.getFailoverDomainsForNode(nodename)
+    for fdom in fdoms:
+      fdom_dict = {}
+      fdom_dict['name'] = fdom.getName()
+      fdomurl = baseurl + "?" + PAGETYPE + "=" + FDOM_CONFIG + "&" + CLUNAME + "=" + clustername + "&fdomname=" + fdom.getName()
+      fdom_dict['fdomurl'] = fdomurl
+      fdom_dict_list.append(fdom_dict)
 
   infohash['fdoms'] = fdom_dict_list
 
@@ -2911,7 +3158,6 @@
 
   infohash['logurl'] = '/luci/logs/?nodename=' + nodename_resolved + '&clustername=' + clustername
   return infohash
-  #get list of faildoms for node
 
 def getNodesInfo(self, model, status, req):
   resultlist = list()
@@ -3015,6 +3261,10 @@
   return resultlist
 
 def getFence(self, model, request):
+  if not model:
+    luci_log.debug_verbose('getFence0: model is None')
+    return {}
+
   map = {}
   fencename = request['fencename']
   fencedevs = model.getFenceDevices()
@@ -3061,6 +3311,10 @@
   raise
   
 def getFenceInfo(self, model, request):
+  if not model:
+    luci_log.debug_verbose('getFenceInfo00: model is None')
+    return {}
+
   try:
     clustername = request['clustername']
   except:
@@ -3311,9 +3565,14 @@
   return map    
       
 def getFencesInfo(self, model, request):
+  map = {}
+  if not model:
+    luci_log.debug_verbose('getFencesInfo0: model is None')
+    map['fencedevs'] = list()
+    return map
+
   clustername = request['clustername']
   baseurl = request['URL']
-  map = {}
   fencedevs = list() #This is for the fencedev list page
 
   #Get list of fence devices
@@ -3798,6 +4057,7 @@
 	for item in modelb.getResources():
 		itemmap = {}
 		itemmap['name'] = item.getName()
+		itemmap['attrs'] = item.attr_hash
 		itemmap['type'] = item.resource_type
 		itemmap['cfgurl'] = baseurl + "?" + "clustername=" + cluname + "&resourcename=" + item.getName() + "&pagetype=" + RESOURCE_CONFIG
 		itemmap['url'] = baseurl + "?" + "clustername=" + cluname + "&resourcename=" + item.getName() + "&pagetype=" + RESOURCE
@@ -3859,6 +4119,82 @@
 			except:
 				continue
 
+def delService(self, request):
+	errstr = 'An error occurred while attempting to set the new cluster.conf'
+
+	try:
+		modelb = request.SESSION.get('model')
+	except Exception, e:
+		luci_log.debug_verbose('delService0: no model: %s' % str(e))
+		return (False, {'errors': [ errstr ] })
+
+	name = None
+	try:
+		name = request['servicename']
+	except:
+		try:
+			name = request.form['servicename']
+		except:
+			pass
+
+	if name is None:
+		luci_log.debug_verbose('delService1: no service name')
+		return (False, {'errors': [ '%s: no service name was provided.' % errstr ]})
+
+	clustername = None
+	try:
+		clustername = request['clustername']
+	except:
+		try:
+			clustername = request.form['clustername']
+		except:
+			pass
+
+	if clustername is None:
+		luci_log.debug_verbose('delService2: no cluster name for %s' % name)
+		return (False, {'errors': [ '%s: no cluster name was provided.' % errstr ]})
+
+	rc = getRicciAgent(self, clustername)
+	if not rc:
+		luci_log.debug_verbose('delService3: unable to get ricci agent for cluster %s' % clustername)
+		return (False, {'errors': [ '%s: unable to find a Ricci agent for this cluster.' % errstr ]})
+
+	try:
+		ragent = rc.hostname()
+		if not ragent:
+			raise Exception, 'unable to determine the hostname of the ricci agent'
+	except Exception, e:
+		luci_log.debug_verbose('delService4: %s: %s' % (errstr, str(e)))
+		return (False, {'errors': [ '%s: unable to find a Ricci agent for this cluster.' % errstr ]})
+
+	try:
+		modelb.deleteService(name)
+	except Exception, e:
+		luci_log.debug_verbose('delService5: Unable to find a service named %s for cluster %s' % (name, clustername))
+		return (False, {'errors': [ '%s: error removing service %s.' % (errstr, name) ]})
+
+	try:
+		conf = modelb.exportModelAsString()
+		if not conf:
+			raise Exception, 'model string is blank'
+	except Exception, e:
+		luci_log.debug_verbose('delService6: exportModelAsString failed: %s' \
+			% str(e))
+		return (False, {'errors': [ '%s: error removing service %s.' % (errstr, name) ]})
+
+	batch_number, result = setClusterConf(rc, str(conf))
+	if batch_number is None or result is None:
+		luci_log.debug_verbose('delService7: missing batch and/or result')
+		return (False, {'errors': [ '%s: error removing service %s.' % (errstr, name) ]})
+
+	try:
+		set_node_flag(self, clustername, ragent, str(batch_number), SERVICE_DELETE, "Removing service \'%s\'" % name)
+	except Exception, e:
+		luci_log.debug_verbose('delService8: failed to set flags: %s' % str(e))
+
+	response = request.RESPONSE
+	response.redirect(request['URL'] + "?pagetype=" + SERVICES + "&clustername=" + clustername + '&busyfirst=true')
+
 def delResource(self, rc, request):
 	errstr = 'An error occurred while attempting to set the new cluster.conf'
 
@@ -4516,7 +4852,7 @@
 	'gfs': addGfs,
 	'nfsm': addNfsm,
 	'nfsx': addNfsx,
-	'nfsc': addNfsx,
+	'nfsc': addNfsc,
 	'scr': addScr,
 	'smb': addSmb
 }
@@ -4651,6 +4987,17 @@
 	response = request.RESPONSE
 	response.redirect(request['URL'] + "?pagetype=" + RESOURCES + "&clustername=" + clustername + '&busyfirst=true')
 
+def getResource(modelb, name):
+	resPtr = modelb.getResourcesPtr()
+	resources = resPtr.getChildren()
+
+	for res in resources:
+		if res.getName() == name:
+			return res
+
+	luci_log.debug_verbose('getResource: unable to find resource \"%s\"' % name)
+	raise KeyError, name
+
 def getResourceForEdit(modelb, name):
 	resPtr = modelb.getResourcesPtr()
 	resources = resPtr.getChildren()
@@ -4660,7 +5007,7 @@
 			resPtr.removeChild(res)
 			return res
 
-	luci_log.debug_verbose('unable to find resource \"%s\"' % name)
+	luci_log.debug_verbose('GRFE0: unable to find resource \"%s\"' % name)
 	raise KeyError, name
 
 def appendModel(request, model):
--- conga/luci/site/luci/Extensions/conga_constants.py	2006/11/16 19:34:53	1.19.2.2
+++ conga/luci/site/luci/Extensions/conga_constants.py	2006/12/07 17:54:31	1.19.2.3
@@ -43,6 +43,7 @@
 FENCEDEV_CONFIG="53"
 FENCEDEV="54"
 CLUSTER_DAEMON="55"
+SERVICE_DELETE = '56'
 
 #Cluster tasks
 CLUSTER_STOP = '1000'
@@ -119,7 +120,7 @@
 PRE_JOIN = "Packages are installed and configuration has been distributed, but the node has not yet joined the cluster."
 
 
-POSSIBLE_REBOOT_MESSAGE = "This node is not currently responding and is probably<br/>rebooting as planned. This state should persist for 5 minutes or so..."
+POSSIBLE_REBOOT_MESSAGE = "This node is not currently responding and is probably rebooting as planned. This state should persist for 5 minutes or so..."
 
 REDIRECT_MSG = " You will be redirected in 5 seconds. Please fasten your safety restraints."
 
--- conga/luci/site/luci/Extensions/ricci_bridge.py	2006/11/20 23:36:12	1.30.2.10
+++ conga/luci/site/luci/Extensions/ricci_bridge.py	2006/12/07 17:54:31	1.30.2.11
@@ -63,7 +63,7 @@
 	batch += '</function_call>'
 	batch += '</request>'
 	batch += '</module>'
-		
+
 	need_reboot = install_base or install_services or install_shared_storage or install_LVS
 	if need_reboot:
 		batch += '<module name="service">'
@@ -96,7 +96,7 @@
 		batch += '<function_call name="install"/>'
 		batch += '</request>'
 		batch += '</module>'
-		
+
 	batch += '<module name="cluster">'
 	batch += '<request API_version="1.0">'
 	batch += '<function_call name="set_cluster.conf">'
@@ -236,7 +236,7 @@
 		batch += '<cman expected_votes="1" two_node="1"/>'
 	else:
 		batch += '<cman/>'
- 
+
 	batch += '<fencedevices/>'
 	batch += '<rm/>'
 	batch += '</cluster>'
@@ -298,66 +298,39 @@
 		pass
 
 	return (None, None)
-	
 
-def getPayload(bt_node):
-	if not bt_node:
-		return None
-
-	mod_node = None
-	for node in bt_node.childNodes:
-		if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.nodeName == 'module':
-			mod_node = node
-	if not mod_node:
-		return None
-
-	resp_node = None
-	for node in mod_node.childNodes:
-		if node.nodeType == xml.dom.Node.ELEMENT_NODE:
-			resp_node = node
-	if not resp_node:
-		return None
+def getClusterStatusBatch(rc):
+	batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="status"/></request></module>'
+	ricci_xml = rc.batch_run(batch_str, async=False)
 
-	fr_node = None
-	for node in resp_node.childNodes:
-		if node.nodeType == xml.dom.Node.ELEMENT_NODE:
-			fr_node = node
-	if not fr_node:
+	try:
+		cluster_tags = ricci_xml.getElementsByTagName('cluster')
+	except Exception, e:
+		luci_log.debug_verbose('getClusterStatusBatch0: %s' % str(e))
 		return None
 
-	varnode = None
-	for node in fr_node.childNodes:
-		if node.nodeName == 'var':
-			varnode = node
-			break
-	if not varnode:
-		return None
+	if len(cluster_tags) < 1:
+		luci_log.debug_verbose('getClusterStatusBatch1: %d entries - expecting 1' \
+			% len(cluster_tags))
+	elif len(cluster_tags) > 1:
+		luci_log.debug_verbose('getClusterStatusBatch2: %d entries - expecting 1, using the first' % len(cluster_tags))
 
-	cl_node = None
-	for node in varnode.childNodes:
-		if node.nodeName == 'cluster':
-			cl_node = node
-			break
-	if not cl_node:
+	try:
+		cluster_node = cluster_tags[0]
+		if not cluster_node:
+			raise Exception, 'element 0 is None'
+	except Exception, e:
+		luci_log.debug_verbose('getClusterStatusBatch3: %s' % str(e))
 		return None
 
-	doc = minidom.Document()
-	doc.appendChild(cl_node)
-	return doc
-
-def getClusterStatusBatch(rc):
-	batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="status"/></request></module>'
-	ricci_xml = rc.batch_run(batch_str, async=False)
-
-	if not ricci_xml or not ricci_xml.firstChild:
-		luci_log.debug_verbose('ricci_xml is None from batch_run')
-		
-	doc = getPayload(ricci_xml.firstChild)
-	if not doc or not doc.firstChild:
-		luci_log.debug_verbose('doc is None from getPayload: %s' % ricci_xml.toxml())
-		return None
+	try:
+		doc = minidom.Document()
+		doc.appendChild(cluster_node)
+		return doc
+	except Exception, e:
+		luci_log.debug_verbose('getClusterStatusBatch4: %s' % str(e))
 
-	return doc
+	return None
 
 def setClusterConf(rc, clusterconf, propagate=True):
 	if propagate == True:
@@ -490,7 +463,7 @@
 		return None, None
 	ricci_xml = rc.batch_run(batch)
 	return batchAttemptResult(ricci_xml)
-	
+
 def restartService(rc, servicename):
 	batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="restart_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
 


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