【问题标题】:Parsing icinga conf files in python在python中解析icinga conf文件
【发布时间】:2015-05-29 15:46:25
【问题描述】:

我正在尝试为 icinga2 实例编写包装器。配置文件里面的对象是这样的;

object object_type "object_name" {
  some_property = "some_value"
}

例子;

object Host "server1" {
  import "generic-host"
  address = "192.168.0.1"
  vars.os = "Linux"
}

object Host "server2" {
  import "generic-host"
  address = "192.168.0.2"
  vars.os = "Linux"
}

我想做类似的事情:

icinga = icinga("/etc/icinga2/conf.d/hosts.conf")

print icinga.hosts_list()

icinga.hosts_add("server3","192.168.0.3")
icinga.hosts_remove("server1")

所以我尝试使用 pynag 之类的;

nc = Config('/etc/icinga2/conf.d/hosts.conf')
nc.parse()
print nc.get_host('server1')

但我明白了;

File "./icinga.py", line 51, in <module>
    print nc.get_host('server1')
  File "/Library/Python/2.7/site-packages/pynag/Parsers/__init__.py", line 1259, in get_host
    return self.get_object('host', object_name, user_key=user_key)
  File "/Library/Python/2.7/site-packages/pynag/Parsers/__init__.py", line 1238, in get_object
    for item in self.data['all_%s' % object_type]:
KeyError: 'all_host'

有没有一种简单的方法来处理这种形式?

【问题讨论】:

    标签: python parsing config icinga


    【解决方案1】:

    使用 pyparsing,处理这样的结构化文本格式并不难。

    下面是解析器的样子:

    from pyparsing import (Suppress, Keyword, Word, alphas, alphanums, Combine, 
        OneOrMore, quotedString, removeQuotes, Group, ZeroOrMore)
    
    LBRACE,RBRACE,EQ = map(Suppress, "{}=")
    
    OBJECT = Keyword("object")
    IMPORT = Keyword("import")
    
    ident = Word(alphas, alphanums)
    dottedIdent = Combine(ident + OneOrMore("." + ident))
    
    quotedString.setParseAction(removeQuotes)
    
    propertyDefn = Group((dottedIdent | ident)("name") + EQ + quotedString("value"))
    
    importDirective = Group(IMPORT + quotedString('source'))
    
    objectBodyDefn = Group(ZeroOrMore(propertyDefn("properties*") | 
                                      importDirective("imports*")))
    
    objectDefn = Group(OBJECT + ident("type") + quotedString("name") +
                        LBRACE + objectBodyDefn("body") + RBRACE)
    
    parser = ZeroOrMore(objectDefn)
    

    以下是如何应用解析器并访问解析后的数据:

    # parsing the sample, and accessing the parsed data fields
    for obj in parser.parseString(sample):
        print(obj.dump())
        print("%(name)s (%(type)s)" % obj)
        print("imports:", ','.join(imp.source for imp in obj.body.imports))
        print("properties:")
        if obj.body.properties:
            for prop in obj.body.properties:
                print('-', prop.name, ':', prop.value)
        else:
            print(' ','<none>')
        print()
    

    有了这个输出:

    ['object', 'Host', 'server1', [['import', 'generic-host'], ['address', '192.168.0.1'], ['vars.os', 'Linux']]]
    - body: [['import', 'generic-host'], ['address', '192.168.0.1'], ['vars.os', 'Linux']]
      - imports: 
        [0]:
          ['import', 'generic-host']
          - source: generic-host
      - properties: 
        [0]:
          ['address', '192.168.0.1']
          - name: address
          - value: 192.168.0.1
        [1]:
          ['vars.os', 'Linux']
          - name: vars.os
          - value: Linux
    - name: server1
    - type: Host
    server1 (Host)
    imports: generic-host
    properties:
    - address : 192.168.0.1
    - vars.os : Linux
    
    ['object', 'Host', 'server2', [['import', 'generic-host'], ['address', '192.168.0.2'], ['vars.os', 'Linux']]]
    - body: [['import', 'generic-host'], ['address', '192.168.0.2'], ['vars.os', 'Linux']]
      - imports: 
        [0]:
          ['import', 'generic-host']
          - source: generic-host
      - properties: 
        [0]:
          ['address', '192.168.0.2']
          - name: address
          - value: 192.168.0.2
        [1]:
          ['vars.os', 'Linux']
          - name: vars.os
          - value: Linux
    - name: server2
    - type: Host
    server2 (Host)
    imports: generic-host
    properties:
    - address : 192.168.0.2
    - vars.os : Linux
    

    【讨论】:

      【解决方案2】:

      我这样使用snipplet:

      icinga_conf+='object Host "%s" {\n\timport "generic-LinuxHost"\n\t' \
                               'address = "%s"\n\t' \
                               'vars.http_vhost="%s"\n\t' \
                               '%s' \
                               '\n\t}' \
                               '\n\n' % (icinga_name,ip,name,backupvars)
      

      【讨论】:

        【解决方案3】:

        我使用主机 conf 文件创建一个字典,如下所示:

        import re
        with open('hosts.conf', 'r') as f:
            lines = f.readlines()
            host=dict()
            add_attributes = False
            p= re.compile('obj[]\w\s]+"(.+)"')
            for line in lines:
                if '}' in line:
                    add_attributes = False
                if  add_attributes and '=' in line:
                    host[name][line.split('=')[0]]=line.split('=')[1]
                if p.search(line):
                    name=p.search(line).group(1)
                    add_attributes = True
                    host[name]=dict()
        

        然后,我有一个易于解析的字典。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-31
          • 1970-01-01
          • 2012-06-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 2014-05-06
          相关资源
          最近更新 更多