[luci] Update to new upstream release and steal fixes from upstream git
Fabio M. Di Nitto
fabbione at fedoraproject.org
Thu Aug 19 13:52:50 UTC 2010
commit f3ea824cfa1a4bc2be0ecb2e934f2238c6b619f9
Author: Fabio M. Di Nitto <fdinitto at redhat.com>
Date: Thu Aug 19 15:52:28 2010 +0200
Update to new upstream release and steal fixes from upstream git
Signed-off-by: Fabio M. Di Nitto <fdinitto at redhat.com>
.gitignore | 2 +
luci.spec | 189 ++++++++++-
sources | 3 +-
stolen_from_git.patch | 854 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1033 insertions(+), 15 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index e69de29..819a1c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/luci-0.22.4.tar.bz2
+/logo.png
diff --git a/luci.spec b/luci.spec
index 8c59e1a..019a0c3 100644
--- a/luci.spec
+++ b/luci.spec
@@ -1,37 +1,47 @@
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%{!?python_sitelib_arch: %define python_sitelib_arch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
%{!?pyver: %define pyver %(%{__python} -c "import sys ; print sys.version[:3]")}
+%global alphatag 0.b9faf868074git
+
Name: luci
-Version: 0.21.0
-Release: 6%{?dist}
-Summary: Web-based cluster administration application
+Version: 0.22.4
+Release: 1%{?alphatag:.%{alphatag}}%{?dist}
+Summary: Web-based high availability administration application
Group: Applications/System
License: GPLv2
URL: http://sources.redhat.com/cluster/conga
-Source0: http://people.redhat.com/rmccabe/luci/luci-0.21.0.tar.bz2
+Source0: http://people.redhat.com/rmccabe/luci/luci-0.22.4.tar.bz2
+Source1: logo.png
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildArch: noarch
-BuildRequires: python-devel python-setuptools python-paste python-paste-script
-Requires: TurboGears2 python-tw-jquery python-repoze-what-quickstart python-catwalk python-tg-devtools
+BuildRequires: python-devel python-setuptools python-paste python-paste-script cyrus-sasl-devel
+Requires: TurboGears2 openssl python-repoze-who-friendlyform python-tw-forms
+Requires: python-paste >= 1.7.2-5.el6
Requires(post): chkconfig initscripts
Requires(preun): chkconfig initscripts
Requires(postun): initscripts
+Patch0: stolen_from_git.patch
+
%description
-Luci is a web-based cluster administration application built on the
+Luci is a web-based high availability administration application built on the
TurboGears 2 framework.
%prep
%setup -q
+cp %{_sourcedir}/logo.png %{_builddir}/luci-0.22.4/luci/public/images
+%patch0 -p1 -b .stolen_from_git
%build
python setup.py build
%install
rm -rf %{buildroot}
+mkdir -p %{buildroot}/var/log/luci
python setup.py install --skip-build --root %{buildroot}
cd init.d && make DESTDIR=%{buildroot} install;cd ..
cd config && make DESTDIR=%{buildroot} install;cd ..
+cd lucipam && python setup.py install --root %{buildroot}; cd ..
%clean
rm -rf %{buildroot}
@@ -40,17 +50,23 @@ rm -rf %{buildroot}
%defattr(-,root,root,-)
%doc README.txt COPYING
%{python_sitelib}/%{name}-%{version}-py%{pyver}.egg-info/
-%{python_sitelib}/luci
+%{python_sitelib}/%{name}/
+%{python_sitelib_arch}/LuciPAM-1.0-py%{pyver}.egg-info
+%{python_sitelib_arch}/lucipam.so
+%config(noreplace) /etc/pam.d/luci
%config(noreplace) %{_localstatedir}/lib/luci/etc/luci.ini
%attr(0600,luci,luci) %{_localstatedir}/lib/luci/etc/luci.ini
+%config(noreplace) %{_localstatedir}/lib/luci/etc/cacert.config
+%attr(0600,luci,luci) %{_localstatedir}/lib/luci/etc/cacert.config
%attr(0750,luci,luci) %{_localstatedir}/lib/luci
%config(noreplace) %{_sysconfdir}/rc.d/init.d/luci
-
+%attr(750, luci, luci) %dir /var/log/luci
%pre
-getent group luci >/dev/null || groupadd -r luci
-getent passwd luci >/dev/null || useradd -r -g luci -d /var/lib/luci -s /sbin/nologin -c "luci user" luci
+/usr/sbin/groupadd -g 141 luci 2> /dev/null
+/usr/sbin/useradd -u 141 -g 141 -d /var/lib/luci -s /sbin/nologin -r \
+ -c "luci user" luci 2> /dev/null
exit 0
%post
@@ -71,8 +87,153 @@ fi
exit 0
%changelog
-* Sun Aug 01 2010 Orcan Ogetbil <oget[dot]fedora[at]gmail[dot]com> - 0.21-0-6
-- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
+* Thu Aug 19 2010 Fabio M. Di Nitto <fdinitto at redhat.com> - 0.22.4-1.0.b9faf868074git
+- New upstream release (0.22.4)
+- Steal fixes from upstream git up to b9faf868074git
+ Fix bz622562 (add support for unfencing)
+ Fix bz624819 (add compatibility with TG2.1)
+- Update spec file to support alphatag
+
+* Tue Aug 03 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-13
+- Remove extra debugging logging from the fix for bz619220
+- Fix bz614130 (implement tomcat6 resource agent)
+- Fix bz618578 (ip resource should have netmask field)
+
+* Tue Aug 03 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-12
+- Fix bz615926 (luci does not handle qdisk / cman config correctly)
+- Fix bz619220 (Luci does extra queries which slows down page load)
+- Fix bz619652 (luci sometimes prints a traceback when deleting multiple nodes at the same time)
+- Fix bz619641 (luci init script prints a python traceback when status is queried by a non-root user)
+
+* Thu Jul 29 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-11
+- Fix bz614433 (cannot configure ipport for fence agents)
+- Fix bz617575 (Unclear options when configuring a cluster)
+- Fix bz617591 (Some fields when adding an IP address are unclear)
+- Fix bz617602 (Fields in "Fence Daemon Properties" have no units)
+- Fix bz618577 (wrong message displayed when adding ip resource)
+- Fix bz619220 (Luci does extra queries which slows down page load)
+
+* Tue Jul 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-10
+- Additional fixes for bz600027 (Fix cluster service creation/configuration UX issues)
+- Additional fixes for bz600055 ("cluster busy" dialog does not work)
+- Fix bz618424 (Can't remove nodes in node add dialog or create cluster dialog)
+- Fix bz616382 (luci db error removing a node from a cluster)
+- Fix bz613871 (luci should not give ungraceful error messages when encountering fence devices that it does not recognize/support)
+
+* Mon Jul 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-9
+- Fix bz600027 (Fix cluster service creation/configuration UX issues)
+- Fix bz600040 (Add nodes to existing cluster does not work)
+- Fix bz600045 (Removing nodes from existing clusters fails)
+- Fix bz600055 ("cluster busy" dialog does not work)
+- Fix bz613868 (Remove fence_virsh from luci UI since this fence is not supported with RHEL HA/Cluster)
+- Fix bz614434 (adding an IP resource ends with an error 500)
+- Fix bz614439 (adding GFS2 resource type in RHEL6 cluster is "interesting")
+- Fix bz615096 (Traceback when unchecking "Prioritized" in Failover Domains)
+- Fix bz615468 (When creating a new failover domain, adding nodes has no effect)
+- Fix bz615872 (unicode error deleting a cluster)
+- Fix bz615889 (luci cannot start an imported cluster)
+- Fix bz615911 (luci shows many unsupported fence devices when adding a new fence device)
+- Fix bz615917 (adding per node fence instance results in error 500 if no fence devices are configured)
+- Fix bz615929 (luci generated cluster.conf with fence_scsi fails to validate)
+- Fix bz616094 (Deleting a fence device which is in use, causes a traceback on Nodes page)
+- Fix bz616228 (Clicking on cluster from manage clusters page results in traceback (500 error))
+- Fix bz616230 (Clicking on the join button doesn't work on nodes page)
+- Fix bz616244 (Clicking on the leave button doesn't work on nodes page.)
+
+* Wed Jul 14 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-8
+- Fix bz600021 (Fix node fence configuration UX issues)
+
+* Tue Jul 13 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-7
+- Build fix for bz600056
+
+* Tue Jul 13 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-6
+- Build fix for bz600056
+
+* Tue Jul 13 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-5
+- Fix bz604740 (Support nfsserver resource agent which is for NFSv4 and NFSv3)
+- Fix bz600056 (Replace logo image)
+
+* Fri Jul 09 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-4
+- Fix bz600059 (Hide optional fields for fence_scsi)
+- Fix bz600077 (cman "two_node" attribute should not be set when using qdisk)
+- Fix bz600083 (Add text to broadcast mode to note that it is for demos only - no production support)
+- Fix bz605780 (Qdisk shouldn't be part of the main page, it should be in the configuration tab)
+
+* Fri Jun 18 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-3
+- Fix bz598859 (Adding fence_xvm fence device through luci interface throws TypeError Traceback)
+- Fix bz599074 ("Use same password for all nodes" doesn't work.)
+- Fix bz599080 (Conga ignores "reboot nodes" check box)
+- Fix bz600047 (luci allows deletion of global resources that are used by services)
+- Fix bz600050 (luci requires wrongly requires users to fill interval / tko / minimum score / votes fields for qdisk configuration)
+- Fix bz600052 (luci allows deletion of the last qdisk heuristics row)
+- Fix bz600058 (ssh_identity field values are dropped)
+- Fix bz600060 (Formatting error on fence devices overview page)
+- Fix bz600061 (Default values not populated in advanced network configuration)
+- Fix bz600066 (Update resource agent labels)
+- Fix bz600069 (Configuration page always returns to General Properties Page)
+- Fix bz600071 (If luci cannot communicate with the nodes they don't appear in the list of nodes)
+- Fix bz600073 (Update resource agent list)
+- Fix bz600074 (Fix display error on the resource list page)
+- Fix bz600075 (update fence_virt / fence_xvm configuration)
+- Fix bz600076 (When creating a cluster no default radio button is selected for Download Packages/Use locally installed packages)
+- Fix bz600079 (Unable to edit existing resources)
+- Fix bz600080 (Homebase page only shows a '-' for Nodes Joined)
+- Fix bz602482 (Multicast settings are not relayed to cluster.conf and no default)
+- Fix bz603833 ("Nodes Joined" in main page is inaccurate when no nodes have joined)
+
+* Tue Jun 01 2010 Chris Feist <cfeist at redhat.com> - 0.22.2-2
+- Fix missing requires which will cause some installations to fail
+- Resolves: rhbz#598725
+
+* Fri May 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.2-1
+- Fix for bugs related to cluster service creation and editing (bz593836).
+
+* Wed May 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.1-3
+- Fix remaining unresolved issues for 593836
+ - Make sure the cluster version is updated when creating services
+ - Fix a bug that caused IP resources to fail in services
+
+* Wed May 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.1-2
+- Rebuild to fix a bug introduced during last build.
+
+* Wed May 26 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.1-1
+- Fix service creation, display, and edit.
+- Fix qdisk heuristic submission.
+
+* Wed May 19 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.0-16
+- Rebase to upstream
+
+* Mon May 17 2010 Chris Feist <cfeist at redhat.com> - 0.22.0-13
+- Added static UID/GID for luci user
+- Resolves: rhbz#585988
+
+* Wed May 12 2010 Chris Feist <cfeist at redhat.com> - 0.22.0-11
+- Add support for PAM authentication
+- Resync with main branch
+- Resolves: rhbz#518206
+
+* Wed May 12 2010 Fabio M. Di Nitto <fdinitto at redhat.com> - 0.21.0-8
+- Do not build on ppc and ppc64.
+ Resolves: rhbz#590987
+
+* Tue Apr 27 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.0-4
+- Update from devel tree.
+
+* Thu Apr 22 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.0-3
+- Update from development tree.
+
+* Thu Apr 08 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.0-2
+- Update from development tree.
+
+* Tue Mar 09 2010 Ryan McCabe <rmccabe at redhat.com> - 0.22.0-1
+- Rebase to luci version 0.22.0
+
+* Mon Mar 1 2010 Fabio M. Di Nitto <fdinitto at redhat.com> - 0.21.0-7
+- Resolves: rhbz#568005
+- Add ExcludeArch to drop s390 and s390x
+
+* Tue Jan 19 2010 Ryan McCabe <rmccabe at redhat.com> - 0.21.0-6
+- Remove dependency on python-tg-devtools
* Wed Nov 04 2009 Ryan McCabe <rmccabe at redhat.com> - 0.21.0-4
- And again.
diff --git a/sources b/sources
index 54895dd..dc93d41 100644
--- a/sources
+++ b/sources
@@ -1 +1,2 @@
-59e01361b7916081b15b2912bb56673f luci-0.21.0.tar.bz2
+ec2d60536291953a941c6e7eb3a8c56d luci-0.22.4.tar.bz2
+c1aec4cca9d3ea87b65543a1267ac4b6 logo.png
diff --git a/stolen_from_git.patch b/stolen_from_git.patch
new file mode 100644
index 0000000..77a6365
--- /dev/null
+++ b/stolen_from_git.patch
@@ -0,0 +1,854 @@
+diff --git a/luci.spec b/luci.spec
+index d82df03..7d31454 100644
+--- a/luci.spec
++++ b/luci.spec
+@@ -9,7 +9,7 @@ Summary: Web-based high availability administration application
+ Group: Applications/System
+ License: GPLv2
+ URL: http://sources.redhat.com/cluster/conga
+-Source0: http://people.redhat.com/rmccabe/luci/luci-0.22.3.tar.bz2
++Source0: http://people.redhat.com/rmccabe/luci/luci-0.22.4.tar.bz2
+ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ BuildRequires: python-devel python-setuptools python-paste python-paste-script cyrus-sasl-devel
+ Requires: TurboGears2 openssl python-repoze-who-friendlyform python-tw-forms
+@@ -45,7 +45,7 @@ rm -rf %{buildroot}
+ %doc README.txt COPYING
+ %{python_sitelib}/%{name}-%{version}-py%{pyver}.egg-info/
+ %{python_sitelib}/%{name}/
+-%{python_sitelib_arch}/LuciPAM-1.0-py2.6.egg-info
++%{python_sitelib_arch}/LuciPAM-1.0-py%{pyver}.egg-info
+ %{python_sitelib_arch}/lucipam.so
+
+ %config(noreplace) /etc/pam.d/luci
+diff --git a/luci/controllers/cluster.py b/luci/controllers/cluster.py
+index 62adfa2..86bc1e0 100644
+--- a/luci/controllers/cluster.py
++++ b/luci/controllers/cluster.py
+@@ -24,6 +24,7 @@ from luci.widget_validators.validate_create_cluster_form import validate_create_
+ from luci.widget_validators.validate_fence import validateNewFenceDevice, validateFenceDevice
+ from luci.widget_validators.validate_resource import validate_clusvc_form, validate_resource_form
+ from luci.lib.ClusterConf.Method import Method
++from luci.lib.ClusterConf.Unfence import Unfence
+ from luci.widget_validators.validate_fence import validate_fenceinstance
+
+ import logging
+@@ -89,7 +90,7 @@ class IndividualClusterController(BaseController):
+ tmpl_context.cluster = self
+
+ @expose("luci.templates.node")
+- def default(self):
++ def index(self):
+ db = get_cluster_db_obj(self.name)
+
+ return dict(page='nodes', name=self.nodename, base_url='/nodes', nodes=db.nodes)
+@@ -121,6 +122,25 @@ class IndividualClusterController(BaseController):
+
+ return self.version
+
++ @staticmethod
++ def remove_fence_instance(node, method, instance):
++ """Macro-like function to remove fence instance from given node and its fence method."""
++ for child in node.getChildren():
++ if child.getTagName() == 'unfence':
++ unfence = child
++ for child_device in unfence.getChildren():
++ # Try to find existing unfence device that mirrored fence device instance
++ # to be removed and remove it, too.
++ if len(set(instance.getAttributes().items()).difference(child_device.getAttributes().items())) == 0:
++ unfence.removeChild(child_device)
++ if len(unfence.getChildren()) == 0:
++ # Remove the whole 'unfence' section from within 'node' section
++ # it is empty.
++ node.removeChild(unfence)
++ break
++ break
++ method.removeChild(instance)
++
+ @expose("luci.templates.node")
+ def nodes(self):
+ db = get_cluster_db_obj(self.name)
+@@ -146,6 +166,8 @@ class IndividualClusterController(BaseController):
+ methodname = kw.get("method_to_remove")
+ for child in node.getFenceNode().getChildren():
+ if child.getName() == methodname:
++ for child_device in child.getChildren():
++ self.remove_fence_instance(node, child, child_device)
+ node.getFenceNode().removeChild(child)
+ break
+ self.model.setModified(True)
+@@ -157,7 +179,7 @@ class IndividualClusterController(BaseController):
+ methodname = kw.get("fenceinst_to_remove_method")
+ for child in node.getFenceNode().getChildren():
+ if child.getName() == methodname:
+- child.removeChild(child.children[int(fenceinst)-1])
++ self.remove_fence_instance(node, child, child.children[int(fenceinst)-1])
+ self.model.setModified(True)
+ rh.update_cluster_conf(self.model)
+
+@@ -204,8 +226,20 @@ class IndividualClusterController(BaseController):
+
+ parent_fencedev = kw['parent_fencedev'].replace('fd_', '', 1)
+
+- retcode, retobj = validate_fenceinstance(parent_fencedev, kw['fence_type'], **kw)
++ retcode, retobj, retunfence = validate_fenceinstance(parent_fencedev, kw['fence_type'], **kw)
+ if retcode is True:
++ # Add unfence section if requested.
++ if retunfence is not None:
++ unfence = None
++ for child in node.getChildren():
++ if child.getTagName() == 'unfence':
++ unfence = child
++ break
++ if unfence is None:
++ unfence = Unfence()
++ node.addChild(unfence)
++ unfence.addChild(retunfence)
++ # ---
+ fence_method.addChild(retobj)
+ if len(levels) == 0:
+ fence_node = node.getFenceNode()
+@@ -224,8 +258,37 @@ class IndividualClusterController(BaseController):
+ (method_num,sep,fence_instance_id) = instance_id.partition('-')
+
+ # Create the fence device, and if it succeeds replace the old one with the new one
+- retcode, retobj = validate_fenceinstance(kw["fencedev"], kw['fence_type'], **kw)
++ retcode, retobj, retunfence = validate_fenceinstance(kw["fencedev"], kw['fence_type'], **kw)
+ if retcode is True:
++ # Add 'unfence' section if requested, remove it otherwise.
++ old_device = node.getFenceNode().children[int(method_num)].children[int(fence_instance_id)]
++ unfence = None
++ unfence_handled = False
++ for child in node.getChildren():
++ if child.getTagName() == 'unfence':
++ unfence = child
++ for child_device in unfence.getChildren():
++ # Try to find existing unfence device that mirrored old fence device instance
++ # (i.e. before the change, with original values of attributes) and remove it
++ # or replace it with current attributes (i.e. after the change).
++ if len(set(old_device.getAttributes().items()).difference(child_device.getAttributes().items())) == 0:
++ if (retunfence is None):
++ unfence.removeChild(child_device)
++ if len(unfence.getChildren()) == 0:
++ # Remove the whole 'unfence' section from within 'node' section
++ # it is empty.
++ node.removeChild(unfence)
++ else:
++ unfence.replaceChild(child_device, retunfence)
++ unfence_handled = True
++ break
++ break
++ if not unfence_handled and retunfence is not None:
++ if unfence is None:
++ unfence = Unfence()
++ node.addChild(unfence)
++ unfence.addChild(retunfence)
++ # ---
+ node.getFenceNode().children[int(method_num)].children[int(fence_instance_id)] = retobj
+ self.model.setModified(True)
+ rh.update_cluster_conf(self.model)
+@@ -727,7 +790,7 @@ class IndividualNodeController(BaseController):
+ tmpl_context.show_sidebar = True
+
+ @expose("luci.templates.node")
+- def default(self):
++ def index(self):
+ db = get_cluster_db_obj(self.name)
+ return dict(page='nodes', name=self.nodename, base_url='/nodes', nodes=db.nodes)
+
+diff --git a/luci/controllers/root.py b/luci/controllers/root.py
+index 02e69db..1d11cd4 100644
+--- a/luci/controllers/root.py
++++ b/luci/controllers/root.py
+@@ -67,6 +67,7 @@ class RootController(BaseController):
+ def homebase(self, homebasepage='homebasepage', **args):
+ tmpl_context.show_sidebar = True
+ tmpl_context.homebase = True
++ tmpl_context.cluster = []
+ return dict(page='homebase', homebasepage=homebasepage, args=args,
+ base_url='/cluster')
+
+diff --git a/luci/lib/ClusterConf/Device.py b/luci/lib/ClusterConf/Device.py
+index 57556f3..9f92f62 100644
+--- a/luci/lib/ClusterConf/Device.py
++++ b/luci/lib/ClusterConf/Device.py
+@@ -35,3 +35,11 @@ class Device(TagObject):
+ if name == OPTION:
+ self.has_native_option_set = True
+ self.attr_hash[name] = value
++
++ def clone(self):
++ """Creates a shallow copy of itself."""
++ ret = TagObject.clone(self)
++ ret.agent_type = self.agent_type
++ ret.has_native_option_set = self.has_native_option_set
++ ret.pretty_fence_names = self.pretty_fence_names
++ return ret
+diff --git a/luci/lib/ClusterConf/ModelBuilder.py b/luci/lib/ClusterConf/ModelBuilder.py
+index e7cdbb6..2d0a73a 100644
+--- a/luci/lib/ClusterConf/ModelBuilder.py
++++ b/luci/lib/ClusterConf/ModelBuilder.py
+@@ -11,6 +11,7 @@ from Cluster import Cluster
+ from ClusterNode import ClusterNode
+ from ClusterNodes import ClusterNodes
+ from Fence import Fence
++from Unfence import Unfence
+ from FenceDevice import FenceDevice
+ from FenceDevices import FenceDevices
+ from Method import Method
+@@ -64,6 +65,7 @@ TAGNAMES = { 'cluster': Cluster,
+ 'clusternode': ClusterNode,
+ 'altname': Altname,
+ 'fence': Fence,
++ 'unfence': Unfence,
+ 'fencedevice': FenceDevice,
+ 'fencedevices': FenceDevices,
+ 'method': Method,
+diff --git a/luci/lib/ClusterConf/TagObject.py b/luci/lib/ClusterConf/TagObject.py
+index 0087dbc..5872f4a 100644
+--- a/luci/lib/ClusterConf/TagObject.py
++++ b/luci/lib/ClusterConf/TagObject.py
+@@ -56,7 +56,8 @@ class TagObject:
+ return self.attr_hash.get(key)
+
+ def getChildren(self):
+- return self.children
++ """Returns copy of children's list."""
++ return self.children[:]
+
+ def getName(self):
+ try:
+@@ -78,3 +79,17 @@ class TagObject:
+ if child is None:
+ continue
+ child.searchTree(objlist, tagtype)
++
++ def replaceChild(self, oldchild, newchild):
++ """Looks up oldchild and replace it with newchild."""
++ idx = self.children.index(oldchild)
++ self.children[idx] = newchild
++
++
++ def clone(self):
++ """Creates a shallow copy of itself."""
++ ret = self.__class__ ()
++ ret.TAG_NAME = self.TAG_NAME
++ ret.attr_hash = self.attr_hash.copy()
++ ret.children = self.children
++ return ret
+diff --git a/luci/lib/ClusterConf/Unfence.py b/luci/lib/ClusterConf/Unfence.py
+new file mode 100644
+index 0000000..411e5a2
+--- /dev/null
++++ b/luci/lib/ClusterConf/Unfence.py
+@@ -0,0 +1,15 @@
++# Copyright (C) 2006-2009 Red Hat, Inc.
++#
++# This program is free software; you can redistribute
++# it and/or modify it under the terms of version 2 of the
++# GNU General Public License as published by the
++# Free Software Foundation.
++
++from TagObject import TagObject
++
++TAG_NAME = "unfence"
++
++class Unfence(TagObject):
++ def __init__(self):
++ TagObject.__init__(self)
++ self.TAG_NAME = TAG_NAME
+diff --git a/luci/lib/app_strings.py b/luci/lib/app_strings.py
+index daa9de3..fde70e0 100644
+--- a/luci/lib/app_strings.py
++++ b/luci/lib/app_strings.py
+@@ -8,7 +8,7 @@
+ # -*- coding: utf-8 -*-
+ """Separated encapsulations of common strings and short sentences."""
+
+-from pylons.i18n import ugettext as _
++from pylons.i18n import lazy_ugettext as l_
+ # Imported, but not in module's header: tg (tmpl_context)
+
+ __all__ = ['Title', 'FlashMsg']
+@@ -50,26 +50,26 @@ class Title:
+ # is used as a key for storing/retrieving such string parameters
+ # to separated dict respectively.
+
+- CLUSTERS = _('clusters')
+- CERTAIN_CLUSTER = _('cluster {cluster}'), 'cluster'
++ CLUSTERS = l_('clusters')
++ CERTAIN_CLUSTER = l_('cluster {cluster}'), 'cluster'
+
+- CLUSTER_CREATE = _('create cluster')
+- CLUSTER_ADD_EXISTING = _('add an existing cluster')
++ CLUSTER_CREATE = l_('create cluster')
++ CLUSTER_ADD_EXISTING = l_('add an existing cluster')
+
+- GLOBAL_RES = _('resources')
+- CERTAIN_GLOBAL_RES = _('resource {global_res}'), 'global_res'
++ GLOBAL_RES = l_('resources')
++ CERTAIN_GLOBAL_RES = l_('resource {global_res}'), 'global_res'
+
+- NODES = _('nodes')
+- CERTAIN_NODE = _('node {node}'), 'node'
++ NODES = l_('nodes')
++ CERTAIN_NODE = l_('node {node}'), 'node'
+
+- SERVICES = _('services')
+- CERTAIN_SERVICE = _('service {service}'), 'service'
++ SERVICES = l_('services')
++ CERTAIN_SERVICE = l_('service {service}'), 'service'
+
+- FAILOVERS = _('failovers')
+- CERTAIN_FAILOVER = _('failover {failover}'), 'failover'
++ FAILOVERS = l_('failovers')
++ CERTAIN_FAILOVER = l_('failover {failover}'), 'failover'
+
+- FENCES = _('fences')
+- CERTAIN_FENCE = _('fence {fence}'), 'fence'
++ FENCES = l_('fences')
++ CERTAIN_FENCE = l_('fence {fence}'), 'fence'
+
+
+ class FlashMsg:
+@@ -81,11 +81,11 @@ class FlashMsg:
+ # Pairs of message and the message status to be used by tg.flash method.
+
+ # Connected with
+- BAD_COMMAND_REQUEST = _('Bad command request.'), STYLE_WARNING
+- INTERNAL_ERROR = _('Internal error.'), STYLE_ERROR
+- NOTHING_CHOSEN = _('Nothing was chosen.'), STYLE_WARNING
++ BAD_COMMAND_REQUEST = l_('Bad command request.'), STYLE_WARNING
++ INTERNAL_ERROR = l_('Internal error.'), STYLE_ERROR
++ NOTHING_CHOSEN = l_('Nothing was chosen.'), STYLE_WARNING
+
+ # Connected with decorators.
+
+- UNSUPPORTED_METHOD = _('%s method not supported in this context.'), STYLE_ERROR
++ UNSUPPORTED_METHOD = l_('%s method not supported in this context.'), STYLE_ERROR
+
+diff --git a/luci/templates/fence_instances.html b/luci/templates/fence_instances.html
+index 41c8270..ede58ba 100644
+--- a/luci/templates/fence_instances.html
++++ b/luci/templates/fence_instances.html
+@@ -2,7 +2,7 @@
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ py:strip="">
+
+-<div py:def="fence_apc_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_apc_instance"
++<div py:def="fence_apc_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_apc_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -56,7 +56,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_egenera_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_egenera_instance"
++<div py:def="fence_egenera_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_egenera_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -94,7 +94,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_lpar_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_lpar_instance"
++<div py:def="fence_lpar_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_lpar_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -133,7 +133,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_vmware_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_vmware_instance"
++<div py:def="fence_vmware_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_vmware_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -180,7 +180,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_wti_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_wti_instance"
++<div py:def="fence_wti_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_wti_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -227,7 +227,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_brocade_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_brocade_instance"
++<div py:def="fence_brocade_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_brocade_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -237,6 +237,15 @@
+ py:attrs="cur_fence_inst and {'value': cur_fence_inst.getAttribute('port')}"/>
+ </td>
+ </tr>
++ <tr>
++ <td>Unfencing</td>
++ <td>
++ <input type="checkbox" class="checkbox" name="unfencing"
++ py:attrs="(not cur_fence_inst or kw.get('unfencing', True)) and {'checked': 'checked'}"/>
++ <label class="choice">Enable</label>
++ <input type="hidden" name="unfence_action" value="enable" />
++ </td>
++ </tr>
+ <tr><td colspan="2">
+ <div>
+ <input type="button" name="remove_fence" value="Remove this instance"
+@@ -251,7 +260,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_vixel_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_vixel_instance"
++<div py:def="fence_vixel_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_vixel_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -275,7 +284,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_sanbox2_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_sanbox2_instance"
++<div py:def="fence_sanbox2_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_sanbox2_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -285,6 +294,15 @@
+ py:attrs="cur_fence_inst and {'value': cur_fence_inst.getAttribute('port')}"/>
+ </td>
+ </tr>
++ <tr>
++ <td>Unfencing</td>
++ <td>
++ <input type="checkbox" class="checkbox" name="unfencing"
++ py:attrs="(not cur_fence_inst or kw.get('unfencing', True)) and {'checked': 'checked'}"/>
++ <label class="choice">Enable</label>
++ <input type="hidden" name="unfence_action" value="enable" />
++ </td>
++ </tr>
+ <tr><td colspan="2">
+ <div>
+ <input type="button" name="remove_fence" value="Remove this instance"
+@@ -299,7 +317,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_mcdata_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_mcdata_instance"
++<div py:def="fence_mcdata_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_mcdata_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -309,6 +327,15 @@
+ py:attrs="cur_fence_inst and {'value': cur_fence_inst.getAttribute('port')}"/>
+ </td>
+ </tr>
++ <tr>
++ <td>Unfencing</td>
++ <td>
++ <input type="checkbox" class="checkbox" name="unfencing"
++ py:attrs="(not cur_fence_inst or kw.get('unfencing', True)) and {'checked': 'checked'}"/>
++ <label class="choice">Enable</label>
++ <input type="hidden" name="unfence_action" value="enable" />
++ </td>
++ </tr>
+ <tr><td colspan="2">
+ <div>
+ <input type="button" name="remove_fence" value="Remove this instance"
+@@ -323,7 +350,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_gnbd_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_gnbd_instance"
++<div py:def="fence_gnbd_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_gnbd_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -347,7 +374,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_bullpap_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_bullpap_instance"
++<div py:def="fence_bullpap_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_bullpap_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -371,7 +398,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_virt_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_virt_instance"
++<div py:def="fence_virt_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_virt_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -395,7 +422,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_xvm_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_xvm_instance"
++<div py:def="fence_xvm_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_xvm_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -419,7 +446,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_bladecenter_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_bladecenter_instance"
++<div py:def="fence_bladecenter_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_bladecenter_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -466,7 +493,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_rackswitch_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_rackswitch_instance"
++<div py:def="fence_rackswitch_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_rackswitch_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -490,7 +517,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ldom_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ldom_instance"
++<div py:def="fence_ldom_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ldom_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -537,7 +564,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_cisco_mds_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_cisco_mds_instance"
++<div py:def="fence_cisco_mds_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_cisco_mds_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -561,7 +588,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_eps_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_eps_instance"
++<div py:def="fence_eps_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_eps_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -585,7 +612,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ibmblade_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ibmblade_instance"
++<div py:def="fence_ibmblade_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ibmblade_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -609,7 +636,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ifmib_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ifmib_instance"
++<div py:def="fence_ifmib_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ifmib_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -633,7 +660,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_intelmodular_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_intelmodular_instance"
++<div py:def="fence_intelmodular_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_intelmodular_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -657,7 +684,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_apc_snmp_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_apc_snmp_instance"
++<div py:def="fence_apc_snmp_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_apc_snmp_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+ <table class="detailstable">
+ <tr>
+@@ -681,7 +708,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_drac_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_drac_instance"
++<div py:def="fence_drac_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_drac_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -690,7 +717,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_drac5_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_drac5_instance"
++<div py:def="fence_drac5_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_drac5_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -699,7 +726,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ilo_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ilo_instance"
++<div py:def="fence_ilo_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ilo_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -708,7 +735,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ilo_mp_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ilo_mp_instance"
++<div py:def="fence_ilo_mp_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ilo_mp_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -717,7 +744,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_rsa_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_rsa_instance"
++<div py:def="fence_rsa_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_rsa_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -726,7 +753,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_ipmilan_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_ipmilan_instance"
++<div py:def="fence_ipmilan_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_ipmilan_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -735,7 +762,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_alom_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_alom_instance"
++<div py:def="fence_alom_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_alom_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -744,7 +771,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_cpint_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_cpint_instance"
++<div py:def="fence_cpint_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_cpint_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -753,7 +780,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_rps10_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_rps10_instance"
++<div py:def="fence_rps10_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_rps10_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -762,7 +789,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_rsb_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_rsb_instance"
++<div py:def="fence_rsb_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_rsb_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -771,7 +798,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_xcat_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_xcat_instance"
++<div py:def="fence_xcat_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_xcat_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -780,7 +807,7 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_zvm_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_zvm_instance"
++<div py:def="fence_zvm_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_zvm_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+@@ -789,16 +816,32 @@
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_scsi_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_scsi_instance"
++<div py:def="fence_scsi_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_scsi_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+-
++ <table class="detailstable">
++ <tr>
++ <td>Unfencing</td>
++ <td>
++ <input type="checkbox" class="checkbox" name="unfencing"
++ py:attrs="(not cur_fence_inst or kw.get('unfencing', True)) and {'checked': 'checked'}"/>
++ <label class="choice">Enable</label>
++ <input type="hidden" name="unfence_action" value="on" />
++ </td>
++ </tr>
++ <tr><td colspan="2">
++ <div>
++ <input type="button" name="remove_fence" value="Remove this instance"
++ py:attrs="fi_id is not None and {'onclick': '$(\'#%s\').remove()' % fi_id} or {}"/>
++ </div>
++ </td></tr>
++ </table>
+ <input type="hidden" name="fence_type" value="fence_scsi" />
+ <input type="hidden" name="fence_instance" value="1" />
+ <input type="hidden" name="parent_fencedev"
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+ </div>
+
+-<div py:def="fence_unknown_instance(cur_fence_inst, cur_fence_dev_id, fi_id)" id="fence_unknown_instance"
++<div py:def="fence_unknown_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_unknown_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <input type="hidden" name="fence_type" value="fence_unknown" />
+diff --git a/luci/templates/master.html b/luci/templates/master.html
+index eccbbab..5b37d77 100644
+--- a/luci/templates/master.html
++++ b/luci/templates/master.html
+@@ -43,7 +43,7 @@
+ <div py:if="flash" py:content="XML(flash)" />
+ </py:with>
+
+- <py:if test="'show_sidebar' in dir(tmpl_context)">
++ <py:if test="'show_sidebar' in dir(tmpl_context) and tmpl_context.show_sidebar">
+ <xi:include href="mainmenu.html" />
+ </py:if>
+
+diff --git a/luci/templates/node.html b/luci/templates/node.html
+index 546774d..5956048 100644
+--- a/luci/templates/node.html
++++ b/luci/templates/node.html
+@@ -296,7 +296,7 @@
+ <th>Type/Values</th>
+ <th></th>
+ </tr>
+- <py:for each="instancenum,(fin,fd) in enumerate(instances)">
++ <py:for each="instancenum,(fin,fd,unfencing) in enumerate(instances)">
+ <?python
+ agent_type = fd.getAgentType()
+ agent_name = fd.getPrettyName()
+@@ -327,7 +327,7 @@
+ inst_fn = eval('fence_unknown_instance')
+ inst_fn(fin, instance_id, None)
+ ?>
+- ${inst_fn(fin, cur_dev_id, '%s_%s' % (cur_dev_id, cur_dev_id))}
++ ${inst_fn(fin, cur_dev_id, '%s_%s' % (cur_dev_id, cur_dev_id), unfencing=unfencing)}
+ </div>
+ <div class="row">
+ <input type="Submit" value="Submit" class="button formsubmit blue" />
+@@ -365,6 +365,10 @@
+ </td>
+ </py:if>
+ </tr>
++ <tr py:if="unfencing == True">
++ <td></td>
++ <td>unfencing enabled</td>
++ </tr>
+ </py:for>
+ <tr>
+ <td colspan="3">
+diff --git a/luci/widget_validators/validate_fence.py b/luci/widget_validators/validate_fence.py
+index ebf24d7..f9339e1 100644
+--- a/luci/widget_validators/validate_fence.py
++++ b/luci/widget_validators/validate_fence.py
+@@ -918,6 +918,9 @@ def validate_fenceinstance(parent_name, fence_agent, **kw):
+ fenceinst.addAttribute('name', parent_name)
+ fenceinst.setAgentType(fence_agent)
+
++ unfence = None
++
++ # XXX: Remove following 4 lines?
+ if kw.has_key('option'):
+ option = kw.get('option').strip()
+ if option:
+@@ -926,12 +929,16 @@ def validate_fenceinstance(parent_name, fence_agent, **kw):
+ try:
+ ret = FI_VALIDATE[fence_agent](fenceinst, parent_name, **kw)
+ if len(ret) > 0:
+- return (False, ret)
++ return (False, ret, None)
+ except Exception, e:
+ log.exception('Error validating fence %s instance of %s' % (fence_agent, parent_name))
+- return (False, [ FI_NEW_FAIL % fence_agent ])
++ return (False, [ FI_NEW_FAIL % fence_agent ], )
+
+- return (True, fenceinst)
++ if kw.has_key('unfencing'):
++ # If unfencing required, create and return it's object.
++ unfence = fenceinst.clone()
++ unfence.addAttribute('action', kw['unfence_action'])
++ return (True, fenceinst, unfence)
+
+ def getDeviceForInstance(fds, name):
+ for fd in fds:
+@@ -1039,9 +1046,11 @@ def get_fence_level_info(fence_level, node, fds, major_num, minor_num):
+ cur_shared.append(shared_struct)
+ return (cur_level, cur_shared, major_num, minor_num)
+
+-# Return a list of lists containing the level/method and fence instances for
+-# that level
+ def getFenceInfo(model, nodename):
++ """Return a list of lists containing the level/method and fence instances for that level.
++
++ """
++
+ fence_map = []
+
+ try:
+@@ -1060,8 +1069,21 @@ def getFenceInfo(model, nodename):
+ fence_map_level = [0,0]
+ fence_map_level[0] = level
+ fence_map_level[1] = []
+- instances = level.getChildren()
+- for instance in instances:
+- fence_map_level[1].append([instance,getDeviceForInstance(fds,instance.getName().strip())])
++
++ for instance in level.getChildren():
++ # Lookup, whether the unfencing was set and add a flag appropriately.
++ unfencing_flag = False
++ for child in node.getChildren():
++ if child.getTagName() == 'unfence':
++ unfence = child
++ for child_device in unfence.getChildren():
++ # Try to find existing unfence device that mirrored fence device instance
++ # to be removed and remove it, too.
++ if len(set(instance.getAttributes().items()).difference(child_device.getAttributes().items())) == 0:
++ unfencing_flag = True
++ break
++ break
++
++ fence_map_level[1].append([instance,getDeviceForInstance(fds,instance.getName().strip()),unfencing_flag])
+ fence_map.append(fence_map_level)
+ return fence_map
+diff --git a/lucipam/lucipam.c b/lucipam/lucipam.c
+index 334adcf..5aa61e6 100644
+--- a/lucipam/lucipam.c
++++ b/lucipam/lucipam.c
+@@ -23,7 +23,7 @@
+ * Author: Chris Feist <cfeist at redhat.com>
+ */
+
+-#include <python2.6/Python.h>
++#include <Python.h>
+ #include <sasl/sasl.h>
+ #include <string.h>
+
More information about the scm-commits
mailing list