Python 脚本尝试生成 YAML 文件(Containerlab 拓扑文件)作为输出,但格式错误

问题描述 投票:0回答:1

我目前正在开发一个 Python 文件,旨在生成“自定义”containerlab 拓扑文件 - yaml 格式 - 但我得到的输出与预期不同,并且我正在努力修复它。

这是我尝试使用提到的Python脚本生成的aimple Lab拓扑文件的示例:

name: Test

topology:
  nodes:
    device1:
      kind: device_type
      image: image
    device2:
      kind: device_type
      image: image
    device3:
      kind: device_type
      image: image
  links:
    - endpoints: ["device1:eth1", "device2:eth1"]
    - endpoints: ["device2:eth2", "device3:eth2"]

相反,我得到了这个:

- name: Test
- topology:
  - nodes:
    - device1:
        kind: device_type
        image: image
    - device2:
        kind: device_type
        image: image
    - device3:
        kind: device_type
        image: image
  links:
  - endpoints:
    - device1:eth1
    - device2:eth1
  - endpoints:
    - device2:eth2
    - device3:eth2

这是我到目前为止的Python脚本:

import ruamel.yaml as yaml

# Create an ordered dictionary representing the lab name
lab_name = yaml.comments.CommentedMap()
lab_name['name'] = yaml.comments.CommentedSeq()

# Create an ordered dictionary representing the topology
topology_dict = yaml.comments.CommentedMap()
topology_dict['topology'] = yaml.comments.CommentedSeq()
topo_dict = yaml.comments.CommentedMap()
topo_dict['nodes'] = yaml.comments.CommentedSeq()
topo_dict['links'] = yaml.comments.CommentedSeq()

# Define the number of nodes
num_nodes = int(input("Enter the number of nodes: "))

# Define the LAB name
# Creating a Function that Verifies Lab valid name or not
def is_valid_lab_name(name):
    if name is None:
        return False
    elif " " in name:
        return False
    elif not all(char.isalnum() or char == "_" for char in name):
        return False
    return True

# Prompt users for input until valid name is provided

while True:
    lab_name_input = input("Enter the Lab Topology name (No Spaces, only '_' allowed): ")
    if is_valid_lab_name(lab_name_input):
        lab_name = {"name":str(f"{lab_name_input}")}
        break
    else:
        print("Invalid name. Please try again.")


# Generate nodes and links
for i in range(1, num_nodes + 1):
    node_name = str(f"ceos{i}")
    node = {
        node_name: {
        "kind": "ceos",
        "image": "device/image"
        }
    }
    topo_dict['nodes'].append(node)

    if i > 1:
        link = {
            "endpoints": str([f"{node_name}:eth1", f"ceos{i-1}:eth1"]),
        }
        topo_dict['links'].append(link)


# Integrating Nodes List Dictionary into Main Topology Dictionary
topology_dict = {'topology': [{'nodes': topo_dict['nodes']}]}


# Loop through LINKS dictionary and refactor links to CLAB format
for item in topo_dict['links']:
    if 'endpoints' in item:
        value = item['endpoints']
        if isinstance(value, str):
            # Remove single quotes and replace square brackets with lists
            updated_value = eval(value.replace("'", '"'))
            
            # Update the original dictionary with the modified value
            item['endpoints'] = updated_value


# Integrating Nodes List Dictionary into Main Topology Dictionary
topology_dict['links'] = list(topo_dict['links'])


# Append both Dictionaries, Name and Topology into the same YAML file
lab_file = [lab_name, topology_dict]


# Create a YAML file
with open("dynamic_topology.yaml", "w") as yaml_file:
    yaml.dump(lab_file, yaml_file, Dumper=yaml.RoundTripDumper, default_flow_style=False)


print("--------------------------------------------")
print("Dynamic topology file created successfully")
print("--------------------------------------------")
python-3.x automation yaml pyyaml ruamel.yaml
1个回答
0
投票

您正在序列化一个列表,而不是一个字典...因此您将获得一个表示列表的 YAML 文档:

lab_file = [lab_name, topology_dict]

如果您想要 YAML 字典作为输出,则需要向

yaml.dump
提供字典。比如:

topology_dict.update(lab_name)
with open("dynamic_topology.yaml", "w") as yaml_file:
    yaml.dump(topology_dict, yaml_file, Dumper=yaml.RoundTripDumper, default_flow_style=False)

另外,请注意:

  links:
  - endpoints:
    - device1:eth1
    - device2:eth1
  - endpoints:
    - device2:eth2
    - device3:eth2

还有这个:

  links:
    - endpoints: ["device1:eth1", "device2:eth1"]
    - endpoints: ["device2:eth2", "device3:eth2"]

是相同数据结构的替代表示。

© www.soinside.com 2019 - 2024. All rights reserved.