【问题标题】:Extract two strings from a line of text with Ansible使用 Ansible 从一行文本中提取两个字符串
【发布时间】:2021-03-04 14:51:59
【问题描述】:

我有这个来自 shell 输出的列表。

- 192.168.20.76:3260,1054 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
- 192.168.21.126:3260,1056 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
- 192.168.21.125:3260,1055 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
- 192.168.20.75:3260,1053 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
- 192.168.22.20:3260,1052 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
- 192.168.22.19:3260,1051 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6

当IP与主机在同一个vlan时,我想从列表中获取IP和iqn.xxxxx。

我能够创建正确 IP 的列表,但不知道如何获得相应的 iqn。

代码:

  - hosts: test_server
    gather_facts: yes 
    tasks: 
      - name:
        set_facts:
          iscsi_vlan: '192.168.20.64/28'
      - name: iscsiadm discovery
        command: /usr/sbin/iscsiadm iscsiadm --mode discovery --type sendtargets --portal {{ storage_fqdn }}
        register: iscsiadm_out
      - name: facts
        set_fact:
          target_list: "{{ target_list + item | regex_findall('(^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})') | ipaddr( iscsi_vlan ) }}"
        loop: "{{ iscsiadm_out.stdout_lines }}"
      - name: target_list
        debug: 
          var: target_list

target_list 包含这个。它使用 ip_addr 函数匹配正确的子网。

ok: [test-server] => 
  target_list:
  - 192.168.20.76
  - 192.168.20.75

基本上,我最终会尝试在一个包含另一个列表内容的列表中进行搜索。

  • 我试过 with_subelements 但它需要一个字符串和一个列表
  • 我试图弄清楚如何使用正则表达式一次性从 iscsiadm_out 中提取正确的 IP 和 iqn,但不能。
  • 我曾考虑将 iscsiadm_out 转换为 json 对象,然后使用 json_query,但我不知道该怎么做。

如何使用此列表从 iscsiadm_out 中提取 iqn,或者以完全不同的方式?

我知道我可以在命令模块中使用 grep 和 awk 等命令,但我不喜欢那个选项。

在我的测试中,我在 Internet 上的这里和其他地方搜索了几个小时。 我是 Ansible 的新手,并且是 python 和 jinja2 的新手,但我也试图调查这些路径也无济于事。

【问题讨论】:

    标签: python list filter ansible


    【解决方案1】:

    还有其他方法可以实现相同的结果,但您可以建立在以下概念之上。我只是在一个字典列表(每个字典包含一个 ip/iqn 对)中一次提取您的预期信息并循环它以过滤掉预期的元素。

    演示手册:

    ---
    - name: Extract IP and IQN
      hosts: localhost
      gather_facts: false
    
      vars:
        # This is what you get from your command
        iscsiadm:
          stdout_lines:
            - 192.168.20.76:3260,1054 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
            - 192.168.21.126:3260,1056 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
            - 192.168.21.125:3260,1055 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
            - 192.168.20.75:3260,1053 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
            - 192.168.22.20:3260,1052 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
            - 192.168.22.19:3260,1051 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6
    
        iscsi_vlan: '192.168.20.64/28'
    
      tasks:
        - name: "Create a list of {ip: x, iqn: y} dicts from the command result"
          vars:
            current_entry:
              - ip: >-
                  {{ item | regex_replace('(^(\d{1,3}\.){3}\d{1,3}).*$', '\g<1>') }}
                iqn: >-
                  {{ item | regex_replace('^.* (iqn\.\d*-\d*.com.netapp).*$', '\g<1>') }}
          set_fact:
            ipqn_list: "{{ ipqn_list | default([]) + current_entry }}"
          loop: "{{ iscsiadm.stdout_lines }}"
    
        - name: Debug element when ip is in our subnet (change to whatever is relevant)
          debug:
            msg: "IP {{ item.ip }} with IQN {{ item.iqn }} is in our subnet"
          loop: "{{ ipqn_list }}"
          when: item.ip | ipaddr(iscsi_vlan)
    

    给出结果:

    PLAY [Extract IP and IQN] **************************************************************************************************************************************************************************************************************
    
    TASK [Create a list of {ip: x, iqn: y} dicts from the command result] ******************************************************************************************************************************************************************
    ok: [localhost] => (item=192.168.20.76:3260,1054 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    ok: [localhost] => (item=192.168.21.126:3260,1056 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    ok: [localhost] => (item=192.168.21.125:3260,1055 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    ok: [localhost] => (item=192.168.20.75:3260,1053 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    ok: [localhost] => (item=192.168.22.20:3260,1052 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    ok: [localhost] => (item=192.168.22.19:3260,1051 iqn.1992-08.com.netapp:sn.f4bc76f43e2611e883e200a098d2174a:vs.6)
    
    TASK [Debug element when ip is in our subnet (change to whatever is relevant)] *********************************************************************************************************************************************************
    ok: [localhost] => (item={'ip': '192.168.20.76', 'iqn': 'iqn.1992-08.com.netapp'}) => {
        "msg": "IP 192.168.20.76 with IQN iqn.1992-08.com.netapp is in our subnet"
    }
    skipping: [localhost] => (item={'ip': '192.168.21.126', 'iqn': 'iqn.1992-08.com.netapp'}) 
    skipping: [localhost] => (item={'ip': '192.168.21.125', 'iqn': 'iqn.1992-08.com.netapp'}) 
    ok: [localhost] => (item={'ip': '192.168.20.75', 'iqn': 'iqn.1992-08.com.netapp'}) => {
        "msg": "IP 192.168.20.75 with IQN iqn.1992-08.com.netapp is in our subnet"
    }
    skipping: [localhost] => (item={'ip': '192.168.22.20', 'iqn': 'iqn.1992-08.com.netapp'}) 
    skipping: [localhost] => (item={'ip': '192.168.22.19', 'iqn': 'iqn.1992-08.com.netapp'}) 
    
    PLAY RECAP *****************************************************************************************************************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    【讨论】:

    • 感谢您的宝贵时间和热心帮助!这正是我想要的方式!我将 iqn 正则表达式中的右括号移动到行尾,因为我需要所有这些。我确实投了赞成票,但由于我是新来的,所以我没有足够的声誉让它公开可见。
    • 您需要更多声望才能获得支持(应该很快就可以了),但如果其中一个解决了您的问题,您仍然可以接受(绿色勾号)任一答案。这会让其他人知道有一个可行的解决方案。
    【解决方案2】:

    解析列表中的项目并创建字典,例如

        - set_fact:
            ipqn_dict: "{{ ipqn_dict|default({})|
                           combine({index: {'ip': ip,
                                            'port': port,
                                            'iqn': iqn,
                                            'code': code,
                                            'vs': vs}}) }}"
          loop: "{{ iscsiadm_out.stdout_lines }}"
          vars:
            a: "{{ item.split(',') }}"
            ip: "{{ a.0.split(':').0 }}"
            port: "{{ a.0.split(':').1 }}"
            b: "{{ a.1.split(' ') }}"
            index: "{{ b.0 }}"
            iqn: "{{ b.1.split(':').0 }}"
            code: "{{ b.1.split(':').1 }}"
            vs: "{{ b.1.split(':').2 }}"
    

    给予

      ipqn_dict:
        '1051':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.22.19
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
        '1052':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.22.20
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
        '1053':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.20.75
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
        '1054':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.20.76
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
        '1055':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.21.125
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
        '1056':
          code: sn.f4bc76f43e2611e883e200a098d2174a
          ip: 192.168.21.126
          iqn: iqn.1992-08.com.netapp
          port: '3260'
          vs: vs.6
    

    这应该会简化所需数据的选择,例如

        - debug:
            msg: "{{ ipqn_dict|json_query('*.[ip,iqn]') }}"
    

    给予

      - - 192.168.20.76
        - iqn.1992-08.com.netapp
      - - 192.168.21.126
        - iqn.1992-08.com.netapp
      - - 192.168.21.125
        - iqn.1992-08.com.netapp
      - - 192.168.20.75
        - iqn.1992-08.com.netapp
      - - 192.168.22.20
        - iqn.1992-08.com.netapp
      - - 192.168.22.19
        - iqn.1992-08.com.netapp
    

    【讨论】:

    • 感谢您的帮助和时间!这是提取文本并将其排序为字典的好方法。稍后我将在其他用例中需要它。我确实投了赞成票,但由于我是新来的,所以我没有足够的声誉让它公开可见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 2023-01-15
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多