~ubuntu-branches/ubuntu/vivid/crmsh/vivid-proposed

« back to all changes in this revision

Viewing changes to modules/ra.py

  • Committer: Package Import Robot
  • Author(s): Martin Loschwitz
  • Date: 2013-08-02 07:37:50 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130802073750-wq5kjrh5w61eu0xf
Tags: 1.2.5+hg1006-1
New upstream checkout for Pacemaker 1.1.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#
17
17
 
18
18
import os
19
 
import sys
20
19
import subprocess
21
20
import copy
22
 
import xml.dom.minidom
 
21
from lxml import etree
23
22
import re
24
23
import glob
25
 
from userprefs import Options, UserPrefs
26
24
from cache import WCache
27
25
from vars import Vars, getpwdent
28
26
from utils import *
38
36
    '''
39
37
    def __init__(self):
40
38
        self.good = self.is_lrmd_accessible()
41
 
    def lrmadmin(self, opts, xml = False):
 
39
    def lrmadmin(self, opts, xml=False):
42
40
        '''
43
41
        Get information directly from lrmd using lrmadmin.
44
42
        '''
45
 
        l = stdout2list("%s %s" % (lrmadmin_prog,opts))
 
43
        rc, l = stdout2list("%s %s" % (lrmadmin_prog, opts))
46
44
        if l and not xml:
47
45
            l = l[1:] # skip the first line
48
46
        return l
52
50
        return subprocess.call(\
53
51
            add_sudo(">/dev/null 2>&1 %s -C" % lrmadmin_prog), \
54
52
            shell=True) == 0
55
 
    def meta(self, ra_class,ra_type,ra_provider):
56
 
        return self.lrmadmin("-M %s %s %s"%(ra_class,ra_type,ra_provider),True)
57
 
    def providers(self, ra_type,ra_class = "ocf"):
 
53
    def meta(self, ra_class, ra_type, ra_provider):
 
54
        return self.lrmadmin("-M %s %s %s"%(ra_class, ra_type, ra_provider), True)
 
55
    def providers(self, ra_type, ra_class="ocf"):
58
56
        'List of providers for a class:type.'
59
 
        return self.lrmadmin("-P %s %s" % (ra_class,ra_type),True)
 
57
        return self.lrmadmin("-P %s %s" % (ra_class, ra_type), True)
60
58
    def classes(self):
61
59
        'List of classes.'
62
60
        return self.lrmadmin("-C")
63
 
    def types(self, ra_class = "ocf", ra_provider = ""):
 
61
    def types(self, ra_class="ocf", ra_provider=""):
64
62
        'List of types for a class.'
65
63
        return self.lrmadmin("-T %s" % ra_class)
66
64
 
70
68
    '''
71
69
    def __init__(self):
72
70
        self.good = True
73
 
    def meta(self, ra_class,ra_type,ra_provider):
 
71
    def meta(self, ra_class, ra_type, ra_provider):
74
72
        l = []
75
73
        if ra_class == "ocf":
76
 
            l = stdout2list("%s/resource.d/%s/%s meta-data" % \
77
 
                (os.environ["OCF_ROOT"],ra_provider,ra_type))
 
74
            rc, l = stdout2list("%s/resource.d/%s/%s meta-data" % \
 
75
                (os.environ["OCF_ROOT"], ra_provider, ra_type))
78
76
        elif ra_class == "stonith":
79
77
            if ra_type.startswith("fence_") and os.path.exists("/usr/sbin/%s" %  ra_type):
80
 
                l = stdout2list("/usr/sbin/%s -o metadata" % ra_type)
 
78
                rc, l = stdout2list("/usr/sbin/%s -o metadata" % ra_type)
81
79
            else:
82
 
                l = stdout2list("stonith -m -t %s" % ra_type)
 
80
                rc, l = stdout2list("stonith -m -t %s" % ra_type)
83
81
        elif ra_class == "nagios":
84
 
            l = stdout2list("%s/check_%s --metadata" % \
 
82
            rc, l = stdout2list("%s/check_%s --metadata" % \
85
83
                (vars.nagios_dir, ra_type))
86
84
        return l
87
 
    def providers(self, ra_type,ra_class = "ocf"):
 
85
    def providers(self, ra_type, ra_class="ocf"):
88
86
        'List of providers for a class:type.'
89
87
        l = []
90
88
        if ra_class == "ocf":
91
 
            for s in glob.glob("%s/resource.d/*/%s" % (os.environ["OCF_ROOT"],ra_type)):
 
89
            for s in glob.glob("%s/resource.d/*/%s" % (os.environ["OCF_ROOT"], ra_type)):
92
90
                a = s.split("/")
93
91
                if len(a) == 7:
94
92
                    l.append(a[5])
96
94
    def classes(self):
97
95
        'List of classes.'
98
96
        return "heartbeat lsb nagios ocf stonith".split()
99
 
    def types(self, ra_class = "ocf", ra_provider = ""):
 
97
    def types(self, ra_class="ocf", ra_provider=""):
100
98
        'List of types for a class.'
101
99
        l = []
102
100
        prov = ra_provider and ra_provider or "*"
103
101
        if ra_class == "ocf":
104
 
            l = os_types_list("%s/resource.d/%s/*" % (os.environ["OCF_ROOT"],prov))
 
102
            l = os_types_list("%s/resource.d/%s/*" % (os.environ["OCF_ROOT"], prov))
105
103
        elif ra_class == "lsb":
106
104
            l = os_types_list("/etc/init.d/*")
107
105
        elif ra_class == "stonith":
108
 
            l = stdout2list("stonith -L")
 
106
            rc, l = stdout2list("stonith -L")
 
107
            if rc != 0:
 
108
                # stonith(8) may not be installed
 
109
                common_debug("stonith exited with code %d" % rc)
 
110
                l = []
109
111
            l.extend(os_types_list("/usr/sbin/fence_*"))
110
112
        elif ra_class == "nagios":
111
113
            l = os_types_list("%s/check_*" % vars.nagios_dir)
128
130
        '''
129
131
        Get information from crm_resource.
130
132
        '''
131
 
        return stdout2list("crm_resource %s" % opts, stderr_on=False)
132
 
    def meta(self, ra_class,ra_type,ra_provider):
133
 
        return self.crm_resource("--show-metadata %s:%s:%s"%(ra_class,ra_provider,ra_type))
134
 
    def providers(self, ra_type,ra_class = "ocf"):
 
133
        rc, s = stdout2list("crm_resource %s" % opts, stderr_on=False)
 
134
        # not clear when/why crm_resource exits with non-zero
 
135
        # code
 
136
        if rc != 0:
 
137
            common_debug("crm_resource %s exited with code %d" % \
 
138
                (opts, rc))
 
139
        return s
 
140
    def meta(self, ra_class, ra_type, ra_provider):
 
141
        return self.crm_resource("--show-metadata %s:%s:%s"%(ra_class, ra_provider, ra_type))
 
142
    def providers(self, ra_type, ra_class="ocf"):
135
143
        'List of providers for OCF:type.'
136
144
        if ra_class != "ocf":
137
145
            common_err("no providers for class %s" % ra_class)
141
149
        'List of classes.'
142
150
        l = self.crm_resource("--list-standards")
143
151
        return l
144
 
    def types(self, ra_class = "ocf", ra_provider = ""):
 
152
    def types(self, ra_class="ocf", ra_provider=""):
145
153
        'List of types for a class.'
146
154
        if ra_provider:
147
 
            return self.crm_resource("--list-agents %s:%s" % (ra_class,ra_provider))
 
155
            return self.crm_resource("--list-agents %s:%s" % (ra_class, ra_provider))
148
156
        else:
149
157
            return self.crm_resource("--list-agents %s" % ra_class)
150
158
 
153
161
    # after this glue release all users can get meta-data and
154
162
    # similar from lrmd
155
163
    minimum_glue = "1.0.10"
156
 
    glue_ver = get_stdout("%s -v" % lrmadmin_prog, stderr_on = False)
 
164
    rc, glue_ver = get_stdout("%s -v" % lrmadmin_prog, stderr_on = False)
157
165
    if not glue_ver: #lrmadmin probably not found
158
166
        return False
159
167
    v_min = version.LooseVersion(minimum_glue)
160
168
    v_this = version.LooseVersion(glue_ver)
161
169
    return v_this >= v_min or \
162
 
        (getpwdent()[0] in ("root",vars.crm_daemon_user))
 
170
        (getpwdent()[0] in ("root", vars.crm_daemon_user))
163
171
def crm_resource_support():
164
 
    s = get_stdout("crm_resource --list-standards", stderr_on = False)
 
172
    rc, s = get_stdout("crm_resource --list-standards", stderr_on = False)
165
173
    return s != ""
166
174
def ra_if():
167
175
    if vars.ra_if:
182
190
        return wcache.retrieve("ra_classes")
183
191
    l = ra_if().classes()
184
192
    l.sort()
185
 
    return wcache.store("ra_classes",l)
186
 
def ra_providers(ra_type,ra_class = "ocf"):
 
193
    return wcache.store("ra_classes", l)
 
194
def ra_providers(ra_type, ra_class="ocf"):
187
195
    'List of providers for a class:type.'
188
 
    id = "ra_providers-%s-%s" % (ra_class,ra_type)
 
196
    id = "ra_providers-%s-%s" % (ra_class, ra_type)
189
197
    if wcache.is_cached(id):
190
198
        return wcache.retrieve(id)
191
 
    l = ra_if().providers(ra_type,ra_class)
 
199
    l = ra_if().providers(ra_type, ra_class)
192
200
    l.sort()
193
 
    return wcache.store(id,l)
194
 
def ra_providers_all(ra_class = "ocf"):
 
201
    return wcache.store(id, l)
 
202
def ra_providers_all(ra_class="ocf"):
195
203
    '''
196
204
    List of providers for a class.
197
205
    '''
201
209
    dir = "%s/resource.d" % os.environ["OCF_ROOT"]
202
210
    l = []
203
211
    for s in os.listdir(dir):
204
 
        if os.path.isdir("%s/%s" % (dir,s)):
 
212
        if os.path.isdir("%s/%s" % (dir, s)):
205
213
            l.append(s)
206
214
    l.sort()
207
 
    return wcache.store(id,l)
208
 
def ra_types(ra_class = "ocf", ra_provider = ""):
 
215
    return wcache.store(id, l)
 
216
def ra_types(ra_class="ocf", ra_provider=""):
209
217
    '''
210
218
    List of RA type for a class.
211
219
    '''
212
220
    if not ra_class:
213
221
        ra_class = "ocf"
214
 
    id = "ra_types-%s-%s" % (ra_class,ra_provider)
 
222
    id = "ra_types-%s-%s" % (ra_class, ra_provider)
215
223
    if wcache.is_cached(id):
216
224
        return wcache.retrieve(id)
217
225
    list = []
218
226
    for ra in ra_if().types(ra_class):
219
227
        if (not ra_provider or \
220
 
                ra_provider in ra_providers(ra,ra_class)) \
 
228
                ra_provider in ra_providers(ra, ra_class)) \
221
229
                and ra not in list:
222
230
            list.append(ra)
223
231
    list.sort()
224
 
    return wcache.store(id,list)
 
232
    return wcache.store(id, list)
225
233
 
226
234
def get_pe_meta():
227
235
    if not vars.pe_metadata:
261
269
    '''
262
270
    l = []
263
271
    if is_program(prog):
264
 
        l = stdout2list("%s metadata" % prog)
 
272
        rc, l = stdout2list("%s metadata" % prog)
 
273
        if rc != 0:
 
274
            common_debug("%s metadata exited with code %d" % (prog, rc))
 
275
            l = []
265
276
    return l
266
 
def get_nodes_text(n,tag):
267
 
    try:
268
 
        node = n.getElementsByTagName(tag)[0]
269
 
        for c in node.childNodes:
270
 
            if c.nodeType == c.TEXT_NODE:
271
 
                return c.data.strip()
 
277
def get_nodes_text(n, tag):
 
278
    try: return n.findtext(tag).strip()
272
279
    except: return ''
273
280
 
274
 
def mk_monitor_name(role,depth):
 
281
def mk_monitor_name(role, depth):
275
282
    depth = depth != "0" and ("_%s" % depth) or ""
276
283
    return role and role != "Started" and \
277
 
        "monitor_%s%s" % (role,depth) or \
 
284
        "monitor_%s%s" % (role, depth) or \
278
285
        "monitor%s" % depth
279
286
def monitor_name_node(node):
280
 
    depth = node.getAttribute("depth") or '0'
281
 
    role = node.getAttribute("role")
282
 
    return mk_monitor_name(role,depth)
 
287
    depth = node.get("depth") or '0'
 
288
    role = node.get("role")
 
289
    return mk_monitor_name(role, depth)
283
290
def monitor_name_pl(pl):
284
291
    depth = find_value(pl, "depth") or '0'
285
292
    role = find_value(pl, "role")
286
 
    return mk_monitor_name(role,depth)
 
293
    return mk_monitor_name(role, depth)
287
294
 
288
295
class RAInfo(object):
289
296
    '''
293
300
    required_ops = ("start", "stop")
294
301
    skip_ops = ("meta-data", "validate-all")
295
302
    skip_op_attr = ("name", "depth", "role")
296
 
    def __init__(self,ra_class,ra_type,ra_provider = "heartbeat"):
 
303
    def __init__(self, ra_class, ra_type, ra_provider="heartbeat"):
297
304
        self.advanced_params = []
298
305
        self.ra_class = ra_class
299
306
        self.ra_type = ra_type
300
307
        self.ra_provider = ra_provider
301
308
        if not self.ra_provider:
302
309
            self.ra_provider = "heartbeat"
303
 
        self.ra_node = None
 
310
        self.ra_elem = None
304
311
    def ra_string(self):
305
312
        return self.ra_class == "ocf" and \
306
313
            "%s:%s:%s" % (self.ra_class, self.ra_provider, self.ra_type) or \
316
323
    def set_advanced_params(self, l):
317
324
        self.advanced_params = l
318
325
    def filter_crmd_attributes(self):
319
 
        for n in self.ra_node.getElementsByTagName("parameter"):
320
 
            if not n.getAttribute("name") in vars.crmd_user_attributes:
321
 
                n.parentNode.removeChild(n)
322
 
    def add_ra_params(self,ra):
 
326
        for p in self.ra_elem.xpath("//parameters/parameter"):
 
327
            if not p.get("name") in vars.crmd_user_attributes:
 
328
                self.ra_elem.remove(p)
 
329
    def add_ra_params(self, ra):
323
330
        '''
324
331
        Add parameters from another RAInfo instance.
325
332
        '''
326
333
        try:
327
 
            if not self.mk_ra_node() or not ra.mk_ra_node():
 
334
            if self.mk_ra_node() is None or ra.mk_ra_node() is None:
328
335
                return
329
336
        except:
330
337
            return
331
338
        try:
332
 
            params_node = self.doc.getElementsByTagName("parameters")[0]
 
339
            params_node = self.ra_elem.findall("parameters")[0]
333
340
        except:
334
 
            params_node = self.doc.createElement("parameters")
335
 
            self.ra_node.appendChild(params_node)
336
 
        for n in ra.ra_node.getElementsByTagName("parameter"):
337
 
            params_node.appendChild(self.doc.importNode(n,1))
 
341
            params_node = etree.SubElement(self.ra_elem, "parameters")
 
342
        for n in ra.ra_elem.xpath("//parameters/parameter"):
 
343
            params_node.append(copy.deepcopy(n))
338
344
    def mk_ra_node(self):
339
345
        '''
340
346
        Return the resource_agent node.
341
347
        '''
342
 
        if self.ra_node:
343
 
            return self.ra_node
 
348
        if self.ra_elem is not None:
 
349
            return self.ra_elem
344
350
        meta = self.meta()
345
351
        try:
346
 
            self.doc = xml.dom.minidom.parseString('\n'.join(meta))
347
 
        except:
348
 
            self.error("could not parse meta-data: %s" % '\n'.join(meta))
349
 
            self.ra_node = None
350
 
            return None
351
 
        try:
352
 
            self.ra_node = self.doc.getElementsByTagName("resource-agent")[0]
353
 
        except:
 
352
            self.ra_elem = etree.fromstring('\n'.join(meta))
 
353
            assert(self.ra_elem.tag == 'resource-agent')
 
354
        except Exception, msg:
 
355
            common_err(msg)
354
356
            self.error("meta-data contains no resource-agent element")
355
 
            self.ra_node = None
 
357
            self.ra_elem = None
356
358
            return None
357
359
        if self.ra_class == "stonith":
358
360
            self.add_ra_params(get_stonithd_meta())
359
 
        return self.ra_node
360
 
    def param_type_default(self,n):
 
361
        return self.ra_elem
 
362
    def param_type_default(self, n):
361
363
        try:
362
 
            content = n.getElementsByTagName("content")[0]
363
 
            type = content.getAttribute("type")
364
 
            default = content.getAttribute("default")
365
 
            return type,default
 
364
            content = n.find("content")
 
365
            type = content.get("type")
 
366
            default = content.get("default")
 
367
            return type, default
366
368
        except:
367
 
            return None,None
 
369
            return None, None
368
370
    def params(self):
369
371
        '''
370
372
        Construct a dict of dicts: parameters are keys and
373
375
        id = "ra_params-%s" % self.ra_string()
374
376
        if wcache.is_cached(id):
375
377
            return wcache.retrieve(id)
376
 
        if not self.mk_ra_node():
 
378
        if self.mk_ra_node() is None:
377
379
            return None
378
380
        d = {}
379
 
        for pset in self.ra_node.getElementsByTagName("parameters"):
380
 
            for c in pset.getElementsByTagName("parameter"):
381
 
                name = c.getAttribute("name")
382
 
                if not name:
383
 
                    continue
384
 
                required = c.getAttribute("required")
385
 
                unique = c.getAttribute("unique")
386
 
                type,default = self.param_type_default(c)
387
 
                d[name] = {
388
 
                    "required": required,
389
 
                    "unique": unique,
390
 
                    "type": type,
391
 
                    "default": default,
392
 
                }
393
 
        return wcache.store(id,d)
 
381
        for c in self.ra_elem.xpath("//parameters/parameter"):
 
382
            name = c.get("name")
 
383
            if not name:
 
384
                continue
 
385
            required = c.get("required")
 
386
            unique = c.get("unique")
 
387
            type, default = self.param_type_default(c)
 
388
            d[name] = {
 
389
                "required": required,
 
390
                "unique": unique,
 
391
                "type": type,
 
392
                "default": default,
 
393
            }
 
394
        return wcache.store(id, d)
394
395
    def completion_params(self):
395
396
        '''
396
397
        Extra method for completion, for we want to filter some
397
398
        (advanced) parameters out. And we want this to be fast.
398
399
        '''
399
 
        if not self.mk_ra_node():
 
400
        if self.mk_ra_node() is None:
400
401
            return None
401
 
        return [c.getAttribute("name")
402
 
            for c in self.ra_node.getElementsByTagName("parameter")
403
 
                if c.getAttribute("name")
404
 
                and c.getAttribute("name") not in self.advanced_params
 
402
        return [c.get("name")
 
403
            for c in self.ra_elem.xpath("//parameters/parameter")
 
404
                if c.get("name")
 
405
                and c.get("name") not in self.advanced_params
405
406
        ]
406
407
    def actions(self):
407
408
        '''
411
412
        id = "ra_actions-%s" % self.ra_string()
412
413
        if wcache.is_cached(id):
413
414
            return wcache.retrieve(id)
414
 
        if not self.mk_ra_node():
 
415
        if self.mk_ra_node() is None:
415
416
            return None
416
417
        d = {}
417
 
        for pset in self.ra_node.getElementsByTagName("actions"):
418
 
            for c in pset.getElementsByTagName("action"):
419
 
                name = c.getAttribute("name")
420
 
                if not name or name in self.skip_ops:
 
418
        for c in self.ra_elem.xpath("//actions/action"):
 
419
            name = c.get("name")
 
420
            if not name or name in self.skip_ops:
 
421
                continue
 
422
            if name == "monitor":
 
423
                name = monitor_name_node(c)
 
424
            d[name] = {}
 
425
            for a in c.attrib.keys():
 
426
                if a in self.skip_op_attr:
421
427
                    continue
422
 
                if name == "monitor":
423
 
                    name = monitor_name_node(c)
424
 
                d[name] = {}
425
 
                for a in c.attributes.keys():
426
 
                    if a in self.skip_op_attr:
427
 
                        continue
428
 
                    v = c.getAttribute(a)
429
 
                    if v:
430
 
                        d[name][a] = v
 
428
                v = c.get(a)
 
429
                if v:
 
430
                    d[name][a] = v
431
431
        # add monitor ops without role, if they don't already
432
432
        # exist
433
433
        d2 = {}
437
437
                if not norole_op in d:
438
438
                    d2[norole_op] = d[op]
439
439
        d.update(d2)
440
 
        return wcache.store(id,d)
 
440
        return wcache.store(id, d)
441
441
    def reqd_params_list(self):
442
442
        '''
443
443
        List of required parameters.
445
445
        d = self.params()
446
446
        if not d: return []
447
447
        return [x for x in d if d[x]["required"] == '1']
448
 
    def param_default(self,pname):
 
448
    def param_default(self, pname):
449
449
        '''
450
450
        Parameter's default.
451
451
        '''
466
466
            if p in ("action", "port"):
467
467
                return True
468
468
        return False
469
 
    def sanity_check_params(self, id, pl, existence_only = False):
 
469
    def sanity_check_params(self, id, pl, existence_only=False):
470
470
        '''
471
 
        pl is a list of (attribute,value) pairs.
 
471
        pl is a list of (attribute, value) pairs.
472
472
        - are all required parameters defined
473
473
        - do all parameters exist
474
474
        '''
475
475
        rc = 0
476
476
        d = {}
477
 
        for p,v in pl:
 
477
        for p, v in pl:
478
478
            d[p] = v
479
479
        if not existence_only:
480
480
            for p in self.reqd_params_list():
481
481
                if self.unreq_param(p):
482
482
                    continue
483
483
                if p not in d:
484
 
                    common_err("%s: required parameter %s not defined" % (id,p))
 
484
                    common_err("%s: required parameter %s not defined" % (id, p))
485
485
                    rc |= user_prefs.get_check_rc()
486
486
        for p in d:
487
487
            if p.startswith("$"):
488
488
                # these are special, non-RA parameters
489
489
                continue
490
490
            if p not in self.params():
491
 
                common_err("%s: parameter %s does not exist" % (id,p))
 
491
                common_err("%s: parameter %s does not exist" % (id, p))
492
492
                rc |= user_prefs.get_check_rc()
493
493
        return rc
494
 
    def get_adv_timeout(self, op, node = None):
495
 
        if node and op == "monitor":
 
494
    def get_adv_timeout(self, op, node=None):
 
495
        if node is not None and op == "monitor":
496
496
            name = monitor_name_node(node)
497
497
        else:
498
498
            name = op
511
511
        for op in ops:
512
512
            n_op = op[0] == "monitor" and monitor_name_pl(op[1]) or op[0]
513
513
            n_ops[n_op] = {}
514
 
            for p,v in op[1]:
 
514
            for p, v in op[1]:
515
515
                if p in self.skip_op_attr:
516
516
                    continue
517
517
                n_ops[n_op][p] = v
524
524
            if self.ra_class == "stonith" and op in ("start", "stop"):
525
525
                continue
526
526
            if op not in self.actions():
527
 
                common_warn("%s: action %s not advertised in meta-data, it may not be supported by the RA" % (id,op))
 
527
                common_warn("%s: action %s not advertised in meta-data, it may not be supported by the RA" % (id, op))
528
528
                rc |= 1
529
529
            if "interval" in n_ops[op]:
530
530
                v = n_ops[op]["interval"]
531
531
                v_msec = crm_msec(v)
532
532
                if op in ("start", "stop") and v_msec != 0:
533
 
                    common_warn("%s: Specified interval for %s is %s, it must be 0" %(id,op,v))
 
533
                    common_warn("%s: Specified interval for %s is %s, it must be 0" %(id, op, v))
534
534
                    rc |= 1
535
535
                if op.startswith("monitor") and v_msec != 0:
536
536
                    if v_msec not in intervals:
550
550
                timeout_string = "default timeout"
551
551
            if crm_msec(v) < 0:
552
552
                continue
553
 
            if crm_time_cmp(adv_timeout,v) > 0:
 
553
            if crm_time_cmp(adv_timeout, v) > 0:
554
554
                common_warn("%s: %s %s for %s is smaller than the advised %s" % \
555
 
                    (id,timeout_string,v,op,adv_timeout))
 
555
                    (id, timeout_string, v, op, adv_timeout))
556
556
                rc |= 1
557
557
        return rc
558
558
    def meta(self):
565
565
        if self.ra_class in vars.meta_progs:
566
566
            l = prog_meta(self.ra_class)
567
567
        else:
568
 
            l = ra_if().meta(self.ra_class,self.ra_type,self.ra_provider)
 
568
            l = ra_if().meta(self.ra_class, self.ra_type, self.ra_provider)
569
569
        self.debug("read and cached meta-data")
570
570
        return wcache.store(id, l)
571
571
    def meta_pretty(self):
572
572
        '''
573
573
        Print the RA meta-data in a human readable form.
574
574
        '''
575
 
        if not self.mk_ra_node():
 
575
        if self.mk_ra_node() is None:
576
576
            return ''
577
577
        l = []
578
578
        title = self.meta_title()
579
579
        l.append(title)
580
 
        longdesc = get_nodes_text(self.ra_node,"longdesc")
 
580
        longdesc = get_nodes_text(self.ra_elem,"longdesc")
581
581
        if longdesc:
582
582
            l.append(longdesc)
583
583
        if self.ra_class != "heartbeat":
588
588
        if actions:
589
589
            l.append(actions)
590
590
        return '\n\n'.join(l)
591
 
    def get_shortdesc(self,n):
592
 
        name = n.getAttribute("name")
 
591
    def get_shortdesc(self, n):
 
592
        name = n.get("name")
593
593
        shortdesc = get_nodes_text(n,"shortdesc")
594
594
        longdesc = get_nodes_text(n,"longdesc")
595
 
        if shortdesc and shortdesc not in (name,longdesc,self.ra_type):
 
595
        if shortdesc and shortdesc not in (name, longdesc, self.ra_type):
596
596
            return shortdesc
597
597
        return ''
598
598
    def meta_title(self):
599
599
        s = self.ra_string()
600
 
        shortdesc = self.get_shortdesc(self.ra_node)
 
600
        shortdesc = self.get_shortdesc(self.ra_elem)
601
601
        if shortdesc:
602
 
            s = "%s (%s)" % (shortdesc,s)
 
602
            s = "%s (%s)" % (shortdesc, s)
603
603
        return s
604
 
    def meta_param_head(self,n):
605
 
        name = n.getAttribute("name")
 
604
    def meta_param_head(self, n):
 
605
        name = n.get("name")
606
606
        if not name:
607
607
            return None
608
608
        s = name
609
 
        if n.getAttribute("required") == "1":
 
609
        if n.get("required") == "1":
610
610
            s = s + "*"
611
 
        type,default = self.param_type_default(n)
 
611
        type, default = self.param_type_default(n)
612
612
        if type and default:
613
 
            s = "%s (%s, [%s])" % (s,type,default)
 
613
            s = "%s (%s, [%s])" % (s, type, default)
614
614
        elif type:
615
 
            s = "%s (%s)" % (s,type)
 
615
            s = "%s (%s)" % (s, type)
616
616
        shortdesc = self.get_shortdesc(n)
617
 
        s = "%s: %s" % (s,shortdesc)
 
617
        s = "%s: %s" % (s, shortdesc)
618
618
        return s
619
 
    def format_parameter(self,n):
 
619
    def format_parameter(self, n):
620
620
        l = []
621
621
        head = self.meta_param_head(n)
622
622
        if not head:
625
625
        l.append(head)
626
626
        longdesc = get_nodes_text(n,"longdesc")
627
627
        if longdesc:
628
 
            longdesc = self.ra_tab + longdesc.replace("\n","\n"+self.ra_tab) + '\n'
 
628
            longdesc = self.ra_tab + longdesc.replace("\n", "\n"+self.ra_tab) + '\n'
629
629
            l.append(longdesc)
630
630
        return '\n'.join(l)
631
 
    def meta_parameter(self,param):
632
 
        if not self.mk_ra_node():
 
631
    def meta_parameter(self, param):
 
632
        if self.mk_ra_node() is None:
633
633
            return ''
634
 
        l = []
635
 
        for pset in self.ra_node.getElementsByTagName("parameters"):
636
 
            for c in pset.getElementsByTagName("parameter"):
637
 
                if c.getAttribute("name") == param:
638
 
                    return self.format_parameter(c)
 
634
        for c in self.ra_elem.xpath("//parameters/parameter"):
 
635
            if c.get("name") == param:
 
636
                return self.format_parameter(c)
639
637
    def meta_parameters(self):
640
 
        if not self.mk_ra_node():
 
638
        if self.mk_ra_node() is None:
641
639
            return ''
642
640
        l = []
643
 
        for pset in self.ra_node.getElementsByTagName("parameters"):
644
 
            for c in pset.getElementsByTagName("parameter"):
645
 
                s = self.format_parameter(c)
646
 
                if s:
647
 
                    l.append(s)
 
641
        for c in self.ra_elem.xpath("//parameters/parameter"):
 
642
            s = self.format_parameter(c)
 
643
            if s:
 
644
                l.append(s)
648
645
        if l:
649
646
            return "Parameters (* denotes required, [] the default):\n\n" + '\n'.join(l)
650
 
    def meta_action_head(self,n):
651
 
        name = n.getAttribute("name")
 
647
    def meta_action_head(self, n):
 
648
        name = n.get("name")
652
649
        if not name:
653
650
            return ''
654
651
        if name in self.skip_ops:
656
653
        if name == "monitor":
657
654
            name = monitor_name_node(n)
658
655
        s = "%-13s" % name
659
 
        for a in n.attributes.keys():
 
656
        for a in n.attrib.keys():
660
657
            if a in self.skip_op_attr:
661
658
                continue
662
 
            v = n.getAttribute(a)
 
659
            v = n.get(a)
663
660
            if v:
664
 
                s = "%s %s=%s" % (s,a,v)
 
661
                s = "%s %s=%s" % (s, a, v)
665
662
        return s
666
663
    def meta_actions(self):
667
664
        l = []
668
 
        for aset in self.ra_node.getElementsByTagName("actions"):
669
 
            for c in aset.getElementsByTagName("action"):
670
 
                s = self.meta_action_head(c)
671
 
                if s:
672
 
                    l.append(self.ra_tab + s)
 
665
        for c in self.ra_elem.xpath("//actions/action"):
 
666
            s = self.meta_action_head(c)
 
667
            if s:
 
668
                l.append(self.ra_tab + s)
673
669
        if l:
674
670
            return "Operations' defaults (advisory minimum):\n\n" + '\n'.join(l)
675
671
 
676
 
def get_ra(node):
677
 
    ra_type = node.getAttribute("type")
678
 
    ra_class = node.getAttribute("class")
679
 
    ra_provider = node.getAttribute("provider")
680
 
    return RAInfo(ra_class,ra_type,ra_provider)
 
672
def get_ra(el):
 
673
    ra_type = el.get("type")
 
674
    ra_class = el.get("class")
 
675
    ra_provider = el.get("provider")
 
676
    return RAInfo(ra_class, ra_type, ra_provider)
681
677
 
682
678
#
683
679
# resource type definition
704
700
    '''
705
701
    l = s.split(':')
706
702
    if not l or len(l) > 3:
707
 
        return ["","",""]
 
703
        return ["", "", ""]
708
704
    if len(l) == 3:
709
705
        return l
710
706
    elif len(l) == 2:
711
 
        ra_class,ra_type = l
 
707
        ra_class, ra_type = l
712
708
    else:
713
709
        ra_class = "ocf"
714
710
        ra_type = l[0]
715
711
    ra_provider = ''
716
712
    if ra_class == "ocf":
717
 
        pl = ra_providers(ra_type,ra_class)
 
713
        pl = ra_providers(ra_type, ra_class)
718
714
        if pl and len(pl) == 1:
719
715
            ra_provider = pl[0]
720
716
        elif not pl:
721
717
            ra_provider = 'heartbeat'
722
 
    return ra_class,ra_provider,ra_type
 
718
    return ra_class, ra_provider, ra_type
723
719
 
724
720
wcache = WCache.getInstance()
725
721
vars = Vars.getInstance()