[Cluster-devel] conga ./clustermon.spec.in.in ./conga.spec.in. ...
kupcevic at sourceware.org
kupcevic at sourceware.org
Thu Nov 16 19:35:00 UTC 2006
CVSROOT: /cvs/cluster
Module name: conga
Branch: RHEL5
Changes by: kupcevic at sourceware.org 2006-11-16 19:34:54
Modified files:
. : clustermon.spec.in.in conga.spec.in.in
luci : Makefile load_site.py pack.py
luci/cluster : form-chooser form-macros index_html
portlet_cluconfig resource-form-macros
resource_form_handlers.js
luci/homebase : form-chooser form-macros homebase_common.js
homebase_portlet_fetcher index_html
luci_homebase.css portlet_homebase
luci/plone-custom: conga.js footer
luci/site/luci/Extensions: FenceDaemon.py FenceHandler.py
LuciSyslog.py cluster_adapters.py
conga_constants.py
homebase_adapters.py ricci_bridge.py
ricci_communicator.py
make : version.in
ricci/modules/log: LogParser.cpp
Added files:
doc : config_rhel5.html
luci/docs : config_rhel5
Removed files:
luci/site/luci/Extensions: Quorumd.py ricci_test.py
Log message:
sync with HEAD, bump to version 0.8-24
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/clustermon.spec.in.in.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.18.2.3&r2=1.18.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/conga.spec.in.in.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.45.2.4&r2=1.45.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/doc/config_rhel5.html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20&r2=1.20.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/load_site.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.14&r2=1.14.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/pack.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-chooser.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.12&r2=1.12.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.90.2.2&r2=1.90.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/index_html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.20.2.3&r2=1.20.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/portlet_cluconfig.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/resource-form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.21.2.1&r2=1.21.2.2
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.1&r2=1.20.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/docs/config_rhel5.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/form-chooser.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.10&r2=1.10.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.44.2.3&r2=1.44.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/homebase_common.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.13&r2=1.13.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/homebase_portlet_fetcher.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/index_html.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.18.2.1&r2=1.18.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/luci_homebase.css.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.28&r2=1.28.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/portlet_homebase.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.7&r2=1.7.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/plone-custom/conga.js.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/plone-custom/footer.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/FenceDaemon.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/FenceHandler.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.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.2&r2=1.2.2.3
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.8&r2=1.120.2.9
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.1&r2=1.19.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/homebase_adapters.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.34.2.5&r2=1.34.2.6
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.6&r2=1.30.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_communicator.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.9.2.3&r2=1.9.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/Quorumd.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_test.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/make/version.in.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.21.2.4&r2=1.21.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/log/LogParser.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.1&r2=1.6.2.2
--- conga/clustermon.spec.in.in 2006/11/01 23:11:25 1.18.2.3
+++ conga/clustermon.spec.in.in 2006/11/16 19:34:52 1.18.2.4
@@ -194,6 +194,10 @@
%changelog
+
+* Thu Nov 16 2006 Stanko Kupcevic <kupcevic at redhat.com> 0.8-24
+ - version bump
+
* Wed Nov 01 2006 Stanko Kupcevic <kupcevic at redhat.com> 0.8-23
- version bump
--- conga/conga.spec.in.in 2006/11/01 23:11:25 1.45.2.4
+++ conga/conga.spec.in.in 2006/11/16 19:34:52 1.45.2.5
@@ -282,6 +282,31 @@
%changelog
+
+* Thu Nov 16 2006 Stanko Kupcevic <kupcevic at redhat.com> 0.8-24
+- Fixed bz215039 (Cannot create a new resource via luci web app)
+- Fixed bz215034 (Cannot change daemon properties via luci web app)
+- Fixed bz214790 (Stop/restart cluster not working via luci web app)
+- Fixed bz213690 (luci - Reversed links in colophon (gui - minor))
+- Fixed bz213266 (Conga - modifying a cluster node's cluster membership in a subnet with other clusters results in the wrong cluster.conf)
+- Fixed bz213083 (luci - should display usernames in some logical/sorted order (usability))
+- Fixed bz212601 (luci - selecting cluster name or cluster node name indicates error in install and displays empty form)
+- Fixed bz212021 (various luci buttons do nothing)
+- Fixed bz212006 (create cluster does not show status as cluster is being created)
+- Fixed bz212584 (luci does not retrieve failed ricci queue elements)
+- Fixed bz212440 (luci persists possibly incorrect name for a system)
+- Improved bz213306 (ricci - log probing can take minutes to complete)
+- Fixed starting/stopping services
+- Fixed deleting cluster
+- Fixed deleting node
+- Fixed redirection for all async->busy wait calls
+- Storage module: properly probe cluster quorum if LVM locking
+ is marked as clustered
+- Resolves: bz215039, bz215034, bz214790, bz213690, bz213266
+- Resolves: bz213083, bz212601, bz212021, bz212006, bz212584
+- Resolves: bz212440
+- Related: bz213306
+
* Wed Nov 01 2006 Stanko Kupcevic <kupcevic at redhat.com> 0.8-23
- 213504: luci does not correctly handle cluster.conf with
nodes lacking FQDN
/cvs/cluster/conga/doc/config_rhel5.html,v --> standard output
revision 1.1.2.1
--- conga/doc/config_rhel5.html
+++ - 2006-11-16 19:34:56.739739000 +0000
@@ -0,0 +1,260 @@
+<html><head><title>Advanced Cluster Configuration Parameters</title>
+</head><body>
+<h2>Advanced Cluster Configuration Parameters</h2>
+<p>
+<dl compact>
+<dt><a name="secauth"><strong>secauth</strong></a><dd>
+This specifies that HMAC/SHA1 authentication should be used to authenticate
+all messages. It further specifies that all data should be encrypted with the
+sober128 encryption algorithm to protect data from eavesdropping.
+<p>
+Enabling this option adds a 36 byte header to every message sent by totem which
+reduces total throughput. Encryption and authentication consume 75% of CPU
+cycles in aisexec as measured with gprof when enabled.
+<p>
+For 100mbit networks with 1500 MTU frame transmissions:
+A throughput of 9mb/sec is possible with 100% cpu utilization when this
+option is enabled on 3ghz cpus.
+A throughput of 10mb/sec is possible wth 20% cpu utilization when this
+optin is disabled on 3ghz cpus.
+<p>
+For gig-e networks with large frame transmissions:
+A throughput of 20mb/sec is possible when this option is enabled on
+3ghz cpus.
+A throughput of 60mb/sec is possible when this option is disabled on
+3ghz cpus.
+<p>
+The default is on.
+<p>
+<dt><a name="rrp_mode"><strong>rrp_mode</strong></a><dd>
+This specifies the mode of redundant ring, which may be none, active, or
+passive. Active replication offers slightly lower latency from transmit
+to delivery in faulty network environments but with less performance.
+Passive replication may nearly double the speed of the totem protocol
+if the protocol doesn't become cpu bound. The final option is none, in
+which case only one network interface will be used to operate the totem
+protocol.
+<p>
+If only one interface directive is specified, none is automatically chosen.
+If multiple interface directives are specified, only active or passive may
+be chosen.
+<p>
+<dt><a name="netmtu"><strong>netmtu</strong></a><dd>
+This specifies the network maximum transmit unit. To set this value beyond
+1500, the regular frame MTU, requires ethernet devices that support large, or
+also called jumbo, frames. If any device in the network doesn't support large
+frames, the protocol will not operate properly. The hosts must also have their
+mtu size set from 1500 to whatever frame size is specified here.
+<p>
+Please note while some NICs or switches claim large frame support, they support
+9000 MTU as the maximum frame size including the IP header. Setting the netmtu
+and host MTUs to 9000 will cause totem to use the full 9000 bytes of the frame.
+Then Linux will add a 18 byte header moving the full frame size to 9018. As a
+result some hardware will not operate properly with this size of data. A netmtu
+of 8982 seems to work for the few large frame devices that have been tested.
+Some manufacturers claim large frame support when in fact they support frame
+sizes of 4500 bytes.
+<p>
+Increasing the MTU from 1500 to 8982 doubles throughput performance from 30MB/sec
+to 60MB/sec as measured with evsbench with 175000 byte messages with the secauth
+directive set to off.
+<p>
+When sending multicast traffic, if the network frequently reconfigures, chances are
+that some device in the network doesn't support large frames.
+<p>
+Choose hardware carefully if intending to use large frame support.
+<p>
+The default is 1500.
+<p>
+<dt><a name="threads"><strong>threads</strong></a><dd>
+This directive controls how many threads are used to encrypt and send multicast
+messages. If secauth is off, the protocol will never use threaded sending.
+If secauth is on, this directive allows systems to be configured to use
+multiple threads to encrypt and send multicast messages.
+<p>
+A thread directive of 0 indicates that no threaded send should be used. This
+mode offers best performance for non-SMP systems.
+<p>
+The default is 0.
+<p>
+<dt><a name="vsftype"><strong>vsftype</strong></a><dd>
+This directive controls the virtual synchrony filter type used to identify
+a primary component. The preferred choice is YKD dynamic linear voting,
+however, for clusters larger then 32 nodes YKD consumes alot of memory. For
+large scale clusters that are created by changing the MAX_PROCESSORS_COUNT
+#define in the C code totem.h file, the virtual synchrony filter "none" is
+recommended but then AMF and DLCK services (which are currently experimental)
+are not safe for use.
+<p>
+The default is ykd. The vsftype can also be set to none.
+<p>
+Within the
+<B>totem </B>
+
+directive, there are several configuration options which are used to control
+the operation of the protocol. It is generally not recommended to change any
+of these values without proper guidance and sufficient testing. Some networks
+may require larger values if suffering from frequent reconfigurations. Some
+applications may require faster failure detection times which can be achieved
+by reducing the token timeout.
+<p>
+<dt><a name="token"><strong>token</strong></a><dd>
+This timeout specifies in milliseconds until a token loss is declared after not
+receiving a token. This is the time spent detecting a failure of a processor
+in the current configuration. Reforming a new configuration takes about 50
+milliseconds in addition to this timeout.
+<p>
+The default is 5000 milliseconds.
+<p>
+<dt><a name="token_retransmit"><strong>token_retransmit</strong></a><dd>
+This timeout specifies in milliseconds after how long before receiving a token
+the token is retransmitted. This will be automatically calculated if token
+is modified. It is not recommended to alter this value without guidance from
+the openais community.
+<p>
+The default is 238 milliseconds.
+<p>
+<dt><a name="hold"><strong>hold</strong></a><dd>
+This timeout specifies in milliseconds how long the token should be held by
+the representative when the protocol is under low utilization. It is not
+recommended to alter this value without guidance from the openais community.
+<p>
+The default is 180 milliseconds.
+<p>
+<dt><a name="retransmits_before_loss"><strong>retransmits_before_loss</strong></a><dd>
+This value identifies how many token retransmits should be attempted before
+forming a new configuration. If this value is set, retransmit and hold will
+be automatically calculated from retransmits_before_loss and token.
+<p>
+The default is 4 retransmissions.
+<p>
+<dt><a name="join"><strong>join</strong></a><dd>
+This timeout specifies in milliseconds how long to wait for join messages in
+the membership protocol.
+<p>
+The default is 100 milliseconds.
+<p>
+<dt><a name="send_join"><strong>send_join</strong></a><dd>
+This timeout specifies in milliseconds an upper range between 0 and send_join
+to wait before sending a join message. For configurations with less then
+32 nodes, this parameter is not necessary. For larger rings, this parameter
+is necessary to ensure the NIC is not overflowed with join messages on
+formation of a new ring. A reasonable value for large rings (128 nodes) would
+be 80msec. Other timer values must also change if this value is changed. Seek
+advice from the openais mailing list if trying to run larger configurations.
+<p>
+The default is 0 milliseconds.
+<p>
+<dt><a name="consensus"><strong>consensus</strong></a><dd>
+This timeout specifies in milliseconds how long to wait for consensus to be
+achieved before starting a new round of membership configuration.
+<p>
+The default is 200 milliseconds.
+<p>
+<dt><a name="merge"><strong>merge</strong></a><dd>
+This timeout specifies in milliseconds how long to wait before checking for
+a partition when no multicast traffic is being sent. If multicast traffic
+is being sent, the merge detection happens automatically as a function of
+the protocol.
+<p>
+The default is 200 milliseconds.
+<p>
+<dt><a name="downcheck"><strong>downcheck</strong></a><dd>
+This timeout specifies in milliseconds how long to wait before checking
+that a network interface is back up after it has been downed.
+<p>
+The default is 1000 millseconds.
+<p>
+<dt><a name="fail_to_recv_const"><strong>fail_to_recv_const</strong></a><dd>
+This constant specifies how many rotations of the token without receiving any
+of the messages when messages should be received may occur before a new
+configuration is formed.
+<p>
+The default is 50 failures to receive a message.
+<p>
+<dt><a name="seqno_unchanged_const"><strong>seqno_unchanged_const</strong></a><dd>
+This constant specifies how many rotations of the token without any multicast
+traffic should occur before the merge detection timeout is started.
+<p>
+The default is 30 rotations.
+<p>
+<dt><a name="heartbeat_failures_allowed"><strong>heartbeat_failures_allowed</strong></a><dd>
+[HeartBeating mechanism]
+Configures the optional HeartBeating mechanism for faster failure detection. Keep in
+mind that engaging this mechanism in lossy networks could cause faulty loss declaration
+as the mechanism relies on the network for heartbeating.
+<p>
+So as a rule of thumb use this mechanism if you require improved failure in low to
+medium utilized networks.
+<p>
+This constant specifies the number of heartbeat failures the system should tolerate
+before declaring heartbeat failure e.g 3. Also if this value is not set or is 0 then the
+heartbeat mechanism is not engaged in the system and token rotation is the method
+of failure detection
+<p>
+The default is 0 (disabled).
+<p>
+<dt><a name="max_network_delay"><strong>max_network_delay</strong></a><dd>
+[HeartBeating mechanism]
+This constant specifies in milliseconds the approximate delay that your network takes
+to transport one packet from one machine to another. This value is to be set by system
+engineers and please dont change if not sure as this effects the failure detection
+mechanism using heartbeat.
+<p>
+The default is 50 milliseconds.
+<p>
+<dt><a name="window_size"><strong>window_size</strong></a><dd>
+This constant specifies the maximum number of messages that may be sent on one
+token rotation. If all processors perform equally well, this value could be
+large (300), which would introduce higher latency from origination to delivery
+for very large rings. To reduce latency in large rings(16+), the defaults are
+a safe compromise. If 1 or more slow processor(s) are present among fast
+processors, window_size should be no larger then 256000 / netmtu to avoid
+overflow of the kernel receive buffers. The user is notified of this by
+the display of a retransmit list in the notification logs. There is no loss
+of data, but performance is reduced when these errors occur.
+<p>
+The default is 50 messages.
+<p>
+<dt><a name="max_messages"><strong>max_messages</strong></a><dd>
+This constant specifies the maximum number of messages that may be sent by one
+processor on receipt of the token. The max_messages parameter is limited to
+256000 / netmtu to prevent overflow of the kernel transmit buffers.
+<p>
+The default is 17 messages.
+<p>
+<dt><a name="rrp_problem_count_timeout"><strong>rrp_problem_count_timeout</strong></a><dd>
+This specifies the time in milliseconds to wait before decrementing the
+problem count by 1 for a particular ring to ensure a link is not marked
+faulty for transient network failures.
+<p>
+The default is 1000 milliseconds.
+<p>
+<dt><a name="rrp_problem_count_threshold"><strong>rrp_problem_count_threshold</strong></a><dd>
+This specifies the number of times a problem is detected with a link before
+setting the link faulty. Once a link is set faulty, no more data is
+transmitted upon it. Also, the problem counter is no longer decremented when
+the problem count timeout expires.
+<p>
+A problem is detected whenever all tokens from the proceeding processor have
+not been received within the rrp_token_expired_timeout. The
+rrp_problem_count_threshold * rrp_token_expired_timeout should be atleast 50
+milliseconds less then the token timeout, or a complete reconfiguration
+may occur.
+<p>
+The default is 20 problem counts.
+<p>
+<dt><a name="rrp_token_expired_timeout"><strong>rrp_token_expired_timeout</strong></a><dd>
+This specifies the time in milliseconds to increment the problem counter for
+the redundant ring protocol after not having received a token from all rings
+for a particular processor.
+<p>
+This value will automatically be calculated from the token timeout and
+problem_count_threshold but may be overridden. It is not recommended to
+override this value without guidance from the openais community.
+<p>
+The default is 47 milliseconds.
+<p>
+</dl>
+</body>
+</html>
--- conga/luci/Makefile 2006/08/09 15:52:14 1.20
+++ conga/luci/Makefile 2006/11/16 19:34:52 1.20.2.1
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.20 2006/08/09 15:52:14 rmccabe Exp $
ZOPEINSTANCE=/var/lib/luci
include ../make/version.in
--- conga/luci/load_site.py 2006/09/19 15:01:20 1.14
+++ conga/luci/load_site.py 2006/11/16 19:34:52 1.14.2.1
@@ -1,5 +1,4 @@
#!/usr/bin/python
-# $Id: load_site.py,v 1.14 2006/09/19 15:01:20 rmccabe Exp $
##############################################################################
#
--- conga/luci/pack.py 2006/07/24 20:17:01 1.4
+++ conga/luci/pack.py 2006/11/16 19:34:52 1.4.2.1
@@ -1,5 +1,4 @@
#!/usr/bin/python
-# $Id: pack.py,v 1.4 2006/07/24 20:17:01 kupcevic Exp $
import os, sys, string
--- conga/luci/cluster/form-chooser 2006/10/16 20:25:33 1.12
+++ conga/luci/cluster/form-chooser 2006/11/16 19:34:52 1.12.2.1
@@ -12,7 +12,7 @@
<span tal:condition="not: busywaiting">
<span tal:omit-tag="" tal:define="global ptype request/pagetype |nothing"/>
<span tal:omit-tag="" tal:condition="python: not ptype">
- <div metal:use-macro="here/form-macros/macros/entry-form"/>
+ <div metal:use-macro="here/form-macros/macros/clusters-form"/>
</span>
<span tal:omit-tag="" tal:condition="python: ptype == '0' or ptype == '1' or ptype == '2' or ptype == '3'">
<div metal:use-macro="here/form-macros/macros/clusters-form"/>
--- conga/luci/cluster/form-macros 2006/10/31 17:28:03 1.90.2.2
+++ conga/luci/cluster/form-macros 2006/11/16 19:34:52 1.90.2.3
@@ -7,7 +7,6 @@
<body>
<div metal:define-macro="entry-form">
- <h2>Entry Form</h2>
</div>
<div metal:define-macro="busywaitpage">
@@ -26,26 +25,33 @@
</span>
<span tal:condition="python: 'isnodecreation' in nodereport and nodereport['isnodecreation'] == True">
<span tal:condition="python: nodereport['iserror'] == True">
- <h2><span tal:content="nodereport/desc" /></h2>
- <font color="red"><span tal:content="nodereport/errormessage"/></font>
+ <h2><span tal:content="nodereport/desc" /></h2>
+ <span class="errmsg" tal:content="nodereport/errormessage"/>
</span>
+
<span tal:condition="python: nodereport['iserror'] == False">
- <h2><span tal:content="nodereport/desc" /></h2>
- <i><span tal:content="nodereport/statusmessage"/></i><br/>
- <span tal:condition="python: nodereport['statusindex'] == 0">
+ <h2><span tal:content="nodereport/desc" /></h2>
+ <em tal:content="nodereport/statusmessage | nothing"/><br/>
+ <span tal:condition="python: nodereport['statusindex'] < 1">
<img src="notstarted.png"/>
</span>
- <span tal:condition="python: nodereport['statusindex'] == 1">
- <img src="installed.png"/>
- </span>
- <span tal:condition="python: nodereport['statusindex'] == 2">
- <img src="rebooted.png"/>
+
+ <span tal:condition="
+ python: nodereport['statusindex'] == 1 or nodereport['statusindex'] == 2">
+ <img src="installed.png" alt="[cluster software installed]" />
</span>
+
<span tal:condition="python: nodereport['statusindex'] == 3">
- <img src="configured.png"/>
+ <img src="rebooted.png" alt="[cluster node rebooted]" />
+ </span>
+
+ <span tal:condition="
+ python: nodereport['statusindex'] == 4 or nodereport['statusindex'] == 5">
+ <img src="configured.png" alt="[cluster node configured]" />
</span>
- <span tal:condition="python: nodereport['statusindex'] == 4">
- <img src="joined.png"/>
+
+ <span tal:condition="python: nodereport['statusindex'] == 6">
+ <img src="joined.png" alt="[cluster node joined cluster]" />
</span>
</span>
</span>
@@ -61,18 +67,17 @@
<div id="cluster_list">
<div class="cluster" tal:repeat="clu clusystems">
-
<tal:block tal:define="
- global ragent python: here.getRicciAgent(clu[0])" />
+ global ricci_agent python: here.getRicciAgent(clu[0])" />
- <div tal:condition="python: not ragent">
+ <div tal:condition="python: not ricci_agent">
<strong class="errmsgs">An error occurred when trying to contact any of the nodes in the <span tal:replace="python: clu[0]"/> cluster.</strong>
<hr/>
</div>
- <tal:block tal:condition="python: ragent">
+ <tal:block tal:condition="python: ricci_agent">
<tal:block tal:define="
- global stat python: here.getClusterStatus(ragent);
+ global stat python: here.getClusterStatus(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');"
/>
@@ -84,15 +89,33 @@
<a href=""
tal:attributes="href cstatus/clucfg | nothing;
class python: 'cluster ' + cluster_status;"
- tal:content="cstatus/clusteralias | string: [unknown]" />
+ tal:content="cstatus/clusteralias | string:[unknown]" />
</td>
<td class="cluster cluster_action">
<form method="post" onSubmit="return dropdown(this.gourl)">
<select name="gourl" id="cluster_action" class="cluster">
- <option tal:condition="python: 'running' in cstatus and cstatus['running'] != 'true'" value="" class="cluster running">Start this cluster</option>
- <option tal:condition="python: 'running' in cstatus and cstatus['running'] == 'true'" value="" class="cluster stopped">Stop this cluster</option>
- <option value="" class="cluster">Restart this cluster</option>
+ <option class="cluster running"
+ tal:condition="python: 'running' in cstatus and cstatus['running'] != 'true'"
+ tal:attributes="value cstatus/start_url | nothing">
+ Start this cluster
+ </option>
+
+ <option class="cluster"
+ tal:attributes="value cstatus/restart_url | nothing">
+ Restart this cluster
+ </option>
+
+ <option class="cluster stopped"
+ tal:condition="python: 'running' in cstatus and cstatus['running'] == 'true'"
+ tal:attributes="value cstatus/stop_url | nothing">
+ Stop this cluster
+ </option>
+
+ <option class="cluster stopped"
+ tal:attributes="value cstatus/delete_url | nothing">
+ Delete this cluster
+ </option>
</select>
<input class="cluster" type="submit" value="Go" />
</form>
@@ -352,34 +375,41 @@
set_page_title('Luci â cluster â Configure cluster properties');
</script>
- <span tal:define="global ricci_agent python: here.getRicciAgentForCluster(request)" />
+ <tal:block tal:define="
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:condition="not: exists: modelb">
+ <tal:block tal:define="global modelb python: None" />
+ </tal:block>
+
<tal:block
tal:define="global clusterinfo python: here.getClusterInfo(modelb, request)" />
+<tal:block tal:condition="clusterinfo">
<span tal:omit-tag="" tal:define="global configTabNum python: 'tab' in request and int(request['tab']) or 1" />
<ul class="configTab">
<li class="configTab">
<a tal:attributes="
- href python: request['URL'] + '?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '&tab=1';
+ href clusterinfo/basecluster_url | nothing;
class python: 'configTab' + (configTabNum == 1 and ' configTabActive' or '');
">General</a>
</li>
<li class="configTab">
<a tal:attributes="
- href python: request['URL'] + '?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '&tab=2';
+ href clusterinfo/fencedaemon_url | nothing;
class python: 'configTab' + (configTabNum == 2 and ' configTabActive' or '');
">Fence</a>
</li>
<li class="configTab">
<a tal:attributes="
- href python: request['URL'] + '?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '&tab=3';
+ href clusterinfo/multicast_url | nothing;
class python: 'configTab' + (configTabNum == 3 and ' configTabActive' or '');
">Multicast</a>
</li>
<li class="configTab">
<a tal:attributes="
- href python: request['URL'] + '?pagetype=' + request['pagetype'] + '&clustername=' + request['clustername'] + '&tab=4';
+ href clusterinfo/quorumd_url | nothing;
class python: 'configTab' + (configTabNum == 4 and ' configTabActive' or '');
">Quorum Partition</a>
</li>
@@ -394,10 +424,15 @@
</script>
<form name="basecluster" action="" method="post">
+ <input type="hidden" name="cluster_version"
+ tal:attributes="value os_version | nothing" />
<input type="hidden" name="pagetype"
tal:attributes="value request/pagetype | request/form/pagetype"
/>
<input type="hidden" name="configtype" value="general" />
+ <input type="hidden" name="clustername"
+ tal:attributes="value request/clustername | clusterinfo/clustername | nothing" />
+
<table id="systemsTable" class="systemsTable" border="0" cellspacing="0">
<thead class="systemsTable">
<tr class="systemsTable"><td class="systemsTable" colspan="1">
@@ -412,7 +447,7 @@
<td class="systemsTable">Cluster Name</td>
<td class="systemsTable">
<input type="text" name="cluname"
- tal:attributes="value clusterinfo/clustername"/>
+ tal:attributes="value clusterinfo/clustername" />
</td>
</tr>
<tr class="systemsTable">
@@ -423,8 +458,272 @@
</td>
</tr>
</tbody>
+ </table>
- <tfoot class="systemsTable">
+ <table tal:condition="python: os_version and os_version == 'rhel5'">
+ <tr class="systemsTable">
+ <td class="systemsTable" colspan="2">
+ <img src="/luci/cluster/arrow_right.png" alt="[+]"
+ onclick="toggle_visible(this, 'genprops_advanced', 'genprops_advanced_label')">
+ <span id="genprops_advanced_label">Show</span>
+ advanced cluster properties
+ </td>
+ </tr>
+
+ <tr class="systemsTable invisible" id="genprops_advanced">
+ <td class="systemsTable" colspan="2">
+ <table class="systemsTable">
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#secauth', 55, 65);">Secure Authentication</a>
+ </td>
+ <td class="systemsTable">
+ <input type="checkbox" name="secauth" checked="checked" />
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#rrp_mode', 55, 65);">Redundant Ring Protocol Mode</a>
+ </td>
+ <td class="systemsTable">
+ <select name="text" name="rrp_mode">
+ <option value="none">
+ None
+ </option>
+ <option value="active">
+ Active
+ </option>
+ <option value="passive">
+ Passive
+ </option>
+ </select>
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#netmtu', 55, 65);">Network MTU</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="netmtu"
+ tal:attributes="value string:1500" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#threads', 55, 65);">Number of Threads
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10" name="threads"
+ tal:attributes="value string:0" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#vsftype', 55, 65);">Virtual Synchrony Type
+ </td>
+ <td class="systemsTable">
+ <select name="vsftype">
+ <option value="none">
+ None
+ </option>
+ <option value="ykd">
+ YKD
+ </option>
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#token', 55, 65);">Token Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10" name="token"
+ tal:attributes="value string:5000" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#token_retransmit', 55, 65);">Token Retransmit</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="token_retransmit"
+ tal:attributes="value string:238" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#hold', 55, 65);">Hold Token Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10" name="hold"
+ tal:attributes="value string:180" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#retransmits_before_loss', 55, 65);">Number of retransmits before loss</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="retransmits_before_loss"
+ tal:attributes="value string:4" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#join', 55, 65);">Join Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10" name="join"
+ tal:attributes="value string:100" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#consensus', 55, 65);">Consensus Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="consensus"
+ tal:attributes="value string:100" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#merge', 55, 65);">Merge Detection Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="merge"
+ tal:attributes="value string:200" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#downcheck', 55, 65);">Interface Down Check Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="downcheck"
+ tal:attributes="value string:1000" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#fail_to_recv_const', 55, 65);">Fail to Receive Constant</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="fail_to_recv_const"
+ tal:attributes="value string:50" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#seqno_unchanged_const', 55, 65);">Rotations with no mcast traffic before merge detection timeout started</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="seqno_unchanged_const"
+ tal:attributes="value string:30" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#heartbeat_failures_allowed', 55, 65);">Number of Heartbeat Failures Allowed</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="heartbeat_failures_allowed"
+ tal:attributes="value string:0" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#max_network_delay', 55, 65);">Maximum Network Delay</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="max_network_delay"
+ tal:attributes="value string:50" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#window_size', 55, 65);">Window Size</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="window_size"
+ tal:attributes="value string:50" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#max_messages', 55, 65);">Maximum Messages</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="max_messages"
+ tal:attributes="value string:17" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#rrp_problem_count_timeout', 55, 65);">RRP Problem Count Timeout</a> (ms)
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="rrp_problem_count_timeout"
+ tal:attributes="value string:1000" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#rrp_problem_count_threshold', 55, 65);">RRP Problem Count Threshold</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="rrp_problem_count_threshold"
+ tal:attributes="value string:20" />
+ </td>
+ </tr>
+
+ <tr class="systemsTable">
+ <td class="systemsTable">
+ <a class="cluster_help" href="javascript:popup_window('/luci/doc/config_rhel5#rrp_token_expired_timeout', 55, 65);">RRP Token Expired Timeout</a>
+ </td>
+ <td class="systemsTable">
+ <input type="text" size="10"
+ name="rrp_token_expired_timeout"
+ tal:attributes="value string:47" />
+ </td>
+ </tr>
+ </table>
+ </td></tr>
+ </table>
+
+ <table class="systemsTable">
<tr class="systemsTable">
<td class="systemsTable" colspan="2">
<div class="systemsTableEnd">
@@ -433,17 +732,21 @@
</div>
</td>
</tr>
- </tfoot>
- </table>
+ </table>
</form>
</div>
<div id="configTabContent" tal:condition="python: configTabNum == 2">
- <form name="fencedaemon" method="post">
+ <form name="fencedaemon" method="post" action="">
<input type="hidden" name="configtype" value="fence" />
<input type="hidden" name="pagetype"
tal:attributes="value request/pagetype | request/form/pagetype"
/>
+ <input type="hidden" name="cluster_version"
+ tal:attributes="value os_version | nothing" />
+ <input type="hidden" name="clustername"
+ tal:attributes="value request/clustername | clusterinfo/clustername | nothing" />
+
<script type="text/javascript"
src="/luci/homebase/homebase_common.js">
</script>
@@ -504,6 +807,10 @@
<input type="hidden" name="pagetype"
tal:attributes="value request/pagetype | request/form/pagetype"
/>
+ <input type="hidden" name="cluster_version"
+ tal:attributes="value os_version | nothing" />
+ <input type="hidden" name="clustername"
+ tal:attributes="value request/clustername | clusterinfo/clustername | nothing" />
<table id="systemsTable" class="systemsTable" border="0" cellspacing="0">
<thead class="systemsTable">
<tr class="systemsTable"><td class="systemsTable" colspan="1">
@@ -570,6 +877,10 @@
tal:attributes="value request/pagetype | request/form/pagetype"
/>
<input type="hidden" name="configtype" value="qdisk" />
+ <input type="hidden" name="cluster_version"
+ tal:attributes="value os_version | nothing" />
+ <input type="hidden" name="clustername"
+ tal:attributes="value request/clustername | clusterinfo/clustername | nothing" />
<div class="configTabContent">
<table id="systemsTable" class="systemsTable" border="0" cellspacing="0">
<thead class="systemsTable">
@@ -779,11 +1090,13 @@
</script>
</form>
</div>
+</tal:block>
</div>
<div metal:define-macro="clusterprocess-form">
- <span tal:define="global r_agent python: here.getRicciAgentForCluster(request)"/>
- <span tal:define="res python: here.processClusterProps(r_agent, request)"/>
+ <tal:block
+ tal:define="result python: here.clusterTaskProcess(modelb, request)"/>
+ <h2>Cluster Process Form</h2>
</div>
<div metal:define-macro="fence-option-list">
@@ -1198,7 +1511,7 @@
<td>ESH Path (Optional)</td>
<td>
<input name="login" type="text"
- tal:attributes="cur_fencedev/login | string: /opt/pan-mgr/bin/esh" />
+ tal:attributes="cur_fencedev/login | string:/opt/pan-mgr/bin/esh" />
</td>
</tr>
</table>
@@ -1412,7 +1725,9 @@
</tal:comment>
<tal:block tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
global nodestatus python: here.getClusterStatus(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'));
@@ -1476,7 +1791,7 @@
tal:condition="python: nodeinfo['nodestate'] == '0' or nodeinfo['nodestate'] == '1'">
<h3>Cluster daemons running on this node</h3>
- <form name="daemon_form">
+ <form name="daemon_form" method="post">
<table class="systemsTable">
<thead>
<tr class="systemsTable">
@@ -1488,23 +1803,38 @@
<tfoot class="systemsTable">
<tr class="systemsTable"><td class="systemsTable" colspan="3">
<div class="systemsTableEnd">
- <input type="button" value="Update node daemon properties" />
+ <input type="Submit" value="Update node daemon properties" />
</div>
</td></tr>
</tfoot>
<tbody class="systemsTable">
<tr class="systemsTable" tal:repeat="demon nodeinfo/d_states">
<td class="systemsTable"><span tal:replace="demon/name"/></td>
- <td class="systemsTable"><span tal:replace="python: demon['running'] and 'yes' or 'no'" /></td>
+ <td class="systemsTable"><span tal:replace="python: demon['running'] == 'true' and 'yes' or 'no'" /></td>
<td class="systemsTable">
- <input type="checkbox"
- tal:attributes="
- name python: nodeinfo['nodename'] + ':' + demon['name'];
- checked python: demon['enabled'] and 'checked'" />
+ <input type="hidden" tal:attributes="
+ name python: '__daemon__:' + demon['name'] + ':';
+ value demon/name" />
+
+ <input type="hidden" tal:attributes="
+ name python: '__daemon__:' + demon['name'] + ':';
+ value python: demon['enabled'] == 'true' and '1' or '0'" />
+
+ <input type="checkbox" tal:attributes="
+ name python: '__daemon__:' + demon['name'] + ':';
+ checked python: demon['enabled'] == 'true' and 'checked'" />
</td>
</tr>
</tbody>
</table>
+
+ <input type="hidden" name="nodename"
+ tal:attributes="value nodeinfo/nodename | request/nodename | nothing" />
+
+ <input type="hidden" name="clustername"
+ tal:attributes="value request/clustername | nothing" />
+
+ <input type="hidden" name="pagetype" value="55" />
</form>
<hr/>
</tal:block>
@@ -1604,10 +1934,13 @@
set_page_title('Luci â cluster â nodes');
</script>
-<div id="node_list" tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
- global status python: here.getClusterStatus(ricci_agent);
- global nds python: here.getNodesInfo(modelb, status, request)">
+<div id="node_list">
+ <tal:block tal:define="
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
+ global status python: here.getClusterStatus(ricci_agent);
+ global nds python: here.getNodesInfo(modelb, status, request)" />
<div tal:repeat="nd nds">
<tal:block
@@ -1628,8 +1961,8 @@
<select class="node" name="gourl">
<option value="">Choose a Task...</option>
<option tal:attributes="value nd/jl_url">
- <span tal:condition="python: nd['status'] == '0'" tal:replace="string: Have node leave cluster" />
- <span tal:condition="python: nd['status'] == '1'" tal:replace="string: Have node join cluster" />
+ <span tal:condition="python: nd['status'] == '0'" tal:replace="string:Have node leave cluster" />
+ <span tal:condition="python: nd['status'] == '1'" tal:replace="string:Have node join cluster" />
</option>
<option value="">----------</option>
<option tal:attributes="value nd/fence_it_url">Fence this node</option>
@@ -1743,7 +2076,7 @@
value request/form/clusterName | request/clustername | nothing"
/>
- <h2>Add a node to <span tal:replace="request/form/clusterName | request/clustername | string: the cluster" /></h2>
+ <h2>Add a node to <span tal:replace="request/form/clusterName | request/clustername | string:the cluster" /></h2>
<table id="systemsTable" class="systemsTable" border="0" cellspacing="0">
<thead class="systemsTable">
@@ -1808,7 +2141,10 @@
<div metal:define-macro="nodeprocess-form">
<tal:block
tal:define="result python: here.nodeTaskProcess(modelb, request)"/>
- <h2>Node Process Form</h2>
+
+ <div>
+ <span tal:replace="result | nothing" />
+ </div>
</div>
<div metal:define-macro="services-form">
@@ -1820,12 +2156,13 @@
set_page_title('Luci â cluster â services');
</script>
- <tal:block tal:omit-tag=""
- tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
- global svcstatus python: here.getClusterStatus(ricci_agent);
- global svcinf python: here.getServicesInfo(svcstatus,modelb,request);
- global svcs svcinf/services" />
+ <tal:block tal:define="
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
+ global svcstatus python: here.getClusterStatus(ricci_agent);
+ global svcinf python: here.getServicesInfo(svcstatus,modelb,request);
+ global svcs svcinf/services" />
<tal:block tal:repeat="svc svcs">
<table class="cluster service" width="100%"
@@ -1866,7 +2203,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="not: autostart" tal:replace="string:not" /> enabled for this service</p>
</td>
</tr>
@@ -1881,7 +2218,6 @@
</div>
<div metal:define-macro="xenvmadd-form">
- <span tal:define="ress python:here.appendModel(request, modelb)"/>
<form method="get" action="" tal:attributes="action python:request['baseurl'] + '?clustername=' + request['clustername'] + '&pagetype=29'">
<h4>Path to configuration file: </h4><input type="text" name="xenvmpath" value=""/>
<h4>Name of configuration file: </h4><input type="text" name="xenvmname" value=""/>
@@ -1890,7 +2226,6 @@
</div>
<div metal:define-macro="xenvmconfig-form">
- <span tal:define="ress python:here.appendModel(request, modelb)"/>
<h4>Properties for Xen VM <font color="green"><span tal:content="request/servicename"/></font></h4>
<span tal:define="global xeninfo python:here.getXenVMInfo(modelb, request)">
<form method="get" action="" tal:attributes="action python:request['baseurl'] + '?clustername=' + request['clustername'] + '&pagetype=29&servicename=' + request['servicename']">
@@ -1974,7 +2309,9 @@
</script>
<tal:block tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
result python: here.serviceStart(ricci_agent, request)" />
<!-- <span metal:use-macro="here/form-macros/macros/serviceconfig-form"/> -->
@@ -1987,7 +2324,9 @@
</script>
<tal:block tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
result python: here.serviceRestart(ricci_agent, request)" />
<!-- <span metal:use-macro="here/form-macros/macros/serviceconfig-form"/> -->
@@ -1998,15 +2337,17 @@
set_page_title('Luci â cluster â services â Stop a service');
</script>
+ <tal:block tal:define="
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
<span tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
result python: here.serviceStop(ricci_agent, request)" />
<!-- <span metal:use-macro="here/form-macros/macros/serviceconfig-form"/> -->
</div>
<div metal:define-macro="serviceconfig-type-macro" tal:omit-tag="">
- <span tal:omit-tag="" tal:condition="python: type == 'IP Address: '">
+ <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'">
@@ -2027,7 +2368,7 @@
<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: '">
+ <span tal:omit-tag="" tal:condition="python: type == 'script'">
<tal:block metal:use-macro="here/resource-form-macros/macros/scr_macro" />
</span>
</div>
@@ -2041,7 +2382,9 @@
</script>
<tal:block tal:define="
- global ricci_agent python: here.getRicciAgentForCluster(request);
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
global global_resources python: here.getResourcesInfo(modelb, request);
global sstat python: here.getClusterStatus(ricci_agent);
global sinfo python: here.getServiceInfo(sstat, modelb, request);
@@ -2209,8 +2552,10 @@
</script>
<tal:block tal:define="
- global ragent python: here.getRicciAgentForCluster(request);
- global sta python: here.getClusterStatus(ragent);
+ global ricci_agent ri_agent | python: here.getRicciAgentForCluster(request)" />
+
+ <tal:block tal:define="
+ global sta python: here.getClusterStatus(ricci_agent);
global fdominfo python: here.getFdomsInfo(modelb, request, sta);" />
<div class="cluster fdom" tal:repeat="fdom fdominfo">
@@ -2299,11 +2644,24 @@
set_page_title('Luci â cluster â fence devices');
</script>
<h2>Shared Fence Devices for Cluster: <span tal:content="request/clustername"/></h2>
- <tal:block tal:define="global fencedevinfo python: here.getFenceInfo(modelb, None)"/>
+ <tal:block tal:define="global fencedevinfo python: here.getFencesInfo(modelb, request)"/>
<tal:block tal:define="global fencedevs python: fencedevinfo['fencedevs']"/>
<span tal:repeat="fencedev fencedevs">
+ <h3>Agent type: <span tal:content="fencedev/pretty_name"/></h3>
<h3>Name: <span tal:content="fencedev/name"/></h3>
- <h3>Agent type: <span tal:content="fencedev/agent"/></h3>
+ <h3>Nodes using this device for fencing:</h3>
+ <ul>
+ <tal:block tal:define="global usednodes python:fencedev['nodesused']"/>
+ <span tal:condition="python: len(usednodes) == 0">
+ <li>No nodes currently employ this fence device</li>
+ </span>
+ <span tal:repeat="usednode usednodes">
+ <li><font color="green">
+ <a href="" tal:attributes="href usednode/nodeurl"><tal:block tal:content="usednode/nodename"/>
+ </a></font>
+ </li>
+ </span>
+ </ul>
<hr/>
</span>
</div>
--- conga/luci/cluster/index_html 2006/11/01 22:06:55 1.20.2.3
+++ conga/luci/cluster/index_html 2006/11/16 19:34:52 1.20.2.4
@@ -9,11 +9,6 @@
xml:lang language">
<head metal:use-macro="here/header/macros/html_header">
-
-
-
-
-
<metal:fillbase fill-slot="base">
<metal:baseslot define-slot="base">
<base href="" tal:attributes="href here/renderBase" />
@@ -29,47 +24,54 @@
</metal:cache>
<metal:headslot define-slot="head_slot" />
- <tal:block tal:define="global sinfo nothing" />
- <div tal:define="global hascluster request/clustername |nothing; global busywaiting python:None;"/>
- <span tal:condition="not: hascluster">
- <meta googaa="ooo"/>
- </span>
-
- <span tal:condition="hascluster">
- <span tal:define="ri_agent python:here.getRicciAgentForCluster(request)">
-
- <span tal:define="resmap python:here.getClusterOS(ri_agent);
- global isVirtualized resmap/isVirtualized;
- global os_version resmap/os;"/>
- </span>
- <span tal:define="global isBusy python:here.isClusterBusy(request)"/>
- <span tal:define="global firsttime request/busyfirst |nothing"/>
- <span tal:condition="firsttime">
- <span tal:define="global busywaiting python:True"/>
- <meta http-equiv="refresh" content="" tal:attributes="content isBusy/refreshurl"/>
- </span>
- <span tal:define="global busy isBusy/busy |nothing"/>
- <span tal:condition="busy">
- <span tal:define="global busywaiting python:True"/>
- <meta http-equiv="refresh" content="" tal:attributes="content isBusy/refreshurl"/>
- </span>
- </span>
-
- <tal:comment replace="nothing"> A slot where you can insert elements in the header from a template </tal:comment>
+ <tal:block tal:define="
+ global sinfo nothing;
+ global hascluster request/clustername |nothing;
+ global isBusy python: False;
+ global firsttime nothing;
+ global ri_agent nothing;
+ global busywaiting python:None" />
+
+ <tal:block tal:condition="not: hascluster">
+ <meta googaa="ooo"/>
+ </tal:block>
+
+ <tal:block tal:condition="hascluster">
+ <tal:block tal:define="
+ global ri_agent python:here.getRicciAgentForCluster(request);
+ resmap python:here.getClusterOS(ri_agent);
+ global isVirtualized resmap/isVirtualized | nothing;
+ global os_version resmap/os | nothing;
+ global isBusy python:here.isClusterBusy(request);
+ global firsttime request/busyfirst |nothing" />
+
+ <tal:block tal:condition="firsttime">
+ <tal:block tal:define="global busywaiting python:True" />
+ <meta http-equiv="refresh"
+ tal:attributes="content isBusy/refreshurl | string:." />
+ </tal:block>
+
+ <tal:block tal:define="global busy isBusy/busy |nothing"/>
+
+ <tal:block tal:condition="busy">
+ <tal:block tal:define="global busywaiting python:True" />
+ <meta http-equiv="refresh"
+ tal:attributes="content isBusy/refreshurl | string:." />
+ </tal:block>
+ </tal:block>
</metal:headslot>
-
-
<metal:cssslot fill-slot="css_slot">
- <tal:comment replace="nothing"> A slot where you can insert CSS in the header from a template </tal:comment>
-
- <style type="text/css"><!-- @import url(./clusterportlet.css); --></style>
- <style type="text/css"><!-- @import url(/luci/homebase/luci_homebase.css); --></style>
- <metal:cssslot define-slot="css_slot" />
+ <style type="text/css">
+ <!-- @import url(./clusterportlet.css); -->
+ </style>
+ <style type="text/css">
+ <!-- @import url(/luci/homebase/luci_homebase.css); -->
+ </style>
+ <metal:cssslot define-slot="css_slot" />
</metal:cssslot>
<metal:javascriptslot fill-slot="javascript_head_slot">
- <tal:comment replace="nothing"> A slot where you can insert javascript in the header from a template </tal:comment>
<script type="text/javascript" src="/luci/conga.js"></script>
<SCRIPT TYPE="text/javascript">
<!--
@@ -121,7 +123,6 @@
</SCRIPT>
<metal:javascriptslot define-slot="javascript_head_slot" />
</metal:javascriptslot>
-
</head>
<body tal:attributes="class here/getSectionFromURL;
@@ -158,15 +159,22 @@
alternative in the plone_tableless skin layer that you can use if you
prefer layouts that don't use tables.
</tal:comment>
- <!-- <div tal:define="global hascluster request/clustername |nothing"/> -->
<tal:block tal:condition="hascluster">
- <tal:block tal:define="global ricci_agent python: here.getRicciAgentForCluster(request)" />
- <tal:block tal:condition="python: ricci_agent"
- tal:define="
- global modelb python:here.getmodelbuilder(ricci_agent,isVirtualized)" />
+ <tal:block tal:condition="python: ri_agent">
+ <tal:block tal:define="
+ global modelb python:here.getmodelbuilder(ri_agent, isVirtualized)" />
+ <tal:block tal:condition="python: modelb">
+ <tal:block
+ tal:define="dummy python: here.appendModel(request, modelb)" />
+ </tal:block>
+ </tal:block>
</tal:block>
+ <tal:block tal:condition="not: exists: modelb">
+ <tal:block tal:define="global modelb nothing" />
+ </tal:block>
+
<table id="portal-columns">
<tbody>
<tr>
@@ -214,8 +222,8 @@
<metal:main-form-content use-macro="here/form-chooser/macros/main-form">
</metal:main-form-content>
- <tal:block tal:condition="python: request.SESSION.has_key('checkRet')"
- tal:define="ret python: request.SESSION.get('checkRet')">
+ <tal:block tal:condition="python: request.SESSION.has_key('checkRet')">
+ <tal:block tal:define="ret python: request.SESSION.get('checkRet')">
<div class="retmsgs" id="retmsgsdiv" tal:condition="python:(ret and 'messages' in ret and len(ret['messages']))">
<div class="hbclosebox">
<a href="javascript:hide_element('retmsgsdiv');"><img src="../homebase/x.png"></a>
@@ -238,6 +246,7 @@
</tal:block>
</ul>
</div>
+ </tal:block>
</tal:block>
</div>
--- conga/luci/cluster/portlet_cluconfig 2006/09/27 22:24:11 1.2
+++ conga/luci/cluster/portlet_cluconfig 2006/11/16 19:34:52 1.2.2.1
@@ -10,7 +10,7 @@
<dl class="portlet" id="portlet-cluconfig-tree">
<dt class="portletHeader">
- <a href="#">
+ <a href="/luci/cluster/index_html?pagetype=3">
Clusters
</a>
</dt>
@@ -36,7 +36,8 @@
<dl class="portlet" id="portlet-cluconfig-tree">
<dt class="portletHeader">
- <a href="#" tal:attributes="href python:here.getClusterURL(request,modelb)">
+ <a href="/luci/cluster/index_html?pagetype=3"
+ tal:attributes="href python:here.getClusterURL(request,modelb)">
<div tal:omit-tag="" tal:content="python: here.getClusterAlias(modelb)" />
</a>
</dt>
--- conga/luci/cluster/resource-form-macros 2006/10/31 17:28:03 1.21.2.1
+++ conga/luci/cluster/resource-form-macros 2006/11/16 19:34:53 1.21.2.2
@@ -43,8 +43,7 @@
<tal:block
tal:define="
- global rescInf python: here.getResourcesInfo(modelb, request);
- global msg python: here.appendModel(request, modelb)" />
+ global rescInf python: here.getResourcesInfo(modelb, request)" />
<table class="systemsTable">
<thead class="systemsTable">
@@ -258,44 +257,43 @@
<tal:block tal:define="global resourcename request/resourcename | request/form/resourceName | nothing" />
<tal:block tal:condition="resourcename"
tal:define="
- global msg python: here.appendModel(request, modelb);
global res python: here.getResourceInfo(modelb, request);
global type python: 'tag_name' in res and res['tag_name'] or ''">
<h2>Configure <span tal:replace="res/name | string: resource" /></h2>
<div class="reschoose">
- <span tal:omit-tag="" tal:condition="python: type == 'ip'">
+ <tal:block tal:condition="python: type == 'ip'">
<div metal:use-macro="here/resource-form-macros/macros/ip_macro" />
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'fs'">
+ <tal:block tal:condition="python: type == 'fs'">
<div metal:use-macro="here/resource-form-macros/macros/fs_macro" />
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'gfs'">
+ <tal:block tal:condition="python: type == 'gfs'">
<div metal:use-macro="here/resource-form-macros/macros/gfs_macro" />
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'nfsm'">
+ <tal:block tal:condition="python: type == 'nfsm'">
<div metal:use-macro="here/resource-form-macros/macros/nfsm_macro"/>
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'nfsx'">
+ <tal:block tal:condition="python: type == 'nfsx'">
<div metal:use-macro="here/resource-form-macros/macros/nfsx_macro"/>
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'nfsc'">
+ <tal:block tal:condition="python: type == 'nfsc'">
<div metal:use-macro="here/resource-form-macros/macros/nfsc_macro"/>
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'smb'">
+ <tal:block tal:condition="python: type == 'smb'">
<div metal:use-macro="here/resource-form-macros/macros/smb_macro" />
- </span>
+ </tal:block>
- <span tal:omit-tag="" tal:condition="python: type == 'script'">
+ <tal:block tal:condition="python: type == 'script'">
<div metal:use-macro="here/resource-form-macros/macros/scr_macro" />
- </span>
+ </tal:block>
</div>
</tal:block>
</div>
@@ -686,14 +684,12 @@
<input type="radio" name="nfstype" value="nfs"
tal:attributes="
disabled python: editDisabled;
- content string: NFS (version 3);
- checked python: nfstype == 'nfs' and 'checked'" />
+ checked python: nfstype != 'nfs4' and 'checked'" />NFS3
<br/>
<input type="radio" name="nfstype" value="nfs4"
tal:attributes="
disabled python: editDisabled;
- content string: NFS4;
- checked python: nfstype == 'nfs4' and 'checked'" />
+ checked python: nfstype == 'nfs4' and 'checked'" />NFS4
</td>
</tr>
--- conga/luci/cluster/resource_form_handlers.js 2006/10/31 17:28:03 1.20.2.1
+++ conga/luci/cluster/resource_form_handlers.js 2006/11/16 19:34:53 1.20.2.2
@@ -101,7 +101,7 @@
function validate_nfs_mount(form) {
var errors = new Array();
- if (!form.mountpoint || str_is_blank(form.mounpoint.value)) {
+ if (!form.mountpoint || str_is_blank(form.mountpoint.value)) {
errors.push('No mount point was given.');
set_form_err(form.mountpoint);
} else
/cvs/cluster/conga/luci/docs/config_rhel5,v --> standard output
revision 1.2.2.1
--- conga/luci/docs/config_rhel5
+++ - 2006-11-16 19:34:57.842868000 +0000
@@ -0,0 +1,260 @@
+<html><head><title>Advanced Cluster Configuration Parameters</title>
+</head><body>
+<h2>Advanced Cluster Configuration Parameters</h2>
+<p>
+<dl compact>
+<dt><a name="secauth"><strong>secauth</strong></a><dd>
+This specifies that HMAC/SHA1 authentication should be used to authenticate
+all messages. It further specifies that all data should be encrypted with the
+sober128 encryption algorithm to protect data from eavesdropping.
+<p>
+Enabling this option adds a 36 byte header to every message sent by totem which
+reduces total throughput. Encryption and authentication consume 75% of CPU
+cycles in aisexec as measured with gprof when enabled.
+<p>
+For 100mbit networks with 1500 MTU frame transmissions:
+A throughput of 9mb/sec is possible with 100% cpu utilization when this
+option is enabled on 3ghz cpus.
+A throughput of 10mb/sec is possible wth 20% cpu utilization when this
+optin is disabled on 3ghz cpus.
+<p>
+For gig-e networks with large frame transmissions:
+A throughput of 20mb/sec is possible when this option is enabled on
+3ghz cpus.
+A throughput of 60mb/sec is possible when this option is disabled on
+3ghz cpus.
+<p>
+The default is on.
+<p>
+<dt><a name="rrp_mode"><strong>rrp_mode</strong></a><dd>
+This specifies the mode of redundant ring, which may be none, active, or
+passive. Active replication offers slightly lower latency from transmit
+to delivery in faulty network environments but with less performance.
+Passive replication may nearly double the speed of the totem protocol
+if the protocol doesn't become cpu bound. The final option is none, in
+which case only one network interface will be used to operate the totem
+protocol.
+<p>
+If only one interface directive is specified, none is automatically chosen.
+If multiple interface directives are specified, only active or passive may
+be chosen.
+<p>
+<dt><a name="netmtu"><strong>netmtu</strong></a><dd>
+This specifies the network maximum transmit unit. To set this value beyond
+1500, the regular frame MTU, requires ethernet devices that support large, or
+also called jumbo, frames. If any device in the network doesn't support large
+frames, the protocol will not operate properly. The hosts must also have their
+mtu size set from 1500 to whatever frame size is specified here.
+<p>
+Please note while some NICs or switches claim large frame support, they support
+9000 MTU as the maximum frame size including the IP header. Setting the netmtu
+and host MTUs to 9000 will cause totem to use the full 9000 bytes of the frame.
+Then Linux will add a 18 byte header moving the full frame size to 9018. As a
+result some hardware will not operate properly with this size of data. A netmtu
+of 8982 seems to work for the few large frame devices that have been tested.
+Some manufacturers claim large frame support when in fact they support frame
+sizes of 4500 bytes.
+<p>
+Increasing the MTU from 1500 to 8982 doubles throughput performance from 30MB/sec
+to 60MB/sec as measured with evsbench with 175000 byte messages with the secauth
+directive set to off.
+<p>
+When sending multicast traffic, if the network frequently reconfigures, chances are
+that some device in the network doesn't support large frames.
+<p>
+Choose hardware carefully if intending to use large frame support.
+<p>
+The default is 1500.
+<p>
+<dt><a name="threads"><strong>threads</strong></a><dd>
+This directive controls how many threads are used to encrypt and send multicast
+messages. If secauth is off, the protocol will never use threaded sending.
+If secauth is on, this directive allows systems to be configured to use
+multiple threads to encrypt and send multicast messages.
+<p>
+A thread directive of 0 indicates that no threaded send should be used. This
+mode offers best performance for non-SMP systems.
+<p>
+The default is 0.
+<p>
+<dt><a name="vsftype"><strong>vsftype</strong></a><dd>
+This directive controls the virtual synchrony filter type used to identify
+a primary component. The preferred choice is YKD dynamic linear voting,
+however, for clusters larger then 32 nodes YKD consumes alot of memory. For
+large scale clusters that are created by changing the MAX_PROCESSORS_COUNT
+#define in the C code totem.h file, the virtual synchrony filter "none" is
+recommended but then AMF and DLCK services (which are currently experimental)
+are not safe for use.
+<p>
+The default is ykd. The vsftype can also be set to none.
+<p>
+Within the
+<B>totem </B>
+
+directive, there are several configuration options which are used to control
+the operation of the protocol. It is generally not recommended to change any
+of these values without proper guidance and sufficient testing. Some networks
+may require larger values if suffering from frequent reconfigurations. Some
+applications may require faster failure detection times which can be achieved
+by reducing the token timeout.
+<p>
+<dt><a name="token"><strong>token</strong></a><dd>
+This timeout specifies in milliseconds until a token loss is declared after not
+receiving a token. This is the time spent detecting a failure of a processor
+in the current configuration. Reforming a new configuration takes about 50
+milliseconds in addition to this timeout.
+<p>
+The default is 5000 milliseconds.
+<p>
+<dt><a name="token_retransmit"><strong>token_retransmit</strong></a><dd>
+This timeout specifies in milliseconds after how long before receiving a token
+the token is retransmitted. This will be automatically calculated if token
+is modified. It is not recommended to alter this value without guidance from
+the openais community.
+<p>
+The default is 238 milliseconds.
+<p>
+<dt><a name="hold"><strong>hold</strong></a><dd>
+This timeout specifies in milliseconds how long the token should be held by
+the representative when the protocol is under low utilization. It is not
+recommended to alter this value without guidance from the openais community.
+<p>
+The default is 180 milliseconds.
+<p>
+<dt><a name="retransmits_before_loss"><strong>retransmits_before_loss</strong></a><dd>
+This value identifies how many token retransmits should be attempted before
+forming a new configuration. If this value is set, retransmit and hold will
+be automatically calculated from retransmits_before_loss and token.
+<p>
+The default is 4 retransmissions.
+<p>
+<dt><a name="join"><strong>join</strong></a><dd>
+This timeout specifies in milliseconds how long to wait for join messages in
+the membership protocol.
+<p>
+The default is 100 milliseconds.
+<p>
+<dt><a name="send_join"><strong>send_join</strong></a><dd>
+This timeout specifies in milliseconds an upper range between 0 and send_join
+to wait before sending a join message. For configurations with less then
+32 nodes, this parameter is not necessary. For larger rings, this parameter
+is necessary to ensure the NIC is not overflowed with join messages on
+formation of a new ring. A reasonable value for large rings (128 nodes) would
+be 80msec. Other timer values must also change if this value is changed. Seek
+advice from the openais mailing list if trying to run larger configurations.
+<p>
+The default is 0 milliseconds.
+<p>
+<dt><a name="consensus"><strong>consensus</strong></a><dd>
+This timeout specifies in milliseconds how long to wait for consensus to be
+achieved before starting a new round of membership configuration.
+<p>
+The default is 200 milliseconds.
+<p>
+<dt><a name="merge"><strong>merge</strong></a><dd>
+This timeout specifies in milliseconds how long to wait before checking for
+a partition when no multicast traffic is being sent. If multicast traffic
+is being sent, the merge detection happens automatically as a function of
+the protocol.
+<p>
+The default is 200 milliseconds.
+<p>
+<dt><a name="downcheck"><strong>downcheck</strong></a><dd>
+This timeout specifies in milliseconds how long to wait before checking
+that a network interface is back up after it has been downed.
+<p>
+The default is 1000 millseconds.
+<p>
+<dt><a name="fail_to_recv_const"><strong>fail_to_recv_const</strong></a><dd>
+This constant specifies how many rotations of the token without receiving any
+of the messages when messages should be received may occur before a new
+configuration is formed.
+<p>
+The default is 50 failures to receive a message.
+<p>
+<dt><a name="seqno_unchanged_const"><strong>seqno_unchanged_const</strong></a><dd>
+This constant specifies how many rotations of the token without any multicast
+traffic should occur before the merge detection timeout is started.
+<p>
+The default is 30 rotations.
+<p>
+<dt><a name="heartbeat_failures_allowed"><strong>heartbeat_failures_allowed</strong></a><dd>
+[HeartBeating mechanism]
+Configures the optional HeartBeating mechanism for faster failure detection. Keep in
+mind that engaging this mechanism in lossy networks could cause faulty loss declaration
+as the mechanism relies on the network for heartbeating.
+<p>
+So as a rule of thumb use this mechanism if you require improved failure in low to
+medium utilized networks.
+<p>
+This constant specifies the number of heartbeat failures the system should tolerate
+before declaring heartbeat failure e.g 3. Also if this value is not set or is 0 then the
+heartbeat mechanism is not engaged in the system and token rotation is the method
+of failure detection
+<p>
+The default is 0 (disabled).
+<p>
+<dt><a name="max_network_delay"><strong>max_network_delay</strong></a><dd>
+[HeartBeating mechanism]
+This constant specifies in milliseconds the approximate delay that your network takes
+to transport one packet from one machine to another. This value is to be set by system
+engineers and please dont change if not sure as this effects the failure detection
+mechanism using heartbeat.
+<p>
+The default is 50 milliseconds.
+<p>
+<dt><a name="window_size"><strong>window_size</strong></a><dd>
+This constant specifies the maximum number of messages that may be sent on one
+token rotation. If all processors perform equally well, this value could be
+large (300), which would introduce higher latency from origination to delivery
+for very large rings. To reduce latency in large rings(16+), the defaults are
+a safe compromise. If 1 or more slow processor(s) are present among fast
+processors, window_size should be no larger then 256000 / netmtu to avoid
+overflow of the kernel receive buffers. The user is notified of this by
+the display of a retransmit list in the notification logs. There is no loss
+of data, but performance is reduced when these errors occur.
+<p>
+The default is 50 messages.
+<p>
+<dt><a name="max_messages"><strong>max_messages</strong></a><dd>
+This constant specifies the maximum number of messages that may be sent by one
+processor on receipt of the token. The max_messages parameter is limited to
+256000 / netmtu to prevent overflow of the kernel transmit buffers.
+<p>
+The default is 17 messages.
+<p>
+<dt><a name="rrp_problem_count_timeout"><strong>rrp_problem_count_timeout</strong></a><dd>
+This specifies the time in milliseconds to wait before decrementing the
+problem count by 1 for a particular ring to ensure a link is not marked
+faulty for transient network failures.
+<p>
+The default is 1000 milliseconds.
+<p>
+<dt><a name="rrp_problem_count_threshold"><strong>rrp_problem_count_threshold</strong></a><dd>
+This specifies the number of times a problem is detected with a link before
+setting the link faulty. Once a link is set faulty, no more data is
+transmitted upon it. Also, the problem counter is no longer decremented when
+the problem count timeout expires.
+<p>
+A problem is detected whenever all tokens from the proceeding processor have
+not been received within the rrp_token_expired_timeout. The
+rrp_problem_count_threshold * rrp_token_expired_timeout should be atleast 50
+milliseconds less then the token timeout, or a complete reconfiguration
+may occur.
+<p>
+The default is 20 problem counts.
+<p>
+<dt><a name="rrp_token_expired_timeout"><strong>rrp_token_expired_timeout</strong></a><dd>
+This specifies the time in milliseconds to increment the problem counter for
+the redundant ring protocol after not having received a token from all rings
+for a particular processor.
+<p>
+This value will automatically be calculated from the token timeout and
+problem_count_threshold but may be overridden. It is not recommended to
+override this value without guidance from the openais community.
+<p>
+The default is 47 milliseconds.
+<p>
+</dl>
+</body>
+</html>
--- conga/luci/homebase/form-chooser 2006/10/09 16:16:11 1.10
+++ conga/luci/homebase/form-chooser 2006/11/16 19:34:53 1.10.2.1
@@ -4,10 +4,6 @@
<title id="pagetitle" tal:content="title">The title</title>
</head>
-<tal:comment replace="nothing">
- $Id: form-chooser,v 1.10 2006/10/09 16:16:11 rmccabe Exp $
-</tal:comment>
-
<body>
<metal:choose-form metal:define-macro="main-form">
--- conga/luci/homebase/form-macros 2006/11/01 22:06:55 1.44.2.3
+++ conga/luci/homebase/form-macros 2006/11/16 19:34:53 1.44.2.4
@@ -1,9 +1,5 @@
<html>
-<tal:comment tal:replace="nothing">
- $Id: form-macros,v 1.44.2.3 2006/11/01 22:06:55 rmccabe Exp $
-</tal:comment>
-
<head>
<title tal:content="string:"></title>
</head>
--- conga/luci/homebase/homebase_common.js 2006/10/04 17:24:58 1.13
+++ conga/luci/homebase/homebase_common.js 2006/11/16 19:34:53 1.13.2.1
@@ -8,6 +8,35 @@
ielem.className = ielem.className.replace(/ formerror/, '');
}
+function toggle_visible(img_obj, elem_id, label_id) {
+ var elem = document.getElementById(elem_id)
+ if (!elem)
+ return (-1);
+
+ var old_state = !!!elem.className.match(/invisible/i);
+
+ if (label_id) {
+ var label = document.getElementById(label_id);
+ if (!label)
+ return (-1);
+ if (old_state)
+ label.innerHTML = 'Show';
+ else
+ label.innerHTML = 'Hide';
+ }
+
+ if (old_state) {
+ img_obj.src = 'arrow_right.png';
+ img_obj.alt = '[-]';
+ elem.className += ' invisible';
+ } else {
+ img_obj.src = 'arrow_down.png';
+ img_obj.alt = '[+]';
+ elem.className = elem.className.replace(/invisible/i,'');
+ }
+ return (0);
+}
+
function is_valid_int(str, min, max) {
if (str.match(/[^0-9 -]/))
return (0);
--- conga/luci/homebase/homebase_portlet_fetcher 2006/05/18 17:47:15 1.3
+++ conga/luci/homebase/homebase_portlet_fetcher 2006/11/16 19:34:53 1.3.2.1
@@ -3,10 +3,6 @@
<body>
-<tal:comment replace="nothing">
- $Id: homebase_portlet_fetcher,v 1.3 2006/05/18 17:47:15 rmccabe Exp $
-</tal:comment>
-
<metal:leftcolumn define-macro="left_column">
<span tal:omit-tag="">
<div tal:omit-tag="" metal:use-macro="here/portlet_homebase/macros/homebase_portlet" />
--- conga/luci/homebase/index_html 2006/10/31 17:28:04 1.18.2.1
+++ conga/luci/homebase/index_html 2006/11/16 19:34:53 1.18.2.2
@@ -14,10 +14,6 @@
tal:attributes="lang language;
xml:lang language">
-<tal:comment replace="nothing">
- $Id: index_html,v 1.18.2.1 2006/10/31 17:28:04 rmccabe Exp $
-</tal:comment>
-
<head metal:use-macro="here/header/macros/html_header">
<metal:fillbase fill-slot="base">
<metal:baseslot define-slot="base">
--- conga/luci/homebase/luci_homebase.css 2006/10/16 19:13:45 1.28
+++ conga/luci/homebase/luci_homebase.css 2006/11/16 19:34:53 1.28.2.1
@@ -380,6 +380,20 @@
padding: .5em;
}
+a.cluster_help:link,
+a.cluster_help:visited,
+a.cluster_help:visited {
+ color: #000000;
+ text-decoration: none ! important;
+}
+
+a.cluster_help:hover {
+ text-decoration: none ! important;
+ cursor: help;
+ color: #000000;
+ border-bottom: 1px solid #cccccc;
+}
+
a.cluster:link,
a.cluster:visited {
border-bottom: 1px dashed #cccccc;
--- conga/luci/homebase/portlet_homebase 2006/06/20 21:21:47 1.7
+++ conga/luci/homebase/portlet_homebase 2006/11/16 19:34:53 1.7.2.1
@@ -5,10 +5,6 @@
<body>
-<tal:comment replace="nothing">
- $Id: portlet_homebase,v 1.7 2006/06/20 21:21:47 rmccabe Exp $
-</tal:comment>
-
<div metal:define-macro="homebase_portlet">
<div class="type-node">
<dl class="portlet" id="portlet-homebase">
--- conga/luci/plone-custom/conga.js 2006/10/10 19:19:13 1.3
+++ conga/luci/plone-custom/conga.js 2006/11/16 19:34:53 1.3.2.1
@@ -8,5 +8,7 @@
function popup_window(url, width_percent, height_percent) {
var width = window.innerWidth * (width_percent / 100);
var height = window.innerHeight * (height_percent / 100);
- window.open('luci/doc', '', 'width=' + width + ',height=' + height + ',scrollbars,resizable', false);
+ var newwin = window.open(url, 'Conga Help', 'width=' + width + ',height=' + height + ',scrollbars,resizable', false);
+ if (newwin)
+ newwin.focus();
}
--- conga/luci/plone-custom/footer 2006/09/19 14:48:21 1.2
+++ conga/luci/plone-custom/footer 2006/11/16 19:34:53 1.2.2.1
@@ -6,7 +6,7 @@
<span i18n:translate="description_copyright" tal:omit-tag="">
The
<span>
- <a href="http://redhat.com">
+ <a href="http://www.sourceware.org/cluster/conga">
Conga Cluster and Storage Management System
</a>
</span>
@@ -19,7 +19,7 @@
i18n:name="current_year"
tal:define="now modules/DateTime/DateTime"
tal:content="now/year" />
- by <a href="http://redhat.com/Conga">Red Hat, Inc</a>
+ by <a href="http://www.redhat.com/">Red Hat, Inc</a>
</span>
</p>
--- conga/luci/site/luci/Extensions/FenceDaemon.py 2006/05/30 20:17:21 1.1
+++ conga/luci/site/luci/Extensions/FenceDaemon.py 2006/11/16 19:34:53 1.1.2.1
@@ -27,4 +27,10 @@
val = self.getAttribute("clean_start")
return val
+ def setPostJoinDelay(self, delay):
+ self.addAttribute("post_join_delay", delay)
+
+ def setPostFailDelay(self, delay):
+ self.addAttribute("post_fail_delay", delay)
+
--- conga/luci/site/luci/Extensions/FenceHandler.py 2006/10/16 19:58:38 1.4
+++ conga/luci/site/luci/Extensions/FenceHandler.py 2006/11/16 19:34:53 1.4.2.1
@@ -68,6 +68,8 @@
"fence_egenera":True,
"fence_bullpap":True,
"fence_drac":False,
+ "fence_xvm":True,
+ "fence_scsi":True,
"fence_ipmilan":False,
"fence_manual":False }
--- conga/luci/site/luci/Extensions/LuciSyslog.py 2006/10/31 17:28:04 1.2.2.2
+++ conga/luci/site/luci/Extensions/LuciSyslog.py 2006/11/16 19:34:53 1.2.2.3
@@ -3,14 +3,12 @@
LOG_DAEMON, LOG_PID, LOG_NDELAY, LOG_INFO, \
LOG_WARNING, LOG_AUTH, LOG_DEBUG
-"""Exception class for the LuciSyslog facility
-"""
+# Exception class for the LuciSyslog facility
class LuciSyslogError(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
-"""Facility that provides centralized syslog(3) functionality for luci
-"""
+# Facility that provides centralized syslog(3) functionality for luci
class LuciSyslog:
def __init__(self):
self.__init = 0
@@ -26,7 +24,8 @@
try:
syslog(LOG_INFO, msg)
except:
- raise LuciSyslogError, 'syslog info call failed'
+ pass
+ #raise LuciSyslogError, 'syslog info call failed'
def warn(self, msg):
if not self.__init:
@@ -34,7 +33,8 @@
try:
syslog(LOG_WARNING, msg)
except:
- raise LuciSyslogError, 'syslog warn call failed'
+ pass
+ #raise LuciSyslogError, 'syslog warn call failed'
def private(self, msg):
if not self.__init:
@@ -42,15 +42,30 @@
try:
syslog(LOG_AUTH, msg)
except:
- raise LuciSyslogError, 'syslog private call failed'
+ pass
+ #raise LuciSyslogError, 'syslog private call failed'
def debug_verbose(self, msg):
if not LUCI_DEBUG_MODE or LUCI_DEBUG_VERBOSITY < 2 or not self.__init:
return
- try:
- syslog(LOG_DEBUG, msg)
- except:
- raise LuciSyslogError, 'syslog debug call failed'
+
+ msg_len = len(msg)
+ if msg_len < 1:
+ return
+
+ while True:
+ cur_len = min(msg_len, 800)
+ cur_msg = msg[:cur_len]
+ try:
+ syslog(LOG_DEBUG, cur_msg)
+ except:
+ pass
+
+ msg_len -= cur_len
+ if msg_len > 0:
+ msg = msg[cur_len:]
+ else:
+ break
def debug(self, msg):
if not LUCI_DEBUG_MODE or not self.__init:
@@ -58,7 +73,8 @@
try:
syslog(LOG_DEBUG, msg)
except:
- raise LuciSyslogError, 'syslog debug call failed'
+ pass
+ #raise LuciSyslogError, 'syslog debug call failed'
def close(self):
try:
--- conga/luci/site/luci/Extensions/cluster_adapters.py 2006/10/31 17:28:04 1.120.2.8
+++ conga/luci/site/luci/Extensions/cluster_adapters.py 2006/11/16 19:34:53 1.120.2.9
@@ -1,11 +1,10 @@
import socket
from ModelBuilder import ModelBuilder
from xml.dom import minidom
-from ZPublisher import HTTPRequest
import AccessControl
from conga_constants import *
from ricci_bridge import *
-from ricci_communicator import *
+from ricci_communicator import RicciCommunicator, RicciError, batch_status, extract_module_status
from string import lower
import time
import Products.ManagedSystem
@@ -20,10 +19,11 @@
from Script import Script
from Samba import Samba
from clusterOS import resolveOSType
+from FenceHandler import FenceHandler, FENCE_OPTS
from GeneralError import GeneralError
from UnknownClusterError import UnknownClusterError
from homebase_adapters import nodeUnauth, nodeAuth, manageCluster, createClusterSystems, havePermCreateCluster, setNodeFlag, delNodeFlag, userAuthenticated, getStorageNode, getClusterNode
-from LuciSyslog import LuciSyslogError, LuciSyslog
+from LuciSyslog import LuciSyslog
#Policy for showing the cluster chooser menu:
#1) If there are no clusters in the ManagedClusterSystems
@@ -33,11 +33,9 @@
#then only display chooser if the current user has
#permissions on at least one. If the user is admin, show ALL clusters
-CLUSTER_FOLDER_PATH = '/luci/systems/cluster/'
-
try:
luci_log = LuciSyslog()
-except LuciSyslogError, e:
+except:
pass
def validateClusterNodes(request, sessionData, clusterName, numStorage):
@@ -114,7 +112,6 @@
def validateCreateCluster(self, request):
errors = list()
- messages = list()
requestResults = {}
if not havePermCreateCluster(self):
@@ -188,7 +185,7 @@
batchNode = createClusterBatch(cluster_os,
clusterName,
clusterName,
- map(lambda x: x['ricci_host'], nodeList),
+ map(lambda x: x['host'], nodeList),
True,
True,
enable_storage,
@@ -213,10 +210,10 @@
for i in nodeList:
success = True
try:
- rc = RicciCommunicator(i['ricci_host'])
+ rc = RicciCommunicator(i['host'])
except RicciError, e:
luci_log.debug('Unable to connect to the ricci agent on %s: %s'\
- % (i['ricci_host'], str(e)))
+ % (i['host'], str(e)))
success = False
except:
success = False
@@ -224,39 +221,48 @@
if success == True:
try:
resultNode = rc.process_batch(batchNode, async=True)
- batch_id_map[i['ricci_host']] = resultNode.getAttribute('batch_id')
+ batch_id_map[i['host']] = resultNode.getAttribute('batch_id')
except:
success = False
if not success:
nodeUnauth(nodeList)
cluster_properties['isComplete'] = False
- errors.append('An error occurred while attempting to add cluster node \"' + i['ricci_host'] + '\"')
+ errors.append('An error occurred while attempting to add cluster node \"' + i['host'] + '\"')
return (False, {'errors': errors, 'requestResults':cluster_properties })
buildClusterCreateFlags(self, batch_id_map, clusterName)
- messages.append('Creation of cluster \"' + clusterName + '\" has begun')
- return (True, {'errors': errors, 'messages': messages })
+ response = request.RESPONSE
+ response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clusterName + '&busyfirst=true')
def buildClusterCreateFlags(self, batch_map, clusterName):
- path = str(CLUSTER_FOLDER_PATH + clusterName)
- clusterfolder = self.restrictedTraverse(path)
- for key in batch_map.keys():
- key = str(key)
- id = batch_map[key]
- batch_id = str(id)
- objname = str(key + "____flag") #This suffix needed to avoid name collision
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #now designate this new object properly
- objpath = str(path + "/" + objname)
- flag = self.restrictedTraverse(objpath)
- #flag[BATCH_ID] = batch_id
- #flag[TASKTYPE] = CLUSTER_ADD
- #flag[FLAG_DESC] = "Creating node " + key + " for cluster " + clusterName
- flag.manage_addProperty(BATCH_ID,batch_id, "string")
- flag.manage_addProperty(TASKTYPE,CLUSTER_ADD, "string")
- flag.manage_addProperty(FLAG_DESC,"Creating node " + key + " for cluster " + clusterName, "string")
- flag.manage_addProperty(LAST_STATUS, 0, "int")
+ path = str(CLUSTER_FOLDER_PATH + clusterName)
+
+ try:
+ clusterfolder = self.restrictedTraverse(path)
+ except Exception, e:
+ luci_log.debug_verbose('buildCCF0: no cluster folder at %s' % path)
+ return None
+
+ for key in batch_map.keys():
+ try:
+ key = str(key)
+ batch_id = str(batch_map[key])
+ #This suffix needed to avoid name collision
+ objname = str(key + "____flag")
+
+ clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
+ #now designate this new object properly
+ objpath = str(path + "/" + objname)
+ flag = self.restrictedTraverse(objpath)
+
+ flag.manage_addProperty(BATCH_ID, batch_id, "string")
+ flag.manage_addProperty(TASKTYPE, CLUSTER_ADD, "string")
+ flag.manage_addProperty(FLAG_DESC, "Creating node " + key + " for cluster " + clusterName, "string")
+ flag.manage_addProperty(LAST_STATUS, 0, "int")
+ except Exception, e:
+ luci_log.debug_verbose('buildCCF1: error creating flag for %s: %s' \
+ % (key, str(e)))
def validateAddClusterNode(self, request):
errors = list()
@@ -264,7 +270,7 @@
requestResults = {}
try:
- sessionData = request.SESSION.get('checkRet')
+ sessionData = request.SESSION.get('checkRet')
except:
sessionData = None
@@ -333,7 +339,8 @@
while i < len(nodeList):
clunode = nodeList[i]
try:
- batchNode = addClusterNodeBatch(clusterName,
+ batchNode = addClusterNodeBatch(clunode['os'],
+ clusterName,
True,
True,
enable_storage,
@@ -346,7 +353,7 @@
clunode['errors'] = True
nodeUnauth(nodeList)
cluster_properties['isComplete'] = False
- errors.append('Unable to initiate node creation for host \"' + clunode['ricci_host'] + '\"')
+ errors.append('Unable to initiate node creation for host \"' + clunode['host'] + '\"')
if not cluster_properties['isComplete']:
return (False, {'errors': errors, 'requestResults': cluster_properties})
@@ -363,28 +370,29 @@
clunode = nodeList[i]
success = True
try:
- rc = RicciCommunicator(clunode['ricci_host'])
- except:
- luci_log.info('Unable to connect to the ricci daemon on host ' + clunode['ricci_host'])
+ rc = RicciCommunicator(clunode['host'])
+ except Exception, e:
+ luci_log.info('Unable to connect to the ricci daemon on host %s: %s'% (clunode['host'], str(e)))
success = False
if success:
try:
resultNode = rc.process_batch(batchNode, async=True)
- batch_id_map[clunode['ricci_host']] = resultNode.getAttribute('batch_id')
+ batch_id_map[clunode['host']] = resultNode.getAttribute('batch_id')
except:
success = False
if not success:
nodeUnauth(nodeList)
cluster_properties['isComplete'] = False
- errors.append('An error occurred while attempting to add cluster node \"' + clunode['ricci_host'] + '\"')
+ errors.append('An error occurred while attempting to add cluster node \"' + clunode['host'] + '\"')
return (False, {'errors': errors, 'requestResults': cluster_properties})
- messages.append('Cluster join initiated for host \"' + clunode['ricci_host'] + '\"')
-
+ messages.append('Cluster join initiated for host \"' + clunode['host'] + '\"')
buildClusterCreateFlags(self, batch_id_map, clusterName)
- return (True, {'errors': errors, 'messages': messages})
+
+ response = request.RESPONSE
+ response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clusterName + '&busyfirst=true')
def validateServiceAdd(self, request):
try:
@@ -420,16 +428,18 @@
form_hash[form_parent] = {'form': None, 'kids': []}
form_hash[form_parent]['kids'].append(form_id)
dummy_form = {}
+
for i in ielems:
try:
- type = str(i.getAttribute('type'))
+ input_type = str(i.getAttribute('type'))
except:
continue
- if not type or type == 'button':
+ if not input_type or input_type == 'button':
continue
try:
dummy_form[str(i.getAttribute('name'))] = str(i.getAttribute('value'))
- except:
+ except Exception, e:
+ luci_log.debug_verbose('Error parsing service XML: %s' % str(e))
pass
try:
@@ -469,7 +479,7 @@
raise Exception, 'An error occurred while adding this resource'
modelb = res[1]
newres = res[0]
- addResource(self, request, modelb, newres)
+ addResource(self, request, modelb, newres, res_type)
except Exception, e:
if len(errors) < 1:
errors.append('An error occurred while adding this resource')
@@ -480,35 +490,52 @@
## Cluster properties form validation routines
-def validateMCastConfig(self, form):
+# rhel5 cluster version
+def validateMCastConfig(model, form):
+ errors = list()
try:
mcast_val = form['mcast'].strip().lower()
if mcast_val != 'true' and mcast_val != 'false':
- raise KeyError(mcast_val)
+ raise KeyError, mcast_val
if mcast_val == 'true':
- mcast_val = 1
+ mcast_manual = True
else:
- mcast_val = 0
+ mcast_manual = False
except KeyError, e:
- return (False, {'errors': ['An invalid multicast selection was made.']})
+ errors.append('An invalid multicast selection was made')
+ return (False, {'errors': errors})
- if not mcast_val:
- return (True, {'messages': ['Changes accepted. - FILL ME IN']})
+ if mcast_manual == True:
+ try:
+ addr_str = form['mcast_addr'].strip()
+ socket.inet_pton(socket.AF_INET, addr_str)
+ except KeyError, e:
+ errors.append('No multicast address was given')
+ except socket.error, e:
+ try:
+ socket.inet_pton(socket.AF_INET6, addr_str)
+ except socket.error, e:
+ errors.append('An invalid multicast address was given: %s')
+ else:
+ addr_str = None
+
+ if (addr_str is None and mcast_manual != True) or (mcast_manual == True and addr_str == model.getMcastAddr()):
+ errors.append('No multicast configuration changes were made.')
+ return (False, {'errors': errors})
try:
- addr_str = form['mcast_addr'].strip()
- socket.inet_pton(socket.AF_INET, addr_str)
- except KeyError, e:
- return (False, {'errors': ['No multicast address was given']})
- except socket.error, e:
- try:
- socket.inet_pton(socket.AF_INET6, addr_str)
- except socket.error, e6:
- return (False, {'errors': ['An invalid multicast address was given: ' + e]})
+ model.usesMulticast = True
+ model.mcast_address = addr_str
+ except Exception, e:
+ luci_log.debug('Error updating mcast properties: %s' % str(e))
+ errors.append('Unable to update cluster multicast properties')
- return (True, {'messages': ['Changes accepted. - FILL ME IN']})
+ if len(errors) > 0:
+ return (False, {'errors': errors})
-def validateQDiskConfig(self, form):
+ return (True, {})
+
+def validateQDiskConfig(model, form):
errors = list()
try:
@@ -520,7 +547,7 @@
else:
qdisk_val = 0
except KeyError, e:
- return (False, {'errors': ['An invalid quorum partition selection was made.']})
+ return (False, {'errors': ['An invalid quorum partition selection was made']})
if not qdisk_val:
return (True, {'messages': ['Changes accepted. - FILL ME IN']})
@@ -528,64 +555,64 @@
try:
interval = int(form['interval'])
if interval < 0:
- raise ValueError('Interval must be 0 or greater.')
+ raise ValueError, 'Interval must be 0 or greater'
except KeyError, e:
- errors.append('No Interval value was given.')
+ errors.append('No Interval value was given')
except ValueError, e:
- errors.append('An invalid Interval value was given: ' + e)
+ errors.append('An invalid Interval value was given: %s' % str(e))
try:
votes = int(form['votes'])
if votes < 1:
- raise ValueError('Votes must be greater than 0')
+ raise ValueError, 'Votes must be greater than 0'
except KeyError, e:
- errors.append('No Votes value was given.')
+ errors.append('No Votes value was given')
except ValueError, e:
- errors.append('An invalid Votes value was given: ' + e)
+ errors.append('An invalid Votes value was given: %s' % str(e))
try:
tko = int(form['tko'])
if tko < 0:
- raise ValueError('TKO must be 0 or greater')
+ raise ValueError, 'TKO must be 0 or greater'
except KeyError, e:
- errors.append('No TKO value was given.')
+ errors.append('No TKO value was given')
except ValueError, e:
- errors.append('An invalid TKO value was given: ' + e)
+ errors.append('An invalid TKO value was given: %s' % str(e))
try:
min_score = int(form['min_score'])
if min_score < 1:
raise ValueError('Minimum Score must be greater than 0')
except KeyError, e:
- errors.append('No Minimum Score value was given.')
+ errors.append('No Minimum Score value was given')
except ValueError, e:
- errors.append('An invalid Minimum Score value was given: ' + e)
+ errors.append('An invalid Minimum Score value was given: %s' % str(e))
try:
device = form['device'].strip()
if not device:
- raise KeyError('device')
+ raise KeyError, 'device is none'
except KeyError, e:
- errors.append('No Device value was given.')
+ errors.append('No Device value was given')
try:
label = form['label'].strip()
if not label:
- raise KeyError('label')
+ raise KeyError, 'label is none'
except KeyError, e:
- errors.append('No Label value was given.')
+ errors.append('No Label value was given')
num_heuristics = 0
try:
num_heuristics = int(form['num_heuristics'])
if num_heuristics < 0:
- raise ValueError(form['num_heuristics'])
+ raise ValueError, 'invalid number of heuristics: %s' % form['num_heuristics']
if num_heuristics == 0:
num_heuristics = 1
except KeyError, e:
errors.append('No number of heuristics was given.')
except ValueError, e:
- errors.append('An invalid number of heuristics was given: ' + e)
+ errors.append('An invalid number of heuristics was given: %s' % str(e))
heuristics = list()
for i in xrange(num_heuristics):
@@ -600,40 +627,49 @@
(not prefix + 'hscore' in form or not form['hscore'].strip())):
# The row is blank; ignore it.
continue
- errors.append('No heuristic name was given for heuristic #' + str(i + 1))
+ errors.append('No heuristic name was given for heuristic #%d' % i + 1)
try:
hpath = form[prefix + 'hpath']
except KeyError, e:
- errors.append('No heuristic path was given for heuristic #' + str(i + 1))
+ errors.append('No heuristic path was given for heuristic #%d' % i + 1)
try:
hint = int(form[prefix + 'hint'])
if hint < 1:
- raise ValueError('Heuristic interval values must be greater than 0.')
+ raise ValueError, 'Heuristic interval values must be greater than 0'
except KeyError, e:
- errors.append('No heuristic interval was given for heuristic #' + str(i + 1))
+ errors.append('No heuristic interval was given for heuristic #%d' % i + 1)
except ValueError, e:
- errors.append('An invalid heuristic interval was given for heuristic #' + str(i + 1) + ': ' + e)
+ errors.append('An invalid heuristic interval was given for heuristic #%d: %s' % (i + 1, str(e)))
try:
hscore = int(form[prefix + 'score'])
if hscore < 1:
- raise ValueError('Heuristic scores must be greater than 0.')
+ raise ValueError, 'Heuristic scores must be greater than 0'
except KeyError, e:
- errors.append('No heuristic score was given for heuristic #' + str(i + 1))
+ errors.append('No heuristic score was given for heuristic #%d' % i + 1)
except ValueError, e:
- errors.append('An invalid heuristic score was given for heuristic #' + str(i + 1) + ': ' + e)
+ errors.append('An invalid heuristic score was given for heuristic #%d: %s' % (i + 1, str(e)))
heuristics.append([ hname, hpath, hint, hscore ])
if len(errors) > 0:
return (False, {'errors': errors })
return (True, {'messages': ['Changes accepted. - FILL ME IN']})
-def validateGeneralConfig(self, form):
+def validateGeneralConfig(model, form):
errors = list()
try:
+ cp = model.getClusterPtr()
+ old_name = model.getClusterAlias()
+ old_ver = int(cp.getConfigVersion())
+ except Exception, e:
+ luci_log.debug_verbose('getConfigVersion: %s' % str(e))
+ errors.append('unable to determine the current configuration version')
+ return (False, {'errors': errors})
+
+ try:
cluster_name = form['cluname'].strip()
if not cluster_name:
raise KeyError('cluname')
@@ -642,19 +678,29 @@
try:
version_num = int(form['cfgver'])
- if version_num < 0:
- raise ValueError('configuration version numbers must be 0 or greater.')
+ if version_num < old_ver:
+ raise ValueError, 'configuration version number must be %d or greater.' % old_ver
+ # we'll increment the cluster version before propagating it.
+ version_num -= 1
except KeyError, e:
errors.append('No cluster configuration version was given.')
except ValueError, e:
- errors.append('An invalid configuration version was given: ' + e)
+ errors.append('An invalid configuration version was given: %s' % str(e))
+
+ if len(errors) < 1:
+ try:
+ if cluster_name != old_name:
+ cp.addAttribute('alias', cluster_name)
+ cp.setConfigVersion(str(version_num))
+ except Exception, e:
+ luci_log.debug_verbose('unable to update general properties: %s' % str(e))
+ errors.append('Unable to update the cluster configuration.')
if len(errors) > 0:
return (False, {'errors': errors})
+ return (True, {})
- return (True, {'messages': ['Changes accepted. - FILL ME IN']})
-
-def validateFenceConfig(self, form):
+def validateFenceConfig(model, form):
errors = list()
try:
@@ -664,7 +710,7 @@
except KeyError, e:
errors.append('No post fail delay was given.')
except ValueError, e:
- errors.append('Invalid post fail delay: ' + e)
+ errors.append('Invalid post fail delay: %s' % str(e))
try:
post_join_delay = int(form['post_join_delay'])
@@ -673,12 +719,26 @@
except KeyError, e:
errors.append('No post join delay was given.')
except ValueError, e:
- errors.append('Invalid post join delay: ' + e)
+ errors.append('Invalid post join delay: %s' % str(e))
+
+ try:
+ fd = model.getFenceDaemonPtr()
+ old_pj_delay = fd.getPostJoinDelay()
+ old_pf_delay = fd.getPostFailDelay()
+
+ if post_join_delay == old_pj_delay and post_fail_delay == old_pf_delay:
+ errors.append('No fence daemon properties were changed.')
+ else:
+ fd.setPostJoinDelay(str(post_join_delay))
+ fd.setPostFailDelay(str(post_fail_delay))
+ except Exception, e:
+ luci_log.debug_verbose('Unable to update fence daemon properties: %s' % str(e))
+ errors.append('An error occurred while attempting to update fence daemon properties.')
if len(errors) > 0:
return (False, {'errors': errors })
- return (True, {'messages': ['Changes accepted. - FILL ME IN']})
+ return (True, {})
configFormValidators = {
'general': validateGeneralConfig,
@@ -690,27 +750,111 @@
def validateConfigCluster(self, request):
errors = list()
messages = list()
+ rc = None
+
+ try:
+ model = request.SESSION.get('model')
+ if not model:
+ raise Exception, 'model is none'
+ except Exception, e:
+ model = None
+ try:
+ cluname = request.form['clustername']
+ except:
+ try:
+ cluname = request['clustername']
+ except:
+ luci_log.debug_verbose('VCC0a: no model, no cluster name')
+ return (False, {'errors': ['No cluster model was found.']})
- if not 'form' in request:
- return (False, {'errors': ['No form was submitted.']})
- if not 'configtype' in request.form:
+ try:
+ model = getModelForCluster(self, cluname)
+ except:
+ model = None
+
+ if model is None:
+ luci_log.debug_verbose('VCC0: unable to get model from session')
+ return (False, {'errors': ['No cluster model was found.']})
+ try:
+ if not 'configtype' in request.form:
+ luci_log.debug_verbose('VCC2: no configtype')
+ raise Exception, 'no config type'
+ except Exception, e:
+ luci_log.debug_verbose('VCC2a: %s' % str(e))
return (False, {'errors': ['No configuration type was submitted.']})
+
if not request.form['configtype'] in configFormValidators:
+ luci_log.debug_verbose('VCC3: invalid config type: %s' % request.form['configtype'])
return (False, {'errors': ['An invalid configuration type was submitted.']})
- val = configFormValidators[request.form['configtype']]
- ret = val(self, request.form)
+ try:
+ cp = model.getClusterPtr()
+ except:
+ luci_log.debug_verbose('VCC3a: getClusterPtr failed')
+ return (False, {'errors': ['No cluster model was found.']})
+
+ config_validator = configFormValidators[request.form['configtype']]
+ ret = config_validator(model, request.form)
retcode = ret[0]
if 'errors' in ret[1]:
errors.extend(ret[1]['errors'])
+
if 'messages' in ret[1]:
messages.extend(ret[1]['messages'])
+ if retcode == True:
+ try:
+ config_ver = int(cp.getConfigVersion()) + 1
+ # always increment the configuration version
+ cp.setConfigVersion(str(config_ver))
+ model.setModified(True)
+ conf_str = model.exportModelAsString()
+ if not conf_str:
+ raise Exception, 'conf_str is none'
+ except Exception, e:
+ luci_log.debug_verbose('VCC4: export model as string failed: %s' \
+ % str(e))
+ errors.append('Unable to store the new cluster configuration')
+
+ try:
+ clustername = model.getClusterName()
+ if not clustername:
+ raise Exception, 'cluster name from modelb.getClusterName() is blank'
+ except Exception, e:
+ luci_log.debug_verbose('VCC5: error: getClusterName: %s' % str(e))
+ errors.append('Unable to determine cluster name from model')
+
+ if len(errors) > 0:
+ return (retcode, {'errors': errors, 'messages': messages})
+
+ if not rc:
+ rc = getRicciAgent(self, clustername)
+ if not rc:
+ luci_log.debug_verbose('VCC6: unable to find a ricci agent for the %s cluster' % clustername)
+ errors.append('Unable to contact a ricci agent for cluster %s' \
+ % clustername)
+
+ if rc:
+ batch_id, result = setClusterConf(rc, str(conf_str))
+ if batch_id is None or result is None:
+ luci_log.debug_verbose('VCC7: setCluserConf: batchid or result is None')
+ errors.append('Unable to propagate the new cluster configuration for %s' \
+ % clustername)
+ else:
+ try:
+ set_node_flag(self, clustername, rc.hostname(), batch_id,
+ CLUSTER_CONFIG, 'Updating cluster configuration')
+ except:
+ pass
+
if len(errors) < 1:
messages.append('The cluster properties have been updated.')
+ else:
+ return (retcode, {'errors': errors, 'messages': messages})
- return (retcode, {'errors': errors, 'messages': messages})
+ response = request.RESPONSE
+ response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clustername + '&busyfirst=true')
def validateFenceAdd(self, request):
return (True, {})
@@ -718,6 +862,89 @@
def validateFenceEdit(self, request):
return (True, {})
+def validateDaemonProperties(self, request):
+ errors = list()
+
+ form = None
+ try:
+ response = request.response
+ form = request.form
+ if not form:
+ form = None
+ raise Exception, 'no form was submitted'
+ except:
+ pass
+
+ if form is None:
+ luci_log.debug_verbose('VDP0: no form was submitted')
+ return (False, {'errors': ['No form was submitted']})
+
+ try:
+ nodename = form['nodename'].strip()
+ if not nodename:
+ raise Exception, 'nodename is blank'
+ except Exception, e:
+ errors.append('Unable to determine the current node name')
+ luci_log.debug_verbose('VDP1: no nodename: %s' % str(e))
+
+ try:
+ clustername = form['clustername'].strip()
+ if not clustername:
+ raise Exception, 'clustername is blank'
+ except Exception, e:
+ errors.append('Unable to determine the current cluster name')
+ luci_log.debug_verbose('VDP2: no clustername: %s' % str(e))
+
+ disable_list = list()
+ enable_list = list()
+ for i in form.items():
+ try:
+ if i[0][:11] == '__daemon__:':
+ daemon_prop = i[1]
+ if len(daemon_prop) == 2:
+ if daemon_prop[1] == '1':
+ disable_list.append(daemon_prop[0])
+ else:
+ if daemon_prop[1] == '0' and daemon_prop[2] == 'on':
+ enable_list.append(daemon_prop[0])
+ except Exception, e:
+ luci_log.debug_verbose('VDP3: error: %s' % str(i))
+
+ if len(enable_list) < 1 and len(disable_list) < 1:
+ luci_log.debug_verbose('VDP4: no changes made')
+ response.redirect(request['URL'] + "?pagetype=" + NODE + "&clustername=" + clustername + '&nodename=' + nodename)
+
+ nodename_resolved = resolve_nodename(self, clustername, nodename)
+ try:
+ rc = RicciCommunicator(nodename_resolved)
+ if not rc:
+ raise Exception, 'rc is None'
+ except Exception, e:
+ luci_log.debug_verbose('VDP5: RC %s: %s' % (nodename_resolved, str(e)))
+ errors.append('Unable to connect to the ricci agent on %s to update cluster daemon properties' % nodename_resolved)
+ return (False, {'errors': errors})
+
+ batch_id, result = updateServices(rc, enable_list, disable_list)
+ if batch_id is None or result is None:
+ luci_log.debug_verbose('VDP6: setCluserConf: batchid or result is None')
+ errors.append('Unable to update the cluster daemon properties on node %s' % nodename_resolved)
+ return (False, {'errors': errors})
+
+ try:
+ status_msg = 'Updating %s daemon properties:' % nodename_resolved
+ if len(enable_list) > 0:
+ status_msg += ' enabling %s' % str(enable_list)[1:-1]
+ if len(disable_list) > 0:
+ status_msg += ' disabling %s' % str(disable_list)[1:-1]
+ set_node_flag(self, clustername, rc.hostname(), batch_id, CLUSTER_DAEMON, status_msg)
+ except:
+ pass
+
+ if len(errors) > 0:
+ return (False, {'errors': errors})
+
+ response.redirect(request['URL'] + "?pagetype=" + NODE + "&clustername=" + clustername + '&nodename=' + nodename + '&busyfirst=true')
+
formValidators = {
6: validateCreateCluster,
7: validateConfigCluster,
@@ -728,11 +955,18 @@
33: validateResourceAdd,
51: validateFenceAdd,
50: validateFenceEdit,
+ 55: validateDaemonProperties
}
def validatePost(self, request):
- pagetype = int(request.form['pagetype'])
+ try:
+ pagetype = int(request.form['pagetype'])
+ except Exception, e:
+ luci_log.debug_verbose('VP0: error: %s' % str(e))
+ return None
+
if not pagetype in formValidators:
+ luci_log.debug_verbose('VP1: no handler for page type %d' % pagetype)
return None
else:
return formValidators[pagetype](self, request)
@@ -748,21 +982,23 @@
except:
request.SESSION.set('checkRet', {})
else:
- try: request.SESSION.set('checkRet', {})
- except: pass
+ try:
+ request.SESSION.set('checkRet', {})
+ except:
+ pass
#First, see if a cluster is chosen, then
#check that the current user can access that system
cname = None
try:
cname = request[CLUNAME]
- except KeyError, e:
+ except:
cname = ""
try:
url = request['URL']
- except KeyError, e:
- url = "."
+ except:
+ url = "/luci/cluster/index_html"
try:
pagetype = request[PAGETYPE]
@@ -811,7 +1047,7 @@
clcfg['show_children'] = False
#loop through all clusters
- syslist= list()
+ syslist = list()
for system in systems:
clsys = {}
clsys['Title'] = system[0]
@@ -839,20 +1075,30 @@
return dummynode
+def getnodes(self, model):
+ mb = model
+ nodes = mb.getNodes()
+ names = list()
+ for node in nodes:
+ names.append(node.getName())
+ return names
def createCluConfigTree(self, request, model):
dummynode = {}
+ if not model:
+ return {}
+
#There should be a positive page type
try:
pagetype = request[PAGETYPE]
- except KeyError, e:
+ except:
pagetype = '3'
try:
url = request['URL']
except KeyError, e:
- url = "."
+ url = "/luci/cluster/index_html"
#The only way this method can run is if there exists
#a clustername query var
@@ -1110,7 +1356,7 @@
kids.append(rvadd)
kids.append(rvcfg)
rv['children'] = kids
- #################################################################
+ ################################################################
fd = {}
fd['Title'] = "Failover Domains"
fd['cfg_type'] = "failoverdomains"
@@ -1266,8 +1512,10 @@
return model.getClusterName()
def getClusterAlias(self, model):
+ if not model:
+ return ''
alias = model.getClusterAlias()
- if alias == None:
+ if alias is None:
return model.getClusterName()
else:
return alias
@@ -1281,6 +1529,7 @@
portaltabs = list()
if not userAuthenticated(self):
return portaltabs
+
selectedtab = "homebase"
try:
baseurl = req['URL']
@@ -1291,12 +1540,7 @@
else:
selectedtab = "homebase"
except KeyError, e:
- pass
-
- try:
- base2 = req['BASE2']
- except KeyError, e:
- base2 = req['HTTP_HOST'] + req['SERVER_PORT']
+ selectedtab = None
htab = { 'Title':"homebase",
'Description':"Home base for this luci server",
@@ -1309,7 +1553,7 @@
ctab = { 'Title':"cluster",
'Description':"Cluster configuration page",
- 'Taburl':"/luci/cluster?pagetype=3"}
+ 'Taburl':"/luci/cluster/index_html?pagetype=3"}
if selectedtab == "cluster":
ctab['isSelected'] = True
else:
@@ -1331,7 +1575,7 @@
-def check_clusters(self,clusters):
+def check_clusters(self, clusters):
clist = list()
for cluster in clusters:
if cluster_permission_check(cluster[1]):
@@ -1357,15 +1601,15 @@
try:
clusterfolder = self.restrictedTraverse(path)
if not clusterfolder:
- luci_log.debug('GRA: cluster folder %s for %s is missing.' \
+ luci_log.debug('GRA0: cluster folder %s for %s is missing.' \
% (path, clustername))
raise Exception, 'no cluster folder at %s' % path
nodes = clusterfolder.objectItems('Folder')
if len(nodes) < 1:
- luci_log.debug('GRA: no cluster nodes for %s found.' % clustername)
+ luci_log.debug('GRA1: no cluster nodes for %s found.' % clustername)
raise Exception, 'no cluster nodes were found at %s' % path
except Exception, e:
- luci_log.debug('GRA: cluster folder %s for %s is missing: %s.' \
+ luci_log.debug('GRA2: cluster folder %s for %s is missing: %s.' \
% (path, clustername, str(e)))
return None
@@ -1383,17 +1627,31 @@
try:
rc = RicciCommunicator(hostname)
except RicciError, e:
- luci_log.debug('GRA: ricci error: %s' % str(e))
+ luci_log.debug('GRA3: ricci error: %s' % str(e))
continue
try:
clu_info = rc.cluster_info()
except Exception, e:
- luci_log.debug('GRA: cluster_info error: %s' % str(e))
+ luci_log.debug('GRA4: cluster_info error: %s' % str(e))
+
+ try:
+ cur_name = str(clu_info[0]).strip().lower()
+ if not cur_name:
+ raise
+ except:
+ cur_name = None
- if cluname != lower(clu_info[0]) and cluname != lower(clu_info[1]):
+ try:
+ cur_alias = str(clu_info[1]).strip().lower()
+ if not cur_alias:
+ raise
+ except:
+ cur_alias = None
+
+ if (cur_name is not None and cluname != cur_name) and (cur_alias is not None and cluname != cur_alias):
try:
- luci_log.debug('GRA: %s reports it\'s in cluster %s:%s; we expect %s' \
+ luci_log.debug('GRA5: %s reports it\'s in cluster %s:%s; we expect %s' \
% (hostname, clu_info[0], clu_info[1], cluname))
setNodeFlag(self, node, CLUSTER_NODE_NOT_MEMBER)
except:
@@ -1407,29 +1665,43 @@
except:
pass
- luci_log.debug('GRA: no ricci agent could be found for cluster %s' % cluname)
+ luci_log.debug('GRA6: no ricci agent could be found for cluster %s' \
+ % cluname)
return None
def getRicciAgentForCluster(self, req):
+ clustername = None
try:
clustername = req['clustername']
- except KeyError, e:
+ if not clustername:
+ clustername = None
+ raise
+ except:
try:
clustername = req.form['clusterName']
if not clustername:
- raise
+ clustername = None
except:
- luci_log.debug('no cluster name was specified in getRicciAgentForCluster')
- return None
+ pass
+
+ if clustername is None:
+ luci_log.debug('GRAFC0: no cluster name was found')
+ return None
return getRicciAgent(self, clustername)
def getClusterStatus(self, rc):
- doc = getClusterStatusBatch(rc)
+ try:
+ doc = getClusterStatusBatch(rc)
+ except Exception, e:
+ luci_log.debug_verbose('GCS0: error: %s' % str(e))
+ doc = None
+
if not doc:
try:
- luci_log.debug_verbose('getClusterStatusBatch returned None for %s/%s' % rc.cluster_info())
+ luci_log.debug_verbose('GCS1: returned None for %s/%s' % rc.cluster_info())
except:
pass
+
return {}
results = list()
@@ -1477,18 +1749,18 @@
baseurl = req['URL']
if not baseurl:
raise KeyError, 'is blank'
- except KeyError, e:
- baseurl = '.'
+ except:
+ baseurl = '/luci/cluster/index_html'
try:
cluname = req['clustername']
if not cluname:
raise KeyError, 'is blank'
- except KeyError, e:
+ except:
try:
cluname = req.form['clusterName']
if not cluname:
- raise
+ raise KeyError, 'is blank'
except:
cluname = '[error retrieving cluster name]'
@@ -1504,7 +1776,7 @@
svc = modelb.retrieveServiceByName(item['name'])
dom = svc.getAttribute("domain")
- if dom != None:
+ if dom is not None:
itemmap['faildom'] = dom
else:
itemmap['faildom'] = "No Failover Domain"
@@ -1522,8 +1794,8 @@
baseurl = req['URL']
if not baseurl:
raise KeyError, 'is blank'
- except KeyError, e:
- baseurl = '.'
+ except:
+ baseurl = '/luci/cluster/index_html'
try:
cluname = req['clustername']
@@ -1588,7 +1860,7 @@
#first get service by name from model
svc = modelb.getService(servicename)
resource_list = list()
- if svc != None:
+ if svc is not None:
indent_ctr = 0
children = svc.getChildren()
for child in children:
@@ -1603,7 +1875,7 @@
#Call yourself on every children
#then return
rc_map = {}
- if parent != None:
+ if parent is not None:
rc_map['parent'] = parent
rc_map['name'] = child.getName()
if child.isRefObject() == True:
@@ -1631,22 +1903,27 @@
return child_depth + 1
def serviceStart(self, rc, req):
+ svcname = None
try:
svcname = req['servicename']
- except KeyError, e:
+ except:
try:
svcname = req.form['servicename']
except:
- luci_log.debug_verbose('serviceStart error: no service name')
- return None
+ pass
+
+ if svcname is None:
+ luci_log.debug_verbose('serviceStart0: no service name')
+ return None
+ nodename = None
try:
nodename = req['nodename']
- except KeyError, e:
+ except:
try:
nodename = req.form['nodename']
except:
- nodename = None
+ pass
cluname = None
try:
@@ -1658,52 +1935,38 @@
pass
if cluname is None:
- luci_log.debug_verbose('serviceStart error: %s no service name' \
+ luci_log.debug_verbose('serviceStart2: no cluster name for svc %s' \
% svcname)
return None
- ricci_agent = rc.hostname()
-
batch_number, result = startService(rc, svcname, nodename)
if batch_number is None or result is None:
- luci_log.debug_verbose('startService %s call failed' \
- % svcname)
+ luci_log.debug_verbose('startService3: SS(%s,%s,%s) call failed' \
+ % (svcname, cluname, nodename))
return None
- #Now we need to create a DB flag for this system.
- path = str(CLUSTER_FOLDER_PATH + cluname)
- batch_id = str(batch_number)
- objname = str(ricci_agent + "____flag")
-
try:
- clusterfolder = self.restrictedTraverse(path)
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- objpath = str(path + "/" + objname)
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, SERVICE_START, "string")
- flag.manage_addProperty(FLAG_DESC, "Starting service \'" + svcname + "\'", "string")
+ set_node_flag(self, cluname, rc.hostname(), str(batch_number), SERVICE_START, "Starting service \'%s\'" % svcname)
except Exception, e:
- luci_log.debug_verbose('Error creating flag at %s: %s' % (objpath, str(e)))
+ luci_log.debug_verbose('startService4: error setting flags for service %s at node %s for cluster %s' % (svcname, nodename, cluname))
response = req.RESPONSE
- response.redirect(req['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(req['URL'] + "?pagetype=" + SERVICE_LIST + "&clustername=" + cluname + '&busyfirst=true')
def serviceRestart(self, rc, req):
+ svcname = None
try:
svcname = req['servicename']
- except KeyError, e:
+ except:
try:
svcname = req.form['servicename']
except:
- luci_log.debug_verbose('no service name for serviceRestart')
- return None
- except:
- luci_log.debug_verbose('no service name for serviceRestart')
+ pass
+
+ if svcname is None:
+ luci_log.debug_verbose('serviceRestart0: no service name')
return None
- #Now we need to create a DB flag for this system.
cluname = None
try:
cluname = req['clustername']
@@ -1714,51 +1977,36 @@
pass
if cluname is None:
- luci_log.debug_verbose('unable to determine cluser name for serviceRestart %s' % svcname)
+ luci_log.debug_verbose('serviceRestart1: no cluster for %s' % svcname)
return None
batch_number, result = restartService(rc, svcname)
if batch_number is None or result is None:
- luci_log.debug_verbose('restartService for %s failed' % svcname)
+ luci_log.debug_verbose('serviceRestart2: %s failed' % svcname)
return None
- ricci_agent = rc.hostname()
-
- path = str(CLUSTER_FOLDER_PATH + cluname)
- batch_id = str(batch_number)
- objname = str(ricci_agent + "____flag")
-
try:
- clusterfolder = self.restrictedTraverse(path)
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
-
- #Now we need to annotate the new DB object
- objpath = str(path + "/" + objname)
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, SERVICE_RESTART, "string")
- flag.manage_addProperty(FLAG_DESC, "Restarting service " + svcname, "string")
+ set_node_flag(self, cluname, rc.hostname(), str(batch_number), SERVICE_RESTART, "Restarting service \'%s\'" % svcname)
except Exception, e:
- luci_log.debug_verbose('Error creating flag in restartService %s: %s' \
- % (svcname, str(e)))
+ luci_log.debug_verbose('serviceRestart3: error setting flags for service %s for cluster %s' % (svcname, cluname))
response = req.RESPONSE
- response.redirect(req['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(req['URL'] + "?pagetype=" + SERVICE_LIST + "&clustername=" + cluname + '&busyfirst=true')
def serviceStop(self, rc, req):
+ svcname = None
try:
svcname = req['servicename']
- except KeyError, e:
+ except:
try:
svcname = req.form['servicename']
except:
- luci_log.debug_verbose('no service name for serviceStop')
- return None
- except:
- luci_log.debug_verbose('no service name for serviceStop')
+ pass
+
+ if svcname is None:
+ luci_log.debug_verbose('serviceStop0: no service name')
return None
- #Now we need to create a DB flag for this system.
cluname = None
try:
cluname = req['clustername']
@@ -1769,37 +2017,21 @@
pass
if cluname is None:
- luci_log.debug_verbose('unable to determine cluser name for serviceStop %s' % svcname)
+ luci_log.debug_verbose('serviceStop1: no cluster name for %s' % svcname)
return None
batch_number, result = stopService(rc, svcname)
if batch_number is None or result is None:
- luci_log.debug_verbose('stopService for %s failed' % svcname)
+ luci_log.debug_verbose('serviceStop2: stop %s failed' % svcname)
return None
- ricci_agent = rc.hostname()
-
- path = str(CLUSTER_FOLDER_PATH + cluname)
- batch_id = str(batch_number)
- objname = str(ricci_agent + "____flag")
-
try:
- clusterfolder = self.restrictedTraverse(path)
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- objpath = str(path + "/" + objname)
- flag = self.restrictedTraverse(objpath)
-
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, SERVICE_STOP, "string")
- flag.manage_addProperty(FLAG_DESC, "Stopping service " + svcname, "string")
- time.sleep(2)
+ set_node_flag(self, cluname, rc.hostname(), str(batch_number), SERVICE_STOP, "Stopping service \'%s\'" % svcname)
except Exception, e:
- luci_log.debug_verbose('Error creating flags for stopService %s: %s' \
- % (svcname, str(e)))
+ luci_log.debug_verbose('serviceStop3: error setting flags for service %s for cluster %s' % (svcname, cluname))
response = req.RESPONSE
- response.redirect(req['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(req['URL'] + "?pagetype=" + SERVICE_LIST + "&clustername=" + cluname + '&busyfirst=true')
def getFdomsInfo(self, modelb, request, clustatus):
slist = list()
@@ -1820,11 +2052,11 @@
fdom_map['cfgurl'] = baseurl + "?pagetype=" + FDOM_LIST + "&clustername=" + clustername
ordered_attr = fdom.getAttribute('ordered')
restricted_attr = fdom.getAttribute('restricted')
- if ordered_attr != None and (ordered_attr == "true" or ordered_attr == "1"):
+ if ordered_attr is not None and (ordered_attr == "true" or ordered_attr == "1"):
fdom_map['ordered'] = True
else:
fdom_map['ordered'] = False
- if restricted_attr != None and (restricted_attr == "true" or restricted_attr == "1"):
+ if restricted_attr is not None and (restricted_attr == "true" or restricted_attr == "1"):
fdom_map['restricted'] = True
else:
fdom_map['restricted'] = False
@@ -1845,7 +2077,7 @@
else:
nodesmap['status'] = NODE_INACTIVE
priority_attr = node.getAttribute('priority')
- if priority_attr != None:
+ if priority_attr is not None:
nodesmap['priority'] = "0"
nodelist.append(nodesmap)
fdom_map['nodeslist'] = nodelist
@@ -1858,7 +2090,7 @@
break #found more info about service...
domain = svc.getAttribute("domain")
- if domain != None:
+ if domain is not None:
if domain == fdom.getName():
svcmap = {}
svcmap['name'] = svcname
@@ -1870,54 +2102,87 @@
fdomlist.append(fdom_map)
return fdomlist
-def processClusterProps(self, ricci_agent, request):
- #First, retrieve cluster.conf from session
- conf = request.SESSION.get('conf')
- model = ModelBuilder(0, None, None, conf)
-
- #Next, determine actiontype and switch on it
- actiontype = request[ACTIONTYPE]
-
- if actiontype == BASECLUSTER:
- cp = model.getClusterPtr()
- cfgver = cp.getConfigVersion()
-
- rcfgver = request['cfgver']
-
- if cfgver != rcfgver:
- cint = int(cfgver)
- rint = int(rcfgver)
- if rint > cint:
- cp.setConfigVersion(rcfgver)
-
- rname = request['cluname']
- name = model.getClusterAlias()
+def clusterTaskProcess(self, model, request):
+ try:
+ task = request['task']
+ except:
+ try:
+ task = request.form['task']
+ except:
+ luci_log.debug_verbose('CTP1: no task specified')
+ task = None
- if rname != name:
- cp.addAttribute('alias', rname)
+ if not model:
+ try:
+ cluname = request['clustername']
+ if not cluname:
+ raise Exception, 'cluname is blank'
+ except:
+ try:
+ cluname = request.form['clustername']
+ if not cluname:
+ raise Exception, 'cluname is blank'
+ except:
+ luci_log.debug_verbose('CTP0: no model/no cluster name')
+ return 'Unable to determine the cluster name.'
+ try:
+ model = getModelForCluster(self, cluname)
+ except Exception, e:
+ luci_log.debug_verbose('CPT1: GMFC failed for %s' % cluname)
+ model = None
- response = request.RESPONSE
- response.redirect(request['HTTP_REFERER'] + "&busyfirst=true")
- return
+ if not model:
+ return 'Unable to get the model object for %s' % cluname
- elif actiontype == FENCEDAEMON:
- pass
+ if task == CLUSTER_STOP:
+ clusterStop(self, model)
+ elif task == CLUSTER_START:
+ clusterStart(self, model)
+ elif task == CLUSTER_RESTART:
+ clusterRestart(self, model)
+ elif task == CLUSTER_DELETE:
+ clusterStop(self, model, delete=True)
+ else:
+ return 'An unknown cluster task was requested.'
- elif actiontype == MULTICAST:
- pass
+ response = request.RESPONSE
+ response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
+ % (request['URL'], NODES, model.getClusterName()))
- elif actiontype == QUORUMD:
- pass
+def getClusterInfo(self, model, req):
+ try:
+ cluname = req[CLUNAME]
+ except:
+ try:
+ cluname = req.form['clustername']
+ except:
+ try:
+ cluname = req.form['clusterName']
+ except:
+ luci_log.debug_verbose('GCI0: unable to determine cluster name')
+ return {}
- else:
- 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())
+ 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))
+ except Exception, e:
+ luci_log.debug_verbose('GCI3: unable to get model for cluster %s: %s' % (cluname, str(e)))
+ return {}
-def getClusterInfo(self, model, req):
- cluname = req[CLUNAME]
- baseurl = req['URL'] + "?" + PAGETYPE + "=" + CLUSTER_PROCESS + "&" + CLUNAME + "=" + cluname + "&"
+ prop_baseurl = req['URL'] + '?' + PAGETYPE + '=' + CLUSTER_CONFIG + '&' + CLUNAME + '=' + cluname + '&'
map = {}
- basecluster_url = baseurl + ACTIONTYPE + "=" + BASECLUSTER
+ basecluster_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_GENERAL_TAB
#needed:
map['basecluster_url'] = basecluster_url
#name field
@@ -1929,14 +2194,14 @@
#new cluster params - if rhel5
#-------------
#Fence Daemon Props
- fencedaemon_url = baseurl + ACTIONTYPE + "=" + FENCEDAEMON
+ fencedaemon_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_FENCE_TAB
map['fencedaemon_url'] = fencedaemon_url
fdp = model.getFenceDaemonPtr()
pjd = fdp.getAttribute('post_join_delay')
- if pjd == None:
+ if pjd is None:
pjd = "6"
pfd = fdp.getAttribute('post_fail_delay')
- if pfd == None:
+ if pfd is None:
pfd = "0"
#post join delay
map['pjd'] = pjd
@@ -1944,7 +2209,7 @@
map['pfd'] = pfd
#-------------
#if multicast
- multicast_url = baseurl + ACTIONTYPE + "=" + MULTICAST
+ multicast_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_MCAST_TAB
map['multicast_url'] = multicast_url
#mcast addr
is_mcast = model.isMulticast()
@@ -1958,7 +2223,7 @@
#-------------
#quorum disk params
- quorumd_url = baseurl + ACTIONTYPE + "=" + QUORUMD
+ quorumd_url = prop_baseurl + PROPERTIES_TAB + "=" + PROP_QDISK_TAB
map['quorumd_url'] = quorumd_url
is_quorumd = model.isQuorumd()
map['is_quorumd'] = is_quorumd
@@ -1975,27 +2240,27 @@
if is_quorumd:
qdp = model.getQuorumdPtr()
interval = qdp.getAttribute('interval')
- if interval != None:
+ if interval is not None:
map['interval'] = interval
tko = qdp.getAttribute('tko')
- if tko != None:
+ if tko is not None:
map['tko'] = tko
votes = qdp.getAttribute('votes')
- if votes != None:
+ if votes is not None:
map['votes'] = votes
min_score = qdp.getAttribute('min_score')
- if min_score != None:
+ if min_score is not None:
map['min_score'] = min_score
device = qdp.getAttribute('device')
- if device != None:
+ if device is not None:
map['device'] = device
label = qdp.getAttribute('label')
- if label != None:
+ if label is not None:
map['label'] = label
heuristic_kids = qdp.getChildren()
@@ -2003,24 +2268,24 @@
for kid in heuristic_kids:
hmap = {}
hname = kid.getAttribute('name')
- if hname == None:
+ if hname is None:
hname = h_ctr
h_ctr = h_ctr + 1
hprog = kid.getAttribute('program')
hscore = kid.getAttribute('score')
hinterval = kid.getAttribute('interval')
- if hprog == None:
+ if hprog is None:
continue
- if hname != None:
+ if hname is not None:
hmap['hname'] = hname
else:
hmap['hname'] = ""
hmap['hprog'] = hprog
- if hscore != None:
+ if hscore is not None:
hmap['hscore'] = hscore
else:
hmap['hscore'] = ""
- if hinterval != None:
+ if hinterval is not None:
hmap['hinterval'] = hinterval
else:
hmap['hinterval'] = ""
@@ -2029,7 +2294,7 @@
return map
-def getClustersInfo(self,status,req):
+def getClustersInfo(self, status, req):
map = {}
nodelist = list()
svclist = list()
@@ -2062,6 +2327,12 @@
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
+ map['stop_url'] = baseurl + "?" + PAGETYPE + "=" + CLUSTER_PROCESS + "&" + CLUNAME + "=" + clustername + '&task=' + CLUSTER_STOP
+ map['start_url'] = baseurl + "?" + PAGETYPE + "=" + CLUSTER_PROCESS + "&" + CLUNAME + "=" + clustername + '&task=' + CLUSTER_START
+ map['delete_url'] = baseurl + "?" + PAGETYPE + "=" + CLUSTER_PROCESS + "&" + CLUNAME + "=" + clustername + '&task=' + CLUSTER_DELETE
+
svc_dict_list = list()
for svc in svclist:
svc_dict = {}
@@ -2093,6 +2364,317 @@
return map
+def nodeLeave(self, rc, clustername, nodename_resolved):
+ path = str(CLUSTER_FOLDER_PATH + clustername + '/' + nodename_resolved)
+
+ try:
+ nodefolder = self.restrictedTraverse(path)
+ if not nodefolder:
+ raise Exception, 'cannot find database object at %s' % path
+ except Exception, e:
+ luci_log.debug('NLO: node_leave_cluster err: %s' % str(e))
+ return None
+
+ objname = str(nodename_resolved + "____flag")
+ fnpresent = noNodeFlagsPresent(self, nodefolder, objname, nodename_resolved)
+
+ if fnpresent is None:
+ luci_log.debug('NL1: An error occurred while checking flags for %s' \
+ % nodename_resolved)
+ return None
+
+ if fnpresent == False:
+ luci_log.debug('NL2: flags are still present for %s -- bailing out' \
+ % nodename_resolved)
+ return None
+
+ batch_number, result = nodeLeaveCluster(rc)
+ if batch_number is None or result is None:
+ luci_log.debug_verbose('NL3: nodeLeaveCluster error: batch_number and/or result is None')
+ return None
+
+ try:
+ set_node_flag(self, clustername, rc.hostname(), str(batch_number), NODE_LEAVE_CLUSTER, "Node \'%s\' leaving cluster" % nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('NL4: failed to set flags: %s' % str(e))
+ return True
+
+def nodeJoin(self, rc, clustername, nodename_resolved):
+ batch_number, result = nodeJoinCluster(rc)
+ if batch_number is None or result is None:
+ luci_log.debug_verbose('NJ0: batch_number and/or result is None')
+ return None
+
+ try:
+ set_node_flag(self, clustername, rc.hostname(), str(batch_number), NODE_JOIN_CLUSTER, "Node \'%s\' joining cluster" % nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('NJ1: failed to set flags: %s' % str(e))
+ return True
+
+def clusterStart(self, model):
+ if model is None:
+ return None
+
+ clustername = model.getClusterName()
+ nodes = model.getNodes()
+ if not nodes or len(nodes) < 1:
+ return None
+
+ errors = 0
+ for node in nodes:
+ nodename = node.getName().strip()
+ nodename_resolved = resolve_nodename(self, clustername, nodename)
+
+ try:
+ rc = RicciCommunicator(nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('CStart: RC %s: %s' \
+ % (nodename_resolved, str(e)))
+ errors += 1
+ continue
+ if nodeJoin(self, rc, clustername, nodename_resolved) is None:
+ luci_log.debug_verbose('CStart1: nodeLeave %s' % nodename_resolved)
+ errors += 1
+
+ return errors
+
+def clusterStop(self, model, delete=False):
+ if model is None:
+ return None
+
+ clustername = model.getClusterName()
+ nodes = model.getNodes()
+ if not nodes or len(nodes) < 1:
+ return None
+
+ errors = 0
+ for node in nodes:
+ nodename = node.getName().strip()
+ nodename_resolved = resolve_nodename(self, clustername, nodename)
+
+ try:
+ rc = RicciCommunicator(nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('[%d] CStop0: RC %s: %s' \
+ % (delete, nodename_resolved, str(e)))
+ errors += 1
+ continue
+ if nodeLeave(self, rc, clustername, nodename_resolved) is None:
+ luci_log.debug_verbose('[%d] CStop1: nodeLeave %s' \
+ % (delete, nodename_resolved))
+ errors += 1
+ return errors
+
+def clusterRestart(self, model):
+ snum_err = clusterStop(self, model)
+ if snum_err:
+ luci_log.debug_verbose('cluRestart0: clusterStop: %d errs' % snum_err)
+ jnum_err = clusterStart(self, model)
+ if jnum_err:
+ luci_log.debug_verbose('cluRestart0: clusterStart: %d errs' % jnum_err)
+ return snum_err + jnum_err
+
+def clusterDelete(self, model):
+ return clusterStop(self, model, delete=True)
+
+def forceNodeReboot(self, rc, clustername, nodename_resolved):
+ batch_number, result = nodeReboot(rc)
+ if batch_number is None or result is None:
+ luci_log.debug_verbose('FNR0: batch_number and/or result is None')
+ return None
+
+ try:
+ set_node_flag(self, clustername, rc.hostname(), str(batch_number), NODE_REBOOT, "Node \'%s\' is being rebooted" % nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('FNR1: failed to set flags: %s' % str(e))
+ return True
+
+def forceNodeFence(self, clustername, nodename, nodename_resolved):
+ path = str(CLUSTER_FOLDER_PATH + clustername)
+
+ try:
+ clusterfolder = self.restrictedTraverse(path)
+ if not clusterfolder:
+ raise Exception, 'no cluster folder at %s' % path
+ except Exception, e:
+ luci_log.debug('FNF0: The cluster folder %s could not be found: %s' \
+ % (clustername, str(e)))
+ return None
+
+ try:
+ nodes = clusterfolder.objectItems('Folder')
+ if not nodes or len(nodes) < 1:
+ raise Exception, 'no cluster nodes'
+ except Exception, e:
+ luci_log.debug('FNF1: No cluster nodes for %s were found: %s' \
+ % (clustername, str(e)))
+ return None
+
+ found_one = False
+ for node in nodes:
+ if node[1].getId().find(nodename) != (-1):
+ continue
+
+ try:
+ rc = RicciCommunicator(node[1].getId())
+ if not rc:
+ raise Exception, 'rc is None'
+ except Exception, e:
+ luci_log.debug('FNF2: ricci error for host %s: %s' \
+ % (node[0], str(e)))
+ continue
+
+ if not rc.authed():
+ rc = None
+ try:
+ snode = getStorageNode(self, node[1].getId())
+ setNodeFlag(snode, CLUSTER_NODE_NEED_AUTH)
+ except:
+ pass
+
+ try:
+ setNodeFlag(node[1], CLUSTER_NODE_NEED_AUTH)
+ except:
+ pass
+
+ continue
+ found_one = True
+ break
+
+ if not found_one:
+ return None
+
+ batch_number, result = nodeFence(rc, nodename)
+ if batch_number is None or result is None:
+ luci_log.debug_verbose('FNF3: batch_number and/or result is None')
+ return None
+
+ try:
+ set_node_flag(self, clustername, rc.hostname(), str(batch_number), NODE_FENCE, "Node \'%s\' is being fenced" % nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('FNF4: failed to set flags: %s' % str(e))
+ return True
+
+def nodeDelete(self, rc, model, clustername, nodename, nodename_resolved):
+ #We need to get a node name other than the node
+ #to be deleted, then delete the node from the cluster.conf
+ #and propogate it. We will need two ricci agents for this task.
+
+ # Make sure we can find a second node before we hose anything.
+ path = str(CLUSTER_FOLDER_PATH + clustername)
+ try:
+ clusterfolder = self.restrictedTraverse(path)
+ if not clusterfolder:
+ raise Exception, 'no cluster folder at %s' % path
+ except Exception, e:
+ luci_log.debug_verbose('ND0: node delete error for cluster %s: %s' \
+ % (clustername, str(e)))
+ return None
+
+ try:
+ nodes = clusterfolder.objectItems('Folder')
+ if not nodes or len(nodes) < 1:
+ raise Exception, 'no cluster nodes in DB'
+ except Exception, e:
+ luci_log.debug_verbose('ND1: node delete error for cluster %s: %s' \
+ % (clustername, str(e)))
+
+ found_one = False
+ for node in nodes:
+ if node[1].getId().find(nodename) != (-1):
+ continue
+ #here we make certain the node is up...
+ # XXX- we should also make certain this host is still
+ # in the cluster we believe it is.
+ try:
+ rc2 = RicciCommunicator(node[1].getId())
+ except Exception, e:
+ luci_log.info('ND2: ricci %s error: %s' % (node[0], str(e)))
+ continue
+
+ if not rc2.authed():
+ try:
+ setNodeFlag(node[1], CLUSTER_NODE_NEED_AUTH)
+ except:
+ pass
+
+ try:
+ snode = getStorageNode(self, node[0])
+ setNodeFlag(snode, CLUSTER_NODE_NEED_AUTH)
+ except:
+ pass
+
+ luci_log.debug_verbose('ND3: %s is not authed' % node[0])
+ rc2 = None
+ continue
+ else:
+ found_one = True
+ break
+
+ if not found_one:
+ luci_log.debug_verbose('ND4: unable to find ricci agent to delete %s from %s' % (nodename, clustername))
+ return None
+
+ #First, delete cluster.conf from node to be deleted.
+ #next, have node leave cluster.
+ batch_number, result = nodeLeaveCluster(rc, purge=True)
+ if batch_number is None or result is None:
+ luci_log.debug_verbose('ND5: batch_number and/or result is None')
+ return None
+
+ #It is not worth flagging this node in DB, as we are going
+ #to delete it anyway. Now, we need to delete node from model
+ #and send out new cluster.conf
+ delete_target = None
+ nodelist = model.getNodes()
+ find_node = lower(nodename)
+ for n in nodelist:
+ try:
+ if lower(n.getName()) == find_node:
+ delete_target = n
+ break
+ except:
+ continue
+
+ if delete_target is None:
+ luci_log.debug_verbose('ND6: unable to find delete target for %s in %s' \
+ % (nodename, clustername))
+ return None
+
+ model.deleteNode(delete_target)
+
+ try:
+ str_buf = model.exportModelAsString()
+ if not str_buf:
+ raise Exception, 'model string is blank'
+ except Exception, e:
+ luci_log.debug_verbose('ND7: exportModelAsString: %s' % str(e))
+ return None
+
+ # propagate the new cluster.conf via the second node
+ batch_number, result = setClusterConf(rc2, str(str_buf))
+ if batch_number is None:
+ luci_log.debug_verbose('ND8: batch number is None after del node in NTP')
+ return None
+
+ #Now we need to delete the node from the DB
+ path = str(CLUSTER_FOLDER_PATH + clustername)
+ del_path = str(path + '/' + nodename_resolved)
+
+ try:
+ delnode = self.restrictedTraverse(del_path)
+ clusterfolder = self.restrictedTraverse(path)
+ clusterfolder.manage_delObjects(delnode[0])
+ except Exception, e:
+ luci_log.debug_verbose('ND9: error deleting %s: %s' \
+ % (del_path, str(e)))
+
+ try:
+ set_node_flag(self, clustername, rc2.hostname(), str(batch_number), NODE_DELETE, "Deleting node \'%s\'" % nodename_resolved)
+ except Exception, e:
+ luci_log.debug_verbose('ND10: failed to set flags: %s' % str(e))
+ return True
+
def nodeTaskProcess(self, model, request):
try:
clustername = request['clustername']
@@ -2122,9 +2704,6 @@
return None
nodename_resolved = resolve_nodename(self, clustername, nodename)
- if not nodename_resolved or not nodename or not task or not clustername:
- luci_log.debug('resolve_nodename failed for NTP')
- return None
if task != NODE_FENCE:
# Fencing is the only task for which we don't
@@ -2171,319 +2750,43 @@
return None
if task == NODE_LEAVE_CLUSTER:
- path = str(CLUSTER_FOLDER_PATH + clustername + "/" + nodename_resolved)
-
- try:
- nodefolder = self.restrictedTraverse(path)
- if not nodefolder:
- raise Exception, 'cannot find directory at %s' % path
- except Exception, e:
- luci_log.debug('node_leave_cluster err: %s' % str(e))
+ if nodeLeave(self, rc, clustername, nodename_resolved) is None:
+ luci_log.debug_verbose('NTP: nodeLeave failed')
return None
- objname = str(nodename_resolved + "____flag")
-
- fnpresent = noNodeFlagsPresent(self, nodefolder, objname, nodename_resolved)
- if fnpresent is None:
- luci_log.debug('An error occurred while checking flags for %s' \
- % nodename_resolved)
- return None
-
- if fnpresent == False:
- luci_log.debug('flags are still present for %s -- bailing out' \
- % nodename_resolved)
- return None
-
- batch_number, result = nodeLeaveCluster(rc)
- if batch_number is None or result is None:
- luci_log.debug_verbose('nodeLeaveCluster error: batch_number and/or result is None')
- return None
-
- batch_id = str(batch_number)
- objpath = str(path + "/" + objname)
-
- try:
- nodefolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, NODE_LEAVE_CLUSTER, "string")
- flag.manage_addProperty(FLAG_DESC, "Node \'" + nodename + "\' leaving cluster", "string")
- except:
- luci_log.debug('An error occurred while setting flag %s' % objpath)
-
response = request.RESPONSE
- #Is this correct? Should we re-direct to the cluster page?
- response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clustername)
+ response.redirect(request['URL'] + "?pagetype=" + NODES + "&clustername=" + clustername + '&busyfirst=true')
elif task == NODE_JOIN_CLUSTER:
- batch_number, result = nodeJoinCluster(rc)
- if batch_number is None or result is None:
- luci_log.debug_verbose('nodeJoin error: batch_number and/or result is None')
+ if nodeJoin(self, rc, clustername, nodename_resolved) is None:
+ luci_log.debug_verbose('NTP: nodeJoin failed')
return None
- path = str(CLUSTER_FOLDER_PATH + clustername + "/" + nodename_resolved)
- batch_id = str(batch_number)
- objname = str(nodename_resolved + "____flag")
- objpath = str(path + "/" + objname)
-
- try:
- nodefolder = self.restrictedTraverse(path)
- nodefolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, NODE_JOIN_CLUSTER, "string")
- flag.manage_addProperty(FLAG_DESC, "Node \'" + nodename + "\' joining cluster", "string")
- except Exception, e:
- luci_log.debug_verbose('nodeJoin error: creating flags at %s: %s' \
- % (path, str(e)))
-
response = request.RESPONSE
- #Once again, is this correct? Should we re-direct to the cluster page?
- response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clustername)
+ response.redirect(request['URL'] + "?pagetype=" + NODES + "&clustername=" + clustername + '&busyfirst=true')
elif task == NODE_REBOOT:
- batch_number, result = nodeReboot(rc)
- if batch_number is None or result is None:
- luci_log.debug_verbose('nodeReboot: batch_number and/or result is None')
+ if forceNodeReboot(self, rc, clustername, nodename_resolved) is None:
+ luci_log.debug_verbose('NTP: nodeReboot failed')
return None
- path = str(CLUSTER_FOLDER_PATH + clustername + "/" + nodename_resolved)
- batch_id = str(batch_number)
- objname = str(nodename_resolved + "____flag")
- objpath = str(path + "/" + objname)
-
- try:
- nodefolder = self.restrictedTraverse(path)
- nodefolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, NODE_REBOOT, "string")
- flag.manage_addProperty(FLAG_DESC, "Node \'" + nodename + "\' is being rebooted", "string")
- except Exception, e:
- luci_log.debug_verbose('nodeReboot err: creating flags at %s: %s' \
- % (path, str(e)))
-
response = request.RESPONSE
- #Once again, is this correct? Should we re-direct to the cluster page?
- response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clustername)
+ response.redirect(request['URL'] + "?pagetype=" + NODES + "&clustername=" + clustername + '&busyfirst=true')
elif task == NODE_FENCE:
- #here, we DON'T want to open connection to node to be fenced.
- path = str(CLUSTER_FOLDER_PATH + clustername)
- try:
- clusterfolder = self.restrictedTraverse(path)
- if not clusterfolder:
- raise Exception, 'no cluster folder at %s' % path
- except Exception, e:
- luci_log.debug('The cluster folder for %s could not be found: %s' \
- % (clustername, str(e)))
- return None
-
- try:
- nodes = clusterfolder.objectItems('Folder')
- if not nodes or len(nodes) < 1:
- raise Exception, 'no cluster nodes'
- except Exception, e:
- luci_log.debug('No cluster nodes for %s were found: %s' \
- % (clustername, str(e)))
- return None
-
- found_one = False
- for node in nodes:
- if node[1].getId().find(nodename) != (-1):
- continue
-
- try:
- rc = RicciCommunicator(node[1].getId())
- if not rc:
- continue
- except RicciError, e:
- luci_log.debug('ricci error for host %s: %s' \
- % (node[0], str(e)))
- continue
- except:
- continue
-
- if not rc.authed():
- rc = None
- try:
- snode = getStorageNode(self, node[1].getId())
- setNodeFlag(snode, CLUSTER_NODE_NEED_AUTH)
- except:
- pass
-
- try:
- setNodeFlag(node[1], CLUSTER_NODE_NEED_AUTH)
- except:
- pass
-
- continue
- found_one = True
- break
-
- if not found_one:
- return None
-
- batch_number, result = nodeFence(rc, nodename)
- if batch_number is None or result is None:
- luci_log.debug_verbose('nodeFence: batch_number and/or result is None')
+ if forceNodeFence(self, clustername, nodename, nodename_resolved) is None:
+ luci_log.debug_verbose('NTP: nodeFencefailed')
return None
- path = str(path + "/" + nodename_resolved)
- batch_id = str(batch_number)
- objname = str(nodename_resolved + "____flag")
- objpath = str(path + "/" + objname)
-
- try:
- nodefolder = self.restrictedTraverse(path)
- nodefolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, NODE_FENCE, "string")
- flag.manage_addProperty(FLAG_DESC, "Node \'" + nodename + "\' is being fenced", "string")
- except Exception, e:
- luci_log.debug_verbose('nodeFence err: creating flags at %s: %s' \
- % (path, str(e)))
-
response = request.RESPONSE
- #Once again, is this correct? Should we re-direct to the cluster page?
- response.redirect(request['URL'] + "?pagetype=" + CLUSTER_CONFIG + "&clustername=" + clustername)
+ response.redirect(request['URL'] + "?pagetype=" + NODES + "&clustername=" + clustername + '&busyfirst=true')
elif task == NODE_DELETE:
- #We need to get a node name other than the node
- #to be deleted, then delete the node from the cluster.conf
- #and propogate it. We will need two ricci agents for this task.
-
- # Make sure we can find a second node before we hose anything.
- path = str(CLUSTER_FOLDER_PATH + clustername)
- try:
- clusterfolder = self.restrictedTraverse(path)
- if not clusterfolder:
- raise Exception, 'no cluster folder at %s' % path
- except Exception, e:
- luci_log.debug_verbose('node delete error for cluster %s: %s' \
- % (clustername, str(e)))
+ if nodeDelete(self, rc, model, clustername, nodename, nodename_resolved) is None:
+ luci_log.debug_verbose('NTP: nodeDelete failed')
return None
-
- try:
- nodes = clusterfolder.objectItems('Folder')
- if not nodes or len(nodes) < 1:
- raise Exception, 'no cluster nodes in DB'
- except Exception, e:
- luci_log.debug_verbose('node delete error for cluster %s: %s' \
- % (clustername, str(e)))
-
- found_one = False
- for node in nodes:
- if node[1].getId().find(nodename) != (-1):
- continue
- #here we make certain the node is up...
- # XXX- we should also make certain this host is still
- # in the cluster we believe it is.
- try:
- rc2 = RicciCommunicator(node[1].getId())
- except Exception, e:
- luci_log.info('ricci %s error: %s' % (node[0], str(e)))
- continue
- except:
- continue
-
- if not rc2.authed():
- try:
- setNodeFlag(node[1], CLUSTER_NODE_NEED_AUTH)
- except:
- pass
-
- try:
- snode = getStorageNode(self, node[0])
- setNodeFlag(snode, CLUSTER_NODE_NEED_AUTH)
- except:
- pass
-
- luci_log.debug_verbose('%s is not authed' % node[0])
- rc2 = None
- continue
- else:
- found_one = True
- break
-
- if not found_one:
- luci_log.debug_verbose('unable to find ricci node to delete %s from %s' % (nodename, clustername))
- return None
-
- #First, delete cluster.conf from node to be deleted.
- #next, have node leave cluster.
- batch_number, result = nodeLeaveCluster(rc, purge=True)
- if batch_number is None or result is None:
- luci_log.debug_verbose('nodeDelete: batch_number and/or result is None')
- return None
-
- #It is not worth flagging this node in DB, as we are going
- #to delete it anyway. Now, we need to delete node from model
- #and send out new cluster.conf
- delete_target = None
- nodelist = model.getNodes()
- find_node = lower(nodename)
- for n in nodelist:
- try:
- if lower(n.getName()) == find_node:
- delete_target = n
- break
- except:
- continue
-
- if delete_target is None:
- luci_log.debug_verbose('unable to find delete target for %s in %s' \
- % (nodename, clustername))
- return None
-
- model.deleteNode(delete_target)
-
- try:
- str_buf = model.exportModelAsString()
- if not str_buf:
- raise Exception, 'model string is blank'
- except Exception, e:
- luci_log.debug_verbose('NTP exportModelAsString: %s' % str(e))
- return None
-
- # propagate the new cluster.conf via the second node
- batch_number, result = setClusterConf(rc2, str(str_buf))
- if batch_number is None:
- luci_log.debug_verbose('batch number is None after del node in NTP')
- return None
-
- #Now we need to delete the node from the DB
- path = str(CLUSTER_FOLDER_PATH + clustername)
- del_path = str(path + "/" + nodename_resolved)
-
- try:
- delnode = self.restrictedTraverse(del_path)
- clusterfolder = self.restrictedTraverse(path)
- clusterfolder.manage_delObjects(delnode[0])
- except Exception, e:
- luci_log.debug_verbose('error deleting %s: %s' % (del_path, str(e)))
-
- batch_id = str(batch_number)
- objname = str(nodename_resolved + "____flag")
- objpath = str(path + "/" + objname)
-
- try:
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, NODE_DELETE, "string")
- flag.manage_addProperty(FLAG_DESC, "Deleting node \'" + nodename + "\'", "string")
- except Exception, e:
- luci_log.debug_verbose('nodeDelete %s err setting flag at %s: %s' \
- % (nodename, objpath, str(e)))
-
response = request.RESPONSE
- response.redirect(request['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(request['URL'] + "?pagetype=" + NODES + "&clustername=" + clustername + '&busyfirst=true')
def getNodeInfo(self, model, status, request):
infohash = {}
+ item = None
baseurl = request['URL']
nodestate = NODE_ACTIVE
svclist = list()
@@ -2553,25 +2856,38 @@
#return infohash
infohash['d_states'] = None
+
+ nodename_resolved = resolve_nodename(self, clustername, nodename)
+
if nodestate == NODE_ACTIVE or nodestate == NODE_INACTIVE:
#call service module on node and find out which daemons are running
- rc = RicciCommunicator(nodename)
- dlist = list()
- dlist.append("ccsd")
- dlist.append("cman")
- dlist.append("fenced")
- dlist.append("rgmanager")
- states = getDaemonStates(rc, dlist)
- infohash['d_states'] = states
+ try:
+ rc = RicciCommunicator(nodename_resolved)
+ if not rc:
+ raise Exception, 'rc is none'
+ except Exception, e:
+ rc = None
+ luci_log.info('Error connecting to %s: %s' \
+ % (nodename_resolved, str(e)))
+
+ if rc is not None:
+ dlist = list()
+ dlist.append("ccsd")
+ dlist.append("cman")
+ dlist.append("fenced")
+ dlist.append("rgmanager")
+ states = getDaemonStates(rc, dlist)
+ infohash['d_states'] = states
- infohash['logurl'] = '/luci/logs/?nodename=' + nodename + '&clustername=' + clustername
+ infohash['logurl'] = '/luci/logs/?nodename=' + nodename_resolved + '&clustername=' + clustername
return infohash
#get list of faildoms for node
-def getNodesInfo(self, model,status,req):
+def getNodesInfo(self, model, status, req):
resultlist = list()
nodelist = list()
svclist = list()
+
#Sort into lists...
for item in status:
if item['type'] == "node":
@@ -2581,13 +2897,36 @@
else:
continue
+ try:
+ clustername = req['clustername']
+ if not clustername:
+ raise KeyError, 'clustername is blank'
+ except:
+ try:
+ clustername = req.form['clustername']
+ raise KeyError, 'clustername is blank'
+ except:
+ try:
+ clustername = req.form['clusterName']
+ except:
+ try:
+ clustername = model.getClusterName()
+ except:
+ luci_log.debug_verbose('GNI0: unable to determine cluster name')
+ return {}
+
+
for item in nodelist:
map = {}
name = item['name']
map['nodename'] = name
- clustername = req['clustername']
- baseurl = req['URL']
+ try:
+ baseurl = req['URL']
+ except:
+ baseurl = '/luci/cluster/index_html'
+
cfgurl = baseurl + "?" + PAGETYPE + "=" + NODE + "&" + CLUNAME + "=" + clustername + "&nodename=" + name
+
map['configurl'] = cfgurl
map['fenceurl'] = cfgurl + "#fence"
if item['clustered'] == "true":
@@ -2600,7 +2939,10 @@
map['status'] = NODE_INACTIVE
map['status_str'] = NODE_INACTIVE_STR
- map['logurl'] = '/luci/logs?nodename=' + name + '&clustername=' + clustername
+ nodename_resolved = resolve_nodename(self, clustername, name)
+
+ map['logurl'] = '/luci/logs?nodename=' + nodename_resolved + '&clustername=' + clustername
+
#set up URLs for dropdown menu...
if map['status'] == NODE_ACTIVE:
map['jl_url'] = baseurl + "?pagetype=" + NODE_PROCESS + "&task=" + NODE_LEAVE_CLUSTER + "&nodename=" + name + "&clustername=" + clustername
@@ -2644,115 +2986,328 @@
def getFence(self, model, request):
map = {}
- fencename = request['fencedevicename']
+ fencename = request['fencename']
fencedevs = model.getFenceDevices()
for fencedev in fencedevs:
if fencedev.getName().strip() == fencename:
map = fencedev.getAttributes()
+ try:
+ map['pretty_name'] = FENCE_OPTS[fencedev.getAgentType()]
+ except:
+ map['pretty_name'] = fencedev.getAgentType()
+
+ nodes_used = list()
+ nodes = model.getNodes()
+ for node in nodes:
+ flevels = node.getFenceLevels()
+ for flevel in flevels: #These are the method blocks...
+ kids = flevel.getChildren()
+ for kid in kids: #These are actual devices in each level
+ if kid.getName().strip() == fencedev.getName().strip():
+ #See if this fd already has an entry for this node
+ found_duplicate = False
+ for item in nodes_used:
+ if item['nodename'] == node.getName().strip():
+ found_duplicate = True
+ if found_duplicate == True:
+ continue
+ baseurl = request['URL']
+ clustername = model.getClusterName()
+ node_hash = {}
+ node_hash['nodename'] = node.getName().strip()
+ node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
+ nodes_used.append(node_hash)
+
+ map['nodesused'] = nodes_used
return map
return map
+
+def getFDForInstance(fds, name):
+ for fd in fds:
+ if fd.getName().strip() == name:
+ return fd
+
+ raise
def getFenceInfo(self, model, request):
+ clustername = request['clustername']
+ baseurl = request['URL']
map = {}
- fencedevs = list()
- level1 = list()
- level2 = list()
+ level1 = list() #First level fence devices
+ level2 = list() #Second level fence devices
+ shared1 = list() #List of available sharable fence devs not used in level1
+ shared2 = list() #List of available sharable fence devs not used in level2
map['level1'] = level1
map['level2'] = level2
- map['fencedevs'] = fencedevs
- nodename = ""
- if request == None: #this is being called by the fence device page
- #Get list of fence devices
- fds = model.getFenceDevices()
- for fd in fds:
- #create fencedev hashmap
- if fd.isShared() == True:
- fencedev = fd.getAttributes()
- fencedevs.append(fencedev)
-
- return map
+ map['shared1'] = shared1
+ map['shared2'] = shared2
- else:
- try:
- nodename = request['nodename']
- except KeyError, e:
- raise GeneralError('FATAL', "Could not extract nodename from request")
+ major_num = 1
+ minor_num = 100
+
+ try:
+ nodename = request['nodename']
+ except KeyError, e:
+ raise GeneralError('FATAL', "Could not extract nodename from request")
- #here we need to get fences for a node - just the first two levels
- #then fill in two data structures with all attr's
- try:
- node = model.retrieveNodeByName(nodename)
- except GeneralError, e:
- raise GeneralError('FATAL', "Couldn't find node name in current node list")
+ #Here we need to get fences for a node - just the first two levels
+ #Each level has its own list of fence devs used in that level
+ #For each fence dev, a list of instance structs is appended
+ #In addition, for each level, a list of available but unused fence devs
+ #is returned.
+ try:
+ node = model.retrieveNodeByName(nodename)
+ except GeneralError, e:
+ raise GeneralError('FATAL', "Couldn't find node name in current node list")
- levels = node.getFenceLevels()
- len_levels = len(levels)
+ fds = model.getFenceDevices()
- if len_levels == 0:
- return map
+ levels = node.getFenceLevels()
+ len_levels = len(levels)
+
+ if len_levels == 0:
+ return map
- for i in xrange(2):
- if not i in levels:
+ if len_levels >= 1:
+ first_level = levels[0]
+ kids = first_level.getChildren()
+ last_kid_fd = None #This is a marker for allowing multi instances
+ #beneath a fencedev
+ for kid in kids:
+ instance_name = kid.getName().strip()
+ try:
+ fd = getFDForInstance(fds, instance_name)
+ except:
+ fd = None #Set to None in case last time thru loop
continue
- fence_struct = {}
- if levels[i] != None:
- level = levels[i]
- else:
- #No more levels...
+
+ if fd is not None:
+ if fd.isShared() == False: #Not a shared dev...build struct and add
+ fencedev = {}
+ fencedev['prettyname'] = FENCE_OPTS[fd.getAgentType()]
+ fencedev['isShared'] = False
+ fencedev['id'] = str(major_num)
+ major_num = major_num + 1
+ devattrs = fd.getAttributes()
+ kees = devattrs.keys()
+ for kee in kees:
+ fencedev[kee] = devattrs[kee]
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
+ for kee in kees:
+ if kee == "name":
+ continue #Don't duplicate name attr
+ fencedev[kee] = kidattrs[kee]
+ #This fencedev struct is complete, and needs to be placed on the
+ #level1 Q. Because it is non-shared, we should set last_kid_fd
+ #to none.
+ last_kid_fd = None
+ level1.append(fencedev)
+ else: #This dev is shared
+ if (last_kid_fd is not None) and (fd.getName().strip() == last_kid_fd.getName().strip()): #just append a new instance struct to last_kid_fd
+ instance_struct = {}
+ instance_struct['id'] = str(minor_num)
+ minor_num = minor_num + 1
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
+ for kee in kees:
+ if kee == "name":
+ continue
+ instance_struct[kee] = kidattrs[kee]
+ #Now just add this struct to last_kid_fd and reset last_kid_fd
+ ilist = last_kid_fd['instance_list']
+ ilist.append(instance_struct)
+ last_kid_fd = fd
+ continue
+ else: #Shared, but not used above...so we need a new fencedev struct
+ fencedev = {}
+ fencedev['prettyname'] = FENCE_OPTS[fd.getAgentType()]
+ fencedev['isShared'] = True
+ fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
+ fencedev['id'] = str(major_num)
+ major_num = major_num + 1
+ inlist = list()
+ fencedev['instance_list'] = inlist
+ devattrs = fd.getAttributes()
+ kees = devattrs.keys()
+ for kee in kees:
+ fencedev[kee] = devattrs[kee]
+ instance_struct = {}
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
+ for kee in kees:
+ if kee == "name":
+ continue
+ instance_struct[kee] = kidattrs[kee]
+ inlist.append(instance_struct)
+ level1.append(fencedev)
+ last_kid_fd = fd
+ continue
+
+ #level1 list is complete now, but it is still necessary to build shared1
+ sharednames = list()
+ for fd in fds:
+ isUnique = True
+ if fd.isShared() == False:
continue
- kids = level.getChildren()
- if len(kids) == 0:
+ for fdev in level1:
+ if fd.getName().strip() == fdev['name']:
+ isUnique = False
+ break
+ if isUnique == True:
+ shared_struct = {}
+ shared_struct['name'] = fd.getName().strip()
+ agentname = fd.getAgentType()
+ shared_struct['agent'] = agentname
+ shared_struct['prettyname'] = FENCE_OPTS[agentname]
+ shared1.append(shared_struct)
+
+ #YUK: This next section violates the DRY rule, :-(
+ if len_levels >= 2:
+ second_level = levels[1]
+ kids = second_level.getChildren()
+ last_kid_fd = None #This is a marker for allowing multi instances
+ #beneath a fencedev
+ for kid in kids:
+ instance_name = kid.getName().strip()
+ try:
+ fd = getFDForInstance(fds, instance_name)
+ except:
+ fd = None #Set to None in case last time thru loop
continue
- else:
- #for each kid,
- ### resolve name, find fence device
- ### Add fd to list, if it is not there yet
- ### determine if it is a shared fence type
- ### if it is a shared device, add instance entry
- fds = model.getFenceDevices()
- fence_struct = None
- for kid in kids:
- name = kid.getName()
- found_fd = False
- if not i in map:
- continue
- for entry in map[i]:
- if entry['name'] == name:
- fence_struct = entry
- found_fd = True
- break
- if found_fd == False:
- for fd in fds:
- if fd.getName() == name: #Found the fence device
- fence_struct = {}
- fence_struct['isShareable'] = fd.isShared()
- fd_attrs = fd.getAttributes()
- kees = fd_attrs.keys()
- for kee in kees:
- fence_struct[kee] = fd_attrs[kee]
- fi_attrs = kid.getAttributes()
- kees = fi_attrs.keys()
- if fence_struct['isShareable'] == True:
+ if fd is not None:
+ if fd.isShared() == False: #Not a shared dev...build struct and add
+ fencedev = {}
+ fencedev['prettyname'] = FENCE_OPTS[fd.getAgentType()]
+ fencedev['isShared'] = False
+ fencedev['id'] = str(major_num)
+ major_num = major_num + 1
+ devattrs = fd.getAttributes()
+ kees = devattrs.keys()
+ for kee in kees:
+ fencedev[kee] = devattrs[kee]
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
+ for kee in kees:
+ if kee == "name":
+ continue #Don't duplicate name attr
+ fencedev[kee] = kidattrs[kee]
+ #This fencedev struct is complete, and needs to be placed on the
+ #level2 Q. Because it is non-shared, we should set last_kid_fd
+ #to none.
+ last_kid_fd = None
+ level2.append(fencedev)
+ else: #This dev is shared
+ if (last_kid_fd is not None) and (fd.getName().strip() == last_kid_fd.getName().strip()): #just append a new instance struct to last_kid_fd
instance_struct = {}
+ instance_struct['id'] = str(minor_num)
+ minor_num = minor_num + 1
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
for kee in kees:
- instance_struct[kee] = fi_attrs[kee]
- try:
- check = fence_struct['instances']
- check.append(instance_struct)
- except KeyError, e:
- fence_struct['instances'] = list()
- fence_struct['instances'].append(instance_struct)
- else: #Not a shareable fence device type
+ if kee == "name":
+ continue
+ instance_struct[kee] = kidattrs[kee]
+ #Now just add this struct to last_kid_fd and reset last_kid_fd
+ ilist = last_kid_fd['instance_list']
+ ilist.append(instance_struct)
+ last_kid_fd = fd
+ continue
+ else: #Shared, but not used above...so we need a new fencedev struct
+ fencedev = {}
+ fencedev['prettyname'] = FENCE_OPTS[fd.getAgentType()]
+ fencedev['isShared'] = True
+ fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
+ fencedev['id'] = str(major_num)
+ major_num = major_num + 1
+ inlist = list()
+ fencedev['instance_list'] = inlist
+ devattrs = fd.getAttributes()
+ kees = devattrs.keys()
for kee in kees:
- fence_struct[kee] = fi_attrs[kee]
- if i == 0:
- level1.append(fence_struct)
- else:
- level2.append(fence_struct)
+ fencedev[kee] = devattrs[kee]
+ instance_struct = {}
+ kidattrs = kid.getAttributes()
+ kees = kidattrs.keys()
+ for kee in kees:
+ if kee == "name":
+ continue
+ instance_struct[kee] = kidattrs[kee]
+ inlist.append(instance_struct)
+ level2.append(fencedev)
+ last_kid_fd = fd
+ continue
- return map
+ #level2 list is complete but like above, we need to build shared2
+ sharednames = list()
+ for fd in fds:
+ isUnique = True
+ if fd.isShared() == False:
+ continue
+ for fdev in level2:
+ if fd.getName.strip() == fdev['name']:
+ isUnique = False
+ break
+ if isUnique == True:
+ shared_struct = {}
+ shared_struct['name'] = fd.getName().strip()
+ agentname = fd.getAgentType()
+ shared_struct['agent'] = agentname
+ shared_struct['prettyname'] = FENCE_OPTS[agentname]
+ shared2.append(shared_struct)
+
+ return map
+def getFencesInfo(self, model, request):
+ clustername = request['clustername']
+ baseurl = request['URL']
+ map = {}
+ fencedevs = list() #This is for the fencedev list page
+ map['fencedevs'] = fencedevs
+ #Get list of fence devices
+ fds = model.getFenceDevices()
+ nodes_used = list() #This section determines which nodes use the dev
+ for fd in fds:
+ #create fencedev hashmap
+ if fd.isShared() == True:
+ fencedev = {}
+ attr_hash = fd.getAttributes()
+ kees = attr_hash.keys()
+ for kee in kees:
+ fencedev[kee] = attr_hash[kee] #copy attrs over
+ try:
+ fencedev['pretty_name'] = FENCE_OPTS[fd.getAgentType()]
+ except:
+ fencedev['pretty_name'] = fd.getAgentType()
+ #Add config url for this fencedev
+ fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
+
+ nodes = model.getNodes()
+ for node in nodes:
+ flevels = node.getFenceLevels()
+ for flevel in flevels: #These are the method blocks...
+ kids = flevel.getChildren()
+ for kid in kids: #These are actual devices in each level
+ if kid.getName().strip() == fd.getName().strip():
+ #See if this fd already has an entry for this node
+ found_duplicate = False
+ for item in nodes_used:
+ if item['nodename'] == node.getName().strip():
+ found_duplicate = True
+ if found_duplicate == True:
+ continue
+ node_hash = {}
+ node_hash['nodename'] = node.getName().strip()
+ node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
+ nodes_used.append(node_hash)
+
+ fencedev['nodesused'] = nodes_used
+ fencedevs.append(fencedev)
+
+ return map
+
+
def getLogsForNode(self, request):
try:
nodename = request['nodename']
@@ -2780,12 +3335,7 @@
if clustername is None:
nodename_resolved = nodename
else:
- try:
- nodename_resolved = resolve_nodename(self, clustername, nodename)
- except:
- luci_log.debug_verbose('Unable to resolve node name %s/%s to retrieve logging information' \
- % (nodename, clustername))
- return 'Unable to resolve node name for %s in cluster %s' % (nodename, clustername)
+ nodename_resolved = resolve_nodename(self, clustername, nodename)
try:
rc = RicciCommunicator(nodename_resolved)
@@ -2838,7 +3388,7 @@
try:
stringbuf = model.exportModelAsString()
if not stringbuf:
- raise Exception, 'model is blank'
+ raise Exception, 'model is blank'
except Exception, e:
luci_log.debug_verbose('exportModelAsString error: %s' % str(e))
return None
@@ -2861,17 +3411,14 @@
def getXenVMInfo(self, model, request):
try:
xenvmname = request['servicename']
- except KeyError, e:
+ except:
try:
xenvmname = request.form['servicename']
except:
luci_log.debug_verbose('servicename is missing from request')
return {}
- except:
- luci_log.debug_verbose('servicename is missing from request')
- return {}
- try:
+ try:
xenvm = model.retrieveXenVMsByName(xenvmname)
except:
luci_log.debug('An error occurred while attempting to get VM %s' \
@@ -2915,7 +3462,7 @@
try:
items = clusterfolder.objectItems('ManagedSystem')
if not items or len(items) < 1:
- luci_log.debug_verbose('ICB3: no flags at %s for cluster %s' \
+ luci_log.debug_verbose('ICB3: NOT BUSY: no flags at %s for cluster %s' \
% (cluname, path))
return map #This returns an empty map, and should indicate not busy
except Exception, e:
@@ -2925,7 +3472,7 @@
luci_log.debug('ICB5: An error occurred while looking for cluster %s flags at path %s' % (cluname, path))
return map
- luci_log.debug_verbose('ICB6: isClusterBusy: %s is busy: %d flags' \
+ luci_log.debug_verbose('ICB6: %s is busy: %d flags' \
% (cluname, len(items)))
map['busy'] = "true"
#Ok, here is what is going on...if there is an item,
@@ -2962,27 +3509,25 @@
rc = RicciCommunicator(ricci[0])
if not rc:
rc = None
- raise RicciError, 'rc is None for %s' % ricci[0]
- except RicciError, e:
+ luci_log.debug_verbose('ICB6b: rc is none')
+ except Exception, e:
rc = None
- luci_log.debug_verbose('ICB7: ricci returned error in iCB for %s: %s' \
+ luci_log.debug_verbose('ICB7: RC: %s: %s' \
% (cluname, str(e)))
- except:
- rc = None
- luci_log.info('ICB8: ricci connection failed for cluster %s' % cluname)
batch_id = None
if rc is not None:
try:
batch_id = item[1].getProperty(BATCH_ID)
- luci_log.debug_verbose('ICB8A: got batch_id %s from %s' \
+ luci_log.debug_verbose('ICB8: got batch_id %s from %s' \
% (batch_id, item[0]))
except Exception, e:
try:
luci_log.debug_verbose('ICB8B: failed to get batch_id from %s: %s' \
% (item[0], str(e)))
except:
- luci_log.debug_verbose('ICB8C: failed to get batch_id from %s' % item[0])
+ luci_log.debug_verbose('ICB8C: failed to get batch_id from %s' \
+ % item[0])
if batch_id is not None:
try:
@@ -3030,18 +3575,31 @@
elif laststatus == 0:
node_report['statusindex'] = 0
node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + PRE_INSTALL
+ elif laststatus == DISABLE_SVC_TASK:
+ node_report['statusindex'] = DISABLE_SVC_TASK
+ node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + PRE_CFG
elif laststatus == REBOOT_TASK:
node_report['statusindex'] = REBOOT_TASK
node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + PRE_CFG
elif laststatus == SEND_CONF:
node_report['statusindex'] = SEND_CONF
node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + PRE_JOIN
+ elif laststatus == ENABLE_SVC_TASK:
+ node_report['statusindex'] = ENABLE_SVC_TASK
+ node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + PRE_JOIN
+ else:
+ node_report['statusindex'] = 0
+ node_report['statusmessage'] = RICCI_CONNECT_FAILURE_MSG + ' Install is in an unknown state.'
nodereports.append(node_report)
continue
elif creation_status == -(INSTALL_TASK):
node_report['iserror'] = True
(err_code, err_msg) = extract_module_status(batch_xml, INSTALL_TASK)
node_report['errormessage'] = CLUNODE_CREATE_ERRORS[INSTALL_TASK] + err_msg
+ elif creation_status == -(DISABLE_SVC_TASK):
+ node_report['iserror'] = True
+ (err_code, err_msg) = extract_module_status(batch_xml, DISABLE_SVC_TASK)
+ node_report['errormessage'] = CLUNODE_CREATE_ERRORS[DISABLE_SVC_TASK] + err_msg
elif creation_status == -(REBOOT_TASK):
node_report['iserror'] = True
(err_code, err_msg) = extract_module_status(batch_xml, REBOOT_TASK)
@@ -3050,6 +3608,10 @@
node_report['iserror'] = True
(err_code, err_msg) = extract_module_status(batch_xml, SEND_CONF)
node_report['errormessage'] = CLUNODE_CREATE_ERRORS[SEND_CONF] + err_msg
+ elif creation_status == -(ENABLE_SVC_TASK):
+ node_report['iserror'] = True
+ (err_code, err_msg) = extract_module_status(batch_xml, DISABLE_SVC_TASK)
+ node_report['errormessage'] = CLUNODE_CREATE_ERRORS[ENABLE_SVC_TASK] + err_msg
elif creation_status == -(START_NODE):
node_report['iserror'] = True
(err_code, err_msg) = extract_module_status(batch_xml, START_NODE)
@@ -3057,7 +3619,13 @@
else:
node_report['iserror'] = True
node_report['errormessage'] = CLUNODE_CREATE_ERRORS[0]
- clusterfolder.manage_delObjects(item[0])
+
+ try:
+ clusterfolder.manage_delObjects(item[0])
+ except Exception, e:
+ luci_log.debug_verbose('ICB14: delObjects: %s: %s' \
+ % (item[0], str(e)))
+
nodereports.append(node_report)
continue
else: #either batch completed successfully, or still running
@@ -3069,7 +3637,7 @@
try:
clusterfolder.manage_delObjects(item[0])
except Exception, e:
- luci_log.info('ICB14: Unable to delete %s: %s' % (item[0], str(e)))
+ luci_log.info('ICB15: Unable to delete %s: %s' % (item[0], str(e)))
continue
else:
map['busy'] = "true"
@@ -3079,23 +3647,41 @@
nodereports.append(node_report)
propslist = list()
propslist.append(LAST_STATUS)
- item[1].manage_delProperties(propslist)
- item[1].manage_addProperty(LAST_STATUS,creation_status, "int")
+ try:
+ item[1].manage_delProperties(propslist)
+ item[1].manage_addProperty(LAST_STATUS, creation_status, "int")
+ except Exception, e:
+ luci_log.debug_verbose('ICB16: last_status err: %s %d: %s' \
+ % (item[0], creation_status, str(e)))
continue
else:
node_report = {}
node_report['isnodecreation'] = False
ricci = item[0].split("____") #This removes the 'flag' suffix
- rc = RicciCommunicator(ricci[0])
- finished = checkBatch(rc, item[1].getProperty(BATCH_ID))
+
+ try:
+ rc = RicciCommunicator(ricci[0])
+ except Exception, e:
+ rc = None
+ finished = False
+ luci_log.debug_verbose('ICB15: ricci error: %s: %s' \
+ % (ricci[0], str(e)))
+
+ if rc is not None:
+ finished = checkBatch(rc, item[1].getProperty(BATCH_ID))
+
if finished == True:
- node_report['desc'] = item[1].getProperty(FLAG_DESC) + REDIRECT_MSG
+ flag_desc = item[1].getProperty(FLAG_DESC)
+ if flag_desc is None:
+ node_report['desc'] = REDIRECT_MSG
+ else:
+ node_report['desc'] = flag_desc + REDIRECT_MSG
nodereports.append(node_report)
try:
clusterfolder.manage_delObjects(item[0])
except Exception, e:
- luci_log.info('Unable to delete %s: %s' % (item[0], str(e)))
+ luci_log.info('ICB16: Unable to delete %s: %s' % (item[0], str(e)))
else:
node_report = {}
map['busy'] = "true"
@@ -3106,6 +3692,7 @@
if isBusy:
part1 = req['ACTUAL_URL']
part2 = req['QUERY_STRING']
+
dex = part2.find("&busyfirst")
if dex != (-1):
tmpstr = part2[:dex] #This strips off busyfirst var
@@ -3113,11 +3700,14 @@
###FIXME - The above assumes that the 'busyfirst' query var is at the
###end of the URL...
wholeurl = part1 + "?" + part2
- #map['url'] = "5, url=" + req['ACTUAL_URL'] + "?" + req['QUERY_STRING']
map['refreshurl'] = "5; url=" + wholeurl
req['specialpagetype'] = "1"
else:
- map['refreshurl'] = '5; url=\".\"'
+ try:
+ query = req['QUERY_STRING'].replace('&busyfirst=true', '')
+ map['refreshurl'] = '5; url=' + req['ACTUAL_URL'] + '?' + query
+ except:
+ map['refreshurl'] = '5; url=/luci/cluster?pagetype=3'
return map
def getClusterOS(self, rc):
@@ -3145,15 +3735,12 @@
try:
cluname = request['clustername']
- except KeyError, e:
+ except:
try:
cluname = request.form['clustername']
except:
luci_log.debug_verbose('getResourcesInfo missing cluster name')
return resList
- except:
- luci_log.debug_verbose('getResourcesInfo missing cluster name')
- return resList
for item in modelb.getResources():
itemmap = {}
@@ -3167,24 +3754,22 @@
def getResourceInfo(modelb, request):
if not modelb:
- luci_log.debug_verbose('no modelb obj in getResourceInfo')
+ luci_log.debug_verbose('GRI0: no modelb object in session')
return {}
name = None
try:
name = request['resourcename']
- except KeyError, e:
+ except:
try:
name = request.form['resourcename']
except:
pass
- except:
- pass
if name is None:
try:
- type = request.form['type']
- if type == 'ip':
+ res_type = request.form['type']
+ if res_type == 'ip':
name = request.form['value'].strip()
except:
pass
@@ -3195,15 +3780,12 @@
try:
cluname = request['clustername']
- except KeyError, e:
+ except:
try:
cluname = request.form['clustername']
except:
luci_log.debug_verbose('getResourceInfo missing cluster name')
return {}
- except:
- luci_log.debug_verbose('getResourceInfo missing cluster name')
- return {}
try:
baseurl = request['URL']
@@ -3225,41 +3807,47 @@
continue
def delResource(self, rc, request):
- errstr = 'An error occurred in while attempting to set the cluster.conf'
+ errstr = 'An error occurred while attempting to set the new cluster.conf'
try:
modelb = request.SESSION.get('model')
- except:
- luci_log.debug_verbose('delRes unable to extract model from SESSION')
+ except Exception, e:
+ luci_log.debug_verbose('delResource0: no model: %s' % str(e))
return errstr
+ name = None
try:
name = request['resourcename']
- except KeyError, e:
+ except:
try:
name = request.form['resourcename']
except:
- luci_log.debug_verbose('delRes missing resname %s' % str(e))
- return errstr + ': ' + str(e)
- except:
- luci_log.debug_verbose('delRes missing resname')
- return errstr + ': ' + str(e)
+ pass
+ if name is None:
+ luci_log.debug_verbose('delResource1: no resource name')
+ return errstr + ': no resource name was provided.'
+
+ clustername = None
try:
clustername = request['clustername']
- except KeyError, e:
+ except:
try:
clustername = request.form['clustername']
except:
- luci_log.debug_verbose('delRes missing cluster name')
- return errstr + ': could not determine the cluster name.'
+ pass
+
+ if clustername is None:
+ luci_log.debug_verbose('delResource2: no cluster name for %s' % name)
+ return errstr + ': could not determine the cluster name.'
try:
ragent = rc.hostname()
if not ragent:
- raise
- except:
- return errstr
+ raise Exception, 'unable to determine the hostname of the ricci agent'
+ except Exception, e:
+ luci_log.debug_verbose('delResource3: %s: %s' % (errstr, str(e)))
+ return errstr + ': could not determine the ricci agent hostname'
resPtr = modelb.getResourcesPtr()
resources = resPtr.getChildren()
@@ -3272,7 +3860,7 @@
break
if not found:
- luci_log.debug_verbose('delRes cant find res %s' % name)
+ luci_log.debug_verbose('delResource4: cant find res %s' % name)
return errstr + ': the specified resource was not found.'
try:
@@ -3280,36 +3868,22 @@
if not conf:
raise Exception, 'model string is blank'
except Exception, e:
- luci_log.debug_verbose('delRes: exportModelAsString failed: %s' % str(e))
+ luci_log.debug_verbose('delResource5: exportModelAsString failed: %s' \
+ % str(e))
return errstr
batch_number, result = setClusterConf(rc, str(conf))
if batch_number is None or result is None:
- luci_log.debug_verbose('delRes: missing batch and/or result from setClusterConf')
+ luci_log.debug_verbose('delResource6: missing batch and/or result')
return errstr
- modelstr = ""
- path = CLUSTER_FOLDER_PATH + str(clustername)
- clusterfolder = self.restrictedTraverse(path)
- batch_id = str(batch_number)
- objname = str(ragent) + '____flag'
- objpath = str(path + '/' + objname)
-
try:
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, RESOURCE_REMOVE, "string")
- flag.manage_addProperty(FLAG_DESC, "Removing Resource \'" + request['resourcename'] + "\'", "string")
+ set_node_flag(self, clustername, ragent, str(batch_number), RESOURCE_REMOVE, "Removing Resource \'%s\'" % request['resourcename'])
except Exception, e:
- luci_log.debug('delRes: An error occurred while setting flag %s: %s' \
- % (objname, str(e)))
- except:
- luci_log.debug('delRes: An error occurred while setting flag %s' % objname)
+ luci_log.debug_verbose('delResource7: failed to set flags: %s' % str(e))
response = request.RESPONSE
- response.redirect(request['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(request['URL'] + "?pagetype=" + RESOURCES + "&clustername=" + clustername + '&busyfirst=true')
def addIp(request, form=None):
if form is None:
@@ -3335,7 +3909,7 @@
return None
else:
try:
- res = apply(Ip)
+ res = Ip()
if not res:
raise Exception, 'apply(Ip) is None'
except Exception, e:
@@ -3391,7 +3965,7 @@
return None
else:
try:
- res = apply(Fs)
+ res = Fs()
if not res:
raise Exception, 'apply(Fs) is None'
except Exception, e:
@@ -3499,7 +4073,7 @@
return None
else:
try:
- res = apply(Clusterfs)
+ res = Clusterfs()
if not res:
raise Exception, 'apply(Clusterfs) is None'
except Exception, e:
@@ -3586,7 +4160,7 @@
return None
else:
try:
- res = apply(Netfs)
+ res = Netfs()
except Exception, e:
luci_log.debug_verbose('addNfsm error: %s' % str(e))
return None
@@ -3681,7 +4255,7 @@
return None
else:
try:
- res = apply(NFSClient)
+ res = NFSClient()
except:
luci_log.debug_verbose('addNfsc error: %s' % str(e))
return None
@@ -3745,7 +4319,7 @@
return None
else:
try:
- res = apply(NFSExport)
+ res = NFSExport()
except:
luci_log.debug_verbose('addNfsx error: %s', str(e))
return None
@@ -3793,7 +4367,7 @@
return None
else:
try:
- res = apply(Script)
+ res = Script()
except Exception, e:
luci_log.debug_verbose('addScr error: %s' % str(e))
return None
@@ -3814,10 +4388,10 @@
luci_log.debug_verbose('addScr error: %s' % err)
try:
- file = form['file'].strip()
- if not file:
+ path = form['file'].strip()
+ if not path:
raise KeyError, 'file path is blank'
- res.attr_hash['file'] = file
+ res.attr_hash['file'] = path
except Exception, e:
err = str(e)
errors.append(err)
@@ -3851,7 +4425,7 @@
return None
else:
try:
- res = apply(Samba)
+ res = Samba()
except Exception, e:
luci_log.debug_verbose('addSmb error: %s' % str(e))
return None
@@ -3900,7 +4474,7 @@
if not mb_nodes or not len(mb_nodes):
raise Exception, 'node list is empty'
except Exception, e:
- luci_log.debug_verbose('no model builder nodes found for %s: %s' \
+ luci_log.debug_verbose('RCC0: no model builder nodes found for %s: %s' \
% (str(e), clusterName))
return 'Unable to find cluster nodes for %s' % clusterName
@@ -3909,17 +4483,18 @@
if not cluster_node:
raise Exception, 'cluster node is none'
except Exception, e:
- luci_log.debug('cant find cluster node for %s: %s'
+ luci_log.debug('RCC1: cant find cluster node for %s: %s'
% (clusterName, str(e)))
return 'Unable to find an entry for %s in the Luci database.' % clusterName
try:
db_nodes = map(lambda x: x[0], cluster_node.objectItems('Folder'))
if not db_nodes or not len(db_nodes):
- raise
- except:
+ raise Exception, 'no database nodes'
+ except Exception, e:
# Should we just create them all? Can this even happen?
- return 'Unable to find database entries for any nodes in ' + clusterName
+ luci_log.debug('RCC2: error: %s' % str(e))
+ return 'Unable to find database entries for any nodes in %s' % clusterName
same_host = lambda x, y: x == y or x[:len(y) + 1] == y + '.' or y[:len(x) + 1] == x + '.'
@@ -3946,11 +4521,15 @@
messages = list()
for i in missing_list:
- cluster_node.delObjects([i])
- ## or alternately
- #new_node = cluster_node.restrictedTraverse(i)
- #setNodeFlag(self, new_node, CLUSTER_NODE_NOT_MEMBER)
- messages.append('Node \"' + i + '\" is no longer in a member of cluster \"' + clusterName + '.\". It has been deleted from the management interface for this cluster.')
+ try:
+ ## or alternately
+ ##new_node = cluster_node.restrictedTraverse(i)
+ ##setNodeFlag(self, new_node, CLUSTER_NODE_NOT_MEMBER)
+ cluster_node.delObjects([i])
+ messages.append('Node \"%s\" is no longer in a member of cluster \"%s\." It has been deleted from the management interface for this cluster.' % (i, clusterName))
+ luci_log.debug_verbose('VCC3: deleted node %s' % i)
+ except Exception, e:
+ luci_log.debug_verbose('VCC4: delObjects: %s: %s' % (i, str(e)))
new_flags = CLUSTER_NODE_NEED_AUTH | CLUSTER_NODE_ADDED
for i in new_list:
@@ -3958,69 +4537,66 @@
cluster_node.manage_addFolder(i, '__luci__:csystem:' + clusterName)
new_node = cluster_node.restrictedTraverse(i)
setNodeFlag(self, new_node, new_flags)
- messages.append('A new node, \"' + i + ',\" is now a member of cluster \"' + clusterName + '.\" It has added to the management interface for this cluster, but you must authenticate to it in order for it to be fully functional.')
- except:
- messages.append('A new node, \"' + i + ',\" is now a member of cluster \"' + clusterName + ',\". but has not added to the management interface for this cluster as a result of an error creating the database entry.')
+ messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s.\" It has been added to the management interface for this cluster, but you must authenticate to it in order for it to be fully functional.' % (i, clusterName))
+ except Exception, e:
+ messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s,\". but it has not been added to the management interface for this cluster as a result of an error creating a database entry for it.' % (i, clusterName))
+ luci_log.debug_verbose('VCC5: addFolder: %s/%s: %s' \
+ % (clusterName, i, str(e)))
return messages
-def addResource(self, request, modelb, res):
+def addResource(self, request, modelb, res, res_type):
clustername = modelb.getClusterName()
if not clustername:
- raise Exception, 'cluster name from modelb.getClusterName() is blank'
+ luci_log.debug_verbose('addResource0: no cluname from mb')
+ return 'Unable to determine cluster name'
rc = getRicciAgent(self, clustername)
if not rc:
- raise Exception, 'Unable to find a ricci agent for the %s cluster' % clustername
+ luci_log.debug_verbose('addResource1: unable to find a ricci agent for cluster %s' % clustername)
+ return 'Unable to find a ricci agent for the %s cluster' % clustername
- modelb.getResourcesPtr().addChild(res)
+ try:
+ modelb.getResourcesPtr().addChild(res)
+ except Exception, e:
+ luci_log.debug_verbose('addResource2: adding the new resource failed: %s' % str(e))
+ return 'Unable to add the new resource'
try:
conf = modelb.exportModelAsString()
if not conf:
raise Exception, 'model string for %s is blank' % clustername
except Exception, e:
- luci_log.debug_verbose('addResource: exportModelAsString err: %s' % str(e))
+ luci_log.debug_verbose('addResource3: exportModelAsString : %s' \
+ % str(e))
return 'An error occurred while adding this resource'
try:
ragent = rc.hostname()
if not ragent:
- luci_log.debug_verbose('missing hostname')
+ luci_log.debug_verbose('addResource4: missing ricci hostname')
raise Exception, 'unknown ricci agent hostname'
- luci_log.debug_verbose('SENDING NEW CLUSTER CONF: %s' % conf)
+
batch_number, result = setClusterConf(rc, str(conf))
if batch_number is None or result is None:
- luci_log.debug_verbose('missing batch_number or result')
- raise Exception, 'batch_number or results is None from setClusterConf'
+ luci_log.debug_verbose('addResource5: missing batch_number or result')
+ raise Exception, 'unable to save the new cluster configuration.'
except Exception, e:
+ luci_log.debug_verbose('addResource6: %s' % str(e))
return 'An error occurred while propagating the new cluster.conf: %s' % str(e)
- path = str(CLUSTER_FOLDER_PATH + clustername)
- clusterfolder = self.restrictedTraverse(path)
- batch_id = str(batch_number)
- objname = str(ragent + '____flag')
- objpath = str(path + '/' + objname)
+ if res_type != 'ip':
+ res_name = res.attr_hash['name']
+ else:
+ res_name = res.attr_hash['address']
try:
- clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
- #Now we need to annotate the new DB object
- flag = self.restrictedTraverse(objpath)
- flag.manage_addProperty(BATCH_ID, batch_id, "string")
- flag.manage_addProperty(TASKTYPE, RESOURCE_ADD, "string")
-
- if type != 'ip':
- flag.manage_addProperty(FLAG_DESC, "Creating New Resource \'" + res.attr_hash['name'] + "\'", "string")
- else:
- flag.manage_addProperty(FLAG_DESC, "Creating New Resource \'" + res.attr_hash['address'] + "\'", "string")
+ set_node_flag(self, clustername, ragent, str(batch_number), RESOURCE_ADD, "Creating New Resource \'%s\'" % res_name)
except Exception, e:
- try:
- luci_log.info('Unable to create flag %s: %s' % (objpath, str(e)))
- except:
- pass
+ luci_log.debug_verbose('addResource7: failed to set flags: %s' % str(e))
response = request.RESPONSE
- response.redirect(request['HTTP_REFERER'] + "&busyfirst=true")
+ response.redirect(request['URL'] + "?pagetype=" + RESOURCES + "&clustername=" + clustername + '&busyfirst=true')
def getResourceForEdit(modelb, name):
resPtr = modelb.getResourcesPtr()
@@ -4048,21 +4624,26 @@
clusterfolder = self.restrictedTraverse(path)
objs = clusterfolder.objectItems('Folder')
except Exception, e:
- luci_log.info('resolve_nodename failed for %s/%s: %s' \
+ luci_log.info('RNN0: error for %s/%s: %s' \
% (nodename, clustername, str(e)))
+ return nodename
for obj in objs:
- if obj[0].find(nodename) != (-1):
- return obj[0]
+ try:
+ if obj[0].find(nodename) != (-1):
+ return obj[0]
+ except:
+ continue
- luci_log.info('resolve_nodename failed for %s/%s' % (nodename, clustername))
- return None
+ luci_log.info('RNN1: failed for %s/%s: nothing found' \
+ % (nodename, clustername))
+ return nodename
def noNodeFlagsPresent(self, nodefolder, flagname, hostname):
try:
items = nodefolder.objectItems('ManagedSystem')
except:
- luci_log.debug('An error occurred while trying to list flags for cluster ' + nodefolder[0])
+ luci_log.debug('NNFP0: error getting flags for %s' % nodefolder[0])
return None
for item in items:
@@ -4071,9 +4652,10 @@
#a flag already exists... try to delete it
try:
+ # hostname must be a FQDN
rc = RicciCommunicator(hostname)
- except RicciError, e:
- luci_log.info('Unable to connect to the ricci daemon: %s' % str(e))
+ except Exception, e:
+ luci_log.info('NNFP1: ricci error %s: %s' % (hostname, str(e)))
return None
if not rc.authed():
@@ -4082,15 +4664,14 @@
setNodeFlag(snode, CLUSTER_NODE_NEED_AUTH)
except:
pass
- luci_log.info('Node %s is not authenticated' % item[0])
- return None
+ luci_log.info('NNFP2: %s not authenticated' % item[0])
finished = checkBatch(rc, item[1].getProperty(BATCH_ID))
if finished == True:
try:
nodefolder.manage_delObjects(item[0])
except Exception, e:
- luci_log.info('manage_delObjects for %s failed: %s' \
+ luci_log.info('NNFP3: manage_delObjects for %s failed: %s' \
% (item[0], str(e)))
return None
return True
@@ -4100,22 +4681,62 @@
return True
-def getModelBuilder(rc, isVirtualized):
+def getModelBuilder(self, rc, isVirtualized):
try:
cluster_conf_node = getClusterConf(rc)
if not cluster_conf_node:
- raise
- except:
- luci_log.debug('unable to get cluster_conf_node in getModelBuilder')
+ raise Exception, 'getClusterConf returned None'
+ except Exception, e:
+ luci_log.debug_verbose('GMB0: unable to get cluster_conf_node in getModelBuilder: %s' % str(e))
return None
try:
modelb = ModelBuilder(0, None, None, cluster_conf_node)
+ if not modelb:
+ raise Exception, 'ModelBuilder returned None'
except Exception, e:
try:
- luci_log.debug('An error occurred while trying to get modelb for conf \"%s\": %s' % (cluster_conf_node.toxml(), str(e)))
+ luci_log.debug_verbose('GMB1: An error occurred while trying to get modelb for conf \"%s\": %s' % (cluster_conf_node.toxml(), str(e)))
except:
- pass
+ luci_log.debug_verbose('GMB1: ModelBuilder failed')
- modelb.setIsVirtualized(isVirtualized)
+ if modelb:
+ modelb.setIsVirtualized(isVirtualized)
return modelb
+
+def getModelForCluster(self, clustername):
+ rc = getRicciAgent(self, clustername)
+ if not rc:
+ luci_log.debug_verbose('GMFC0: unable to find a ricci agent for %s' \
+ % clustername)
+ return None
+
+ try:
+ model = getModelBuilder(None, rc, rc.dom0())
+ if not model:
+ raise Exception, 'model is none'
+ except Exception, e:
+ luci_log.debug_verbose('GMFC1: unable to get model builder for %s: %s' \
+ % (clustername, str(e)))
+ return None
+
+ return model
+
+def set_node_flag(self, cluname, agent, batchid, task, desc):
+ path = str(CLUSTER_FOLDER_PATH + cluname)
+ batch_id = str(batchid)
+ objname = str(agent + '____flag')
+
+ try:
+ clusterfolder = self.restrictedTraverse(path)
+ clusterfolder.manage_addProduct['ManagedSystem'].addManagedSystem(objname)
+ objpath = str(path + '/' + objname)
+ flag = self.restrictedTraverse(objpath)
+ flag.manage_addProperty(BATCH_ID, batch_id, 'string')
+ flag.manage_addProperty(TASKTYPE, task, 'string')
+ flag.manage_addProperty(FLAG_DESC, desc, 'string')
+ except Exception, e:
+ errmsg = 'SNF0: error creating flag (%s,%s,%s) at %s: %s' \
+ % (batch_id, task, desc, objpath, str(e))
+ luci_log.debug_verbose(errmsg)
+ raise Exception, errmsg
--- conga/luci/site/luci/Extensions/conga_constants.py 2006/10/24 16:36:23 1.19.2.1
+++ conga/luci/site/luci/Extensions/conga_constants.py 2006/11/16 19:34:53 1.19.2.2
@@ -42,6 +42,13 @@
FENCEDEV_LIST="52"
FENCEDEV_CONFIG="53"
FENCEDEV="54"
+CLUSTER_DAEMON="55"
+
+#Cluster tasks
+CLUSTER_STOP = '1000'
+CLUSTER_START = '1001'
+CLUSTER_RESTART = '1002'
+CLUSTER_DELETE = '1003'
#General tasks
NODE_LEAVE_CLUSTER="100"
@@ -55,6 +62,13 @@
MULTICAST="203"
QUORUMD="204"
+PROPERTIES_TAB = 'tab'
+
+PROP_GENERAL_TAB = '1'
+PROP_FENCE_TAB = '2'
+PROP_MCAST_TAB = '3'
+PROP_QDISK_TAB = '4'
+
PAGETYPE="pagetype"
ACTIONTYPE="actiontype"
TASKTYPE="tasktype"
@@ -66,6 +80,9 @@
PATH_TO_PRIVKEY="/var/lib/luci/var/certs/privkey.pem"
PATH_TO_CACERT="/var/lib/luci/var/certs/cacert.pem"
+# Zope DB paths
+CLUSTER_FOLDER_PATH = '/luci/systems/cluster/'
+
#Node states
NODE_ACTIVE="0"
NODE_INACTIVE="1"
@@ -75,26 +92,36 @@
NODE_UNKNOWN_STR="Unknown State"
#cluster/node create batch task index
-INSTALL_TASK=1
-REBOOT_TASK=2
-SEND_CONF=3
-START_NODE=4
-RICCI_CONNECT_FAILURE=(-1000)
+INSTALL_TASK = 1
+DISABLE_SVC_TASK = 2
+REBOOT_TASK = 3
+SEND_CONF = 4
+ENABLE_SVC_TASK = 5
+START_NODE = 6
+RICCI_CONNECT_FAILURE = (-1000)
-RICCI_CONNECT_FAILURE_MSG="A problem was encountered connecting with this node. "
+RICCI_CONNECT_FAILURE_MSG = "A problem was encountered connecting with this node. "
#cluster/node create error messages
-CLUNODE_CREATE_ERRORS = ["An unknown error occurred when creating this node: ", "A problem occurred when installing packages: ","A problem occurred when rebooting this node: ", "A problem occurred when propagating the configuration to this node: ", "A problem occurred when starting this node: "]
+CLUNODE_CREATE_ERRORS = [
+ "An unknown error occurred when creating this node: ",
+ "A problem occurred when installing packages: ",
+ "A problem occurred when disabling cluster services on this node: ",
+ "A problem occurred when rebooting this node: ",
+ "A problem occurred when propagating the configuration to this node: ",
+ "A problem occurred when enabling cluster services on this node: ",
+ "A problem occurred when starting this node: "
+]
#cluster/node create error status messages
-PRE_INSTALL="The install state is not yet complete"
-PRE_REBOOT="Installation complete, but reboot not yet complete"
-PRE_CFG="Reboot stage successful, but configuration for the cluster is not yet distributed"
-PRE_JOIN="Packages are installed and configuration has been distributed, but the node has not yet joined the cluster."
+PRE_INSTALL = "The install state is not yet complete"
+PRE_REBOOT = "Installation complete, but reboot not yet complete"
+PRE_CFG = "Reboot stage successful, but configuration for the cluster is not yet distributed"
+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<br/>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."
+REDIRECT_MSG = " You will be redirected in 5 seconds. Please fasten your safety restraints."
# Homebase-specific constants
@@ -112,7 +139,7 @@
CLUSTER_NODE_NOT_MEMBER = 0x02
CLUSTER_NODE_ADDED = 0x04
-PLONE_ROOT='luci'
+PLONE_ROOT = 'luci'
LUCI_DEBUG_MODE = 1
LUCI_DEBUG_VERBOSITY = 2
--- conga/luci/site/luci/Extensions/homebase_adapters.py 2006/11/01 22:06:55 1.34.2.5
+++ conga/luci/site/luci/Extensions/homebase_adapters.py 2006/11/16 19:34:53 1.34.2.6
@@ -1,23 +1,20 @@
-import string
import re
-import sys
import os
from AccessControl import getSecurityManager
-from ZPublisher import HTTPRequest
-import xml.dom
import cgi
-from ricci_defines import *
+from conga_constants import PLONE_ROOT, CLUSTER_NODE_NEED_AUTH, \
+ HOMEBASE_ADD_CLUSTER, HOMEBASE_ADD_CLUSTER_INITIAL, \
+ HOMEBASE_ADD_SYSTEM, HOMEBASE_ADD_USER, \
+ HOMEBASE_DEL_SYSTEM, HOMEBASE_DEL_USER, HOMEBASE_PERMS
from ricci_bridge import getClusterConf
-from ricci_communicator import RicciCommunicator
-from ricci_communicator import CERTS_DIR_PATH
+from ricci_communicator import RicciCommunicator, CERTS_DIR_PATH
from clusterOS import resolveOSType
-from conga_constants import *
-from LuciSyslog import LuciSyslog, LuciSyslogError
+from LuciSyslog import LuciSyslog
try:
luci_log = LuciSyslog()
-except LuciSyslogError, e:
+except:
pass
def siteIsSetup(self):
@@ -27,8 +24,8 @@
except: pass
return False
-def strFilter(regex, replaceChar, str):
- return re.sub(regex, replaceChar, str)
+def strFilter(regex, replaceChar, arg):
+ return re.sub(regex, replaceChar, arg)
def validateDelSystem(self, request):
errors = list()
@@ -74,6 +71,8 @@
try:
user = self.portal_membership.getMemberById(userId)
+ if not user:
+ raise Exception, 'user %s does not exist' % userId
except:
return (False, {'errors': [ 'No such user: \"' + userId + '\"' ] })
@@ -138,8 +137,12 @@
rc = RicciCommunicator(host)
rc.unauth()
i['cur_auth'] = False
- except:
- pass
+ except Exception, e:
+ try:
+ luci_log.debug_verbose('unauth for %s failed: %s' \
+ % (i['host'], str(e)))
+ except:
+ pass
def nodeAuth(cluster, host, passwd):
messages = list()
@@ -531,7 +534,7 @@
i[1].manage_setLocalRoles(userId, roles)
messages.append('Added permission for ' + userId + ' for cluster ' + i[0])
except:
- errors.append('Failed to add permission for ' + userId + ' for cluster ' + i[0])
+ errors.append('Failed to add permission for ' + userId + ' for cluster ' + i[0])
else:
try:
if user.has_role('View', i[1]):
@@ -545,7 +548,7 @@
messages.append('Removed permission for ' + userId + ' for cluster ' + i[0])
except:
- errors.append('Failed to remove permission for ' + userId + ' for cluster ' + i[0])
+ errors.append('Failed to remove permission for ' + userId + ' for cluster ' + i[0])
storage = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
if not '__SYSTEM' in request.form:
@@ -572,7 +575,7 @@
i[1].manage_setLocalRoles(userId, roles)
messages.append('Added permission for ' + userId + ' for system ' + i[0])
except:
- errors.append('Failed to add permission for ' + userId + ' for system ' + i[0])
+ errors.append('Failed to add permission for ' + userId + ' for system ' + i[0])
else:
try:
if user.has_role('View', i[1]):
@@ -586,7 +589,7 @@
messages.append('Removed permission for ' + userId + ' for system ' + i[0])
except:
- errors.append('Failed to remove permission for ' + userId + ' for system ' + i[0])
+ errors.append('Failed to remove permission for ' + userId + ' for system ' + i[0])
if len(errors) > 0:
returnCode = False
@@ -665,23 +668,25 @@
]
def userAuthenticated(self):
- if (isAdmin(self) or getSecurityManager().getUser().has_role('Authenticated', self.restrictedTraverse(PLONE_ROOT))):
- return True
-
+ try:
+ if (isAdmin(self) or getSecurityManager().getUser().has_role('Authenticated', self.restrictedTraverse(PLONE_ROOT))):
+ return True
+ except Exception, e:
+ luci_log.debug_verbose('UA0: %s' % str(e))
return False
def isAdmin(self):
try:
return getSecurityManager().getUser().has_role('Owner', self.restrictedTraverse(PLONE_ROOT))
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('IA0: %s' % str(e))
return False
def userIsAdmin(self, userId):
try:
return self.portal_membership.getMemberById(userId).has_role('Owner', self.restrictedTraverse(PLONE_ROOT))
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('UIA0: %s: %s' % (userId, str(e)))
return False
def homebaseControlPost(self, request):
@@ -698,15 +703,19 @@
if 'pagetype' in request.form:
pagetype = int(request.form['pagetype'])
else:
- try: request.SESSION.set('checkRet', {})
- except: pass
+ try:
+ request.SESSION.set('checkRet', {})
+ except:
+ pass
return homebasePortal(self, request, '.', '0')
try:
validatorFn = formValidators[pagetype - 1]
except:
- try: request.SESSION.set('checkRet', {})
- except: pass
+ try:
+ request.SESSION.set('checkRet', {})
+ except:
+ pass
return homebasePortal(self, request, '.', '0')
if validatorFn == validateAddClusterInitial or validatorFn == validateAddCluster:
@@ -913,71 +922,111 @@
def getClusterSystems(self, clusterName):
if isAdmin(self):
- return self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName + '/objectItems')('Folder')
+ try:
+ return self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName + '/objectItems')('Folder')
+ except Exception, e:
+ luci_log.debug_verbose('GCS0: %s: %s' % (clusterName, str(e)))
+ return None
try:
i = getSecurityManager().getUser()
if not i:
- raise
- except:
+ raise Exception, 'GCSMGU failed'
+ except Exception, e:
+ luci_log.debug_verbose('GCS1: %s: %s' % (clusterName, str(e)))
return None
- csystems = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName + '/objectItems')('Folder')
- if not csystems:
+ try:
+ csystems = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName + '/objectItems')('Folder')
+ if not csystems or len(csystems) < 1:
+ return None
+ except Exception, e:
+ luci_log.debug_verbose('GCS2: %s: %s' % (clusterName, str(e)))
return None
allowedCSystems = list()
for c in csystems:
- if i.has_role('View', c[1]):
- allowedCSystems.append(c)
- return (c)
+ try:
+ if i.has_role('View', c[1]):
+ allowedCSystems.append(c)
+ except Exception, e:
+ luci_log.debug_verbose('GCS3: %s: %s: %s' \
+ % (clusterName, c[0], str(e)))
+
+ return allowedCSystems
def getClusters(self):
if isAdmin(self):
- return self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
+ try:
+ return self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
+ except Exception, e:
+ luci_log.debug_verbose('GC0: %s' % str(e))
+ return None
try:
i = getSecurityManager().getUser()
if not i:
- raise
- except:
+ raise Exception, 'GSMGU failed'
+ except Exception, e:
+ luci_log.debug_verbose('GC1: %s' % str(e))
return None
- clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
- if not clusters:
+ try:
+ clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
+ if not clusters or len(clusters) < 1:
+ return None
+ except Exception, e:
+ luci_log.debug_verbose('GC2: %s' % str(e))
return None
allowedClusters = list()
for c in clusters:
- if i.has_role('View', c[1]):
- allowedClusters.append(c)
+ try:
+ if i.has_role('View', c[1]):
+ allowedClusters.append(c)
+ except Exception, e:
+ luci_log.debug_verbose('GC3: %s: %s' % (c[0], str(e)))
return allowedClusters
def getStorage(self):
if isAdmin(self):
- return self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
+ try:
+ return self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
+ except Exception, e:
+ luci_log.debug_verbose('GS0: %s' % str(e))
+ return None
+
try:
i = getSecurityManager().getUser()
if not i:
- return None
- except:
+ raise Exception, 'GSMGU failed'
+ except Exception, e:
+ luci_log.debug_verbose('GS1: %s' % str(e))
return None
- storage = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
- if not storage:
+ try:
+ storage = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
+ if not storage or len(storage) < 1:
+ return None
+ except Exception, e:
+ luci_log.debug_verbose('GS2: %s' % str(e))
return None
allowedStorage = list()
for s in storage:
- if i.has_role('View', s[1]):
- allowedStorage.append(s)
+ try:
+ if i.has_role('View', s[1]):
+ allowedStorage.append(s)
+ except Exception, e:
+ luci_log.debug_verbose('GS3: %s' % str(e))
return allowedStorage
def createSystem(self, host, passwd):
try:
exists = self.restrictedTraverse(PLONE_ROOT +'/systems/storage/' + host)
- return 'Storage system \"' + host + '\" is already managed.'
+ luci_log.debug_verbose('CS0: %s already exists' % host)
+ return 'Storage system %s is already managed' % host
except:
pass
@@ -986,49 +1035,52 @@
if rc is None:
raise Exception, 'unknown error'
except Exception, e:
+ luci_log.debug_verbose('CS1: %s: %s' % (host, str(e)))
return 'Unable to establish a connection to the ricci agent on %s: %s' \
% (host, str(e))
try:
if not rc.authed():
rc.auth(passwd)
- except:
- return 'Unable to communicate with the ricci agent on \"' + host + '\" for authentication'
+ except Exception, e:
+ luci_log.debug_verbose('CS2: %s: %s' % (host, str(e)))
+ return 'Unable to communicate with the ricci agent on %s for authentication' % host
try:
i = rc.authed()
- except:
- return 'Unable to authenticate to the ricci agent on \"' + host + '\"'
+ except Exception, e:
+ luci_log.debug_verbose('CS3 %s: %s' % (host, str(e)))
+ return 'Unable to authenticate to the ricci agent on %s' % host
if i != True:
- return 'Authentication for storage system \"' + host + '\" failed'
-
-# rhost = rc.system_name()
-# if rhost and rhost != host and rhost[:9] != 'localhost' and rhost[:5] != '127.0':
-# host = str(rhost)
+ return 'Authentication for storage system %s failed' % host
try:
- exists = self.restrictedTraverse(PLONE_ROOT +'/systems/storage/' + host)
- return 'Storage system \"' + host + '\" is already managed.'
+ exists = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
+ luci_log.debug_verbose('CS4 %s already exists' % host)
+ return 'Storage system %s is already managed' % host
except:
pass
try:
ssystem = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/')
except Exception, e:
- return 'Unable to create storage system %s: %s' % (host, str(e))
+ luci_log.debug_verbose('CS5 %s: %s' % (host, str(e)))
+ return 'Unable to create storage system %s: %s' % host
try:
ssystem.manage_addFolder(host, '__luci__:system')
newSystem = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
except Exception, e:
- return 'Unable to create storage system %s: %s' % (host, str(e))
+ luci_log.debug_verbose('CS6 %s: %s' % (host, str(e)))
+ return 'Unable to create DB entry for storage system %s' % host
try:
newSystem.manage_acquiredPermissions([])
- newSystem.manage_role('View', ['Access contents information','View'])
+ newSystem.manage_role('View', ['Access contents information', 'View'])
except Exception, e:
- return 'Unable to set permissions on storage system %s: %s' % (host, str(e))
+ luci_log.debug_verbose('CS7 %s: %s' % (host, str(e)))
+ return 'Unable to set permissions on storage system %s' % host
return None
@@ -1036,26 +1088,27 @@
try:
sessionData = request.SESSION.get('checkRet')
nodeUnauth(sessionData['requestResults']['nodeList'])
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('AMC0: %s' % str(e))
def manageCluster(self, clusterName, nodeList):
clusterName = str(clusterName)
- luci_log.debug_verbose('manageCluster for %s' % clusterName)
try:
clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/')
if not clusters:
raise Exception, 'cannot find the cluster entry in the DB'
- except:
+ except Exception, e:
nodeUnauth(nodeList)
- return 'Unable to create cluster \"' + clusterName + '\": the cluster directory is missing.'
+ luci_log.debug_verbose('MC0: %s: %s' % (clusterName, str(e)))
+ return 'Unable to create cluster %s: the cluster directory is missing.' % clusterName
try:
newCluster = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName)
if newCluster:
nodeUnauth(nodeList)
- return 'A cluster named \"' + clusterName + '\" is already managed by Luci'
+ luci_log.debug_verbose('MC1: cluster %s: already exists' % clusterName)
+ return 'A cluster named %s is already managed by Luci' % clusterName
except:
pass
@@ -1063,20 +1116,22 @@
clusters.manage_addFolder(clusterName, '__luci__:cluster')
newCluster = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName)
if not newCluster:
- raise Exception, 'unable to find cluster folder for %s' % clusterName
+ raise Exception, 'unable to create the cluster DB entry for %s' % clusterName
except Exception, e:
nodeUnauth(nodeList)
+ luci_log.debug_verbose('MC2: %s: %s' % (clusterName, str(e)))
return 'Unable to create cluster %s: %s' % (clusterName, str(e))
try:
newCluster.manage_acquiredPermissions([])
- newCluster.manage_role('View', ['Access Contents Information','View'])
+ newCluster.manage_role('View', ['Access Contents Information', 'View'])
except Exception, e:
+ luci_log.debug_verbose('MC3: %s: %s' % (clusterName, str(e)))
nodeUnauth(nodeList)
try:
clusters.manage_delObjects([clusterName])
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('MC4: %s: %s' % (clusterName, str(e)))
return 'Unable to set permissions on new cluster: %s: %s' % (clusterName, str(e))
try:
@@ -1084,14 +1139,14 @@
if not cluster_os:
raise KeyError, 'Cluster OS is blank'
except KeyError, e:
- luci_log.debug_verbose('Warning adding cluster %s: %s' \
- % (clusterName, str(e)))
+ luci_log.debug_verbose('MC5: %s: %s' % (clusterName, str(e)))
cluster_os = 'rhel5'
try:
newCluster.manage_addProperty('cluster_os', cluster_os, 'string')
- except:
- pass # we were unable to set the OS property string on this cluster
+ except Exception, e:
+ luci_log.debug_verbose('MC5: %s: %s: %s' \
+ % (clusterName, cluster_os, str(e)))
for i in nodeList:
#if 'ricci_host' in i:
@@ -1103,15 +1158,19 @@
newCluster.manage_addFolder(host, '__luci__:csystem:' + clusterName)
newSystem = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName + '/' + host)
if not newSystem:
- raise Exception, 'unable to create cluster system DB entry'
+ raise Exception, 'unable to create cluster system DB entry for node %s' % host
newSystem.manage_acquiredPermissions([])
newSystem.manage_role('View', [ 'Access contents information' , 'View' ])
except Exception, e:
nodeUnauth(nodeList)
try:
clusters.manage_delObjects([clusterName])
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('MC6: %s: %s: %s' \
+ % (clusterName, host, str(e)))
+
+ luci_log.debug_verbose('MC7: %s: %s: %s' \
+ % (clusterName, host, str(e)))
return 'Unable to create cluster node %s for cluster %s: %s' \
% (host, clusterName, str(e))
@@ -1120,6 +1179,7 @@
if not ssystem:
raise Exception, 'The storage DB entry is missing'
except Exception, e:
+ luci_log.debug_verbose('MC8: %s: %s: %s' % (clusterName, host, str(e)))
return 'Error adding storage node %s: %s' % (host, str(e))
# Only add storage systems if the cluster and cluster node DB
@@ -1134,22 +1194,25 @@
# It's already there, as a storage system, no problem.
exists = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
continue
- except: pass
+ except:
+ pass
try:
ssystem.manage_addFolder(host, '__luci__:system')
newSystem = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
newSystem.manage_acquiredPermissions([])
newSystem.manage_role('View', [ 'Access contents information' , 'View' ])
- except: pass
+ except Exception, e:
+ luci_log.debug_verbose('MC9: %s: %s: %s' % (clusterName, host, str(e)))
def createClusterSystems(self, clusterName, nodeList):
try:
clusterObj = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName)
if not clusterObj:
raise Exception, 'cluster %s DB entry is missing' % clusterName
- except:
+ except Exception, e:
nodeUnauth(nodeList)
+ luci_log.debug_verbose('CCS0: %s: %s' % (clusterName, str(e)))
return 'No cluster named \"' + clusterName + '\" is managed by Luci'
for i in nodeList:
@@ -1168,6 +1231,7 @@
newSystem.manage_role('View', [ 'Access contents information' , 'View' ])
except Exception, e:
nodeUnauth(nodeList)
+ luci_log.debug_verbose('CCS1: %s: %s: %s' % (clusterName, host, str(e)))
return 'Unable to create cluster node %s for cluster %s: %s' \
% (host, clusterName, str(e))
@@ -1176,8 +1240,7 @@
if not ssystem:
raise Exception, 'storage DB entry is missing'
except Exception, e:
- luci_log.debug_verbose('Error: adding storage DB node for %s: %s' \
- % (host, str(e)))
+ luci_log.debug_verbose('CCS2: %s: %s' % (clusterName, host, str(e)))
return
# Only add storage systems if the and cluster node DB
@@ -1192,14 +1255,16 @@
# It's already there, as a storage system, no problem.
exists = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
continue
- except: pass
+ except:
+ pass
try:
ssystem.manage_addFolder(host, '__luci__:system')
newSystem = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + host)
newSystem.manage_acquiredPermissions([])
newSystem.manage_role('View', [ 'Access contents information' , 'View' ])
- except: pass
+ except Exception, e:
+ luci_log.debug_verbose('CCS3: %s: %s' % (clusterName, host, str(e)))
def delSystem(self, systemName):
try:
@@ -1207,6 +1272,7 @@
if not ssystem:
raise Exception, 'storage DB entry is missing'
except Exception, e:
+ luci_log.debug_verbose('delSystem0: %s: %s' % (systemName, str(e)))
return 'Unable to find storage system %s: %s' % (systemName, str(e))
try:
@@ -1216,27 +1282,33 @@
except Exception, e:
try:
ssystem.manage_delObjects([systemName])
- except:
- return 'Unable to delete the storage system \"' + systemName + '\"'
- luci_log.debug_verbose('ricci error for %s: %s' % (systemName, str(e)))
+ except Exception, e:
+ luci_log.debug_verbose('delSystem1: %s: %s' % (systemName, str(e)))
+ return 'Unable to delete the storage system %s' % systemName
+ luci_log.debug_verbose('delSystem2: %s: %s' % (systemName, str(e)))
return
# Only unauthenticate if the system isn't a member of
# a managed cluster.
cluster_info = rc.cluster_info()
if not cluster_info[0]:
- try: rc.unauth()
- except: pass
+ try:
+ rc.unauth()
+ except:
+ pass
else:
try:
newSystem = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + cluster_info[0] + '/' + systemName)
except:
- try: rc.unauth()
- except: pass
+ try:
+ rc.unauth()
+ except:
+ pass
try:
ssystem.manage_delObjects([systemName])
except Exception, e:
+ luci_log.debug_verbose('delSystem3: %s: %s' % (systemName, str(e)))
return 'Unable to delete storage system %s: %s' \
% (systemName, str(e))
@@ -1244,9 +1316,10 @@
try:
clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/')
if not clusters:
- raise
- except:
- return 'Unable to find cluster \"' + clusterName + '\"'
+ raise Exception, 'clusters DB entry is missing'
+ except Exception, e:
+ luci_log.debug_verbose('delCluster0: %s' % str(e))
+ return 'Unable to find cluster %s' % clusterName
err = delClusterSystems(self, clusterName)
if err:
@@ -1254,26 +1327,28 @@
try:
clusters.manage_delObjects([clusterName])
- except:
- return 'Unable to delete cluster \"' + clusterName + '\"'
+ except Exception, e:
+ luci_log.debug_verbose('delCluster1: %s' % str(e))
+ return 'Unable to delete cluster %s' % clusterName
def delClusterSystem(self, cluster, systemName):
try:
if not self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + systemName):
raise
except:
+ # It's not a storage system, so unauthenticate.
try:
rc = RicciCommunicator(systemName)
rc.unauth()
except Exception, e:
- luci_log.debug_verbose('ricci error for %s: %s' \
+ luci_log.debug_verbose('delClusterSystem0: ricci error for %s: %s' \
% (systemName, str(e)))
try:
cluster.manage_delObjects([systemName])
except Exception, e:
err_str = 'Error deleting cluster object %s: %s' % (systemName, str(e))
- luci_log.debug_verbose(err_str)
+ luci_log.debug_verbose('delClusterSystem1: %s' % err_str)
return err_str
def delClusterSystems(self, clusterName):
@@ -1285,7 +1360,7 @@
except Exception, e:
luci_log.debug_verbose('delCluSysterms: error for %s: %s' \
% (clusterName, str(e)))
- return 'Unable to find any systems for cluster \"' + clusterName + '\"'
+ return 'Unable to find any systems for cluster %s' % clusterName
errors = ''
for i in csystems:
@@ -1297,34 +1372,65 @@
def getDefaultUser(self, request):
try:
user = request.form['userList']
- except:
+ except KeyError, e:
try:
user = request['user']
except:
try:
- user = self.portal_membership.listMembers()[0].getUserName()
- except:
+ members = list()
+ members.extend(self.portal_membership.listMembers())
+ members.sort()
+ user = members[0].getUserName()
+ except Exception, e:
+ luci_log.debug_verbose('getDefaultUser0: %s' % str(e))
user = None
+ if not user:
+ luci_log.debug_verbose('getDefaultUser1: user is none')
return user
def getUserPerms(self):
perms = {}
- for i in self.portal_membership.listMembers():
+
+ try:
+ members = list()
+ members.extend(self.portal_membership.listMembers())
+ if len(members) < 1:
+ raise Exception, 'no portal members exist'
+ members.sort()
+ except Exception, e:
+ luci_log.debug_verbose('getUserPerms0: %s' % str(e))
+ return {}
+
+ for i in members:
userName = i.getUserName()
perms[userName] = {}
perms[userName]['cluster'] = {}
perms[userName]['storage'] = {}
- clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
- storage = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
+ try:
+ clusters = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/objectItems')('Folder')
+ storage = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/objectItems')('Folder')
+ except Exception, e:
+ luci_log.debug_verbose('getUserPerms1: user %s: %s' % (userName, str(e)))
+ continue
for c in clusters:
- perms[userName]['cluster'][c[0]] = i.has_role('View', c[1])
-
+ try:
+ perms[userName]['cluster'][c[0]] = i.has_role('View', c[1])
+ except Exception, e:
+ luci_log.debug_verbose('getUserPerms2: user %s, obj %s: %s' \
+ % (userName, c[0], str(e)))
+ continue
+
for s in storage:
- perms[userName]['storage'][s[0]] = i.has_role('View', s[1])
+ try:
+ perms[userName]['storage'][s[0]] = i.has_role('View', s[1])
+ except Exception, e:
+ luci_log.debug_verbose('getUserPerms2: user %s, obj %s: %s' \
+ % (userName, s[0], str(e)))
+ continue
return perms
@@ -1397,39 +1503,52 @@
def getClusterNode(self, nodename, clustername):
try:
cluster_node = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + str(clustername) + '/' + str(nodename))
+ if not cluster_node:
+ raise Exception, 'cluster node is none'
return cluster_node
- except:
+ except Exception, e:
+ luci_log.debug_verbose('getClusterNode0: %s %s: %s' \
+ % (nodename, clustername, str(e)))
return None
def getStorageNode(self, nodename):
try:
storage_node = self.restrictedTraverse(PLONE_ROOT + '/systems/storage/' + '/' + str(nodename))
+ if not storage_node:
+ raise Exception, 'storage node is none'
return storage_node
- except:
+ except Exception, e:
+ luci_log.debug_verbose('getStorageNode0: %s: %s' % (nodename, str(e)))
return None
def testNodeFlag(node, flag_mask):
try:
flags = node.getProperty('flags')
+ if flags is None:
+ return False
return flags & flag_mask != 0
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('testNodeFlag0: %s' % str(e))
return False
def setNodeFlag(node, flag_mask):
try:
flags = node.getProperty('flags')
+ if flags is None:
+ flags = 0
node.manage_changeProperties({ 'flags': flags | flag_mask })
except:
try:
node.manage_addProperty('flags', flag_mask, 'int')
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('setNodeFlag0: %s' % str(e))
def delNodeFlag(node, flag_mask):
try:
flags = node.getProperty('flags')
+ if flags is None:
+ return
if flags & flag_mask != 0:
node.manage_changeProperties({ 'flags': flags & ~flag_mask })
- except:
- pass
+ except Exception, e:
+ luci_log.debug_verbose('delNodeFlag0: %s' % str(e))
--- conga/luci/site/luci/Extensions/ricci_bridge.py 2006/11/01 22:06:55 1.30.2.6
+++ conga/luci/site/luci/Extensions/ricci_bridge.py 2006/11/16 19:34:53 1.30.2.7
@@ -18,7 +18,7 @@
return False
try:
- batchid = batch.getAttribute('batch_id')
+ dummy = batch.getAttribute('batch_id')
result = batch.getAttribute('status')
except:
return False
@@ -28,7 +28,8 @@
return False
-def addClusterNodeBatch(cluster_name,
+def addClusterNodeBatch(os_str,
+ cluster_name,
install_base,
install_services,
install_shared_storage,
@@ -65,13 +66,31 @@
need_reboot = install_base or install_services or install_shared_storage or install_LVS
if need_reboot:
+ batch += '<module name="service">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="disable">'
+ batch += '<var mutable="false" name="services" type="list_xml">'
+ if os_str == 'rhel4':
+ batch += '<service name="ccsd"/>'
+ batch += '<service name="cman"/>'
+ batch += '</var>'
+ batch += '</function_call>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="reboot">'
batch += '<request API_version="1.0">'
batch += '<function_call name="reboot_now"/>'
batch += '</request>'
batch += '</module>'
else:
- # need placeholder instead of reboot
+ # need 2 placeholders instead of disable services / reboot
+ batch += '<module name="rpm">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="install"/>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="rpm">'
batch += '<request API_version="1.0">'
batch += '<function_call name="install"/>'
@@ -95,6 +114,26 @@
batch += '</request>'
batch += '</module>'
+ if need_reboot:
+ batch += '<module name="service">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="enable">'
+ batch += '<var mutable="false" name="services" type="list_xml">'
+ if os_str == 'rhel4':
+ batch += '<service name="ccsd"/>'
+ batch += '<service name="cman"/>'
+ batch += '</var>'
+ batch += '</function_call>'
+ batch += '</request>'
+ batch += '</module>'
+ else:
+ # placeholder instead of enable services
+ batch += '<module name="rpm">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="install"/>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="cluster">'
batch += '<request API_version="1.0">'
batch += '<function_call name="start_node"/>'
@@ -114,13 +153,6 @@
install_LVS,
upgrade_rpms):
- if os_str == 'rhel5':
- cluster_version = '5'
- elif os_str == 'rhel4':
- cluster_version = '4'
- else:
- cluster_version = 'unknown'
-
batch = '<?xml version="1.0" ?>'
batch += '<batch>'
batch += '<module name="rpm">'
@@ -149,13 +181,31 @@
need_reboot = install_base or install_services or install_shared_storage or install_LVS
if need_reboot:
+ batch += '<module name="service">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="disable">'
+ batch += '<var mutable="false" name="services" type="list_xml">'
+ if os_str == 'rhel4':
+ batch += '<service name="ccsd"/>'
+ batch += '<service name="cman"/>'
+ batch += '</var>'
+ batch += '</function_call>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="reboot">'
batch += '<request API_version="1.0">'
batch += '<function_call name="reboot_now"/>'
batch += '</request>'
batch += '</module>'
else:
- # need placeholder instead of reboot
+ # need 2 placeholders instead of disable services / reboot
+ batch += '<module name="rpm">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="install"/>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="rpm">'
batch += '<request API_version="1.0">'
batch += '<function_call name="install"/>'
@@ -195,6 +245,26 @@
batch += '</request>'
batch += '</module>'
+ if need_reboot:
+ batch += '<module name="service">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="enable">'
+ batch += '<var mutable="false" name="services" type="list_xml">'
+ if os_str == 'rhel4':
+ batch += '<service name="ccsd"/>'
+ batch += '<service name="cman"/>'
+ batch += '</var>'
+ batch += '</function_call>'
+ batch += '</request>'
+ batch += '</module>'
+ else:
+ # placeholder instead of enable services
+ batch += '<module name="rpm">'
+ batch += '<request API_version="1.0">'
+ batch += '<function_call name="install"/>'
+ batch += '</request>'
+ batch += '</module>'
+
batch += '<module name="cluster">'
batch += '<request API_version="1.0">'
batch += '<function_call name="start_node">'
@@ -276,7 +346,7 @@
return doc
def getClusterStatusBatch(rc):
- batch_str ='<module name="cluster"><request API_version="1.0"><function_call name="status"/></request></module>'
+ 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:
@@ -308,7 +378,7 @@
def getNodeLogs(rc):
errstr = 'log not accessible'
- batch_str = '<module name="log"><request sequence="1254" API_version="1.0"><function_call name="get"><var mutable="false" name="age" type="int" value="18000"/><var mutable="false" name="tags" type="list_str"></var></function_call></request></module>'
+ batch_str = '<module name="log"><request API_version="1.0"><function_call name="get"><var mutable="false" name="age" type="int" value="18000"/><var mutable="false" name="tags" type="list_str"></var></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str, async=False)
if not ricci_xml:
@@ -318,8 +388,8 @@
if not log_entries or len(log_entries) < 1:
raise Exception, 'no log data is available.'
except Exception, e:
- 'Error retrieving log data from %s: %s' \
- % (rc.hostname(), str(e))
+ luci_log.debug_verbose('Error retrieving log data from %s: %s' \
+ % (rc.hostname(), str(e)))
return None
time_now = time()
entry = ''
@@ -357,7 +427,7 @@
return entry
def nodeReboot(rc):
- batch_str = '<module name="reboot"><request sequence="111" API_version="1.0"><function_call name="reboot_now"/></request></module>'
+ batch_str = '<module name="reboot"><request API_version="1.0"><function_call name="reboot_now"/></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
@@ -371,13 +441,13 @@
if purge == False:
purge_conf = 'false'
- batch_str = '<module name="cluster"><request sequence="111" API_version="1.0"><function_call name="stop_node"><var mutable="false" name="cluster_shutdown" type="boolean" value="' + cshutdown + '"/><var mutable="false" name="purge_conf" type="boolean" value="' + purge_conf + '"/></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="stop_node"><var mutable="false" name="cluster_shutdown" type="boolean" value="' + cshutdown + '"/><var mutable="false" name="purge_conf" type="boolean" value="' + purge_conf + '"/></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
def nodeFence(rc, nodename):
- batch_str = '<module name="cluster"><request sequence="111" API_version="1.0"><function_call name="fence_node"><var mutable="false" name="nodename" type="string" value="' + nodename + '"/></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="fence_node"><var mutable="false" name="nodename" type="string" value="' + nodename + '"/></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
@@ -387,28 +457,48 @@
if cluster_startup == True:
cstartup = 'true'
- batch_str = '<module name="cluster"><request sequence="111" API_version="1.0"><function_call name="start_node"><var mutable="false" name="cluster_startup" type="boolean" value="' + cstartup + '"/></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="start_node"><var mutable="false" name="cluster_startup" type="boolean" value="' + cstartup + '"/></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
def startService(rc, servicename, preferrednode=None):
if preferrednode != None:
- batch_str = '<module name="cluster"><request sequence="1254" API_version="1.0"><function_call name="start_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/><var mutable="false" name="nodename" type="string" value=\"' + preferrednode + '\" /></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="start_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/><var mutable="false" name="nodename" type="string" value=\"' + preferrednode + '\" /></function_call></request></module>'
else:
- batch_str = '<module name="cluster"><request sequence="1254" API_version="1.0"><function_call name="start_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="start_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
+def updateServices(rc, enable_list, disable_list):
+ batch = ''
+
+ if enable_list and len(enable_list) > 0:
+ batch += '<module name="service"><request API_version="1.0"><function_call name="enable"><var mutable="false" name="services" type="list_xml">'
+ for i in enable_list:
+ batch += '<service name="%s"/>' % str(i)
+ batch += '</var></function_call></request></module>'
+
+ if disable_list and len(disable_list) > 0:
+ batch += '<module name="service"><request API_version="1.0"><function_call name="disable"><var mutable="false" name="services" type="list_xml">'
+ for i in disable_list:
+ batch += '<service name="%s"/>' % str(i)
+ batch += '</var></function_call></request></module>'
+
+ if batch == '':
+ return None
+ ricci_xml = rc.batch_run(batch)
+ return batchAttemptResult(ricci_xml)
+
def restartService(rc, servicename):
- batch_str = '<module name="cluster"><request sequence="1254" API_version="1.0"><function_call name="restart_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
+ 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>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
def stopService(rc, servicename):
- batch_str = '<module name="cluster"><request sequence="1254" API_version="1.0"><function_call name="stop_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
+ batch_str = '<module name="cluster"><request API_version="1.0"><function_call name="stop_service"><var mutable="false" name="servicename" type="string" value=\"' + servicename + '\"/></function_call></request></module>'
ricci_xml = rc.batch_run(batch_str)
return batchAttemptResult(ricci_xml)
@@ -463,7 +553,6 @@
return None
resultlist = list()
- svc_node = None
for node in varnode.childNodes:
if node.nodeName == 'service':
svchash = {}
--- conga/luci/site/luci/Extensions/ricci_communicator.py 2006/11/01 22:06:55 1.9.2.3
+++ conga/luci/site/luci/Extensions/ricci_communicator.py 2006/11/16 19:34:53 1.9.2.4
@@ -1,10 +1,8 @@
-from time import *
-from socket import *
+from socket import socket, ssl, AF_INET, SOCK_STREAM
import xml
import xml.dom
from xml.dom import minidom
from LuciSyslog import LuciSyslog
-from HelperFunctions import access_to_host_allowed
CERTS_DIR_PATH = '/var/lib/luci/var/certs/'
@@ -36,7 +34,7 @@
raise RicciError, 'Error connecting to %s:%d: unknown error' \
% (self.__hostname, self.__port)
- luci_log.debug_verbose('Connected to %s:%d' \
+ luci_log.debug_verbose('RC:init0: Connected to %s:%d' \
% (self.__hostname, self.__port))
try:
self.ss = ssl(sock, self.__privkey_file, self.__cert_file)
@@ -53,7 +51,7 @@
# receive ricci header
hello = self.__receive()
try:
- luci_log.debug_verbose('Received header from %s: \"%s\"' \
+ luci_log.debug_verbose('RC:init1: Received header from %s: \"%s\"' \
% (self.__hostname, hello.toxml()))
except:
pass
@@ -69,34 +67,34 @@
def hostname(self):
- luci_log.debug_verbose('[auth %d] reported hostname = %s' \
+ luci_log.debug_verbose('RC:hostname: [auth %d] reported hostname = %s' \
% (self.__authed, self.__hostname))
return self.__hostname
def authed(self):
- luci_log.debug_verbose('reported authed = %d for %s' \
+ luci_log.debug_verbose('RC:authed: reported authed = %d for %s' \
% (self.__authed, self.__hostname))
return self.__authed
def system_name(self):
- luci_log.debug_verbose('[auth %d] reported system_name = %s for %s' \
+ luci_log.debug_verbose('RC:system_name: [auth %d] reported system_name = %s for %s' \
% (self.__authed, self.__reported_hostname, self.__hostname))
return self.__reported_hostname
def cluster_info(self):
- luci_log.debug_verbose('[auth %d] reported cluster_info = (%s,%s) for %s' \
+ luci_log.debug_verbose('RC:cluster_info: [auth %d] reported cluster_info = (%s,%s) for %s' \
% (self.__authed, self.__cluname, self.__clualias, self.__hostname))
return (self.__cluname, self.__clualias)
def os(self):
- luci_log.debug_verbose('[auth %d] reported system_name = %s for %s' \
+ luci_log.debug_verbose('RC:os: [auth %d] reported system_name = %s for %s' \
% (self.__authed, self.__os, self.__hostname))
return self.__os
def dom0(self):
- luci_log.debug_verbose('[auth %d] reported system_name = %s for %s' \
+ luci_log.debug_verbose('RC:dom0: [auth %d] reported system_name = %s for %s' \
% (self.__authed, self.__dom0, self.__hostname))
return self.__dom0
def auth(self, password):
if self.authed():
- luci_log.debug_verbose('already authenticated to %s' \
+ luci_log.debug_verbose('RC:auth0: already authenticated to %s' \
% self.__hostname)
return True
@@ -113,7 +111,8 @@
resp = self.__receive()
self.__authed = resp.firstChild.getAttribute('authenticated') == 'true'
- luci_log.debug_verbose('auth call returning %d' % self.__authed)
+ luci_log.debug_verbose('RC:auth1: auth call returning %d' \
+ % self.__authed)
return self.__authed
@@ -126,26 +125,26 @@
self.__send(doc)
resp = self.__receive()
- luci_log.debug_verbose('trying to unauthenticate to %s' \
+ luci_log.debug_verbose('RC:unauth0: trying to unauthenticate to %s' \
% self.__hostname)
try:
ret = resp.firstChild.getAttribute('success')
- luci_log.debug_verbose('unauthenticate returned %s for %s' \
+ luci_log.debug_verbose('RC:unauth1: unauthenticate returned %s for %s' \
% (ret, self.__hostname))
if ret != '0':
raise Exception, 'Invalid response'
except:
errstr = 'Error authenticating to host %s: %s' \
% (self.__hostname, str(ret))
- luci_log.debug(errstr)
+ luci_log.debug_verbose('RC:unauth2:' + errstr)
raise RicciError, errstr
return True
def process_batch(self, batch_xml, async=False):
try:
- luci_log.debug_verbose('auth=%d to %s for batch %s [async=%d]' \
+ luci_log.debug_verbose('RC:PB0: [auth=%d] to %s for batch %s [async=%d]' \
% (self.__authed, self.__hostname, batch_xml.toxml(), async))
except:
pass
@@ -171,7 +170,7 @@
try:
self.__send(doc)
except Exception, e:
- luci_log.debug('Error sending XML \"%s\" to host %s' \
+ luci_log.debug_verbose('RC:PB1: Error sending XML \"%s\" to host %s' \
% (doc.toxml(), self.__hostname))
raise RicciError, 'Error sending XML to host %s: %s' \
% (self.__hostname, str(e))
@@ -181,13 +180,13 @@
# receive response
doc = self.__receive()
try:
- luci_log.debug_verbose('received from %s XML \"%s\"' \
+ luci_log.debug_verbose('RC:PB2: received from %s XML \"%s\"' \
% (self.__hostname, doc.toxml()))
except:
pass
if doc.firstChild.getAttribute('success') != '0':
- luci_log.debug_verbose('batch command failed')
+ luci_log.debug_verbose('RC:PB3: batch command failed')
raise RicciError, 'The last ricci command to host %s failed' \
% self.__hostname
@@ -197,7 +196,7 @@
if node.nodeName == 'batch':
batch_node = node.cloneNode(True)
if batch_node == None:
- luci_log.debug_verbose('batch node missing <batch/>')
+ luci_log.debug_verbose('RC:PB4: batch node missing <batch/>')
raise RicciError, 'missing <batch/> in ricci\'s response from %s' \
% self.__hostname
@@ -206,23 +205,23 @@
def batch_run(self, batch_str, async=True):
try:
batch_xml_str = '<?xml version="1.0" ?><batch>' + batch_str + '</batch>'
- luci_log.debug_verbose('attempting batch \"%s\" for host %s' \
+ luci_log.debug_verbose('RC:BRun0: attempting batch \"%s\" for host %s' \
% (batch_xml_str, self.__hostname))
batch_xml = minidom.parseString(batch_xml_str).firstChild
except Exception, e:
- luci_log.debug('received invalid batch XML for %s: \"%s\"' \
- % (self.__hostname, batch_xml_str))
+ luci_log.debug_verbose('RC:BRun1: received invalid batch XML for %s: \"%s\": %s' \
+ % (self.__hostname, batch_xml_str, str(e)))
raise RicciError, 'batch XML is malformed'
try:
ricci_xml = self.process_batch(batch_xml, async)
try:
- luci_log.debug_verbose('received XML \"%s\" from host %s in response to batch command.' \
+ luci_log.debug_verbose('RC:BRun2: received XML \"%s\" from host %s in response to batch command.' \
% (ricci_xml.toxml(), self.__hostname))
except:
pass
except:
- luci_log.debug('An error occurred while trying to process the batch job: %s' % batch_xml_str)
+ luci_log.debug_verbose('RC:BRun3: An error occurred while trying to process the batch job: \"%s\"' % batch_xml_str)
return None
doc = minidom.Document()
@@ -230,7 +229,7 @@
return doc
def batch_report(self, batch_id):
- luci_log.debug_verbose('[auth=%d] asking for batchid# %s for host %s' \
+ luci_log.debug_verbose('RC:BRep0: [auth=%d] asking for batchid# %s for host %s' \
% (self.__authed, batch_id, self.__hostname))
if not self.authed():
@@ -273,7 +272,7 @@
try:
pos = self.ss.write(buff)
except Exception, e:
- luci_log.debug('Error sending XML \"%s\" to %s: %s' \
+ luci_log.debug_verbose('RC:send0: Error sending XML \"%s\" to %s: %s' \
% (buff, self.__hostname, str(e)))
raise RicciError, 'write error while sending XML to host %s' \
% self.__hostname
@@ -282,7 +281,7 @@
% self.__hostname
buff = buff[pos:]
try:
- luci_log.debug_verbose('Sent XML \"%s\" to host %s' \
+ luci_log.debug_verbose('RC:send1: Sent XML \"%s\" to host %s' \
% (xml_doc.toxml(), self.__hostname))
except:
pass
@@ -304,19 +303,19 @@
# we haven't received all of the XML data yet.
continue
except Exception, e:
- luci_log.debug('Error reading data from %s: %s' \
+ luci_log.debug_verbose('RC:recv0: Error reading data from %s: %s' \
% (self.__hostname, str(e)))
raise RicciError, 'Error reading data from host %s' % self.__hostname
except:
raise RicciError, 'Error reading data from host %s' % self.__hostname
- luci_log.debug_verbose('Received XML \"%s\" from host %s' \
+ luci_log.debug_verbose('RC:recv1: Received XML \"%s\" from host %s' \
% (xml_in, self.__hostname))
try:
if doc == None:
doc = minidom.parseString(xml_in)
except Exception, e:
- luci_log.debug('Error parsing XML \"%s" from %s' \
+ luci_log.debug_verbose('RC:recv2: Error parsing XML \"%s" from %s' \
% (xml_in, str(e)))
raise RicciError, 'Error parsing XML from host %s: %s' \
% (self.__hostname, str(e))
@@ -328,7 +327,7 @@
try:
if doc.firstChild.nodeName != 'ricci':
- luci_log.debug('Expecting \"ricci\" got XML \"%s\" from %s' %
+ luci_log.debug_verbose('RC:recv3: Expecting \"ricci\" got XML \"%s\" from %s' %
(xml_in, self.__hostname))
raise Exception, 'Expecting first XML child node to be \"ricci\"'
except Exception, e:
@@ -346,7 +345,7 @@
try:
return RicciCommunicator(hostname)
except Exception, e:
- luci_log.debug('Error creating a ricci connection to %s: %s' \
+ luci_log.debug_verbose('RC:GRC0: Error creating a ricci connection to %s: %s' \
% (hostname, str(e)))
return None
pass
@@ -396,7 +395,7 @@
def batch_status(batch_xml):
if batch_xml.nodeName != 'batch':
try:
- luci_log.debug('Expecting an XML batch node. Got \"%s\"' \
+ luci_log.debug_verbose('RC:BS0: Expecting an XML batch node. Got \"%s\"' \
% batch_xml.toxml())
except:
pass
@@ -416,10 +415,10 @@
last = last + 1
last = last - 2 * last
try:
- luci_log.debug_verbose('Returning (%d, %d) for batch_status(\"%s\")' \
+ luci_log.debug_verbose('RC:BS1: Returning (%d, %d) for batch_status(\"%s\")' \
% (last, total, batch_xml.toxml()))
except:
- luci_log.debug_verbose('Returning last, total')
+ luci_log.debug_verbose('RC:BS2: Returning last, total')
return (last, total)
@@ -445,7 +444,7 @@
# * error_msg: error message
def extract_module_status(batch_xml, module_num=1):
if batch_xml.nodeName != 'batch':
- luci_log.debug('Expecting \"batch\" got \"%s\"' % batch_xml.toxml())
+ luci_log.debug_verbose('RC:EMS0: Expecting \"batch\" got \"%s\"' % batch_xml.toxml())
raise RicciError, 'Invalid XML node; expecting a batch node'
c = 0
--- conga/make/version.in 2006/11/01 23:11:25 1.21.2.4
+++ conga/make/version.in 2006/11/16 19:34:53 1.21.2.5
@@ -1,2 +1,2 @@
VERSION=0.8
-RELEASE=23
+RELEASE=24
--- conga/ricci/modules/log/LogParser.cpp 2006/10/23 21:13:21 1.6.2.1
+++ conga/ricci/modules/log/LogParser.cpp 2006/11/16 19:34:53 1.6.2.2
@@ -165,7 +165,8 @@
set<String>&
get_files(const String& path_,
- set<String>& files)
+ set<String>& files,
+ time_t age_time)
{
String path = utils::rstrip(utils::strip(path_), "/");
if (path.empty() || path.find_first_of(" ; & $ ` ? > < ' \" ; | \\ * \n \t") != path.npos)
@@ -178,11 +179,12 @@
// throw String("unable to stat ") + path;
return files;
if (S_ISREG(st.st_mode)) {
- files.insert(path);
+ if (st.st_mtime >= age_time)
+ files.insert(path);
// get rotated logs
for (int i=0; i<25; i++)
- get_files(path + "." + utils::to_string(i), files);
+ get_files(path + "." + utils::to_string(i), files, age_time);
return files;
} else if (S_ISDIR(st.st_mode))
@@ -204,7 +206,7 @@
if (kid_path == "." || kid_path == "..")
continue;
kid_path = path + "/" + kid_path;
- get_files(kid_path, files);
+ get_files(kid_path, files, age_time);
}
} catch ( ... ) {
closedir(d);
@@ -366,6 +368,13 @@
const list<String>& paths)
{
set<LogEntry> ret;
+ time_t age_time = time(NULL);
+
+ if ((long long) age_time - age < 0)
+ age_time = 0;
+ else
+ age_time -= age;
+
// set of requested tags
set<String> req_tags(domains.begin(), domains.end());
@@ -375,10 +384,10 @@
for (list<String>::const_iterator iter = paths.begin();
iter != paths.end();
iter++)
- get_files(*iter, files);
+ get_files(*iter, files, age_time);
if (files.empty()) {
- get_files("/var/log/messages", files);
- get_files("/var/log/syslog", files);
+ get_files("/var/log/messages", files, age_time);
+ get_files("/var/log/syslog", files, age_time);
}
// process log files
More information about the Cluster-devel
mailing list