Package pywbem :: Module mof_compiler
[frames] | no frames]

Source Code for Module pywbem.mof_compiler

   1  #!/usr/bin/env python 
   2  # 
   3  # (C) Copyright 2006-2007 Novell, Inc. 
   4  # 
   5  # This library is free software; you can redistribute it and/or 
   6  # modify it under the terms of the GNU Lesser General Public 
   7  # License as published by the Free Software Foundation; either 
   8  # version 2.1 of the License, or (at your option) any later version. 
   9  # 
  10  # This program is distributed in the hope that it will be useful, but 
  11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
  12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  13  # Lesser General Public License for more details. 
  14  # 
  15  # You should have received a copy of the GNU Lesser General Public 
  16  # License along with this program; if not, write to the Free Software 
  17  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18  # 
  19  # Author: Bart Whiteley <bwhiteley suse.de> 
  20  # 
  21   
  22  import sys 
  23  import os 
  24  from getpass import getpass 
  25   
  26  from pywbem import lex, yacc, cim_obj 
  27  from pywbem.cim_obj import CIMInstance, CIMInstanceName, CIMClass, \ 
  28                             CIMProperty, CIMMethod, CIMParameter, \ 
  29                             CIMQualifier, CIMQualifierDeclaration, NocaseDict 
  30  from pywbem.cim_operations import CIMError, WBEMConnection 
  31  from pywbem.cim_constants import * 
  32   
  33  __all__ = ['MOFParseError', 'MOFWBEMConnection', 'MOFCompiler'] 
  34   
  35  _optimize = 1 
  36  _tabmodule = 'mofparsetab' 
  37  _lextab = 'moflextab' 
  38  _outputdir = 'pywbem' 
  39   
  40  reserved = { 
  41      'any':'ANY', 
  42      'as':'AS', 
  43      'association':'ASSOCIATION', 
  44      'class':'CLASS', 
  45      'disableoverride':'DISABLEOVERRIDE', 
  46      'boolean':'DT_BOOL', 
  47      'char16':'DT_CHAR16', 
  48      'datetime':'DT_DATETIME', 
  49      'pragma':'PRAGMA', 
  50      'real32':'DT_REAL32', 
  51      'real64':'DT_REAL64', 
  52      'sint16':'DT_SINT16', 
  53      'sint32':'DT_SINT32', 
  54      'sint64':'DT_SINT64', 
  55      'sint8':'DT_SINT8', 
  56      'string':'DT_STR', 
  57      'uint16':'DT_UINT16', 
  58      'uint32':'DT_UINT32', 
  59      'uint64':'DT_UINT64', 
  60      'uint8':'DT_UINT8', 
  61      'enableoverride':'ENABLEOVERRIDE', 
  62      'false':'FALSE', 
  63      'flavor':'FLAVOR', 
  64      'indication':'INDICATION', 
  65      'instance':'INSTANCE', 
  66      'method':'METHOD', 
  67      'null':'NULL', 
  68      'of':'OF', 
  69      'parameter':'PARAMETER', 
  70      'property':'PROPERTY', 
  71      'qualifier':'QUALIFIER', 
  72      'ref':'REF', 
  73      'reference':'REFERENCE', 
  74      'restricted':'RESTRICTED', 
  75      'schema':'SCHEMA', 
  76      'scope':'SCOPE', 
  77      'tosubclass':'TOSUBCLASS', 
  78      'translatable':'TRANSLATABLE', 
  79      'true':'TRUE', 
  80      } 
  81   
  82  tokens = reserved.values() + [ 
  83      'IDENTIFIER', 
  84      'stringValue', 
  85      'floatValue', 
  86      'charValue', 
  87      'binaryValue', 
  88      'octalValue', 
  89      'decimalValue', 
  90      'hexValue', 
  91  ] 
  92   
  93  literals = '#(){};[],$:=' 
  94   
  95  # UTF-8 (from Unicode 4.0.0 standard): 
  96  # Table 3-6. Well-Formed UTF-8 Byte Sequences Code Points 
  97  # 1st Byte 2nd Byte 3rd Byte 4th Byte 
  98  # U+0000..U+007F     00..7F 
  99  # U+0080..U+07FF     C2..DF   80..BF 
 100  # U+0800..U+0FFF     E0       A0..BF   80..BF 
 101  # U+1000..U+CFFF     E1..EC   80..BF   80..BF 
 102  # U+D000..U+D7FF     ED       80..9F   80..BF 
 103  # U+E000..U+FFFF     EE..EF   80..BF   80..BF 
 104  # U+10000..U+3FFFF   F0       90..BF   80..BF   80..BF 
 105  # U+40000..U+FFFFF   F1..F3   80..BF   80..BF   80..BF 
 106  # U+100000..U+10FFFF F4       80..8F   80..BF   80..BF 
 107   
 108  utf8_2 = r'[\xC2-\xDF][\x80-\xBF]' 
 109  utf8_3_1 = r'\xE0[\xA0-\xBF][\x80-\xBF]' 
 110  utf8_3_2 = r'[\xE1-\xEC][\x80-\xBF][\x80-\xBF]' 
 111  utf8_3_3 = r'\xED[\x80-\x9F][\x80-\xBF]' 
 112  utf8_3_4 = r'[\xEE-\xEF][\x80-\xBF][\x80-\xBF]' 
 113  utf8_4_1 = r'\xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF]' 
 114  utf8_4_2 = r'[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]' 
 115  utf8_4_3 = r'\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]' 
 116   
 117  utf8Char = r'(%s)|(%s)|(%s)|(%s)|(%s)|(%s)|(%s)|(%s)' % \ 
 118             (utf8_2, utf8_3_1, utf8_3_2, utf8_3_3, utf8_3_4, utf8_4_1, 
 119              utf8_4_2, utf8_4_3) 
120 121 -def t_COMMENT(t):
122 r'//.*' 123 pass
124
125 -def t_MCOMMENT(t):
126 r'/\*(.|\n)*?\*/' 127 t.lineno += t.value.count('\n')
128 129 130 t_binaryValue = r'[+-]?[01]+[bB]' 131 t_octalValue = r'[+-]?0[0-7]+' 132 t_decimalValue = r'[+-]?([1-9][0-9]*|0)' 133 t_hexValue = r'[+-]?0[xX][0-9a-fA-F]+' 134 t_floatValue = r'[+-]?[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?' 135 136 simpleEscape = r"""[bfnrt'"\\]""" 137 hexEscape = r'x[0-9a-fA-F]{1,4}' 138 escapeSequence = r'[\\]((%s)|(%s))' % (simpleEscape, hexEscape) 139 cChar = r"[^'\\\n\r]|(%s)" % escapeSequence 140 sChar = r'[^"\\\n\r]|(%s)' % escapeSequence 141 charValue = r"'%s'" % cChar 142 143 t_stringValue = r'"(%s)*"' % sChar 144 145 identifier_re = r'([a-zA-Z_]|(%s))([0-9a-zA-Z_]|(%s))*' % (utf8Char, utf8Char)
146 147 @lex.TOKEN(identifier_re) 148 -def t_IDENTIFIER(t):
149 # check for reserved word 150 t.type = reserved.get(t.value.lower(), 'IDENTIFIER') 151 return t
152
153 # Define a rule so we can track line numbers 154 -def t_newline(t):
155 r'\n+' 156 t.lexer.lineno += len(t.value) 157 t.lexer.linestart = t.lexpos
158 159 t_ignore = ' \r\t'
160 161 # Error handling rule 162 -def t_error(t):
163 msg = "Illegal character '%s' " % t.value[0] 164 msg += "Line %d, col %d" % (t.lineno, _find_column(t.lexer.parser.mof, t)) 165 t.lexer.parser.log(msg) 166 t.lexer.skip(1)
167
168 -class MOFParseError(ValueError):
169 pass
170
171 -def p_error(p):
172 ex = MOFParseError() 173 if p is None: 174 ex.args = ('Unexpected end of file',) 175 raise ex 176 ex.file = p.lexer.parser.file 177 ex.lineno = p.lineno 178 ex.column = _find_column(p.lexer.parser.mof, p) 179 ex.context = _get_error_context(p.lexer.parser.mof, p) 180 raise ex
181
182 183 -def p_mofSpecification(p):
184 """mofSpecification : mofProductionList"""
185
186 -def p_mofProductionList(p):
187 """mofProductionList : empty 188 | mofProductionList mofProduction 189 """
190
191 -def p_mofProduction(p):
192 """mofProduction : compilerDirective 193 | mp_createClass 194 | mp_setQualifier 195 | mp_createInstance 196 """
197
198 199 -def _create_ns(p, handle, ns):
200 # Figure out the flavor of cim server 201 cimom_type = None 202 ns = ns.strip('/') 203 try: 204 inames = handle.EnumerateInstanceNames('__Namespace', namespace='root') 205 inames = [x['name'] for x in inames] 206 if 'PG_InterOp' in inames: 207 cimom_type = 'pegasus' 208 except CIMError, ce: 209 if ce.args[0] != CIM_ERR_NOT_FOUND: 210 ce.file_line = (p.parser.file, p.lexer.lineno) 211 raise 212 if not cimom_type: 213 try: 214 inames = handle.EnumerateInstanceNames('CIM_Namespace', 215 namespace='Interop') 216 inames = [x['name'] for x in inames] 217 cimom_type = 'proper' 218 except CIMError, ce: 219 ce.file_line = (p.parser.file, p.lexer.lineno) 220 raise 221 222 if not cimom_type: 223 ce = CIMError(CIM_ERR_FAILED, 224 'Unable to determine CIMOM type') 225 ce.file_line = (p.parser.file, p.lexer.lineno) 226 raise ce 227 if cimom_type == 'pegasus': 228 # To create a namespace in Pegasus, create an instance of 229 # __Namespace with __Namespace.Name = '', and create it in 230 # the target namespace to be created. 231 inst = CIMInstance( 232 '__Namespace', 233 properties={'Name':''}, 234 path=CIMInstanceName( 235 '__Namespace', 236 keybindings={'Name':''}, 237 namespace=ns)) 238 try: 239 handle.CreateInstance(inst) 240 except CIMError, ce: 241 if ce.args[0] != CIM_ERR_ALREADY_EXISTS: 242 ce.file_line = (p.parser.file, p.lexer.lineno) 243 raise 244 245 elif cimom_type == 'proper': 246 inst = CIMInstance( 247 'CIM_Namespace', 248 properties={'Name': ns}, 249 path=CIMInstanceName( 250 'CIM_Namespace', 251 namespace='root', 252 keybindings={'Name':ns})) 253 handle.CreateInstance(inst)
254
255 256 257 258 -def p_mp_createClass(p):
259 """mp_createClass : classDeclaration 260 | assocDeclaration 261 | indicDeclaration 262 """ 263 ns = p.parser.handle.default_namespace 264 cc = p[1] 265 try: 266 fixedNS = fixedRefs = fixedSuper = False 267 while not fixedNS or not fixedRefs or not fixedSuper: 268 try: 269 if p.parser.verbose: 270 p.parser.log('Creating class %s:%s' % (ns, cc.classname)) 271 p.parser.handle.CreateClass(cc) 272 if p.parser.verbose: 273 p.parser.log('Created class %s:%s' % (ns, cc.classname)) 274 p.parser.classnames[ns].append(cc.classname.lower()) 275 break 276 except CIMError, ce: 277 ce.file_line = (p.parser.file, p.lexer.lineno) 278 errcode = ce.args[0] 279 if errcode == CIM_ERR_INVALID_NAMESPACE: 280 if fixedNS: 281 raise 282 if p.parser.verbose: 283 p.parser.log('Creating namespace ' + ns) 284 _create_ns(p, p.parser.handle, ns) 285 fixedNS = True 286 continue 287 if not p.parser.search_paths: 288 raise 289 if errcode == CIM_ERR_INVALID_SUPERCLASS: 290 if fixedSuper: 291 raise 292 moffile = p.parser.mofcomp.find_mof(cc.superclass) 293 if not moffile: 294 raise 295 p.parser.mofcomp.compile_file(moffile, ns) 296 fixedSuper = True 297 elif errcode in [CIM_ERR_INVALID_PARAMETER, 298 CIM_ERR_NOT_FOUND, 299 CIM_ERR_FAILED]: 300 if fixedRefs: 301 raise 302 if not p.parser.qualcache[ns]: 303 for fname in ['qualifiers', 'qualifiers_optional']: 304 qualfile = p.parser.mofcomp.find_mof(fname) 305 if qualfile: 306 p.parser.mofcomp.compile_file(qualfile, ns) 307 if not p.parser.qualcache[ns]: 308 # can't find qualifiers 309 raise 310 objects = cc.properties.values() 311 for meth in cc.methods.values(): 312 objects += meth.parameters.values() 313 dep_classes = [] 314 for obj in objects: 315 if obj.type not in ['reference', 'string']: 316 continue 317 if obj.type == 'reference': 318 if obj.reference_class.lower() not in dep_classes: 319 dep_classes.append(obj.reference_class.lower()) 320 continue 321 # else obj.type is 'string' 322 try: 323 embedded_inst = obj.qualifiers['embeddedinstance'] 324 except KeyError: 325 continue 326 embedded_inst = embedded_inst.value.lower() 327 if embedded_inst not in dep_classes: 328 dep_classes.append(embedded_inst) 329 continue 330 for klass in dep_classes: 331 if klass in p.parser.classnames[ns]: 332 continue 333 try: 334 # don't limit it with LocalOnly=True, 335 # PropertyList, IncludeQualifiers=False, ... 336 # because of caching in case we're using the 337 # special WBEMConnection subclass used for 338 # removing schema elements 339 p.parser.handle.GetClass(klass, 340 LocalOnly=False, 341 IncludeQualifiers=True) 342 p.parser.classnames[ns].append(klass) 343 except CIMError: 344 moffile = p.parser.mofcomp.find_mof(klass) 345 if not moffile: 346 raise 347 p.parser.mofcomp.compile_file(moffile, ns) 348 p.parser.classnames[ns].append(klass) 349 fixedRefs = True 350 else: 351 raise 352 353 except CIMError, ce: 354 ce.file_line = (p.parser.file, p.lexer.lineno) 355 if ce.args[0] != CIM_ERR_ALREADY_EXISTS: 356 raise 357 if p.parser.verbose: 358 p.parser.log('Class %s already exist. Modifying...' % cc.classname) 359 try: 360 p.parser.handle.ModifyClass(cc, ns) 361 except CIMError, ce: 362 p.parser.log('Error Modifying class %s: %s, %s' % \ 363 (cc.classname, ce.args[0], ce.args[1]))
364
365 -def p_mp_createInstance(p):
366 """mp_createInstance : instanceDeclaration""" 367 inst = p[1] 368 if p.parser.verbose: 369 p.parser.log('Creating instance of %s.' % inst.classname) 370 try: 371 p.parser.handle.CreateInstance(inst) 372 except CIMError, ce: 373 if ce.args[0] == CIM_ERR_ALREADY_EXISTS: 374 if p.parser.verbose: 375 p.parser.log('Instance of class %s already exist. ' \ 376 'Modifying...' % inst.classname) 377 try: 378 p.parser.handle.ModifyInstance(inst) 379 except CIMError, ce: 380 if ce.args[0] == CIM_ERR_NOT_SUPPORTED: 381 if p.parser.verbose: 382 p.parser.log('ModifyInstance not supported. ' \ 383 'Deleting instance of %s: %s' % \ 384 (inst.classname, inst.path)) 385 p.parser.handle.DeleteInstance(inst.path) 386 if p.parser.verbose: 387 p.parser.log('Creating instance of %s.' % \ 388 inst.classname) 389 p.parser.handle.CreateInstance(inst) 390 else: 391 ce.file_line = (p.parser.file, p.lexer.lineno) 392 raise
393
394 -def p_mp_setQualifier(p):
395 """mp_setQualifier : qualifierDeclaration""" 396 qualdecl = p[1] 397 ns = p.parser.handle.default_namespace 398 if p.parser.verbose: 399 p.parser.log('Setting qualifier %s' % qualdecl.name) 400 try: 401 p.parser.handle.SetQualifier(qualdecl) 402 except CIMError, ce: 403 if ce.args[0] == CIM_ERR_INVALID_NAMESPACE: 404 if p.parser.verbose: 405 p.parser.log('Creating namespace ' + ns) 406 _create_ns(p, p.parser.handle, ns) 407 if p.parser.verbose: 408 p.parser.log('Setting qualifier %s' % qualdecl.name) 409 p.parser.handle.SetQualifier(qualdecl) 410 elif ce.args[0] == CIM_ERR_NOT_SUPPORTED: 411 if p.parser.verbose: 412 p.parser.log('Qualifier %s already exists. Deleting...' % \ 413 qualdecl.name) 414 p.parser.handle.DeleteQualifier(qualdecl.name) 415 if p.parser.verbose: 416 p.parser.log('Setting qualifier %s' % qualdecl.name) 417 p.parser.handle.SetQualifier(qualdecl) 418 else: 419 ce.file_line = (p.parser.file, p.lexer.lineno) 420 raise 421 p.parser.qualcache[ns][qualdecl.name] = qualdecl
422
423 -def p_compilerDirective(p):
424 """compilerDirective : '#' PRAGMA pragmaName '(' pragmaParameter ')'""" 425 directive = p[3].lower() 426 param = p[5] 427 if directive == 'include': 428 fname = param 429 #if p.parser.file: 430 fname = os.path.dirname(p.parser.file) + '/' + fname 431 p.parser.mofcomp.compile_file(fname, p.parser.handle.default_namespace) 432 elif directive == 'namespace': 433 p.parser.handle.default_namespace = param 434 if param not in p.parser.qualcache: 435 p.parser.qualcache[param] = NocaseDict() 436 437 p[0] = None
438
439 -def p_pragmaName(p):
440 """pragmaName : identifier""" 441 p[0] = p[1]
442
443 -def p_pragmaParameter(p):
444 """pragmaParameter : stringValue""" 445 p[0] = _fixStringValue(p[1])
446
447 -def p_classDeclaration(p):
448 """classDeclaration : 449 CLASS className '{' classFeatureList '}' ';' 450 | CLASS className superClass '{' classFeatureList '}' ';' 451 | CLASS className alias '{' classFeatureList '}' ';' 452 | CLASS className alias superClass '{' classFeatureList '}' ';' 453 | qualifierList CLASS className '{' classFeatureList '}' ';' 454 | qualifierList CLASS className superClass '{' classFeatureList '}' ';' 455 | qualifierList CLASS className alias '{' classFeatureList '}' ';' 456 | qualifierList CLASS className alias superClass '{' 457 classFeatureList '}' ';' 458 """ 459 superclass = None 460 alias = None 461 quals = [] 462 if isinstance(p[1], basestring): # no class qualifiers 463 cname = p[2] 464 if p[3][0] == '$': # alias present 465 alias = p[3] 466 if p[4] == '{': # no superclass 467 cfl = p[5] 468 else: # superclass 469 superclass = p[4] 470 cfl = p[6] 471 else: # no alias 472 if p[3] == '{': # no superclass 473 cfl = p[4] 474 else: # superclass 475 superclass = p[3] 476 cfl = p[5] 477 else: # class qualifiers 478 quals = p[1] 479 cname = p[3] 480 if p[4][0] == '$': # alias present 481 alias = p[4] 482 if p[5] == '{': # no superclass 483 cfl = p[6] 484 else: # superclass 485 superclass = p[5] 486 cfl = p[7] 487 else: # no alias 488 if p[4] == '{': # no superclass 489 cfl = p[5] 490 else: # superclass 491 superclass = p[4] 492 cfl = p[6] 493 quals = dict([(x.name, x) for x in quals]) 494 methods = {} 495 props = {} 496 for item in cfl: 497 item.class_origin = cname 498 if isinstance(item, CIMMethod): 499 methods[item.name] = item 500 else: 501 props[item.name] = item 502 p[0] = CIMClass(cname, properties=props, methods=methods, 503 superclass=superclass, qualifiers=quals) 504 if alias: 505 p.parser.aliases[alias] = p[0]
506
507 -def p_classFeatureList(p):
508 """classFeatureList : empty 509 | classFeatureList classFeature 510 """ 511 if len(p) == 2: 512 p[0] = [] 513 else: 514 p[0] = p[1] + [p[2]]
515
516 -def p_assocDeclaration(p):
517 """assocDeclaration : 518 '[' ASSOCIATION qualifierListEmpty ']' CLASS className '{' 519 associationFeatureList '}' ';' 520 | '[' ASSOCIATION qualifierListEmpty ']' CLASS className superClass '{' 521 associationFeatureList '}' ';' 522 | '[' ASSOCIATION qualifierListEmpty ']' CLASS className alias '{' 523 associationFeatureList '}' ';' 524 | '[' ASSOCIATION qualifierListEmpty ']' CLASS className alias 525 superClass '{' associationFeatureList '}' ';' 526 """ 527 aqual = CIMQualifier('ASSOCIATION', True, type='boolean') 528 # TODO flavor trash. 529 quals = [aqual] + p[3] 530 p[0] = _assoc_or_indic_decl(quals, p)
531
532 -def p_indicDeclaration(p):
533 """indicDeclaration : 534 '[' INDICATION qualifierListEmpty ']' CLASS className '{' 535 classFeatureList '}' ';' 536 | '[' INDICATION qualifierListEmpty ']' CLASS className superClass '{' 537 classFeatureList '}' ';' 538 | '[' INDICATION qualifierListEmpty ']' CLASS className alias '{' 539 classFeatureList '}' ';' 540 | '[' INDICATION qualifierListEmpty ']' CLASS className alias 541 superClass '{' classFeatureList '}' ';' 542 """ 543 iqual = CIMQualifier('INDICATION', True, type='boolean') 544 # TODO flavor trash. 545 quals = [iqual] + p[3] 546 p[0] = _assoc_or_indic_decl(quals, p)
547
548 -def _assoc_or_indic_decl(quals, p):
549 """(refer to grammer rules on p_assocDeclaration and p_indicDeclaration)""" 550 superclass = None 551 alias = None 552 cname = p[6] 553 if p[7] == '{': 554 cfl = p[8] 555 elif p[7][0] == '$': # alias 556 alias = p[7] 557 if p[8] == '{': 558 cfl = p[9] 559 else: 560 superclass = p[8] 561 cfl = p[10] 562 else: 563 superclass = p[7] 564 cfl = p[9] 565 props = {} 566 methods = {} 567 for item in cfl: 568 item.class_origin = cname 569 if isinstance(item, CIMMethod): 570 methods[item.name] = item 571 else: 572 props[item.name] = item 573 quals = dict([(x.name, x) for x in quals]) 574 cc = CIMClass(cname, properties=props, methods=methods, 575 superclass=superclass, qualifiers=quals) 576 if alias: 577 p.parser.aliases[alias] = cc 578 return cc
579
580 -def p_qualifierListEmpty(p):
581 """qualifierListEmpty : empty 582 | qualifierListEmpty ',' qualifier 583 """ 584 if len(p) == 2: 585 p[0] = [] 586 else: 587 p[0] = p[1] + [p[3]]
588
589 -def p_associationFeatureList(p):
590 """associationFeatureList : empty 591 | associationFeatureList associationFeature 592 """ 593 if len(p) == 2: 594 p[0] = [] 595 else: 596 p[0] = p[1] + [p[2]]
597
598 -def p_className(p):
599 """className : identifier""" 600 p[0] = p[1]
601
602 -def p_alias(p):
603 """alias : AS aliasIdentifier""" 604 p[0] = p[2]
605
606 -def p_aliasIdentifier(p):
607 """aliasIdentifier : '$' identifier""" 608 p[0] = '$%s' % p[2]
609
610 -def p_superClass(p):
611 """superClass : ':' className""" 612 p[0] = p[2]
613
614 -def p_classFeature(p):
615 """classFeature : propertyDeclaration 616 | methodDeclaration 617 | referenceDeclaration 618 """ 619 p[0] = p[1]
620
621 -def p_associationFeature(p):
622 """associationFeature : classFeature""" 623 p[0] = p[1]
624
625 -def p_qualifierList(p):
626 """qualifierList : '[' qualifier qualifierListEmpty ']'""" 627 p[0] = [p[2]] + p[3]
628
629 -def p_qualifier(p):
630 """qualifier : qualifierName 631 | qualifierName ':' flavorList 632 | qualifierName qualifierParameter 633 | qualifierName qualifierParameter ':' flavorList 634 """ 635 qname = p[1] 636 ns = p.parser.handle.default_namespace 637 qval = None 638 flavorlist = [] 639 if len(p) == 3: 640 qval = p[2] 641 elif len(p) == 4: 642 flavorlist = p[3] 643 elif len(p) == 5: 644 qval = p[2] 645 flavorlist = p[4] 646 try: 647 qualdecl = p.parser.qualcache[ns][qname] 648 except KeyError: 649 try: 650 quals = p.parser.handle.EnumerateQualifiers() 651 except CIMError, ce: 652 if ce.args[0] != CIM_ERR_INVALID_NAMESPACE: 653 ce.file_line = (p.parser.file, p.lexer.lineno) 654 raise 655 _create_ns(p, p.parser.handle, ns) 656 quals = None 657 658 if quals: 659 for qual in quals: 660 p.parser.qualcache[ns][qual.name] = qual 661 else: 662 for fname in ['qualifiers', 'qualifiers_optional']: 663 qualfile = p.parser.mofcomp.find_mof(fname) 664 if qualfile: 665 p.parser.mofcomp.compile_file(qualfile, ns) 666 try: 667 qualdecl = p.parser.qualcache[ns][qname] 668 except KeyError: 669 ce = CIMError(CIM_ERR_FAILED, 'Unknown Qualifier: %s' % qname) 670 ce.file_line = (p.parser.file, p.lexer.lineno) 671 raise ce 672 673 flavors = _build_flavors(flavorlist, qualdecl) 674 if qval is None: 675 if qualdecl.type == 'boolean': 676 qval = True 677 else: 678 qval = qualdecl.value # default value 679 else: 680 qval = cim_obj.tocimobj(qualdecl.type, qval) 681 p[0] = CIMQualifier(qname, qval, type=qualdecl.type, **flavors)
682 # TODO propagated?
683 684 -def p_flavorList(p):
685 """flavorList : flavor 686 | flavorList flavor 687 """ 688 if len(p) == 2: 689 p[0] = [p[1]] 690 else: 691 p[0] = p[1] + [p[2]]
692
693 -def p_qualifierParameter(p):
694 """qualifierParameter : '(' constantValue ')' 695 | arrayInitializer 696 """ 697 if len(p) == 2: 698 p[0] = p[1] 699 else: 700 p[0] = p[2]
701
702 -def p_flavor(p):
703 """flavor : ENABLEOVERRIDE 704 | DISABLEOVERRIDE 705 | RESTRICTED 706 | TOSUBCLASS 707 | TRANSLATABLE 708 """ 709 p[0] = p[1].lower()
710
711 -def p_propertyDeclaration(p):
712 """propertyDeclaration : propertyDeclaration_1 713 | propertyDeclaration_2 714 | propertyDeclaration_3 715 | propertyDeclaration_4 716 | propertyDeclaration_5 717 | propertyDeclaration_6 718 | propertyDeclaration_7 719 | propertyDeclaration_8 720 """ 721 p[0] = p[1]
722
723 -def p_propertyDeclaration_1(p):
724 """propertyDeclaration_1 : dataType propertyName ';'""" 725 p[0] = CIMProperty(p[2], None, type=p[1])
726
727 -def p_propertyDeclaration_2(p):
728 """propertyDeclaration_2 : dataType propertyName defaultValue ';'""" 729 p[0] = CIMProperty(p[2], p[3], type=p[1])
730
731 -def p_propertyDeclaration_3(p):
732 """propertyDeclaration_3 : dataType propertyName array ';'""" 733 p[0] = CIMProperty(p[2], None, type=p[1], is_array=True, 734 array_size=p[3])
735
736 -def p_propertyDeclaration_4(p):
737 """propertyDeclaration_4 : dataType propertyName array defaultValue ';'""" 738 p[0] = CIMProperty(p[2], p[4], type=p[1], is_array=True, 739 array_size=p[3])
740
741 -def p_propertyDeclaration_5(p):
742 """propertyDeclaration_5 : qualifierList dataType propertyName ';'""" 743 quals = dict([(x.name, x) for x in p[1]]) 744 p[0] = CIMProperty(p[3], None, type=p[2], qualifiers=quals)
745
746 -def p_propertyDeclaration_6(p):
747 """propertyDeclaration_6 : qualifierList dataType propertyName 748 defaultValue ';'""" 749 quals = dict([(x.name, x) for x in p[1]]) 750 p[0] = CIMProperty(p[3], cim_obj.tocimobj(p[2], p[4]), 751 type=p[2], qualifiers=quals)
752
753 -def p_propertyDeclaration_7(p):
754 """propertyDeclaration_7 : qualifierList dataType propertyName array ';'""" 755 quals = dict([(x.name, x) for x in p[1]]) 756 p[0] = CIMProperty(p[3], None, type=p[2], qualifiers=quals, 757 is_array=True, array_size=p[4])
758
759 -def p_propertyDeclaration_8(p):
760 """propertyDeclaration_8 : qualifierList dataType propertyName array 761 defaultValue ';'""" 762 quals = dict([(x.name, x) for x in p[1]]) 763 p[0] = CIMProperty(p[3], cim_obj.tocimobj(p[2], p[5]), 764 type=p[2], qualifiers=quals, is_array=True, 765 array_size=p[4])
766
767 -def p_referenceDeclaration(p):
768 """referenceDeclaration : 769 objectRef referenceName ';' 770 | objectRef referenceName defaultValue ';' 771 | qualifierList objectRef referenceName ';' 772 | qualifierList objectRef referenceName defaultValue ';' 773 """ 774 quals = [] 775 dv = None 776 if isinstance(p[1], list): # qualifiers 777 quals = p[1] 778 cname = p[2] 779 pname = p[3] 780 if len(p) == 6: 781 dv = p[4] 782 else: 783 cname = p[1] 784 pname = p[2] 785 if len(p) == 5: 786 dv = p[3] 787 quals = dict([(x.name, x) for x in quals]) 788 p[0] = CIMProperty(pname, dv, type='reference', 789 reference_class=cname, qualifiers=quals)
790
791 -def p_methodDeclaration(p):
792 """methodDeclaration : 793 dataType methodName '(' ')' ';' 794 | dataType methodName '(' parameterList ')' ';' 795 | qualifierList dataType methodName '(' ')' ';' 796 | qualifierList dataType methodName '(' parameterList ')' ';' 797 """ 798 paramlist = [] 799 quals = [] 800 if isinstance(p[1], basestring): # no quals 801 dt = p[1] 802 mname = p[2] 803 if p[4] != ')': 804 paramlist = p[4] 805 else: # quals present 806 quals = p[1] 807 dt = p[2] 808 mname = p[3] 809 if p[5] != ')': 810 paramlist = p[5] 811 params = dict([(param.name, param) for param in paramlist]) 812 quals = dict([(q.name, q) for q in quals]) 813 p[0] = CIMMethod(mname, return_type=dt, parameters=params, 814 qualifiers=quals)
815 # note: class_origin is set when adding method to class.
816 # TODO what to do with propagated? 817 818 -def p_propertyName(p):
819 """propertyName : identifier""" 820 p[0] = p[1]
821
822 -def p_referenceName(p):
823 """referenceName : identifier""" 824 p[0] = p[1]
825
826 -def p_methodName(p):
827 """methodName : identifier""" 828 p[0] = p[1]
829
830 -def p_dataType(p):
831 """dataType : DT_UINT8 832 | DT_SINT8 833 | DT_UINT16 834 | DT_SINT16 835 | DT_UINT32 836 | DT_SINT32 837 | DT_UINT64 838 | DT_SINT64 839 | DT_REAL32 840 | DT_REAL64 841 | DT_CHAR16 842 | DT_STR 843 | DT_BOOL 844 | DT_DATETIME 845 """ 846 p[0] = p[1].lower()
847
848 -def p_objectRef(p):
849 """objectRef : className REF""" 850 p[0] = p[1]
851
852 -def p_parameterList(p):
853 """parameterList : parameter 854 | parameterList ',' parameter 855 """ 856 if len(p) == 2: 857 p[0] = [p[1]] 858 else: 859 p[0] = p[1] + [p[3]]
860
861 -def p_parameter(p):
862 """parameter : parameter_1 863 | parameter_2 864 | parameter_3 865 | parameter_4 866 """ 867 p[0] = p[1]
868
869 -def p_parameter_1(p):
870 """parameter_1 : dataType parameterName 871 | dataType parameterName array 872 """ 873 args = {} 874 if len(p) == 4: 875 args['is_array'] = True 876 args['array_size'] = p[3] 877 p[0] = CIMParameter(p[2], p[1], **args)
878
879 -def p_parameter_2(p):
880 """parameter_2 : qualifierList dataType parameterName 881 | qualifierList dataType parameterName array 882 """ 883 args = {} 884 if len(p) == 5: 885 args['is_array'] = True 886 args['array_size'] = p[4] 887 quals = dict([(x.name, x) for x in p[1]]) 888 p[0] = CIMParameter(p[3], p[2], qualifiers=quals, **args)
889
890 -def p_parameter_3(p):
891 """parameter_3 : objectRef parameterName 892 | objectRef parameterName array 893 """ 894 args = {} 895 if len(p) == 4: 896 args['is_array'] = True 897 args['array_size'] = p[3] 898 p[0] = CIMParameter(p[2], 'reference', reference_class=p[1], 899 **args)
900
901 -def p_parameter_4(p):
902 """parameter_4 : qualifierList objectRef parameterName 903 | qualifierList objectRef parameterName array 904 """ 905 args = {} 906 if len(p) == 5: 907 args['is_array'] = True 908 args['array_size'] = p[4] 909 quals = dict([(x.name, x) for x in p[1]]) 910 p[0] = CIMParameter(p[3], 'reference', qualifiers=quals, 911 reference_class=p[2], **args)
912
913 -def p_parameterName(p):
914 """parameterName : identifier""" 915 p[0] = p[1]
916
917 -def p_array(p):
918 """array : '[' ']' 919 | '[' integerValue ']' 920 """ 921 if len(p) == 3: 922 p[0] = None 923 else: 924 p[0] = p[2]
925
926 -def p_defaultValue(p):
927 """defaultValue : '=' initializer""" 928 p[0] = p[2]
929
930 -def p_initializer(p):
931 """initializer : constantValue 932 | arrayInitializer 933 | referenceInitializer 934 """ 935 p[0] = p[1]
936
937 -def p_arrayInitializer(p):
938 """arrayInitializer : '{' constantValueList '}' 939 | '{' '}' 940 """ 941 if len(p) == 3: 942 p[0] = [] 943 else: 944 p[0] = p[2]
945
946 -def p_constantValueList(p):
947 """constantValueList : constantValue 948 | constantValueList ',' constantValue 949 """ 950 if len(p) == 2: 951 p[0] = [p[1]] 952 else: 953 p[0] = p[1] + [p[3]]
954
955 -def _fixStringValue(s):
956 s = s[1:-1] 957 rv = '' 958 esc = False 959 i = -1 960 while i < len(s) -1: 961 i += 1 962 ch = s[i] 963 if ch == '\\' and not esc: 964 esc = True 965 continue 966 if not esc: 967 rv += ch 968 continue 969 970 if ch == '"': rv += '"' 971 elif ch == 'n': rv += '\n' 972 elif ch == 't': rv += '\t' 973 elif ch == 'b': rv += '\b' 974 elif ch == 'f': rv += '\f' 975 elif ch == 'r': rv += '\r' 976 elif ch == '\\': rv += '\\' 977 elif ch in ['x', 'X']: 978 hexc = 0 979 j = 0 980 i += 1 981 while j < 4: 982 c = s[i+j]; 983 c = c.upper() 984 if not c.isdigit() and not c in 'ABCDEF': 985 break; 986 hexc <<= 4 987 if c.isdigit(): 988 hexc |= ord(c) - ord('0') 989 else: 990 hexc |= ord(c) - ord('A') + 0XA 991 j += 1 992 rv += chr(hexc) 993 i += j-1 994 995 esc = False 996 997 return rv
998
999 1000 1001 -def p_stringValueList(p):
1002 """stringValueList : stringValue 1003 | stringValueList stringValue 1004 """ 1005 if len(p) == 2: 1006 p[0] = _fixStringValue(p[1]) 1007 else: 1008 p[0] = p[1] + _fixStringValue(p[2])
1009
1010 1011 -def p_constantValue(p):
1012 """constantValue : integerValue 1013 | floatValue 1014 | charValue 1015 | stringValueList 1016 | booleanValue 1017 | nullValue 1018 """ 1019 p[0] = p[1]
1020
1021 -def p_integerValue(p):
1022 """integerValue : binaryValue 1023 | octalValue 1024 | decimalValue 1025 | hexValue 1026 """ 1027 p[0] = int(p[1])
1028 # TODO deal with non-decimal values.
1029 1030 -def p_referenceInitializer(p):
1031 """referenceInitializer : objectHandle 1032 | aliasIdentifier 1033 """ 1034 if p[1][0] == '$': 1035 try: 1036 p[0] = p.parser.aliases[p[1]] 1037 except KeyError: 1038 ce = CIMError(CIM_ERR_FAILED, 1039 'Unknown alias: ' + p[0]) 1040 ce.file_line = (p.parser.file, p.lexer.lineno) 1041 raise ce 1042 else: 1043 p[0] = p[1]
1044
1045 -def p_objectHandle(p):
1046 """objectHandle : identifier""" 1047 p[0] = p[1]
1048
1049 -def p_qualifierDeclaration(p):
1050 """qualifierDeclaration : 1051 QUALIFIER qualifierName qualifierType scope ';' 1052 | QUALIFIER qualifierName qualifierType scope defaultFlavor ';' 1053 """ 1054 qualtype = p[3] 1055 dt, is_array, array_size, value = qualtype 1056 qualname = p[2] 1057 scopes = p[4] 1058 if len(p) == 5: 1059 flist = [] 1060 else: 1061 flist = p[5] 1062 flavors = _build_flavors(flist) 1063 1064 p[0] = CIMQualifierDeclaration( 1065 qualname, dt, value=value, is_array=is_array, array_size=array_size, 1066 scopes=scopes, **flavors)
1067
1068 -def _build_flavors(flist, qualdecl=None):
1069 flavors = {} 1070 if qualdecl is not None: 1071 flavors = {'overridable':qualdecl.overridable, 1072 'translatable':qualdecl.translatable, 1073 'toinstance':qualdecl.toinstance, 1074 'tosubclass':qualdecl.tosubclass} 1075 if 'disableoverride' in flist: 1076 flavors['overridable'] = False 1077 if 'enableoverride' in flist: 1078 flavors['overridable'] = True 1079 if 'translatable' in flist: 1080 flavors['translatable'] = True 1081 if 'restricted' in flist: 1082 flavors['tosubclass'] = False 1083 if 'tosubclass' in flist: 1084 flavors['tosubclass'] = True 1085 try: 1086 if flavors['tosubclass']: 1087 flavors['toinstance'] = True 1088 except KeyError: 1089 pass 1090 return flavors
1091
1092 -def p_qualifierName(p):
1093 """qualifierName : identifier 1094 | ASSOCIATION 1095 | INDICATION 1096 """ 1097 p[0] = p[1]
1098
1099 -def p_qualifierType(p):
1100 """qualifierType : qualifierType_1 1101 | qualifierType_2 1102 """ 1103 p[0] = p[1]
1104
1105 -def p_qualifierType_1(p):
1106 """qualifierType_1 : ':' dataType array 1107 | ':' dataType array defaultValue 1108 """ 1109 dv = None 1110 if len(p) == 5: 1111 dv = p[4] 1112 p[0] = (p[2], True, p[3], dv)
1113
1114 -def p_qualifierType_2(p):
1115 """qualifierType_2 : ':' dataType 1116 | ':' dataType defaultValue 1117 """ 1118 dv = None 1119 if len(p) == 4: 1120 dv = p[3] 1121 p[0] = (p[2], False, None, dv)
1122
1123 -def p_scope(p):
1124 """scope : ',' SCOPE '(' metaElementList ')'""" 1125 slist = p[4] 1126 scopes = {} 1127 for i in ('CLASS', 1128 'ASSOCIATION', 1129 'INDICATION', 1130 'PROPERTY', 1131 'REFERENCE', 1132 'METHOD', 1133 'PARAMETER', 1134 'ANY'): 1135 scopes[i] = i in slist 1136 p[0] = scopes
1137
1138 -def p_metaElementList(p):
1139 """metaElementList : metaElement 1140 | metaElementList ',' metaElement 1141 """ 1142 if len(p) == 2: 1143 p[0] = [p[1]] 1144 else: 1145 p[0] = p[1] + [p[3]]
1146
1147 -def p_metaElement(p):
1148 """metaElement : SCHEMA 1149 | CLASS 1150 | ASSOCIATION 1151 | INDICATION 1152 | QUALIFIER 1153 | PROPERTY 1154 | REFERENCE 1155 | METHOD 1156 | PARAMETER 1157 | ANY 1158 """ 1159 p[0] = p[1].upper()
1160
1161 -def p_defaultFlavor(p):
1162 """defaultFlavor : ',' FLAVOR '(' flavorListWithComma ')'""" 1163 flist = p[4] 1164 flavors = {'ENABLEOVERRIDE':True, 1165 'TOSUBCLASS':True, 1166 'DISABLEOVERRIDE':False, 1167 'RESTRICTED':False, 1168 'TRANSLATABLE':False} 1169 for i in flist: 1170 flavors[i] = True 1171 p[0] = flavors
1172
1173 1174 -def p_flavorListWithComma(p):
1175 """flavorListWithComma : flavor 1176 | flavorListWithComma ',' flavor 1177 """ 1178 if len(p) == 2: 1179 p[0] = [p[1]] 1180 else: 1181 p[0] = p[1] + [p[3]]
1182
1183 -def p_instanceDeclaration(p):
1184 """instanceDeclaration : 1185 INSTANCE OF className '{' valueInitializerList '}' ';' 1186 | INSTANCE OF className alias '{' valueInitializerList '}' ';' 1187 | qualifierList INSTANCE OF className '{' valueInitializerList '}' ';' 1188 | qualifierList INSTANCE OF className alias '{' 1189 valueInitializerList '}' ';' 1190 """ 1191 alias = None 1192 quals = {} 1193 ns = p.parser.handle.default_namespace 1194 if isinstance(p[1], basestring): # no qualifiers 1195 cname = p[3] 1196 if p[4] == '{': 1197 props = p[5] 1198 else: 1199 props = p[6] 1200 alias = p[4] 1201 else: 1202 cname = p[4] 1203 #quals = p[1] # qualifiers on instances are deprecated -- rightly so. 1204 if p[5] == '{': 1205 props = p[6] 1206 else: 1207 props = p[7] 1208 alias = p[5] 1209 1210 try: 1211 cc = p.parser.handle.GetClass(cname, LocalOnly=False, 1212 IncludeQualifiers=True) 1213 p.parser.classnames[ns].append(cc.classname.lower()) 1214 except CIMError, ce: 1215 ce.file_line = (p.parser.file, p.lexer.lineno) 1216 if ce.args[0] == CIM_ERR_NOT_FOUND: 1217 file_ = p.parser.mofcomp.find_mof(cname) 1218 if p.parser.verbose: 1219 p.parser.log('Class %s does not exist' % cname) 1220 if file_: 1221 p.parser.mofcomp.compile_file(file_, ns) 1222 cc = p.parser.handle.GetClass(cname, LocalOnly=False, 1223 IncludeQualifiers=True) 1224 else: 1225 if p.parser.verbose: 1226 p.parser.log("Can't find file to satisfy class") 1227 ce = CIMError(CIM_ERR_INVALID_CLASS, cname) 1228 ce.file_line = (p.parser.file, p.lexer.lineno) 1229 raise ce 1230 else: 1231 raise 1232 path = CIMInstanceName(cname, namespace=ns) 1233 inst = CIMInstance(cname, properties=cc.properties, 1234 qualifiers=quals, path=path) 1235 for prop in props: 1236 pname = prop[1] 1237 pval = prop[2] 1238 try: 1239 cprop = inst.properties[pname] 1240 cprop.value = cim_obj.tocimobj(cprop.type, pval) 1241 except KeyError: 1242 ce = CIMError(CIM_ERR_INVALID_PARAMETER, 1243 'Invalid property: %s' % pname) 1244 ce.file_line = (p.parser.file, p.lexer.lineno) 1245 raise ce 1246 except ValueError, ve: 1247 ce = CIMError(CIM_ERR_INVALID_PARAMETER, 1248 'Invalid value for property: %s: %s' % \ 1249 (pname, ve.message)) 1250 ce.file_line = (p.parser.file, p.lexer.lineno) 1251 raise ce 1252 1253 for prop in inst.properties.values(): 1254 if 'key' not in prop.qualifiers or not prop.qualifiers['key']: 1255 continue 1256 if prop.value is None: 1257 ce = CIMError(CIM_ERR_FAILED, 1258 'Key property %s.%s is not set' % (cname, prop.name)) 1259 ce.file_line = (p.parser.file, p.lexer.lineno) 1260 raise ce 1261 inst.path.keybindings[prop.name] = prop.value 1262 1263 if alias: 1264 p.parser.aliases[alias] = inst.path 1265 p[0] = inst
1266
1267 -def p_valueInitializerList(p):
1268 """valueInitializerList : valueInitializer 1269 | valueInitializerList valueInitializer 1270 """ 1271 if len(p) == 2: 1272 p[0] = [p[1]] 1273 else: 1274 p[0] = p[1] + [p[2]]
1275
1276 1277 -def p_valueInitializer(p):
1278 """valueInitializer : identifier defaultValue ';' 1279 | qualifierList identifier defaultValue ';' 1280 """ 1281 if len(p) == 4: 1282 id_ = p[1] 1283 val = p[2] 1284 quals = [] 1285 else: 1286 quals = p[1] 1287 id_ = p[2] 1288 val = p[3] 1289 p[0] = (quals, id_, val)
1290
1291 -def p_booleanValue(p):
1292 """booleanValue : FALSE 1293 | TRUE 1294 """ 1295 p[0] = p[1].lower() == 'true'
1296
1297 -def p_nullValue(p):
1298 """nullValue : NULL""" 1299 p[0] = None
1300
1301 -def p_identifier(p):
1302 """identifier : IDENTIFIER 1303 | ANY 1304 | AS 1305 | CLASS 1306 | DISABLEOVERRIDE 1307 | dataType 1308 | ENABLEOVERRIDE 1309 | FLAVOR 1310 | INSTANCE 1311 | METHOD 1312 | OF 1313 | PARAMETER 1314 | PRAGMA 1315 | PROPERTY 1316 | QUALIFIER 1317 | REFERENCE 1318 | RESTRICTED 1319 | SCHEMA 1320 | SCOPE 1321 | TOSUBCLASS 1322 | TRANSLATABLE 1323 """ 1324 #| ASSOCIATION 1325 #| INDICATION 1326 p[0] = p[1]
1327
1328 -def p_empty(p):
1329 'empty :' 1330 pass
1331
1332 -def _find_column(input, token):
1333 i = token.lexpos 1334 while i > 0: 1335 if input[i] == '\n': 1336 break 1337 i -= 1 1338 column = (token.lexpos - i)+1 1339 return column
1340
1341 -def _get_error_context(input, token):
1342 try: 1343 line = input[token.lexpos : input.index('\n', token.lexpos)] 1344 except ValueError: 1345 line = input[token.lexpos:] 1346 i = input.rfind('\n', 0, token.lexpos) 1347 if i < 0: 1348 i = 0 1349 line = input[i:token.lexpos] + line 1350 lines = [line.strip('\r\n')] 1351 col = token.lexpos - i 1352 while len(lines) < 5 and i > 0: 1353 end = i 1354 i = input.rfind('\n', 0, i) 1355 if i < 0: 1356 i = 0 1357 lines.insert(0, input[i:end].strip('\r\n')) 1358 pointer = '' 1359 for ch in token.value: 1360 pointer += '^' 1361 pointline = '' 1362 i = 0 1363 while i < col -1: 1364 if lines[-1][i].isspace(): 1365 pointline += lines[-1][i] 1366 # otherwise, tabs complicate the alignment 1367 else: 1368 pointline += ' ' 1369 i += 1 1370 lines.append(pointline + pointer) 1371 return lines
1372
1373 -def _print_logger(str):
1374 print str
1375
1376 1377 -class MOFWBEMConnection(object):
1378 - def __init__(self, conn=None):
1379 self.conn = conn 1380 self.class_names = {} 1381 self.qualifiers = {} 1382 self.instances = {} 1383 self.classes = {} 1384 if conn is None: 1385 self.__default_namespace = 'root/cimv2'
1386
1387 - def setns(self, value):
1388 if self.conn is not None: 1389 self.conn.default_namespace = value 1390 else: 1391 self.__default_namespace = value
1392
1393 - def getns(self):
1394 if self.conn is not None: 1395 return self.conn.default_namespace 1396 else: 1397 return self.__default_namespace
1398 1399 default_namespace = property(getns, setns, None, 1400 "default_namespace property") 1401
1402 - def GetClass(self, *args, **kwargs):
1403 cname = len(args) > 0 and args[0] or kwargs['ClassName'] 1404 try: 1405 cc = self.classes[self.default_namespace][cname] 1406 except KeyError: 1407 if self.conn is None: 1408 ce = CIMError(CIM_ERR_NOT_FOUND, cname) 1409 raise ce 1410 cc = self.conn.GetClass(*args, **kwargs) 1411 try: 1412 self.classes[self.default_namespace][cc.classname] = cc 1413 except KeyError: 1414 self.classes[self.default_namespace] = \ 1415 NocaseDict({cc.classname:cc}) 1416 if 'LocalOnly' in kwargs and not kwargs['LocalOnly']: 1417 if cc.superclass: 1418 try: 1419 del kwargs['ClassName'] 1420 except KeyError: 1421 pass 1422 if len(args) > 0: 1423 args = args[1:] 1424 super_ = self.GetClass(cc.superclass, *args, **kwargs) 1425 for prop in super_.properties.values(): 1426 if prop.name not in cc.properties: 1427 cc.properties[prop.name] = prop 1428 for meth in super_.methods.values(): 1429 if meth.name not in cc.methods: 1430 cc.methods[meth.name] = meth 1431 return cc
1432
1433 - def CreateClass(self, *args, **kwargs):
1434 cc = len(args) > 0 and args[0] or kwargs['NewClass'] 1435 if cc.superclass: 1436 try: 1437 super_ = self.GetClass(cc.superclass, LocalOnly=True, 1438 IncludeQualifiers=False) 1439 except CIMError, ce: 1440 if ce.args[0] == CIM_ERR_NOT_FOUND: 1441 ce.args = (CIM_ERR_INVALID_SUPERCLASS, cc.superclass) 1442 raise 1443 else: 1444 raise 1445 1446 try: 1447 self.classes[self.default_namespace][cc.classname] = cc 1448 except KeyError: 1449 self.classes[self.default_namespace] = \ 1450 NocaseDict({cc.classname:cc}) 1451 1452 # TODO: should we see if it exists first with 1453 # self.conn.GetClass()? Do we want to create a class 1454 # that already existed? 1455 try: 1456 self.class_names[self.default_namespace].append(cc.classname) 1457 except KeyError: 1458 self.class_names[self.default_namespace] = [cc.classname]
1459
1460 - def ModifyClass(self, *args, **kwargs):
1461 raise CIMError(CIM_ERR_FAILED, 1462 'This should not happen!')
1463
1464 - def ModifyInstance(self, *args, **kwargs):
1465 raise CIMError(CIM_ERR_FAILED, 1466 'This should not happen!')
1467
1468 - def GetQualifier(self, *args, **kwargs):
1469 qualname = len(args) > 0 and args[0] or kwargs['QualifierName'] 1470 try: 1471 qual = self.qualifiers[self.default_namespace][qualname] 1472 except KeyError: 1473 if self.conn is None: 1474 raise CIMError(CIM_ERR_NOT_FOUND, qualname) 1475 qual = self.conn.GetQualifier(*args, **kwargs) 1476 return qual
1477
1478 - def SetQualifier(self, *args, **kwargs):
1479 qual = len(args) > 0 and args[0] or kwargs['QualifierDeclaration'] 1480 try: 1481 self.qualifiers[self.default_namespace][qual.name] = qual 1482 except KeyError: 1483 self.qualifiers[self.default_namespace] = \ 1484 NocaseDict({qual.name:qual})
1485
1486 - def EnumerateQualifiers(self, *args, **kwargs):
1487 if self.conn is not None: 1488 rv = self.conn.EnumerateQualifiers(*args, **kwargs) 1489 else: 1490 rv = [] 1491 try: 1492 rv += self.qualifiers[self.default_namespace].values() 1493 except KeyError: 1494 pass 1495 return rv
1496 1497
1498 - def CreateInstance(self, *args, **kwargs):
1499 inst = len(args) > 0 and args[0] or kwargs['NewInstance'] 1500 try: 1501 self.instances[self.default_namespace].append(inst) 1502 except KeyError: 1503 self.instances[self.default_namespace] = [inst] 1504 return inst.path
1505
1506 - def rollback(self, verbose=False):
1507 for ns, insts in self.instances.items(): 1508 insts.reverse() 1509 for inst in insts: 1510 try: 1511 if verbose: 1512 print 'Deleting instance', inst.path 1513 self.conn.DeleteInstance(inst.path) 1514 except CIMError, ce: 1515 print 'Error deleting instance', inst.path 1516 print ' ', '%s %s' % (ce.args[0], ce.args[1]) 1517 for ns, cnames in self.class_names.items(): 1518 self.default_namespace = ns 1519 cnames.reverse() 1520 for cname in cnames: 1521 try: 1522 if verbose: 1523 print 'Deleting class %s:%s' % (ns, cname) 1524 self.conn.DeleteClass(cname) 1525 except CIMError, ce: 1526 print 'Error deleting class %s:%s' % (ns, cname) 1527 print ' ', '%s %s' % (ce.args[0], ce.args[1])
1528 # TODO: do we want to do anything with qualifiers?
1529 1530 1531 -def _errcode2string(code):
1532 d = { 1533 CIM_ERR_FAILED : 'A general error occurred', 1534 CIM_ERR_ACCESS_DENIED : 'Resource not available', 1535 CIM_ERR_INVALID_NAMESPACE : 'The target namespace does not exist', 1536 CIM_ERR_INVALID_PARAMETER : 'Parameter value(s) invalid', 1537 CIM_ERR_INVALID_CLASS : 'The specified Class does not exist', 1538 CIM_ERR_NOT_FOUND : 'Requested object could not be found', 1539 CIM_ERR_NOT_SUPPORTED : 'Operation not supported', 1540 CIM_ERR_CLASS_HAS_CHILDREN : 'Class has subclasses', 1541 CIM_ERR_CLASS_HAS_INSTANCES : 'Class has instances', 1542 CIM_ERR_INVALID_SUPERCLASS : 'Superclass does not exist', 1543 CIM_ERR_ALREADY_EXISTS : 'Object already exists', 1544 CIM_ERR_NO_SUCH_PROPERTY : 'Property does not exist', 1545 CIM_ERR_TYPE_MISMATCH : 'Value incompatible with type', 1546 CIM_ERR_QUERY_LANGUAGE_NOT_SUPPORTED : 'Query language not supported', 1547 CIM_ERR_INVALID_QUERY : 'Query not valid', 1548 CIM_ERR_METHOD_NOT_AVAILABLE : 'Extrinsic method not executed', 1549 CIM_ERR_METHOD_NOT_FOUND : 'Extrinsic method does not exist', 1550 } 1551 try: 1552 s = d[code] 1553 except KeyError: 1554 s = 'Unknown Error' 1555 return s
1556
1557 -class MOFCompiler(object):
1558 - def __init__(self, handle, search_paths=[], verbose=False, 1559 log_func=_print_logger):
1560 """Initialize the compiler. 1561 1562 Keyword arguments: 1563 handle -- A WBEMConnection or similar object. The following 1564 attributes and methods need to be present, corresponding to the 1565 the attributes and methods on pywbem.WBEMConnection having 1566 the same names: 1567 - default_namespace 1568 - EnumerateInstanceNames() 1569 - CreateClass() 1570 - GetClass() 1571 - ModifyClass() 1572 - DeleteInstance() 1573 - CreateInstance() 1574 - ModifyInstance() 1575 - DeleteQualifier() 1576 - EnumerateQualifiers() 1577 - SetQualifier() 1578 search_paths -- A list of file system paths specifying where 1579 missing schema elements should be looked for. 1580 verbose -- True if extra messages should be printed. 1581 log_func -- A callable that takes a single string argument. 1582 The default logger prints to stdout. 1583 """ 1584 1585 self.parser = yacc.yacc(tabmodule=_tabmodule, optimize=_optimize) 1586 self.parser.search_paths = search_paths 1587 self.handle = handle 1588 self.parser.handle = handle 1589 self.lexer = lex.lex(lextab=_lextab, optimize=_optimize) 1590 self.lexer.parser = self.parser 1591 self.parser.qualcache = {handle.default_namespace: NocaseDict()} 1592 self.parser.classnames = {handle.default_namespace: []} 1593 self.parser.mofcomp = self 1594 self.parser.verbose = verbose 1595 self.parser.log = log_func 1596 self.parser.aliases = {}
1597
1598 - def compile_string(self, mof, ns, filename=None):
1599 """Compile a string of MOF. 1600 1601 Arguments: 1602 mof -- The string of MOF 1603 ns -- The CIM namespace 1604 1605 Keyword arguments: 1606 filename -- The name of the file that the MOF was read from. This 1607 is used in status and error messages. 1608 """ 1609 1610 lexer = self.lexer.clone() 1611 lexer.parser = self.parser 1612 try: 1613 oldfile = self.parser.file 1614 except AttributeError: 1615 oldfile = None 1616 self.parser.file = filename 1617 try: 1618 oldmof = self.parser.mof 1619 except AttributeError: 1620 oldmof = None 1621 self.parser.mof = mof 1622 self.parser.handle.default_namespace = ns 1623 if ns not in self.parser.qualcache: 1624 self.parser.qualcache[ns] = NocaseDict() 1625 if ns not in self.parser.classnames: 1626 self.parser.classnames[ns] = [] 1627 try: 1628 rv = self.parser.parse(mof, lexer=lexer) 1629 self.parser.file = oldfile 1630 self.parser.mof = oldmof 1631 return rv 1632 except MOFParseError, pe: 1633 self.parser.log('Syntax error:') 1634 if hasattr(pe, 'file') and hasattr(pe, 'lineno'): 1635 self.parser.log('%s:%s:' % (pe.file, pe.lineno)) 1636 if hasattr(pe, 'context'): 1637 self.parser.log('\n'.join(pe.context)) 1638 if str(pe): 1639 self.parser.log(str(pe)) 1640 raise 1641 except CIMError, ce: 1642 if hasattr(ce, 'file_line'): 1643 self.parser.log('Fatal Error: %s:%s' % (ce.file_line[0], 1644 ce.file_line[1])) 1645 else: 1646 self.parser.log('Fatal Error:') 1647 self.parser.log('%s%s' % (_errcode2string(ce.args[0]), 1648 ce.args[1] and ': '+ce.args[1] or '')) 1649 raise
1650
1651 - def compile_file(self, filename, ns):
1652 """Compile MOF from a file. 1653 1654 Arguments: 1655 filename -- The file to read MOF from 1656 ns -- The CIM namespace 1657 """ 1658 1659 if self.parser.verbose: 1660 self.parser.log('Compiling file ' + filename) 1661 f = open(filename, 'r') 1662 mof = f.read() 1663 f.close() 1664 1665 return self.compile_string(mof, ns, filename=filename)
1666
1667 - def find_mof(self, classname):
1668 """Find a MOF file corresponding to a CIM class name. The search_paths 1669 provided to __init__() are searched recursively. 1670 1671 Arguments: 1672 classname -- The name of the class to look for 1673 """ 1674 1675 classname = classname.lower() 1676 for search in self.parser.search_paths: 1677 for root, dirs, files in os.walk(search): 1678 for file_ in files: 1679 if file_.endswith('.mof') and \ 1680 file_[:-4].lower() == classname: 1681 return root + '/' + file_ 1682 return None
1683
1684 - def rollback(self, verbose=False):
1685 self.handle.rollback(verbose=verbose)
1686
1687 -def _build():
1688 yacc.yacc(optimize=_optimize, tabmodule=_tabmodule, outputdir=_outputdir) 1689 lex.lex(optimize=_optimize, lextab=_lextab, outputdir=_outputdir)
1690 1691 1692 if __name__ == '__main__': 1693 from optparse import OptionParser 1694 usage = 'usage: %prog -n <namespace> [options] <MOF file> ...' 1695 oparser = OptionParser(usage=usage) 1696 oparser.add_option('-s', '--search', dest='search', 1697 help='Search path to find missing schema elements. ' \ 1698 'This option can be present multiple times.', 1699 metavar='Path', action='append') 1700 oparser.add_option('-n', '--namespace', dest='ns', 1701 help='Specify the namespace', metavar='Namespace') 1702 oparser.add_option('-u', '--url', dest='url', 1703 help='URL to the CIM Server', metavar='URL', 1704 default='/var/run/tog-pegasus/cimxml.socket') 1705 oparser.add_option('-v', '--verbose', 1706 action='store_true', dest='verbose', default=False, 1707 help='Print more messages to stdout') 1708 oparser.add_option('-r', '--remove', 1709 action='store_true', dest='remove', default=False, 1710 help='Remove elements found in MOF, instead of ' \ 1711 'create them') 1712 oparser.add_option('-l', '--username', 1713 dest='username', metavar='Username', 1714 help='Specify the username') 1715 oparser.add_option('-p', '--password', 1716 dest='password', metavar='Password', 1717 help='Specify the password') 1718 oparser.add_option('-d', '--dry-run', 1719 dest='dry_run', default=False, action='store_true', 1720 help="Don't actually modify the repository, just " \ 1721 "check mof file syntax. Connection to CIMOM is " \ 1722 "still required to check qualifiers.") 1723 1724 (options, args) = oparser.parse_args() 1725 search = options.search 1726 if not args: 1727 oparser.error('No input files given for parsing') 1728 if options.ns is None: 1729 oparser.error('No namespace given') 1730 1731 passwd = options.password 1732 if options.username and not passwd: 1733 passwd = getpass('Enter password for %s: ' % options.username) 1734 if options.username: 1735 conn = WBEMConnection(options.url, (options.username, passwd)) 1736 else: 1737 conn = WBEMConnection(options.url) 1738 if options.remove or options.dry_run: 1739 conn = MOFWBEMConnection(conn=conn) 1740 #conn.debug = True 1741 conn.default_namespace = options.ns 1742 if search is None: 1743 search = [] 1744 1745 search = [os.path.abspath(x) for x in search] 1746 for fname in args: 1747 path = os.path.abspath(os.path.dirname(fname)) 1748 for spath in search: 1749 if path.startswith(spath): 1750 break 1751 else: 1752 search.append(path) 1753 1754 # if removing, we'll be verbose later when we actually remove stuff. 1755 # We don't want MOFCompiler to be verbose, as that would be confusing. 1756 verbose = options.verbose and not options.remove 1757 1758 mofcomp = MOFCompiler(handle=conn, search_paths=search, 1759 verbose=verbose) 1760 1761 try: 1762 for fname in args: 1763 if fname[0] != '/': 1764 fname = os.path.curdir + '/' + fname 1765 mofcomp.compile_file(fname, options.ns) 1766 except MOFParseError, pe: 1767 sys.exit(1) 1768 except CIMError, ce: 1769 sys.exit(1) 1770 1771 if options.remove and not options.dry_run: 1772 conn.rollback(verbose=options.verbose) 1773