[luci] luci: Add support for the IP "prefer_interface" attr
by Ryan McCabe
commit 33c0d6a2d324e82671aa81e43b554c31b327d0e2
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Mon Jun 30 11:20:12 2014 -0400
luci: Add support for the IP "prefer_interface" attr
Add support for editing the "prefer_interface" attribute of
the IP resource while in expert mode.
Resolves: rhbz#917738
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/templates/resource_list.html | 7 +++++++
luci/validation/validate_resource.py | 8 ++++++++
2 files changed, 15 insertions(+), 0 deletions(-)
---
diff --git a/luci/templates/resource_list.html b/luci/templates/resource_list.html
index a195f3c..983023e 100644
--- a/luci/templates/resource_list.html
+++ b/luci/templates/resource_list.html
@@ -118,6 +118,13 @@
py:attrs="res and {'value': res.getAttribute('sleeptime'), 'disabled':global_resource and 'disabled' or None} or {}" />
</td>
</tr>
+ <tr py:if="expertMode and (cluster_os != 'RHEL' or os_version > 6.4)">
+ <td>Prefer Interface</td>
+ <td>
+ <input type="text" class="text" name="prefer_interface"
+ py:attrs="res and {'value':res.getAttribute('prefer_interface'), 'disabled':global_resource and 'disabled' or None} or {}" />
+ </td>
+ </tr>
${res_footer(res)}
</table>
</div>
diff --git a/luci/validation/validate_resource.py b/luci/validation/validate_resource.py
index c3187cd..70b29ee 100644
--- a/luci/validation/validate_resource.py
+++ b/luci/validation/validate_resource.py
@@ -127,6 +127,14 @@ def addIp(res, rname, model, **kw):
res.removeAttribute('monitor_link')
if not res.getBinaryAttribute('disable_rdisc'):
res.removeAttribute('disable_rdisc')
+
+ if kw.get('expert_mode'):
+ prefer_interface = kw.get('prefer_interface')
+ if prefer_interface and not prefer_interface.isspace():
+ res.addAttribute('prefer_interface', prefer_interface)
+ else:
+ res.removeAttribute('prefer_interface')
+
return errors
def addFs(res, rname, model, **kw):
9 years, 10 months
[luci] Resolves: rhbz#991575
by Ryan McCabe
commit 7dc551da44d6698b7685c5059876e800192452a8
Author: Jan Pokorný <jpokorny(a)redhat.com>
Date: Mon Jun 23 15:39:24 2014 +0200
Resolves: rhbz#991575
Add the ability to block weak ciphers in luci.
Currently, this feature only applies to web browser connecting to luci.
Signed-off-by: Jan Pokorný <jpokorny(a)redhat.com>
luci/initwrappers.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 81 insertions(+), 2 deletions(-)
---
diff --git a/luci/initwrappers.py b/luci/initwrappers.py
index a75aa46..366ce70 100644
--- a/luci/initwrappers.py
+++ b/luci/initwrappers.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright 2014 Red Hat, Inc.
#
# This program is free software; you can redistribute
# it and/or modify it under the terms of version 2 of the
@@ -8,9 +8,10 @@
"""\
Wrappers for parts used during initial phase of running luci.
"""
-
+_
from pylons.util import PylonsInstaller as _PylonsInstaller
from repoze.who.config import WhoConfig as _WhoConfig, make_middleware_with_config
+from paste.httpserver import server_runner as _server_runner
from luci import config_template
@@ -74,3 +75,81 @@ def repoze_who_make_middleware_with_config(app,
)
return app
+
+
+# This is a workaround for problem, that repoze.who < 1.0.14 cannot handle
+# "timeout" and "reissue_time" (+ "userid_checker") parameters when passed
+# into make_plugin function of repoze.who.plugins.auth_tkt.
+#
+# The only remaining problem is that the session will not timeout after some
+# time of inactivity in case of repoze.who < 1.0.14.
+def auth_tkt_make_plugin(secret=None,
+ secretfile=None,
+ cookie_name='auth_tkt',
+ secure=False,
+ include_ip=False,
+ timeout=None,
+ reissue_time=None,
+ userid_checker=None):
+ # We can presume that this package and function exist (see setup.py).
+ from repoze.who.plugins.auth_tkt import make_plugin
+ try:
+ return make_plugin(secret=secret,
+ secretfile=secretfile,
+ cookie_name=cookie_name,
+ secure=secure,
+ include_ip=include_ip,
+ timeout=timeout,
+ reissue_time=reissue_time,
+ userid_checker=userid_checker)
+ except TypeError:
+ # Workaround for repoze.who < 1.0.14 case.
+ return make_plugin(secret=secret,
+ secretfile=secretfile,
+ cookie_name=cookie_name,
+ secure=secure,
+ include_ip=include_ip)
+
+
+# This is a way how to inject custom SSL context and in turn, how to have
+# a control over allowed ciphers (rhbz#991575).
+def server_runner(wsgi_app, global_conf, **kwargs):
+ try:
+ from OpenSSL import SSL
+ except ImportError:
+ # let it fail later if need be
+ pass
+ else:
+ ssl_cipher_list = kwargs.pop('ssl_cipher_list', '')
+ if ssl_cipher_list:
+ ssl_pem = kwargs.pop('ssl_pem')
+ ssl_context = SSL.Context(SSL.SSLv23_METHOD)
+ if kwargs.pop('ssl_allow_insecure', False) \
+ in ('', 'false', False):
+ # XXX note that SSL.OP_NO_COMPRESSION is missing
+ ssl_context.set_options(SSL.OP_NO_SSLv2)
+ ssl_context.use_privatekey_file(ssl_pem)
+ ssl_context.use_certificate_chain_file(ssl_pem)
+ ssl_context.set_cipher_list(ssl_cipher_list)
+ kwargs['ssl_context'] = ssl_context
+
+ return server_runner(wsgi_app, global_conf, **kwargs)
+
+
+server_runner.__doc__ = (_server_runner.__doc__ or '') + """
+
+ You can also set these luci-specific options:
+
+ ``ssl_cipher_list``:
+
+ The list of ciphers to be used in this context.
+ See the OpenSSL manual for more information (e.g. ciphers(1)).
+ Defaults to whatever OpenSSL uses as a default.
+
+ ``ssl_allow_insecure``:
+
+ If and only if specifying ciphers manually via ``ssl_cipher_list``,
+ SSLv2 communication is suppressed by default (not the case without
+ specification). To allow SSLv2 with its known security issues even
+ then, set this option to 'true'.
+"""
9 years, 10 months
[luci] Check length of secret (beaker.session.secret) on startup
by Ryan McCabe
commit cf0857f32303014d2aa63876a916cc6891e3fb30
Author: Jan Pokorný <jpokorny(a)redhat.com>
Date: Mon Jun 23 17:41:14 2014 +0200
Check length of secret (beaker.session.secret) on startup
Signed-off-by: Jan Pokorný <jpokorny(a)redhat.com>
luci/config/environment.py | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
---
diff --git a/luci/config/environment.py b/luci/config/environment.py
index 5bcda70..48a9655 100644
--- a/luci/config/environment.py
+++ b/luci/config/environment.py
@@ -12,6 +12,15 @@ __all__ = ['load_environment']
def make_load_environment(wrapped_f):
def load_environment(global_conf, app_conf):
+ # rhbz#982771
+ secret_length = len(app_conf.get('beaker.session.secret', '').strip())
+ if secret_length < 20:
+ msg = ("Insufficient length of 'beaker.session.secret': {0}"
+ .format(secret_length))
+ with open('/var/log/luci/luci.log', 'a') as f:
+ f.write(msg.join(('\n', '\n')))
+ raise RuntimeError(msg)
+
del_global = filter(
lambda o: o.startswith("tmp.")
or o.startswith("def."),
9 years, 10 months
[luci] luci: Don't remove attributes from xvm fence devs in non-expert mode
by Ryan McCabe
commit 080e1b685dde98cbfcfd4f39a786b540afbb69d2
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Mon Jun 23 09:40:30 2014 -0400
luci: Don't remove attributes from xvm fence devs in non-expert mode
If attributes are set on an xvm fence device that are only shown in
expert mode, and the device is edited in non-expert mode, the
attributes that are shown only in expert mode are removed. This patch
corrects that.
Resolves: rhbz#1004011
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/validation/validate_fence.py | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
---
diff --git a/luci/validation/validate_fence.py b/luci/validation/validate_fence.py
index eff2547..d102c51 100644
--- a/luci/validation/validate_fence.py
+++ b/luci/validation/validate_fence.py
@@ -562,6 +562,10 @@ def val_xcat_fd(fencedev, fence_name, **kw):
def val_xvm_fd(fencedev, fence_name, **kw):
params = (
+ ('timeout', False),
+ )
+
+ params_expert = (
('auth', False),
('hash', False),
('ip_family', False),
@@ -572,7 +576,10 @@ def val_xvm_fd(fencedev, fence_name, **kw):
('retrans', False),
)
- errors = config_fence_attr(params, fencedev, fence_name, **kw)
+ if kw.get('expert_mode'):
+ errors = config_fence_attr(params_expert, fencedev, fence_name, **kw)
+ else:
+ errors = config_fence_attr(params, fencedev, fence_name, **kw)
return errors
def val_zvm_fd(fencedev, fence_name, **kw):
9 years, 10 months
[luci] luci: Disallow XML-unsafe characters in attribute values
by Ryan McCabe
commit 76fa69f399e245471c026c20c03adbfe39a01d3f
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 17:19:16 2014 -0400
luci: Disallow XML-unsafe characters in attribute values
Disallow the use of the <, >, ", and & characters inside
attribute values.
Resolves: rhbz#855112
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/controllers/cluster.py | 5 ++++-
luci/lib/ClusterConf/ModelBuilder.py | 1 +
luci/lib/ClusterConf/TagObject.py | 8 ++++++--
luci/lib/db_helpers.py | 17 +++++++++++------
4 files changed, 22 insertions(+), 9 deletions(-)
---
diff --git a/luci/controllers/cluster.py b/luci/controllers/cluster.py
index 0e3f043..3159145 100644
--- a/luci/controllers/cluster.py
+++ b/luci/controllers/cluster.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2009-2012 Red Hat, Inc.
+# Copyright (C) 2009-2014 Red Hat, Inc.
#
# This program is free software; you can redistribute
# it and/or modify it under the terms of version 2 of the
@@ -134,6 +134,9 @@ class IndividualClusterController(BaseController):
if not self.model:
try:
self.model = get_model_for_cluster(self.name, self.get_agent())
+ except Exception, e:
+ flash('Error reading the cluster configuration: %s' % str(e), status="error")
+ try:
if self.model:
reconcile_db_with_conf(self.name, self.model.getNodeNames())
except:
diff --git a/luci/lib/ClusterConf/ModelBuilder.py b/luci/lib/ClusterConf/ModelBuilder.py
index c26bbb0..8e878df 100644
--- a/luci/lib/ClusterConf/ModelBuilder.py
+++ b/luci/lib/ClusterConf/ModelBuilder.py
@@ -440,6 +440,7 @@ class ModelBuilder:
if self.lock_version is True:
self.getClusterPtr().is_cfg_version_dirty = True
except Exception, e:
+ log.exception("Error exporting cluster.conf XML")
strbuf = ""
return strbuf
diff --git a/luci/lib/ClusterConf/TagObject.py b/luci/lib/ClusterConf/TagObject.py
index dbd9b82..fec05d9 100644
--- a/luci/lib/ClusterConf/TagObject.py
+++ b/luci/lib/ClusterConf/TagObject.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2011 Red Hat, Inc.
+# Copyright (C) 2006-2014 Red Hat, Inc.
#
# This program is free software; you can redistribute
# it and/or modify it under the terms of version 2 of the
@@ -17,6 +17,7 @@ class TagObject(object):
self.element_text = None
self.errors = False
self.parent = None
+ self.badchars = set('<>&"')
def getParent(self):
return self.parent
@@ -38,7 +39,10 @@ class TagObject(object):
def addAttribute(self, name, value):
if value is None:
return self.removeAttribute(name)
- self.attr_hash[name] = unicode(value)
+ uvalue = unicode(value)
+ if any((c in self.badchars) for c in uvalue):
+ raise ValueError, 'Attributes may not contain the following characters: > < " &'
+ self.attr_hash[name] = uvalue
return value
def addIntegerAttribute(self, name, val, bounds=(None, None)):
diff --git a/luci/lib/db_helpers.py b/luci/lib/db_helpers.py
index 0b7daa3..2ec55b0 100644
--- a/luci/lib/db_helpers.py
+++ b/luci/lib/db_helpers.py
@@ -122,15 +122,14 @@ def get_model_for_cluster(cluster_name, rc=None):
try:
from luci.lib.ClusterConf.ModelBuilder import ModelBuilder
conf = rq.getClusterConf(rc)
- if conf is not None:
- model = ModelBuilder(conf, rc.cluster_version())
- return model
except Exception, e:
log.exception("Error getting cluster configuration for %s: %s"
% (cluster_name, e))
- # Couldn't get the conf from any nodes
- return None
+ model = None
+ if conf is not None:
+ model = ModelBuilder(conf, rc.cluster_version())
+ return model
def get_cluster_status(rc):
try:
@@ -218,8 +217,14 @@ def get_cluster_list_full():
'status': ClusterStatus(None)
}
continue
+
+ try:
+ model = get_model_for_cluster(cluster_name, rc)
+ except Exception, e:
+ model = None
+
cluster_list[cluster_name] = {
- 'model': get_model_for_cluster(cluster_name, rc),
+ 'model': model,
'status': get_status_for_cluster(cluster_name, rc)
}
return cluster_list
9 years, 10 months
[luci] luci: Fix broken display on permissions page
by Ryan McCabe
commit ffc4ba6a3fa121b8c5639be4fdc3e70bfbfb8fe5
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 16:29:08 2014 -0400
luci: Fix broken display on permissions page
Fix an issue that could cause the user roles
lists on the permissions page to be staggered.
Resolves: rhbz#988446
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/public/css/style.css | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/luci/public/css/style.css b/luci/public/css/style.css
index 076cc91..0425734 100644
--- a/luci/public/css/style.css
+++ b/luci/public/css/style.css
@@ -241,7 +241,7 @@ form>label, label {
}
label.wide {
- width: 260px;
+ width: 50%;
}
label.choice {
9 years, 10 months
[luci] luci: Allow configuration of more fence_xvm attributes
by Ryan McCabe
commit 12386f8d6aabc432412fafb85872b9d7dca8ba02
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 16:10:50 2014 -0400
luci: Allow configuration of more fence_xvm attributes
Allow configuration of all useful fence_xvm attributes
while in expert mode. Previously, only name could be
configured.
Resolves: rhbz#1004011
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/templates/fence_devices.html | 82 +++++++++++++++++++++++++++++++++++++
luci/validation/validate_fence.py | 17 +++++++-
2 files changed, 98 insertions(+), 1 deletions(-)
---
diff --git a/luci/templates/fence_devices.html b/luci/templates/fence_devices.html
index fcc1747..dcf15c3 100644
--- a/luci/templates/fence_devices.html
+++ b/luci/templates/fence_devices.html
@@ -1181,6 +1181,88 @@
py:attrs="cur_fencedev and {'value': cur_fencedev.getName()} or {}"/>
</td>
</tr>
+ <tr>
+ <td>Timeout (optional)</td>
+ <td>
+ <input name="timeout" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('timeout')}"/>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>Path to Key File (optional)</td>
+ <td>
+ <input name="key_file" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('key_file')}"/>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>IP Port (optional)</td>
+ <td>
+ <input name="ipport" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('ipport')} or {}"/>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>Multicast Address (optional)</td>
+ <td>
+ <input name="multicast_address" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('multicast_address')}"/>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>Multicast Retransmit Time (1/10s) (optional)</td>
+ <td>
+ <input name="retrans" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('retrans')}"/>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>IP Family</td>
+ <td>
+ <select name="ip_family" class="fencedevformselect">
+ <option value=""
+ py:attrs="(not cur_fencedev or not cur_fencedev.getAttribute('ip_family')) and {'selected':'selected'} or {}">Default</option>
+ <option value="ipv4"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('ip_family') and cur_fencedev.getAttribute('ip_family').lower() == 'ipv4' and {'selected':'selected'} or {}">IPv4</option>
+ <option value="ipv6"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('ip_family') and cur_fencedev.getAttribute('ip_family').lower() == 'ipv6' and {'selected':'selected'} or {}">IPv6</option>
+ </select>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>Authentication Type</td>
+ <td>
+ <select name="auth" class="fencedevformselect">
+ <option value=""
+ py:attrs="(not cur_fencedev or not cur_fencedev.getAttribute('auth')) and {'selected':'selected'} or {}">Default</option>
+ <option value="none"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('auth') == 'none' and {'selected':'selected'} or {}">None</option>
+ <option value="sha1"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('auth') == 'sha1' and {'selected':'selected'} or {}">SHA1</option>
+ <option value="sha256"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('auth') == 'sha256' and {'selected':'selected'} or {}">SHA256</option>
+ <option value="sha512"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('auth') == 'sha512' and {'selected':'selected'} or {}">SHA512</option>
+ </select>
+ </td>
+ </tr>
+ <tr py:if="expertMode">
+ <td>Packet Hash Type</td>
+ <td>
+ <select name="hash" class="fencedevformselect">
+ <option value=""
+ py:attrs="(not cur_fencedev or not cur_fencedev.getAttribute('hash')) and {'selected':'selected'} or {}">Default</option>
+ <option value="none"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('hash') == 'none' and {'selected':'selected'} or {}">None</option>
+ <option value="sha1"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('hash') == 'sha1' and {'selected':'selected'} or {}">SHA1</option>
+ <option value="sha256"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('hash') == 'sha256' and {'selected':'selected'} or {}">SHA256</option>
+ <option value="sha512"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('hash') == 'sha512' and {'selected':'selected'} or {}">SHA512</option>
+ </select>
+ </td>
+ </tr>
</table>
<py:if test="cur_fencedev">
diff --git a/luci/validation/validate_fence.py b/luci/validation/validate_fence.py
index c9fe626..eff2547 100644
--- a/luci/validation/validate_fence.py
+++ b/luci/validation/validate_fence.py
@@ -560,6 +560,21 @@ def val_xcat_fd(fencedev, fence_name, **kw):
errors = config_fence_attr(params, fencedev, fence_name, **kw)
return errors
+def val_xvm_fd(fencedev, fence_name, **kw):
+ params = (
+ ('auth', False),
+ ('hash', False),
+ ('ip_family', False),
+ ('ipport', False),
+ ('key_file', False),
+ ('multicast_address', False),
+ ('timeout', False),
+ ('retrans', False),
+ )
+
+ errors = config_fence_attr(params, fencedev, fence_name, **kw)
+ return errors
+
def val_zvm_fd(fencedev, fence_name, **kw):
params = (
('ipl', True),
@@ -892,7 +907,7 @@ FD_VALIDATE = {
'fence_vmware_soap': val_vmware_soap_fd,
'fence_wti': val_wti_fd,
'fence_xcat': val_xcat_fd,
- 'fence_xvm': val_noop_fd,
+ 'fence_xvm': val_xvm_fd,
'fence_zvm': val_zvm_fd,
}
9 years, 10 months
[luci] luci: Add support for sorting by columns of the resource list table
by Ryan McCabe
commit 7e275025375d2ec616330de8b8dfc50539c0e2d4
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 15:51:09 2014 -0400
luci: Add support for sorting by columns of the resource list table
Allow the list of resources to be sorted by the values of any
of the columns.
Resolves: rhbz#bz919225.patch
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/public/css/style.css | 13 +++++++++++++
luci/public/images/asc.gif | Bin 0 -> 54 bytes
luci/public/images/bg.gif | Bin 0 -> 64 bytes
luci/public/images/desc.gif | Bin 0 -> 54 bytes
luci/public/js/jquery.tablesorter.min.js | 4 ++++
luci/templates/resource.html | 12 ++++++++++--
6 files changed, 27 insertions(+), 2 deletions(-)
---
diff --git a/luci/public/css/style.css b/luci/public/css/style.css
index 57778f3..076cc91 100644
--- a/luci/public/css/style.css
+++ b/luci/public/css/style.css
@@ -649,3 +649,16 @@ display: none ! important;
.emptyfenceinst {
padding: 2em 0em 0em 0em;
}
+
+table.tablesorter thead tr .header {
+ background: transparent url(../images/bg.gif) no-repeat center right;
+ cursor: pointer;
+}
+
+table.tablesorter thead tr .headerSortUp {
+ background-image: url(../images/asc.gif);
+}
+
+table.tablesorter thead tr .headerSortDown {
+ background-image: url(../images/desc.gif);
+}
diff --git a/luci/public/images/asc.gif b/luci/public/images/asc.gif
new file mode 100644
index 0000000..7415786
Binary files /dev/null and b/luci/public/images/asc.gif differ
diff --git a/luci/public/images/bg.gif b/luci/public/images/bg.gif
new file mode 100644
index 0000000..fac668f
Binary files /dev/null and b/luci/public/images/bg.gif differ
diff --git a/luci/public/images/desc.gif b/luci/public/images/desc.gif
new file mode 100644
index 0000000..3b30b3c
Binary files /dev/null and b/luci/public/images/desc.gif differ
diff --git a/luci/public/js/jquery.tablesorter.min.js b/luci/public/js/jquery.tablesorter.min.js
new file mode 100644
index 0000000..d3ff430
--- /dev/null
+++ b/luci/public/js/jquery.tablesorter.min.js
@@ -0,0 +1,4 @@
+
+(function($){$.extend({tablesorter:new
+function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).
metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cel
ls[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cac
he for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}r
ows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableH
eaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
+var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function c
heckHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;i
f(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgO
rderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY
: "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!thi
s.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.h
eaderList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}
).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.a
pply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.t
est(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us")
{s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if (c.dateFormat == "pt") {s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");} else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Dat
e();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
diff --git a/luci/templates/resource.html b/luci/templates/resource.html
index 1b47c6f..79fcea7 100644
--- a/luci/templates/resource.html
+++ b/luci/templates/resource.html
@@ -18,6 +18,14 @@
<body py:with="cluster_data = tmpl_context.cluster.get_model();
cluster_status = tmpl_context.cluster.get_status()">
<script type="text/javascript" src="/js/resource.js"></script>
+ <script src="/js/jquery.tablesorter.min.js" type="text/javascript"></script>
+ <script type="text/javascript" id="js">
+ $(document).ready(function() {
+ $('#resource_tlist').tablesorter({
+ widgets: ['zebra','repeatHeaders']
+ });
+ });
+ </script>
<xi:include href="resource_list.html" />
<form action="${tg.url(resources_cmd)}" method="post">
@@ -30,7 +38,7 @@
<!--! OVERVIEW SECTION. -->
<div id="overview">
- <table id="resource_tlist" class="maintable">
+ <table id="resource_tlist" class="maintable tablesorter">
<thead>
<tr>
<th class="checkbox"></th>
@@ -45,7 +53,7 @@
<tr py:for="(i, resource_data) in enumerate(cluster_data.getResources())"
py:with="entity_name = resource_data.getName();
refcount = resource_data.getRefcount()"
- py:attrs="entity_name==name and {'class': 'chosen'} or (not i%2 and {'class': 'even'} or None)">
+ py:attrs="entity_name==name and {'class': 'chosen'} or None">
<td class="checkbox">
<input type="checkbox" name="${entity_name}"
onclick="update_multi_action(this)" class="MultiActionItem"
9 years, 10 months
[luci] luci: Add support for fence_kdump
by Ryan McCabe
commit fa826852a89f59aecca38f9b5c8675094d26bf46
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 15:47:11 2014 -0400
luci: Add support for fence_kdump
Add support for fence_kdump
Resolves: rhbz#bz918795
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/lib/ClusterConf/FenceDeviceAttr.py | 2 +
luci/templates/fence_devices.html | 64 +++++++++++++++++++++++++++++++
luci/templates/fence_instances.html | 11 +++++
luci/validation/validate_fence.py | 13 ++++++
4 files changed, 90 insertions(+), 0 deletions(-)
---
diff --git a/luci/lib/ClusterConf/FenceDeviceAttr.py b/luci/lib/ClusterConf/FenceDeviceAttr.py
index 90883dd..6de49b8 100644
--- a/luci/lib/ClusterConf/FenceDeviceAttr.py
+++ b/luci/lib/ClusterConf/FenceDeviceAttr.py
@@ -36,6 +36,7 @@ FENCE_OPTS = {
'fence_idrac': 'Dell iDRAC',
'fence_imm': 'IBM Integrated Management Module',
'fence_ipdu': 'IBM iPDU',
+ 'fence_kdump': 'Fence kdump',
'fence_drac': 'Dell DRAC',
'fence_drac5': 'Dell DRAC 5',
'fence_rsa': 'IBM RSA II Device',
@@ -102,6 +103,7 @@ FENCE_SHARED = {
'fence_ipmilan': False,
'fence_idrac': False,
'fence_imm': False,
+ 'fence_kdump': False,
'fence_drac': False,
'fence_drac5': False,
'fence_rps10': False,
diff --git a/luci/templates/fence_devices.html b/luci/templates/fence_devices.html
index d71ef92..fcc1747 100644
--- a/luci/templates/fence_devices.html
+++ b/luci/templates/fence_devices.html
@@ -1195,6 +1195,68 @@
<input type="hidden" name="fence_type" value="fence_xvm" />
</div>
+<div py:def="fence_kdump(cur_fencedev, ni)" id="fence_kdump" class="fencedevform row"
+ py:attrs="cur_fencedev and {'id': 'fd_%s' % cur_fencedev.getName()}">
+ <table class="formtable">
+ <tr>
+ <td>Fence Type</td>
+ <td>Fence kdump</td>
+ </tr>
+ <tr>
+ <td>Name</td>
+ <td>
+ <input name="name" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getName()} or {}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Node Name</td>
+ <td>
+ <input name="nodename" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('nodename')} or {}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>IP Family</td>
+ <td>
+ <select name="family" class="fencedevformselect">
+ <option value=""
+ py:attrs="(not cur_fencedev or not cur_fencedev.getAttribute('family')) and {'selected':'selected'} or {}">Default</option>
+ <option value="ipv4"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('family') and cur_fencedev.getAttribute('family').lower() == 'ipv4' and {'selected':'selected'} or {}">IPv4</option>
+ <option value="ipv6"
+ py:attrs="cur_fencedev and cur_fencedev.getAttribute('family') and cur_fencedev.getAttribute('family').lower() == 'ipv6' and {'selected':'selected'} or {}">IPv6</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>IP Port (optional)</td>
+ <td>
+ <input name="ipport" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('ipport')} or {}"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Operation Timeout (seconds) (optional)</td>
+ <td>
+ <input name="timeout" type="text" class="text"
+ py:attrs="cur_fencedev and {'value': cur_fencedev.getAttribute('timeout')}"/>
+ </td>
+ </tr>
+ </table>
+
+ <py:if test="cur_fencedev">
+ <input type="hidden"
+ name="orig_name" value="${cur_fencedev.getName()}"/>
+ <input type="hidden"
+ name="existing_device" value="1" />
+ </py:if>
+
+ <input type="hidden" name="sharable" value="1" />
+ <input type="hidden" name="num_instances" value="${ni}"/>
+ <input type="hidden" name="fence_type" value="fence_kdump" />
+</div>
+
<div py:def="fence_scsi(cur_fencedev, ni)" id="fence_scsi" class="fencedevform row"
py:attrs="cur_fencedev and {'id': 'fd_%s' % cur_fencedev.getName()}">
<table class="formtable">
@@ -4853,6 +4915,7 @@ ${fence_rsa(None,0)}
${fence_rsb(None,0)}
${fence_rps10(None,0)}
${fence_ipmilan(None,0)}
+${fence_kdump(None,0)}
${fence_idrac(None,0)}
${fence_imm(None,0)}
${fence_alom(None,0)}
@@ -4952,6 +5015,7 @@ ${fence_unknown(None,0)}
</py:if>
<option name="fence_ipmilan" value="fence_ipmilan">IPMI Lan</option>
+ <option name="fence_kdump" value="fence_kdump">Fence kdump</option>
<option py:if="cluster_version == 2" name="fence_lpar" value="fence_lpar">LPAR Fencing</option>
<option py:if="cluster_version == 2" name="fence_mcdata" value="fence_mcdata">McData SAN Switch</option>
diff --git a/luci/templates/fence_instances.html b/luci/templates/fence_instances.html
index dd42b09..d8b9684 100644
--- a/luci/templates/fence_instances.html
+++ b/luci/templates/fence_instances.html
@@ -957,6 +957,16 @@
py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
</div>
+<div py:def="fence_kdump_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_kdump_instance"
+ py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
+
+ <div class="emptyfenceinst">No additional parameters</div>
+ <input type="hidden" name="fence_type" value="fence_kdump" />
+ <input type="hidden" name="fence_instance" value="1" />
+ <input type="hidden" name="parent_fencedev"
+ py:attrs="cur_fence_dev_id and {'value': cur_fence_dev_id} or {}" />
+</div>
+
<div py:def="fence_idrac_instance(cur_fence_inst, cur_fence_dev_id, fi_id, **kw)" id="fence_idrac_instance"
py:attrs="fi_id is not None and {'id': fi_id, 'class':'fenceinst'}">
@@ -1227,6 +1237,7 @@ ${fence_ilo4_instance(None, None, None)}
${fence_ilo_mp_instance(None, None, None)}
${fence_rsa_instance(None, None, None)}
${fence_ipmilan_instance(None, None, None)}
+${fence_kdump_instance(None, None, None)}
${fence_imm_instance(None, None, None)}
${fence_idrac_instance(None, None, None)}
${fence_alom_instance(None, None, None)}
diff --git a/luci/validation/validate_fence.py b/luci/validation/validate_fence.py
index 55d1e8d..c9fe626 100644
--- a/luci/validation/validate_fence.py
+++ b/luci/validation/validate_fence.py
@@ -493,6 +493,17 @@ def val_ipmilan_fd(fencedev, fence_name, **kw):
errors = config_fence_attr(params, fencedev, fence_name, **kw)
return errors
+def val_kdump_fd(fencedev, fence_name, **kw):
+ params = (
+ ('nodename', True),
+ ('family', False),
+ ('ipport', False),
+ ('timeout', False),
+ )
+
+ errors = config_fence_attr(params, fencedev, fence_name, **kw)
+ return errors
+
def val_alom_fd(fencedev, fence_name, **kw):
params = (
('ipaddr', True),
@@ -861,6 +872,7 @@ FD_VALIDATE = {
'fence_ipmilan': val_ipmilan_fd,
'fence_idrac': val_ipmilan_fd,
'fence_imm': val_ipmilan_fd,
+ 'fence_kdump': val_kdump_fd,
'fence_ldom': val_ldom_fd,
'fence_lpar': val_lpar_fd,
'fence_manual': val_noop_fd,
@@ -1270,6 +1282,7 @@ FI_VALIDATE = {
'fence_ilo4': val_noop_fi,
'fence_intelmodular': val_intelmodular_fi,
'fence_ipmilan': val_noop_fi,
+ 'fence_kdump': val_noop_fi,
'fence_idrac': val_noop_fi,
'fence_imm': val_noop_fi,
'fence_ldom': val_ldom_fi,
9 years, 10 months
[luci] luci: Fix crash when config contains a globally defined vm resource
by Ryan McCabe
commit 9d8d11ca91553840a75d7264353b84c563b647b0
Author: Ryan McCabe <rmccabe(a)redhat.com>
Date: Sun Jun 22 15:21:16 2014 -0400
luci: Fix crash when config contains a globally defined vm resource
When a vm tag was a child of the resources tag of cluster.conf, the
luci server would crash, giving error 500. This patch fixes the
crash and allows the vm resource to be properly viewed and edited.
Resolves: rhbz#1100817
Signed-off-by: Ryan McCabe <rmccabe(a)redhat.com>
luci/lib/ClusterConf/Vm.py | 8 +++++++-
luci/templates/resource_list.html | 7 +++++++
luci/validation/validate_resource.py | 4 ++--
3 files changed, 16 insertions(+), 3 deletions(-)
---
diff --git a/luci/lib/ClusterConf/Vm.py b/luci/lib/ClusterConf/Vm.py
index 2163500..05e6897 100644
--- a/luci/lib/ClusterConf/Vm.py
+++ b/luci/lib/ClusterConf/Vm.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2012 Red Hat, Inc.
+# Copyright (C) 2006-2014 Red Hat, Inc.
#
# This program is free software; you can redistribute
# it and/or modify it under the terms of version 2 of the
@@ -8,7 +8,10 @@
from Service import Service
from BaseResource import BaseResource
+from gettext import gettext as _
+
TAG_NAME = "vm"
+RESOURCE_TYPE = _('Virtual Machine')
vm_attributes = ('migration_mapping', 'xmlfile', 'migrate',
'path', 'snapshot', 'hypervisor_uri',
@@ -18,6 +21,9 @@ class Vm(Service, BaseResource):
def __init__(self):
Service.__init__(self)
self.TAG_NAME = TAG_NAME
+ self.refcount = 1
+ self.reflist = []
+ self.resource_type = RESOURCE_TYPE
def getResourceAttributes(self):
attrs = self.getAttributes()
diff --git a/luci/templates/resource_list.html b/luci/templates/resource_list.html
index 5ca7777..a195f3c 100644
--- a/luci/templates/resource_list.html
+++ b/luci/templates/resource_list.html
@@ -1722,6 +1722,13 @@
<input name="type" type="hidden" value="vm" />
<table class="formtable">
+ <tr py:if="res">
+ <td>Name</td>
+ <td>
+ <input type="text" class="text" name="resourcename"
+ py:attrs="res and {'value':res.getAttribute('name'), 'disabled':global_resource and 'disabled' or None} or {}" />
+ </td>
+ </tr>
<tr>
<td>Migration Type</td>
<td>
diff --git a/luci/validation/validate_resource.py b/luci/validation/validate_resource.py
index a5e86a7..c3187cd 100644
--- a/luci/validation/validate_resource.py
+++ b/luci/validation/validate_resource.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2009-2011 Red Hat, Inc.
+# Copyright (C) 2009-2014 Red Hat, Inc.
#
# This program is free software; you can redistribute
# it and/or modify it under the terms of version 2 of the
@@ -586,7 +586,7 @@ def create_resource(res_type, model, **kw):
if res_type == 'ip':
rname = kw.get('address')
- elif res_type == 'vm':
+ elif res_type == 'vm' and not resource_edit:
rname = ''
res = BaseResource()
else:
9 years, 10 months